unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
@ 2023-02-26 16:23 Arthur Miller
  2023-02-26 18:03 ` Dmitry Gutov
  0 siblings, 1 reply; 9+ messages in thread
From: Arthur Miller @ 2023-02-26 16:23 UTC (permalink / raw)
  To: 61817


What actions trigger the bug:

Two different, unrelated repositories with emacs source code tree. My tree(s)
looks like this:

~/repos/emsrc/emacs/
~/repos/enacs-tests/emacs/

Where in both the last "emacs/" is the Emacs source tree from main git
repository.

~/repos/emsrc/emacs/ is the one I use for my "everyday" Emacs. I build Emacs now
and then once in a week or few weeks with a script, and I make each build in its
own our-of-source worktree. The other one is one where I used to do some tests. 
It shouldn't matter since all worktrees are contained withing parent directory,
which in one case is "emsrc" and in the other case "emacs-tests", but for some
reason project.el sees the wrong one.

1. create two parent folders each one containing a copy of emacs sources
1. create out of source worktree for Emacs source under one of those
2. navigate to the worktree/lisp/progmodes
3. run M-: (project-known-project-roots)

In my Emacs, I am in my currently installed emacs worktree, where git root is

~/repos/emsrc/emacs but project.el returns ("~/repos/emacs-tests/emacs/") as a
result, which is totally unrelated to this source tree. I don't know what
happends, but I guess project.el goes "too far" out in search for roots; no
idea, I am not chasing the bug, but I don't see much code in project.el related
to worktrees. The only place I see them mentioned is about submodules.I
personally have used this one for quite some time, and it seems to correctly
handle worktrees for me:

#+begin_src emacs-lisp
(defun git-root (&optional directory)
  "Find git root in a git project.

If DIRECTORY is not given, return git root of DEFAULT-DIRECTORY.

This should correctly find git root even for worktrees placed outside of a git
repository as well as in subdirectories in main git repository."
  (let* ((directory (expand-file-name (or directory default-directory)))
         (git-dir (locate-dominating-file directory ".git"))
         (git-file (and git-dir (expand-file-name ".git" git-dir))))
    (if (and git-file (file-directory-p git-file))
          git-dir
      (and git-file
           (with-temp-buffer
             (insert-file-contents-literally git-file)
             (when (search-forward "gitdir: " nil t)
               (let ((beg (point))
                     (end (search-forward ".git" nil t)))
                 (buffer-substring-no-properties beg (- end 4)))))))))
#+end_src

I don't use submodules, so I don't know if it works there, and there are
probably better ways to handle this, perhaps asking git for worktree list, but
that cost executing a git process, while parsing a file is relatively cheap and
much faster.

I don't know if this use-case is too bisarre; I will actually remove my
emacs-tests folder, it is an old remain, but still, I don't think project.el
should repport invalid project roots anyway.




In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, cairo version 1.17.8) of
 2023-02-26 built on pascal
Repository revision: 013655811aa1c89754372610c8c6ccccec166035
Repository branch: no-gtk-with-cairo-and-native-230226-061643
Windowing system distributor 'The X.Org Foundation', version 11.0.12101007
System Description: Arch Linux

Configured using:
 'configure --with-native-compilation --with-x --with-x-toolkit=no
 --without-gconf --without-gsettings --without-toolkit-scroll-bars
 --with-xinput2 --without-included-regex --without-compress-install 'CFLAGS=-O2
 -march=native''

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM HARFBUZZ JPEG JSON LCMS2 LIBOTF
LIBSYSTEMD LIBXML2 M17N_FLT MODULES NATIVE_COMP NOTIFY INOTIFY OLDXMENU PDUMPER
PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TREE_SITTER WEBP X11 XDBE XIM
XINPUT2 XPM ZLIB

Important settings:
  value of $LANG: sv_SE.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Dired by name

Minor modes in effect:
  ace-window-display-mode: t
  helm-flx-mode: t
  windmove-mode: t
  emms-mode-line-mode: t
  emms-playing-time-display-mode: t
  emms-playing-time-mode: t
  beacon-mode: t
  server-mode: t
  which-key-mode: t
  wrap-region-global-mode: t
  electric-pair-mode: t
  global-auto-revert-mode: t
  global-hl-line-mode: t
  global-subword-mode: t
  subword-mode: t
  auto-image-file-mode: t
  display-time-mode: t
  delete-selection-mode: t
  save-place-mode: t
  winner-mode: t
  pixel-scroll-precision-mode: t
  auto-insert-mode: t
  helm-mode: t
  helm-minibuffer-history-mode: t
  helm-adaptive-mode: t
  dired-auto-readme-mode: t
  dired-omit-mode: t
  dired-async-mode: t
  dired-hide-details-mode: t
  shell-dirtrack-mode: t
  helm-autoresize-mode: t
  helm--remap-mouse-mode: t
  async-bytecomp-package-mode: t
  speed-of-thought-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  buffer-read-only: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  auto-save-visited-mode: t
  abbrev-mode: t

Load-path shadows:
/home/arthur/.config/emacs/lisp/emacs-lisp/package hides /home/arthur/.emacs.d/lisp/package
/home/arthur/.emacs.d/elpa/with-editor-20230212.2214/with-editor hides /home/arthur/.emacs.d/elpa/with-editor-20230210.1157/with-editor
/home/arthur/.emacs.d/elpa/with-editor-20230212.2214/with-editor-autoloads hides /home/arthur/.emacs.d/elpa/with-editor-20230210.1157/with-editor-autoloads
/home/arthur/.emacs.d/elpa/with-editor-20230212.2214/with-editor-pkg hides /home/arthur/.emacs.d/elpa/with-editor-20230210.1157/with-editor-pkg
/home/arthur/.emacs.d/elpa/with-editor-20230212.2214/with-editor hides /home/arthur/.emacs.d/elpa/with-editor-20230118.1656/with-editor
/home/arthur/.emacs.d/elpa/with-editor-20230212.2214/with-editor-autoloads hides /home/arthur/.emacs.d/elpa/with-editor-20230118.1656/with-editor-autoloads
/home/arthur/.emacs.d/elpa/with-editor-20230212.2214/with-editor-pkg hides /home/arthur/.emacs.d/elpa/with-editor-20230118.1656/with-editor-pkg
/home/arthur/.config/emacs/lisp/transient hides /home/arthur/.emacs.d/elpa/transient-20230220.1425/transient
/home/arthur/.config/emacs/lisp/transient hides /home/arthur/.emacs.d/elpa/transient-20230209.2250/transient
/home/arthur/.emacs.d/elpa/transient-20230220.1425/transient-autoloads hides /home/arthur/.emacs.d/elpa/transient-20230209.2250/transient-autoloads
/home/arthur/.emacs.d/elpa/transient-20230220.1425/transient-pkg hides /home/arthur/.emacs.d/elpa/transient-20230209.2250/transient-pkg
/home/arthur/.config/emacs/lisp/transient hides /home/arthur/.emacs.d/elpa/transient-20230201.1644/transient
/home/arthur/.emacs.d/elpa/transient-20230220.1425/transient-autoloads hides /home/arthur/.emacs.d/elpa/transient-20230201.1644/transient-autoloads
/home/arthur/.emacs.d/elpa/transient-20230220.1425/transient-pkg hides /home/arthur/.emacs.d/elpa/transient-20230201.1644/transient-pkg
/home/arthur/.config/emacs/lisp/transient hides /home/arthur/.emacs.d/elpa/transient-20230107.1528/transient
/home/arthur/.emacs.d/elpa/transient-20230220.1425/transient-autoloads hides /home/arthur/.emacs.d/elpa/transient-20230107.1528/transient-autoloads
/home/arthur/.emacs.d/elpa/transient-20230220.1425/transient-pkg hides /home/arthur/.emacs.d/elpa/transient-20230107.1528/transient-pkg
/home/arthur/.config/emacs/lisp/textmodes/string-edit hides /home/arthur/.emacs.d/elpa/string-edit-20220604.2128/string-edit
/home/arthur/.emacs.d/elpa/sotlisp-20220909.803/sotlisp hides /home/arthur/.emacs.d/elpa/sotlisp-1.6.2/sotlisp
/home/arthur/.emacs.d/elpa/peg-1.0.1/peg-autoloads hides /home/arthur/.emacs.d/elpa/peg-1.0/peg-autoloads
/home/arthur/.emacs.d/elpa/peg-1.0.1/peg-tests hides /home/arthur/.emacs.d/elpa/peg-1.0/peg-tests
/home/arthur/.emacs.d/elpa/peg-1.0.1/peg hides /home/arthur/.emacs.d/elpa/peg-1.0/peg
/home/arthur/.emacs.d/elpa/peg-1.0.1/peg-pkg hides /home/arthur/.emacs.d/elpa/peg-1.0/peg-pkg
/home/arthur/.emacs.d/elpa/peep-dired-20160321.2237/peep-dired hides /home/arthur/.emacs.d/elpa/peep-dired-1.1.0/peep-dired
/home/arthur/.emacs.d/elpa/peep-dired-20160321.2237/peep-dired-autoloads hides /home/arthur/.emacs.d/elpa/peep-dired-1.1.0/peep-dired-autoloads
/home/arthur/.emacs.d/elpa/peep-dired-20160321.2237/peep-dired-pkg hides /home/arthur/.emacs.d/elpa/peep-dired-1.1.0/peep-dired-pkg
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section hides /home/arthur/.emacs.d/elpa/magit-section-20230211.1642/magit-section
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-pkg hides /home/arthur/.emacs.d/elpa/magit-section-20230211.1642/magit-section-pkg
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-autoloads hides /home/arthur/.emacs.d/elpa/magit-section-20230211.1642/magit-section-autoloads
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section hides /home/arthur/.emacs.d/elpa/magit-section-20230204.1138/magit-section
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-pkg hides /home/arthur/.emacs.d/elpa/magit-section-20230204.1138/magit-section-pkg
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-autoloads hides /home/arthur/.emacs.d/elpa/magit-section-20230204.1138/magit-section-autoloads
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section hides /home/arthur/.emacs.d/elpa/magit-section-20230106.1659/magit-section
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-pkg hides /home/arthur/.emacs.d/elpa/magit-section-20230106.1659/magit-section-pkg
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-autoloads hides /home/arthur/.emacs.d/elpa/magit-section-20230106.1659/magit-section-autoloads
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section hides /home/arthur/.emacs.d/elpa/magit-section-20221127.2227/magit-section
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-pkg hides /home/arthur/.emacs.d/elpa/magit-section-20221127.2227/magit-section-pkg
/home/arthur/.emacs.d/elpa/magit-section-20230213.2018/magit-section-autoloads hides /home/arthur/.emacs.d/elpa/magit-section-20221127.2227/magit-section-autoloads
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-xml hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-xml
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-prolog hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-prolog
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-steep hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-steep
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-sorbet hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-sorbet
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-vetur hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-vetur
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-beancount hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-beancount
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-dockerfile hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-dockerfile
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-tex hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-tex
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-hack hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-hack
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-r hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-r
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-haxe hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-haxe
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-yaml hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-yaml
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-pylsp hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-pylsp
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-elixir hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-elixir
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-groovy hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-groovy
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-rf hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-rf
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-elm hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-elm
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-nginx hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-nginx
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-json hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-json
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-angular hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-angular
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-svelte hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-svelte
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-toml hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-toml
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-zig hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-zig
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-pwsh hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-pwsh
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-protocol hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-protocol
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-icons hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-icons
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-cmake hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-cmake
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-rust hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-rust
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-php hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-php
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-diagnostics hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-diagnostics
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-erlang hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-erlang
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-mode-autoloads hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-mode-autoloads
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-actionscript hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-actionscript
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-purescript hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-purescript
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-racket hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-racket
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-html hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-html
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-solargraph hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-solargraph
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-lens hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-lens
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-nim hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-nim
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-ocaml hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-ocaml
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-ada hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-ada
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-csharp hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-csharp
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-semantic-tokens hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-semantic-tokens
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-lua hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-lua
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-css hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-css
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-markdown hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-markdown
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-v hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-v
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-vimscript hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-vimscript
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-dired hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-dired
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-graphql hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-graphql
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-go hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-go
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-vala hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-vala
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-mode hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-mode
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-javascript hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-javascript
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-completion hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-completion
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-fsharp hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-fsharp
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-sqls hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-sqls
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-perl hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-perl
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-clojure hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-clojure
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-gdscript hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-gdscript
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-dhall hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-dhall
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-pyls hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-pyls
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-nix hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-nix
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-verilog hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-verilog
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-fortran hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-fortran
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-kotlin hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-kotlin
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-modeline hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-modeline
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-iedit hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-iedit
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-ido hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-ido
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-crystal hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-crystal
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-terraform hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-terraform
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-vhdl hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-vhdl
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-clangd hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-clangd
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-headerline hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-headerline
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-d hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-d
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-bash hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-bash
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-mode-pkg hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-mode-pkg
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp
/home/arthur/.emacs.d/elpa/lsp-mode-20230221.1558/lsp-eslint hides /home/arthur/.emacs.d/elpa/lsp-mode-20211211.1834/lsp-eslint
/home/arthur/.emacs.d/elpa/lispy-20221225.1927/elpa hides /home/arthur/.emacs.d/elpa/ivy-20220926.1250/elpa
/home/arthur/.config/emacs/lisp/emacs-lisp/helper hides /home/arthur/.emacs.d/elpa/helper-0.5/helper
/home/arthur/.emacs.d/lisp/helm-git-branch hides /home/arthur/.emacs.d/elpa/helm-git-branch-0.1/helm-git-branch
/home/arthur/.emacs.d/elpa/git-commit-20230220.1901/git-commit hides /home/arthur/.emacs.d/elpa/git-commit-20221106.1128/git-commit
/home/arthur/.emacs.d/elpa/git-commit-20230220.1901/git-commit-autoloads hides /home/arthur/.emacs.d/elpa/git-commit-20221106.1128/git-commit-autoloads
/home/arthur/.emacs.d/elpa/git-commit-20230220.1901/git-commit-pkg hides /home/arthur/.emacs.d/elpa/git-commit-20221106.1128/git-commit-pkg
/home/arthur/.emacs.d/elpa/emacsql-sqlite-20230221.1532/emacsql-sqlite hides /home/arthur/.emacs.d/elpa/emacsql-20230221.1532/emacsql-sqlite
/home/arthur/.emacs.d/elpa/emacsql-20230221.1532/emacsql hides /home/arthur/.emacs.d/elpa/emacsql-20230118.2020/emacsql
/home/arthur/.emacs.d/elpa/emacsql-20230221.1532/emacsql-pkg hides /home/arthur/.emacs.d/elpa/emacsql-20230118.2020/emacsql-pkg
/home/arthur/.emacs.d/elpa/emacsql-20230221.1532/emacsql-compiler hides /home/arthur/.emacs.d/elpa/emacsql-20230118.2020/emacsql-compiler
/home/arthur/.emacs.d/elpa/emacsql-20230221.1532/emacsql-autoloads hides /home/arthur/.emacs.d/elpa/emacsql-20230118.2020/emacsql-autoloads
/home/arthur/.emacs.d/elpa/elisp-refs-20220704.2141/elisp-refs hides /home/arthur/.emacs.d/elpa/elisp-refs-1.4/elisp-refs
/home/arthur/.emacs.d/elpa/elisp-refs-20220704.2141/elisp-refs-autoloads hides /home/arthur/.emacs.d/elpa/elisp-refs-1.4/elisp-refs-autoloads
/home/arthur/.emacs.d/elpa/elisp-refs-20220704.2141/elisp-refs-pkg hides /home/arthur/.emacs.d/elpa/elisp-refs-1.4/elisp-refs-pkg
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-26 hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-26
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-25 hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-25
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-29 hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-29
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-27 hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-27
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-pkg hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-pkg
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-28 hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-28
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-autoloads hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-autoloads
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-macs hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat-macs
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat hides /home/arthur/.emacs.d/elpa/compat-29.1.3.2/compat
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-26 hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-26
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-25 hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-25
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-29 hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-29
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-27 hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-27
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-pkg hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-pkg
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-28 hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-28
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-autoloads hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-autoloads
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-macs hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat-macs
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat hides /home/arthur/.emacs.d/elpa/compat-29.1.1.0/compat
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-26 hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-26
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-25 hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-25
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-27 hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-27
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-pkg hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-pkg
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-28 hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-28
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-autoloads hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-autoloads
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-macs hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-macs
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat hides /home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-26 hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-26
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-25 hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-25
/home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-help hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-help
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-27 hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-27
/home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-font-lock hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-font-lock
/home/arthur/.emacs.d/elpa/compat-28.1.2.2/compat-24 hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-24
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-pkg hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-pkg
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-macs hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-macs
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-28 hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-28
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat-autoloads hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat-autoloads
/home/arthur/.emacs.d/elpa/compat-29.1.3.4/compat hides /home/arthur/.emacs.d/elpa/compat-28.1.1.1/compat
/home/arthur/.emacs.d/lisp/company-cmake hides /home/arthur/.emacs.d/elpa/company-20230209.134/company-cmake
/home/arthur/.emacs.d/elpa/closql-20230220.1944/closql-autoloads hides /home/arthur/.emacs.d/elpa/closql-20230212.2019/closql-autoloads
/home/arthur/.emacs.d/elpa/closql-20230220.1944/closql-pkg hides /home/arthur/.emacs.d/elpa/closql-20230212.2019/closql-pkg
/home/arthur/.emacs.d/elpa/closql-20230220.1944/closql hides /home/arthur/.emacs.d/elpa/closql-20230212.2019/closql
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-clojuredocs hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-clojuredocs
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-completion hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-completion
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-profile hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-profile
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-cheatsheet hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-cheatsheet
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-format hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-format
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-eldoc hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-eldoc
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-find hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-find
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-client hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-client
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-classpath hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-classpath
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-common hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-common
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-jar hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-jar
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-util hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-util
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-repl-history hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-repl-history
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-debug hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-debug
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-eval hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-eval
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-browse-ns hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-browse-ns
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-stacktrace hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-stacktrace
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-overlays hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-overlays
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-repl hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-repl
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-tracing hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-tracing
/home/arthur/.emacs.d/elpa/cider-20230218.915/nrepl-dict hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/nrepl-dict
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-selector hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-selector
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-ns hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-ns
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-browse-spec hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-browse-spec
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-test hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-test
/home/arthur/.emacs.d/elpa/cider-20230218.915/nrepl-client hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/nrepl-client
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-macroexpansion hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-macroexpansion
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-connection hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-connection
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-doc hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-doc
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-resolve hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-resolve
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-xref hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-xref
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-scratch hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-scratch
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-inspector hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-inspector
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-autoloads hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-autoloads
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-mode hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-mode
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-apropos hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-apropos
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-popup hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-popup
/home/arthur/.emacs.d/elpa/cider-20230218.915/cider-pkg hides /home/arthur/.emacs.d/elpa/cider-20230208.2108/cider-pkg

Features:
(shadow mail-extr emacsbug qp gnus-ml gnus-topic nndraft nnmh nnfolder utf-7
network-stream gnus-agent gnus-srvr gnus-score score-mode nnvirtual gnus-msg
nntp gnus-cache cus-start help-fns radix-tree cl-print bug-reference bookmark
tabify org-capture timezone org-goto cursor-sensor org-mouse let-alist
ob-hide-markers ace-window avy org-eldoc org-element org-persist org-id
org-refile avl-tree oc-basic ol-eww eww url-queue mm-url ol-rmail ol-mhe ol-irc
ol-info ol-gnus nnselect gnus-art mm-uu mml2015 mm-view mml-smime smime gnutls
dig gnus-sum shr pixel-fill kinsoku url-file svg dom gnus-group gnus-undo
gnus-start gnus-dbus gnus-cloud nnimap nnmail mail-source utf7 nnoo gnus-spec
gnus-int gnus-range message sendmail yank-media rfc822 mml mml-sec epa epg
rfc6068 epg-config mm-decode mm-bodies mm-encode mailabbrev gmm-utils mailheader
gnus-win ol-docview doc-view jka-compr ol-bibtex bibtex ol-bbdb ol-w3m ol-doi
org-link-doi vc-git diff-mode vc-dispatcher helm-command dired-narrow
helm-external helm-net tramp-archive tramp-gvfs tramp-cache time-stamp zeroconf
ffap helm-flx flx emms-mpris dbus sv-kalender lunar solar cal-dst holidays
holiday-loaddefs extras windmove recentf tree-widget emms-librefm-stream xml
emms-librefm-scrobbler emms-i18n emms-history emms-score emms-stream-info
emms-metaplaylist-mode emms-bookmarks emms-cue emms-mode-line-icon emms-browser
sort emms-playlist-sort emms-last-played emms-player-xine emms-player-mpd tq
emms-lyrics emms-url emms-streams emms-show-all emms-tag-editor
emms-tag-tracktag emms-mark emms-cache emms-info-native bindat
emms-info-exiftool emms-info-tinytag emms-info-metaflac emms-info-opusinfo
emms-info-ogginfo emms-info-mp3info emms-player-vlc emms-player-mplayer
emms-player-mpv emms-mode-line-cycle emms-mode-line emms-playing-time
emms-player-simple emms-info emms-later-do emms-playlist-limit emms-volume
emms-volume-sndioctl emms-volume-mixerctl emms-volume-pulse emms-volume-amixer
emms-playlist-mode emms-source-playlist emms-source-file locate emms-setup emms
emms-compat beacon c++-setup server overseer pkg-info url-http url-auth
mail-parse rfc2231 rfc2047 rfc2045 ietf-drums url-gw nsm puny epl f f-shortdoc s
disp-table page-break-lines company-yasnippet company-ispell ispell
company-clang company-elisp company-etags etags fileloop generator xref
company-semantic company-template company-keywords make-mode nnir gnus nnheader
gnus-util mail-utils range mm-util mail-prsvr which-key solarized-dark-theme
solarized solarized-faces wrap-region elec-pair autorevert hl-line cap-words
superword subword image-file image-converter time delsel saveplace winner
pixel-scroll cua-base cl-extras autoinsert elisp-extras popup helm-pages
helm-mode helm-misc helm-adaptive helm-projectile projectile project lisp-mnt
grep compile ibuf-ext ibuffer ibuffer-loaddefs helm-eshell helm-elisp helm-files
image-dired image-dired-tags image-dired-external image-dired-util xdg
image-mode dired-setup tmtxt-dired-async tmtxt-async-tasks dired-auto-readme
text-property-search dired-git-log dired-copy-paste dired-subtree
dired-hacks-utils dash org-view-mode org-view-font face-remap markdown-mode
color thingatpt openwith dired-x wdired dired-async dired-aux dired
dired-loaddefs exif filenotify tramp tramp-loaddefs trampver tramp-integration
cus-edit pp cus-load wid-edit files-x tramp-compat shell parse-time iso8601
ls-lisp helm-buffers helm-occur helm-tags helm-locate helm-grep helm-regexp
helm-eval edebug-x comp comp-cstr warnings advice which-func imenu edebug debug
backtrace helm-info helm-utils helm-types helm-help helm helm-global-bindings
helm-core helm-source helm-multi-match helm-lib async-bytecomp async
yasnippet-snippets yasnippet cl-extra derived easy-mmode help-mode outshine
outshine-org-cmds outorg org-pretty-table org-protocol org ob ob-tangle ob-ref
ob-lob ob-table ob-exp org-macro org-src ob-comint org-pcomplete pcomplete
comint ansi-osc ansi-color ring org-list org-footnote org-faces org-entities
time-date ob-emacs-lisp ob-core ob-eval org-cycle org-table ol rx org-fold
org-fold-core org-keys oc org-loaddefs find-func cal-menu calendar cal-loaddefs
org-version org-compat org-macs format-spec noutline outline icons company-files
company-capf company sotlisp skeleton paredit edmacro kmacro diminish cl
helm-easymenu pcase info package browse-url url url-proxy url-privacy url-expand
url-methods url-history url-cookie generate-lisp-file url-domsuf url-util
mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs
password-cache json subr-x map byte-opt gv bytecomp byte-compile url-vars
cl-loaddefs cl-lib rmc iso-transl tooltip cconv eldoc paren electric uniquify
ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode register page
tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse
jit-lock font-lock syntax font-core term/tty-colors frame minibuffer nadvice seq
simple cl-generic indonesian philippine cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew
greek romanian slovak czech european ethiopic indian cyrillic chinese composite
emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help abbrev
obarray oclosure cl-preloaded button loaddefs theme-loaddefs faces cus-face
macroexp files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote threads
dbusbind inotify lcms2 dynamic-setting font-render-setting cairo xinput2 x
multi-tty make-network-process native-compile emacs)

Memory information:
((conses 16 1097924 136505)
 (symbols 48 48935 1)
 (strings 32 202453 20654)
 (string-bytes 1 7492488)
 (vectors 16 116979)
 (vector-slots 8 2994192 162034)
 (floats 8 1542 7804)
 (intervals 56 37098 2620)
 (buffers 984 45))





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-26 16:23 bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees Arthur Miller
@ 2023-02-26 18:03 ` Dmitry Gutov
  2023-02-27  7:32   ` Arthur Miller
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Gutov @ 2023-02-26 18:03 UTC (permalink / raw)
  To: Arthur Miller, 61817

On 26/02/2023 18:23, Arthur Miller wrote:
> What actions trigger the bug:
> 
> Two different, unrelated repositories with emacs source code tree. My tree(s)
> looks like this:
> 
> ~/repos/emsrc/emacs/
> ~/repos/enacs-tests/emacs/
> 
> Where in both the last "emacs/" is the Emacs source tree from main git
> repository.
> 
> ~/repos/emsrc/emacs/  is the one I use for my "everyday" Emacs. I build Emacs now
> and then once in a week or few weeks with a script, and I make each build in its
> own our-of-source worktree. The other one is one where I used to do some tests.
> It shouldn't matter since all worktrees are contained withing parent directory,
> which in one case is "emsrc" and in the other case "emacs-tests", but for some
> reason project.el sees the wrong one.
> 
> 1. create two parent folders each one containing a copy of emacs sources
> 1. create out of source worktree for Emacs source under one of those
> 2. navigate to the worktree/lisp/progmodes
> 3. run M-: (project-known-project-roots)
> 
> In my Emacs, I am in my currently installed emacs worktree, where git root is
> 
> ~/repos/emsrc/emacs but project.el returns ("~/repos/emacs-tests/emacs/") as a
> result

What does (project-root (project-current)) return? And which dirs you 
are testing it in?

> I am not chasing the bug, but I don't see much code in project.el related
> to worktrees.

Normally, there shouldn't be any need to handle worktree specially: it 
contains a file called .git at the top which can serve as a marker just 
fine.

> The only place I see them mentioned is about submodules.I
> personally have used this one for quite some time, and it seems to correctly
> handle worktrees for me:

You code looks like it can return the "actual git root" that can be a 
directory residing somewhere else than the current directory tree. Is 
that what you wanted? Off the top of my head, that should break the 
'project-files' method.





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-26 18:03 ` Dmitry Gutov
@ 2023-02-27  7:32   ` Arthur Miller
  2023-02-27 11:51     ` Dmitry Gutov
  0 siblings, 1 reply; 9+ messages in thread
From: Arthur Miller @ 2023-02-27  7:32 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: 61817

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 26/02/2023 18:23, Arthur Miller wrote:
>> What actions trigger the bug:
>> Two different, unrelated repositories with emacs source code tree. My tree(s)
>> looks like this:
>> ~/repos/emsrc/emacs/
>> ~/repos/enacs-tests/emacs/
>> Where in both the last "emacs/" is the Emacs source tree from main git
>> repository.
>> ~/repos/emsrc/emacs/  is the one I use for my "everyday" Emacs. I build Emacs
>> now
>> and then once in a week or few weeks with a script, and I make each build in its
>> own our-of-source worktree. The other one is one where I used to do some tests.
>> It shouldn't matter since all worktrees are contained withing parent directory,
>> which in one case is "emsrc" and in the other case "emacs-tests", but for some
>> reason project.el sees the wrong one.
>> 1. create two parent folders each one containing a copy of emacs sources
>> 1. create out of source worktree for Emacs source under one of those
>> 2. navigate to the worktree/lisp/progmodes
>> 3. run M-: (project-known-project-roots)
>> In my Emacs, I am in my currently installed emacs worktree, where git root is
>> ~/repos/emsrc/emacs but project.el returns ("~/repos/emacs-tests/emacs/") as a
>> result
>
> What does (project-root (project-current)) return? And which dirs you are
> testing it in?

It returns the current worktree folder:

"/home/arthur/repos/emsrc/no-gtk-with-cairo-and-native-230226-061643/"

which I guess is what project.el finds as root since it only uses .git as a
marker, if I understand correctly what you write little further.

>> I am not chasing the bug, but I don't see much code in project.el related
>> to worktrees.
>
> Normally, there shouldn't be any need to handle worktree specially: it contains
> a file called .git at the top which can serve as a marker just fine.

Well define "normally" and "just fine" :). Anyway, when I read your reply it seems
like I have wrong expectation from project.el, so the fault is on my side. I
thought it can deal with git projects in general, but as I understand it then,
it only works with files in current directory.

>> The only place I see them mentioned is about submodules.I
>> personally have used this one for quite some time, and it seems to correctly
>> handle worktrees for me:
>
> You code looks like it can return the "actual git root" that can be a directory
> residing somewhere else than the current directory tree.

Git worktrees can be placed outside the main repository tree:

    git worktree add ../my-new-shiny-emacs-patch

as an example. The code will find correct git root both outside, or within the
repo. But I think it should be done by actually asking git to list worktrees
instead.

>                                                          Is that what you
> wanted?

Yes that is what I wanted? :-).

For automation purpose I need to find the project root, so I can pull sources to
main, create a clean worktree from main, and switch Emacs to the new worktree
interactively in one command, like M-x make-new-patch. Emacs asks me for a name
and create a clean worktree from the main trunk for current project. Actually
better variant is to ask which branch to patch, but the first one is slightly
faster and works just fine in many cases.






^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-27  7:32   ` Arthur Miller
@ 2023-02-27 11:51     ` Dmitry Gutov
  2023-02-27 14:15       ` Arthur Miller
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Gutov @ 2023-02-27 11:51 UTC (permalink / raw)
  To: Arthur Miller; +Cc: 61817

On 27/02/2023 09:32, Arthur Miller wrote:
> Dmitry Gutov <dgutov@yandex.ru> writes:
> 
>> On 26/02/2023 18:23, Arthur Miller wrote:
>>> What actions trigger the bug:
>>> Two different, unrelated repositories with emacs source code tree. My tree(s)
>>> looks like this:
>>> ~/repos/emsrc/emacs/
>>> ~/repos/enacs-tests/emacs/
>>> Where in both the last "emacs/" is the Emacs source tree from main git
>>> repository.
>>> ~/repos/emsrc/emacs/  is the one I use for my "everyday" Emacs. I build Emacs
>>> now
>>> and then once in a week or few weeks with a script, and I make each build in its
>>> own our-of-source worktree. The other one is one where I used to do some tests.
>>> It shouldn't matter since all worktrees are contained withing parent directory,
>>> which in one case is "emsrc" and in the other case "emacs-tests", but for some
>>> reason project.el sees the wrong one.
>>> 1. create two parent folders each one containing a copy of emacs sources
>>> 1. create out of source worktree for Emacs source under one of those
>>> 2. navigate to the worktree/lisp/progmodes
>>> 3. run M-: (project-known-project-roots)
>>> In my Emacs, I am in my currently installed emacs worktree, where git root is
>>> ~/repos/emsrc/emacs but project.el returns ("~/repos/emacs-tests/emacs/") as a
>>> result
>>
>> What does (project-root (project-current)) return? And which dirs you are
>> testing it in?
> 
> It returns the current worktree folder:
> 
> "/home/arthur/repos/emsrc/no-gtk-with-cairo-and-native-230226-061643/"
> 
> which I guess is what project.el finds as root since it only uses .git as a
> marker, if I understand correctly what you write little further.
> 
>>> I am not chasing the bug, but I don't see much code in project.el related
>>> to worktrees.
>>
>> Normally, there shouldn't be any need to handle worktree specially: it contains
>> a file called .git at the top which can serve as a marker just fine.
> 
> Well define "normally" and "just fine" :). Anyway, when I read your reply it seems
> like I have wrong expectation from project.el, so the fault is on my side. I
> thought it can deal with git projects in general, but as I understand it then,
> it only works with files in current directory.

We could change project-try-vc to follow the link to the parent repo, 
but how is the rest of it going to work?

If the project root is the parent repo, which set of files would 
(project-files pr) return? And how could that be implemented?

>>> The only place I see them mentioned is about submodules.I
>>> personally have used this one for quite some time, and it seems to correctly
>>> handle worktrees for me:
>>
>> You code looks like it can return the "actual git root" that can be a directory
>> residing somewhere else than the current directory tree.
> 
> Git worktrees can be placed outside the main repository tree:
> 
>      git worktree add ../my-new-shiny-emacs-patch
> 
> as an example. The code will find correct git root both outside, or within the
> repo.

Exactly.

> But I think it should be done by actually asking git to list worktrees
> instead.
> 
>>                                                           Is that what you
>> wanted?
> 
> Yes that is what I wanted? :-).
> 
> For automation purpose I need to find the project root, so I can pull sources to
> main, create a clean worktree from main, and switch Emacs to the new worktree
> interactively in one command, like M-x make-new-patch. Emacs asks me for a name
> and create a clean worktree from the main trunk for current project. Actually
> better variant is to ask which branch to patch, but the first one is slightly
> faster and works just fine in many cases.

It sounds like your code is Git-specific, not project-neutral.

But you still could find the worktree root using project.el, and then 
read the contents of .git, follow the link and do your automation stuff.





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-27 11:51     ` Dmitry Gutov
@ 2023-02-27 14:15       ` Arthur Miller
  2023-02-27 22:39         ` Dmitry Gutov
  0 siblings, 1 reply; 9+ messages in thread
From: Arthur Miller @ 2023-02-27 14:15 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: 61817

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 27/02/2023 09:32, Arthur Miller wrote:
>> Dmitry Gutov <dgutov@yandex.ru> writes:
>> 
>>> On 26/02/2023 18:23, Arthur Miller wrote:
>>>> What actions trigger the bug:
>>>> Two different, unrelated repositories with emacs source code tree. My tree(s)
>>>> looks like this:
>>>> ~/repos/emsrc/emacs/
>>>> ~/repos/enacs-tests/emacs/
>>>> Where in both the last "emacs/" is the Emacs source tree from main git
>>>> repository.
>>>> ~/repos/emsrc/emacs/  is the one I use for my "everyday" Emacs. I build Emacs
>>>> now
>>>> and then once in a week or few weeks with a script, and I make each build in its
>>>> own our-of-source worktree. The other one is one where I used to do some tests.
>>>> It shouldn't matter since all worktrees are contained withing parent directory,
>>>> which in one case is "emsrc" and in the other case "emacs-tests", but for some
>>>> reason project.el sees the wrong one.
>>>> 1. create two parent folders each one containing a copy of emacs sources
>>>> 1. create out of source worktree for Emacs source under one of those
>>>> 2. navigate to the worktree/lisp/progmodes
>>>> 3. run M-: (project-known-project-roots)
>>>> In my Emacs, I am in my currently installed emacs worktree, where git root is
>>>> ~/repos/emsrc/emacs but project.el returns ("~/repos/emacs-tests/emacs/") as a
>>>> result
>>>
>>> What does (project-root (project-current)) return? And which dirs you are
>>> testing it in?
>> It returns the current worktree folder:
>> "/home/arthur/repos/emsrc/no-gtk-with-cairo-and-native-230226-061643/"
>> which I guess is what project.el finds as root since it only uses .git as a
>> marker, if I understand correctly what you write little further.
>> 
>>>> I am not chasing the bug, but I don't see much code in project.el related
>>>> to worktrees.
>>>
>>> Normally, there shouldn't be any need to handle worktree specially: it contains
>>> a file called .git at the top which can serve as a marker just fine.
>> Well define "normally" and "just fine" :). Anyway, when I read your reply it
>> seems
>> like I have wrong expectation from project.el, so the fault is on my side. I
>> thought it can deal with git projects in general, but as I understand it then,
>> it only works with files in current directory.
>
> We could change project-try-vc to follow the link to the parent repo, but how is
> the rest of it going to work?
>
> If the project root is the parent repo, which set of files would (project-files
> pr) return? And how could that be implemented?

I don't know how it works now, so I can't really tell you, but you have called
git root "actual git root", so perhaps something that differentiate between
directory hierarchy root (worktree), and real git root (project). Perhaps
project-vc-root, if you don't already use that name, or something similar?

>>>> The only place I see them mentioned is about submodules.I
>>>> personally have used this one for quite some time, and it seems to correctly
>>>> handle worktrees for me:
>>>
>>> You code looks like it can return the "actual git root" that can be a directory
>>> residing somewhere else than the current directory tree.
>> Git worktrees can be placed outside the main repository tree:
>>      git worktree add ../my-new-shiny-emacs-patch
>> as an example. The code will find correct git root both outside, or within the
>> repo.
>
> Exactly.
>
>> But I think it should be done by actually asking git to list worktrees
>> instead.
>> 
>>>                                                           Is that what you
>>> wanted?
>> Yes that is what I wanted? :-).
>> For automation purpose I need to find the project root, so I can pull sources
>> to
>> main, create a clean worktree from main, and switch Emacs to the new worktree
>> interactively in one command, like M-x make-new-patch. Emacs asks me for a name
>> and create a clean worktree from the main trunk for current project. Actually
>> better variant is to ask which branch to patch, but the first one is slightly
>> faster and works just fine in many cases.
>
> It sounds like your code is Git-specific, not project-neutral.

Yepp. Question is what project.el then really is, if it can't handle vc specific
"projects", if it is only synomim for operations on directory trees? Perhpas it
should be called dirtree.el, because that is what it does: it works on
directory trees and uses "project markers" to know where to start/stop? I am not
trying to by sarcastic or negative. I don't mean it is not useful, we need both,
operations that work as projectile/project, on directory trees, but also those
that actually understand a possible project structure. To me projectile and now
project.el seems more like they are an extension to Dired, not in some negative
connotation, but at least conceptually, then really project handling. I am not
trying to be negative, I am a bit oversimplistic and exaggerating, becuase I am
trying to illustrate the difference how I think about "projects".

Version control has become an integral part of all projects, at least in
software industry, just as building projects, boilerplate generating projects
etc. What I am saying is that project-neutral is OK, we don't want just a
different name for Git commands, but any project library nowadays should be able
to work with vc systems, build systems etc. At least for software management
projects. 

> But you still could find the worktree root using project.el, and then read the
> contents of .git, follow the link and do your automation stuff.

Yeah, but it what does it saves me? In Git case it is really synonym to:

    (git-dir (locate-dominating-file directory ".git"))

I can just as well call built-in function instead of requiring project.el.

As said I thought project.el was more general to work with projects on a deeper
level, sort-of EDE replacement or complement, and I wanted to use it as library,
but I understand now it is not.






^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-27 14:15       ` Arthur Miller
@ 2023-02-27 22:39         ` Dmitry Gutov
  2023-02-28  0:34           ` Arthur Miller
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Gutov @ 2023-02-27 22:39 UTC (permalink / raw)
  To: Arthur Miller; +Cc: 61817

On 27/02/2023 16:15, Arthur Miller wrote:

>> We could change project-try-vc to follow the link to the parent repo, but how is
>> the rest of it going to work?
>>
>> If the project root is the parent repo, which set of files would (project-files
>> pr) return? And how could that be implemented?
> 
> I don't know how it works now, so I can't really tell you, but you have called
> git root "actual git root", so perhaps something that differentiate between
> directory hierarchy root (worktree), and real git root (project). Perhaps
> project-vc-root, if you don't already use that name, or something similar?

Do you mean you want a separate helper to get to the "worktree parent" 
repository? We could add something like that to VC, I guess. But your 
own code seems to be working well too.

I haven't had a use for "worktree parent" myself, though. And until we 
get a good idea for how people will use a feature, it's a little 
difficult to choose a place for it.

>>> Yes that is what I wanted? :-).
>>> For automation purpose I need to find the project root, so I can pull sources
>>> to
>>> main, create a clean worktree from main, and switch Emacs to the new worktree
>>> interactively in one command, like M-x make-new-patch. Emacs asks me for a name
>>> and create a clean worktree from the main trunk for current project. Actually
>>> better variant is to ask which branch to patch, but the first one is slightly
>>> faster and works just fine in many cases.
>>
>> It sounds like your code is Git-specific, not project-neutral.
> 
> Yepp. Question is what project.el then really is, if it can't handle vc specific
> "projects", if it is only synomim for operations on directory trees? Perhpas it
> should be called dirtree.el, because that is what it does: it works on
> directory trees and uses "project markers" to know where to start/stop? I am not
> trying to by sarcastic or negative.

It uses VCS-specific information and converts it to a shape that should 
be usable without the caller being aware of which underlying data that 
information is determined by.

In particular, it reads .gitmodules, .git and .gitignore.

And, well, different backends can make different decisions on the 
backends's behavior. But, ideally, it should be good for the majority of 
uses. Such as our built-in commands, for example: project-vc-dir, 
project-eshell, etc.

> I don't mean it is not useful, we need both,
> operations that work as projectile/project, on directory trees, but also those
> that actually understand a possible project structure. To me projectile and now
> project.el seems more like they are an extension to Dired, not in some negative
> connotation, but at least conceptually, then really project handling. I am not
> trying to be negative, I am a bit oversimplistic and exaggerating, becuase I am
> trying to illustrate the difference how I think about "projects".

It a way -- yes, because we describe a project as a set of files. With a 
well-defined root. But it doesn't absolutely have to be in the shape of 
a single directory tree, though it usually is.

Whenever one chooses a different shape, though, they should consider how 
that will affect the common uses.

> Version control has become an integral part of all projects, at least in
> software industry, just as building projects, boilerplate generating projects
> etc. What I am saying is that project-neutral is OK, we don't want just a
> different name for Git commands, but any project library nowadays should be able
> to work with vc systems, build systems etc. At least for software management
> projects.

You seem to be assigning a lot of meaning to the fact that the root 
doesn't point to "worktree root", but to the current repository root 
(modulo the search in the parent directory when the current repo is 
detemined to be a submodule).

But would it be a better choice?

When I use worktrees, it's to carry on development in a certain branch. 
Meaning, I need to be able to pull/push/commit in that branch, all 
within the same worktree.

To do a pull, or to run some commands in that worktree, I can call 
project-eshell. To do a commit, I can call up project-vc-dir. In both 
cases, the useful thing to do for 'project-root' is to return the 
current repository root, not the worktree parent. Because you don't make 
new commits in the parent repo when working on a worktree, you make them 
in the current one.

I'm all for adding new Version Control related features, but they should 
be based off realistic, specific user scenarios.

>> But you still could find the worktree root using project.el, and then read the
>> contents of .git, follow the link and do your automation stuff.
> 
> Yeah, but it what does it saves me? In Git case it is really synonym to:
> 
>      (git-dir (locate-dominating-file directory ".git"))
> 
> I can just as well call built-in function instead of requiring project.el.

Sure. locate-dominating-file is an underrated function. If you just want 
to find the current repository root (no matter if it's a submodule or 
etc), the above will easily work. project-try-vc adds some caching on 
top of that, but you might not need it.

> As said I thought project.el was more general to work with projects on a deeper
> level, sort-of EDE replacement or complement, and I wanted to use it as library,
> but I understand now it is not.

The idea was for a more simple/transparent and extensible EDE 
alternative. Or an extension point to plug Projectile in.

It can still grow some additions (such as build tool support), but for 
now we have what we have.





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-27 22:39         ` Dmitry Gutov
@ 2023-02-28  0:34           ` Arthur Miller
  2023-02-28 23:51             ` Dmitry Gutov
  0 siblings, 1 reply; 9+ messages in thread
From: Arthur Miller @ 2023-02-28  0:34 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: 61817

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 27/02/2023 16:15, Arthur Miller wrote:
>
>>> We could change project-try-vc to follow the link to the parent repo, but how is
>>> the rest of it going to work?
>>>
>>> If the project root is the parent repo, which set of files would (project-files
>>> pr) return? And how could that be implemented?
>> I don't know how it works now, so I can't really tell you, but you have called
>> git root "actual git root", so perhaps something that differentiate between
>> directory hierarchy root (worktree), and real git root (project). Perhaps
>> project-vc-root, if you don't already use that name, or something similar?
>
> Do you mean you want a separate helper to get to the "worktree parent"
> repository?

I wouldn't call it "worktree parent", because it relatively git specific; if you
prefer to be project neutral; but something like that yes.

> repository? We could add something like that to VC, I guess. But your own code
> seems to be working well too.

I didn't meant to ask for someone to write it for me :), I can use my own
code, but as said I had somewhat different expectation from project.el when I
did this request. You can just close it, it is ok; I am sorry for the trouble.

> I haven't had a use for "worktree parent" myself, though. And until we get a
> good idea for how people will use a feature, it's a little difficult to choose a
> place for it.

If you have a branch "main", work in a branch X, and would like to test/fix
something unrelated to X, wouldn't you create a new workree Y from clean "main"?
It is a bit special case, which I personally use, so to automate this, "worktree"
as root is not enough, I need the actual root. For other purposes I need the
worktree. So as said, both are needed. Of course, worktree will be used more
frequently for natural reasons.

More general case is to create patch for some unrelated branch Z, in which case
I am not sure, but I believe I need to exec git branch and/or git worktree list
and parse the output to see where to jump, and from which branch and directory
to create a new worktree.

>>>> Yes that is what I wanted? :-).
>>>> For automation purpose I need to find the project root, so I can pull sources
>>>> to
>>>> main, create a clean worktree from main, and switch Emacs to the new worktree
>>>> interactively in one command, like M-x make-new-patch. Emacs asks me for a name
>>>> and create a clean worktree from the main trunk for current project. Actually
>>>> better variant is to ask which branch to patch, but the first one is slightly
>>>> faster and works just fine in many cases.
>>>
>>> It sounds like your code is Git-specific, not project-neutral.
>> Yepp. Question is what project.el then really is, if it can't handle vc
>> specific
>> "projects", if it is only synomim for operations on directory trees? Perhpas it
>> should be called dirtree.el, because that is what it does: it works on
>> directory trees and uses "project markers" to know where to start/stop? I am not
>> trying to by sarcastic or negative.
>
> It uses VCS-specific information and converts it to a shape that should be
> usable without the caller being aware of which underlying data that information
> is determined by.
>
> In particular, it reads .gitmodules, .git and .gitignore.
>
> And, well, different backends can make different decisions on the backends's
> behavior. But, ideally, it should be good for the majority of uses. Such as our
> built-in commands, for example: project-vc-dir, project-eshell, etc.

Yes, they are nice, and they illustrate that for some purpose, worktree is
needed.

>> I don't mean it is not useful, we need both,
>> operations that work as projectile/project, on directory trees, but also those
>> that actually understand a possible project structure. To me projectile and now
>> project.el seems more like they are an extension to Dired, not in some negative
>> connotation, but at least conceptually, then really project handling. I am not
>> trying to be negative, I am a bit oversimplistic and exaggerating, becuase I am
>> trying to illustrate the difference how I think about "projects".
>
> It a way -- yes, because we describe a project as a set of files. With a
> well-defined root. But it doesn't absolutely have to be in the shape of a single
> directory tree, though it usually is.
>
> Whenever one chooses a different shape, though, they should consider how that
> will affect the common uses.

It is not about the shape; you can put a worktree as a subdirectory in a main
repository, it does not need to be out of source tree; project.el will still not
find the real git root. You can test it yourself in Emacs source:

In Emacs repo create new worktree: git worktree add new-test; change to newly
created folder and test your tools, they will work only on new-test.

>> Version control has become an integral part of all projects, at least in
>> software industry, just as building projects, boilerplate generating projects
>> etc. What I am saying is that project-neutral is OK, we don't want just a
>> different name for Git commands, but any project library nowadays should be able
>> to work with vc systems, build systems etc. At least for software management
>> projects.
>
> You seem to be assigning a lot of meaning to the fact that the root doesn't
> point to "worktree root", but to the current repository root (modulo the search
> in the parent directory when the current repo is detemined to be a submodule).
>
> But would it be a better choice?

I don't think it is either one; definitely not an exclusive choice. I tried to
say that we need both.

But the root :) of this discussion, is that I missunderstood project.el as an
attempt to create a useful middleware for general working with projects, but I
guess you and other authors are more seeing it as an end-user application. I
appologize, I should have probably looked more into the code and asked. I just
tried to use some functions :). 

> When I use worktrees, it's to carry on development in a certain branch. Meaning,
> I need to be able to pull/push/commit in that branch, all within the same
> worktree.

Yes, in some cases that is a workflow. But there are cases when its prefered to
checkout other branch, while work on something else; and as said above, in that
case is prefered to make a new worktree from either "clean" main or some other branch.

> To do a pull, or to run some commands in that worktree, I can call
> project-eshell. To do a commit, I can call up project-vc-dir. In both cases, the
> useful thing to do for 'project-root' is to return the current repository root,
> not the worktree parent. Because you don't make new commits in the parent repo
> when working on a worktree, you make them in the current one.

In this cases yes; but in some other cases no. Uses you mention are definitely
more frequent, then checking out unrelated branch, but I don't think it is so
uncommon either.

> I'm all for adding new Version Control related features, but they should be
> based off realistic, specific user scenarios.

Automation. I don't want to open terminal (or magit, does not matter), switch
branches and do that stuff manually (if I don't have to).

>>> But you still could find the worktree root using project.el, and then read the
>>> contents of .git, follow the link and do your automation stuff.
>> Yeah, but it what does it saves me? In Git case it is really synonym to:
>>      (git-dir (locate-dominating-file directory ".git"))
>> I can just as well call built-in function instead of requiring project.el.
>
> Sure. locate-dominating-file is an underrated function. If you just want to find
> the current repository root (no matter if it's a submodule or etc), the above
> will easily work. project-try-vc adds some caching on top of that, but you might
> not need it.

I didn't know you have caching in project.el; that is a good feature to have. I
personally don't need it, but definitely good to know it is there.

>> As said I thought project.el was more general to work with projects on a deeper
>> level, sort-of EDE replacement or complement, and I wanted to use it as library,
>> but I understand now it is not.
>
> The idea was for a more simple/transparent and extensible EDE alternative. Or an
> extension point to plug Projectile in.

Ede is extensible; it is just a bit arcane and there is not too much
documentation, unfortunately. I would prefer if Ede was re-used instead of the
duplicated effort, but I do understand if you want to replace it.

> It can still grow some additions (such as build tool support), but for now we
> have what we have.

In my opinion, Emacs lacks

1) a good and easy to use boiler-plate generator framework. Ede is meant for that,
but it is arcane to use and is meant to be used with existing projects. Also, Emacs
will automatically create a new folder if asked to find-file, when folder does
not exists. But, if a foder exists, it creates new file in that folder, which is not
preferred behavior.

In the end, as an end-user I have to manually create folders or run scripts
before I can ask Ede to fill-in with some code generator.

There is no reason to not automate project generation. We do have all the tools
in Emacs already but I haven't seen any good generator. Maybe there is some, but
I am not aware of one.

I am playing with a little framework based on org-capture; but it is nothing
polished I wish to share with anyone. With boilerplate I mean init git, generate
readme, lsp database, makefiles and that sort of stuff. I think a combo between
Ede and project.el would be nice.

2) better integration with tools for common workflow(s). Adding
features, fixes, tests etc, is mostly about creating a new patch, which with
addition of worktrees in Git can be super nicely automated. For example: add new
library, or add new executable, or add new fix, it all boiles down to add new
branch which leads to add new worktree, add a possible target in Makefile,
create possibly a test file, probably some other thing. It would be nice to be
able to say: M-x add-new-shared-library or M-x add-new-executable, or M-x
add-new-fix and Emacs will do at least initial boilerplate.

If you plan to add build tool support to project.el, it would be welcome :).





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-28  0:34           ` Arthur Miller
@ 2023-02-28 23:51             ` Dmitry Gutov
  2023-03-01  3:03               ` Arthur Miller
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Gutov @ 2023-02-28 23:51 UTC (permalink / raw)
  To: Arthur Miller; +Cc: 61817-done

On 28/02/2023 02:34, Arthur Miller wrote:
> Dmitry Gutov <dgutov@yandex.ru> writes:
> 
>> On 27/02/2023 16:15, Arthur Miller wrote:
>>
>>>> We could change project-try-vc to follow the link to the parent repo, but how is
>>>> the rest of it going to work?
>>>>
>>>> If the project root is the parent repo, which set of files would (project-files
>>>> pr) return? And how could that be implemented?
>>> I don't know how it works now, so I can't really tell you, but you have called
>>> git root "actual git root", so perhaps something that differentiate between
>>> directory hierarchy root (worktree), and real git root (project). Perhaps
>>> project-vc-root, if you don't already use that name, or something similar?
>>
>> Do you mean you want a separate helper to get to the "worktree parent"
>> repository?
> 
> I wouldn't call it "worktree parent", because it relatively git specific; if you
> prefer to be project neutral; but something like that yes.

It's a Git-based relation.

Depending on how we might define a "project parent" in the future 
(probably as "project of root's parent directory", though), and how the 
worktrees reside on disk relative to the parent, these notions won't 
necessarily match.

>> repository? We could add something like that to VC, I guess. But your own code
>> seems to be working well too.
> 
> I didn't meant to ask for someone to write it for me :), I can use my own
> code, but as said I had somewhat different expectation from project.el when I
> did this request. You can just close it, it is ok; I am sorry for the trouble.

Sure, closing. I just didn't want to shut the thread down before all 
questions are answered.

>> I haven't had a use for "worktree parent" myself, though. And until we get a
>> good idea for how people will use a feature, it's a little difficult to choose a
>> place for it.
> 
> If you have a branch "main", work in a branch X, and would like to test/fix
> something unrelated to X, wouldn't you create a new workree Y from clean "main"?
> It is a bit special case, which I personally use, so to automate this, "worktree"
> as root is not enough, I need the actual root. For other purposes I need the
> worktree. So as said, both are needed. Of course, worktree will be used more
> frequently for natural reasons.

That sounds like a fine approach, though not the only possible one. I 
usually have a limited number of worktrees: some constant, and some for 
temporary branches. I suppose it depends whether you need to create some 
configuration files specific to the local system when deploying and 
testing a new repository checkout.

>>> I don't mean it is not useful, we need both,
>>> operations that work as projectile/project, on directory trees, but also those
>>> that actually understand a possible project structure. To me projectile and now
>>> project.el seems more like they are an extension to Dired, not in some negative
>>> connotation, but at least conceptually, then really project handling. I am not
>>> trying to be negative, I am a bit oversimplistic and exaggerating, becuase I am
>>> trying to illustrate the difference how I think about "projects".
>>
>> It a way -- yes, because we describe a project as a set of files. With a
>> well-defined root. But it doesn't absolutely have to be in the shape of a single
>> directory tree, though it usually is.
>>
>> Whenever one chooses a different shape, though, they should consider how that
>> will affect the common uses.
> 
> It is not about the shape; you can put a worktree as a subdirectory in a main
> repository, it does not need to be out of source tree; project.el will still not
> find the real git root. You can test it yourself in Emacs source:

Indeed, it won't, because nobody told it it should traverse up to 
"worktree parent", always or under certain condition.

That structure would also be quite weird, though: root in dir A, but all 
project files residing in some sub-sub-directory D of A. Doesn't that 
sound weird?

> In Emacs repo create new worktree: git worktree add new-test; change to newly
> created folder and test your tools, they will work only on new-test.

Sure. Just keep in mind that worktrees are not always a subdirectory of 
the "worktree parent". I keep them side-by-side, for example.

>>> Version control has become an integral part of all projects, at least in
>>> software industry, just as building projects, boilerplate generating projects
>>> etc. What I am saying is that project-neutral is OK, we don't want just a
>>> different name for Git commands, but any project library nowadays should be able
>>> to work with vc systems, build systems etc. At least for software management
>>> projects.
>>
>> You seem to be assigning a lot of meaning to the fact that the root doesn't
>> point to "worktree root", but to the current repository root (modulo the search
>> in the parent directory when the current repo is detemined to be a submodule).
>>
>> But would it be a better choice?
> 
> I don't think it is either one; definitely not an exclusive choice. I tried to
> say that we need both.

Then the question would be how to provide both of those pieces of 
information to callers. If we add the constraint that it has to be in 
some abstract way (independent from Git), then the answer is probably 
"no way".

But the feature with "parent" projects will likely satisfy some uses and 
scenarios.

> But the root :) of this discussion, is that I missunderstood project.el as an
> attempt to create a useful middleware for general working with projects, but I
> guess you and other authors are more seeing it as an end-user application. I
> appologize, I should have probably looked more into the code and asked. I just
> tried to use some functions :).

I do believe that it's a "useful middleware". And a trait of such 
middlewares is they usually try to present some abstraction over the 
implementation.

>> When I use worktrees, it's to carry on development in a certain branch. Meaning,
>> I need to be able to pull/push/commit in that branch, all within the same
>> worktree.
> 
> Yes, in some cases that is a workflow. But there are cases when its prefered to
> checkout other branch, while work on something else; and as said above, in that
> case is prefered to make a new worktree from either "clean" main or some other branch.

Sure.

>> I'm all for adding new Version Control related features, but they should be
>> based off realistic, specific user scenarios.
> 
> Automation. I don't want to open terminal (or magit, does not matter), switch
> branches and do that stuff manually (if I don't have to).

If, perhaps, we would add a command doing something like the above to 
project.el, or we envision somebody doing it in some popular extension, 
*and* it would be possible to do with several project backends (maybe 
real and potential ones), then that would sound like a feature for 
project.el.

If a caller, OTOH, needs to know that they're working with Git, and with 
a particular project backend, to do what they wanted, then that would be 
a poor fit for the API. But we could try to fit in features in some 
other way. Adding them to the VC package, perhaps.

>>> As said I thought project.el was more general to work with projects on a deeper
>>> level, sort-of EDE replacement or complement, and I wanted to use it as library,
>>> but I understand now it is not.
>>
>> The idea was for a more simple/transparent and extensible EDE alternative. Or an
>> extension point to plug Projectile in.
> 
> Ede is extensible; it is just a bit arcane and there is not too much
> documentation, unfortunately. I would prefer if Ede was re-used instead of the
> duplicated effort, but I do understand if you want to replace it.

I honestly don't understand EDE enough to have a solid opinion. But it 
did seem to have some pronounced pieces that didn't make sense for 
projects I regularly interact with.

>> It can still grow some additions (such as build tool support), but for now we
>> have what we have.
> 
> In my opinion, Emacs lacks
> 
> 1) a good and easy to use boiler-plate generator framework. Ede is meant for that,
> but it is arcane to use and is meant to be used with existing projects. Also, Emacs
> will automatically create a new folder if asked to find-file, when folder does
> not exists. But, if a foder exists, it creates new file in that folder, which is not
> preferred behavior.
> 
> In the end, as an end-user I have to manually create folders or run scripts
> before I can ask Ede to fill-in with some code generator.
> 
> There is no reason to not automate project generation. We do have all the tools
> in Emacs already but I haven't seen any good generator. Maybe there is some, but
> I am not aware of one.
> 
> I am playing with a little framework based on org-capture; but it is nothing
> polished I wish to share with anyone. With boilerplate I mean init git, generate
> readme, lsp database, makefiles and that sort of stuff. I think a combo between
> Ede and project.el would be nice.

That sounds like a decent feature, though one that is often taken up by 
command line tools. It not quite clear what Emacs integration would add 
to that. Besides, perhaps being able to write templates in Org, or 
something.

But the beauty of it, it doesn't have to be strongly bound to 
project.el. It can *use* project-current/project-root, but be a package 
of its own, with separate naming/features/hooks and language/framework 
detection.

> 2) better integration with tools for common workflow(s). Adding
> features, fixes, tests etc, is mostly about creating a new patch, which with
> addition of worktrees in Git can be super nicely automated. For example: add new
> library, or add new executable, or add new fix, it all boiles down to add new
> branch which leads to add new worktree, add a possible target in Makefile,
> create possibly a test file, probably some other thing. It would be nice to be
> able to say: M-x add-new-shared-library or M-x add-new-executable, or M-x
> add-new-fix and Emacs will do at least initial boilerplate.
> 
> If you plan to add build tool support to project.el, it would be welcome :).

Hmm, as I see it, this is split into two different parts:

- Do a Git-specific thing (create a worktree), once per body of work.
- Do a build tool specific thing, probably several.

The thing about the latter, you have described pretty well the general 
direction of what features a hypothetical buildtool.el might contain. 
Alas, I have little experience with languages where you regularly do 
things like that (adding new shared libraries, new executables, other 
build artefacts), and it seems to be an open question whether there is 
point in adding a language agnostic API on top of that, or if people 
should just create c++-buildtool.el, java-buildtool.el, etc, separately 
without trying to unify the UI.

If somebody else wanted to work on this, though, probably a fair amount 
of people on this list would welcome that, and help with 
advice/review/some later contributions.





^ permalink raw reply	[flat|nested] 9+ messages in thread

* bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees
  2023-02-28 23:51             ` Dmitry Gutov
@ 2023-03-01  3:03               ` Arthur Miller
  0 siblings, 0 replies; 9+ messages in thread
From: Arthur Miller @ 2023-03-01  3:03 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: 61817-done

[-- Attachment #1: Type: text/plain, Size: 9962 bytes --]

Dmitry Gutov <dgutov@yandex.ru> writes:

> Depending on how we might define a "project parent" in the future (probably as
> "project of root's parent directory", though), and how the worktrees reside on
> disk relative to the parent, these notions won't necessarily match.

Sure, but I don't think they have to. I am just telling that we need both; my
suggestion is to use project-vc-root, as the king of all roots; regardless of
the shape of folder structures; and current-project-root for worktrees and what
not. Just as a suggestion, more about this one little further below.

>> If you have a branch "main", work in a branch X, and would like to test/fix
>> something unrelated to X, wouldn't you create a new workree Y from clean "main"?
>> It is a bit special case, which I personally use, so to automate this, "worktree"
>> as root is not enough, I need the actual root. For other purposes I need the
>> worktree. So as said, both are needed. Of course, worktree will be used more
>> frequently for natural reasons.
>
> That sounds like a fine approach, though not the only possible one.

Yeas; of course; there is never one approach only.

> have a limited number of worktrees: some constant, and some for temporary
> branches. I suppose it depends whether you need to create some configuration
> files specific to the local system when deploying and testing a new repository
> checkout.

Exactly. The more general approach is to list branches with completing read and
let user choose one to create a patch to. But the one I described is just a
little quick-fix. M-x add-new-patch, and it does what I described above.

>>> Whenever one chooses a different shape, though, they should consider how that
>>> will affect the common uses.
>> It is not about the shape; you can put a worktree as a subdirectory in a main
>> repository, it does not need to be out of source tree; project.el will still not
>> find the real git root. You can test it yourself in Emacs source:
>
> Indeed, it won't, because nobody told it it should traverse up to "worktree
> parent", always or under certain condition.

Exactly, so once in a worktree, current project.el can't find the "actual git
root" as you called it. I would like it to be able too, so that I can use
project.el as a "generic" library independent of VC system.

> That structure would also be quite weird, though: root in dir A, but all project
> files residing in some sub-sub-directory D of A. Doesn't that sound weird?

Yes, it is very weird, and that why I too also make worktrees out of the main repo,
parallel to it. I took it up because you wrote about choosing different shapes
for directory structures and consequences, but I do same as you.

> Then the question would be how to provide both of those pieces of information to
> callers. If we add the constraint that it has to be in some abstract way
> (independent from Git), then the answer is probably "no way".

I am not sure myself; but obviously for the VC that does not support the
feature, project-vc-root could return just what it returns now, and just act as
a synonym for project-root, while for systems that do (git) it will return
whatever actual root is? 

> I do believe that it's a "useful middleware". And a trait of such middlewares is
> they usually try to present some abstraction over the implementation.

Ok, can we then have some useful stuff like: project-add-new-patch and
project-add-new-target or similar (I welcome better ideas); where at least some
common actions are automated? project-vc-dir already does some VC stuff (push,
pull etc), it can well provide some other useful abstractions? 

I can help to donate those, at least for Git, but the Git part is easy to write
anyway.

> If, perhaps, we would add a command doing something like the above to
> project.el, or we envision somebody doing it in some popular extension, *and* it
> would be possible to do with several project backends (maybe real and potential
> ones), then that would sound like a feature for project.el.
>
> If a caller, OTOH, needs to know that they're working with Git, and with a
> particular project backend, to do what they wanted, then that would be a poor
> fit for the API. But we could try to fit in features in some other way. Adding
> them to the VC package, perhaps.

Exactly; I totally agree; that is why I have started discussion. I can do
git-based everything easily myself, but instead of doing it git-based per
definition I wanted to use project.el as an abstraction so my little project
stuff can work in possibly other scenarios then just with Git.

> I honestly don't understand EDE enough to have a solid opinion. But it did seem
> to have some pronounced pieces that didn't make sense for projects I regularly
> interact with.

EDE seems interesting to me, because of the integration with rest of Emacs,
speedbar etc, but I can't say I have much understanding of Ede myself.

> That sounds like a decent feature, though one that is often taken up by command
> line tools. It not quite clear what Emacs integration would add to
> that. Besides, perhaps being able to write templates in Org, or something.

As said: automation. I have nothing against command line, and I can certainly
just write a little shell or elisp script to create a folder, copy some files,
init git, generate some pieces etc. But everytime I do, manually, or writing a
new script, I am repeating a set of dull steps, which are totally unnecessary
and just take focus from what I really want to do. 

>       Besides, perhaps being able to write templates in Org, or something.

Well, I wouldn't say it is just "or something" and you don't need to use it in
Org at all :).

Org-capture does setup a small gui (read-key) and is easy to re-use. More
important it provides a relatively familiar interface to writing Lisp property
lists (capture templates) even to non-lispers :). org-capture is quite well
accepted in Org community, I believe; and there are a lots of non-programmers
which use it for wrting notes, mailes etc.

I don't know; it is really small, already included, and usually already loaded
into Emacs; and lots easier to use than some other alternatives to provide some
basic gui and entry point for customization. I have attached a toy example for an
illustration. I am sure I could resue transient, hydra, or just write my own too,
but I want something that comes with Emacs which Hydra does not, and am not so
familiar with transient myself, and I believe holds for lots of other people too.

> But the beauty of it, it doesn't have to be strongly bound to project.el. It can
> *use* project-current/project-root, but be a package of its own, with separate
> naming/features/hooks and language/framework detection.

Yes, of course, I know it can; that is what I already do. It does not even need
to use Emacs, I can write it in Bash or as a script for cmd.exe; but that is not
the quesiton. Currently I don't even use project.el, but as said, if it will
provide more backends and abstractions, I would prefer to use it than to make my
own git-specific everything.

>> 2) better integration with tools for common workflow(s). Adding
>> features, fixes, tests etc, is mostly about creating a new patch, which with
>> addition of worktrees in Git can be super nicely automated. For example: add new
>> library, or add new executable, or add new fix, it all boiles down to add new
>> branch which leads to add new worktree, add a possible target in Makefile,
>> create possibly a test file, probably some other thing. It would be nice to be
>> able to say: M-x add-new-shared-library or M-x add-new-executable, or M-x
>> add-new-fix and Emacs will do at least initial boilerplate.
>> If you plan to add build tool support to project.el, it would be welcome :).
>
> Hmm, as I see it, this is split into two different parts:
>
> - Do a Git-specific thing (create a worktree), once per body of work.

Yes, and to me this feels like a good target for an abstraction. Shouldn't
something like that be in project-vc-dir app?

> - Do a build tool specific thing, probably several.

Again yes. That is the harder part, but there is a lot of freedom to implement
just parts of it, and successively per tool, and so on, and the entry point could
be the abstraction above.

> The thing about the latter, you have described pretty well the general direction
> of what features a hypothetical buildtool.el might contain. Alas, I have little
> experience with languages where you regularly do things like that (adding new
> shared libraries, new executables, other build artefacts), and it seems to be an
> open question whether there is point in adding a language agnostic API on top of
> that, or if people should just create c++-buildtool.el, java-buildtool.el, etc,
> separately without trying to unify the UI.

That does not have to be a build artefact, like .dll or .jar or .exe. It is just
a "target". That is the beauty of Makefile which works just with targets and
dependencies, and does not care what a target is. "clean" target as we know it
from C or C++, or start or stop some web or system services are just as normal
as building artefacts.

> If somebody else wanted to work on this, though, probably a fair amount of
> people on this list would welcome that, and help with advice/review/some later
> contributions.

Sure, I am happy to hear suggestions and opinions; especially if someone can
help me to understand and re-use Ede for the tool integration.

However; I am even more happy if you add something like project-vc-root (or
choose any name you want), and some hooks or other abstraction for
project-add/remove-* where * is any of patch, feature, target, ... something
similar, I guess you get the idea :).

Anyway, thank you for the kind answers and interesting discussion, and hope you
don't mind I have deleted older parts; it was a bit hard tp read. so I have left
just your latest and my answers (mostly); hope it is ok.


[-- Attachment #2: project-capture.el --]
[-- Type: text/plain, Size: 4689 bytes --]

;;; org-project.el --- Bootstrap projects with org-capture  -*- lexical-binding: t; -*-

;; Copyright (C) 2022  Arthur Miller

;; Author: Arthur Miller <arthur.miller@live.com>
;; Keywords: 

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; 

;;; Code:
\f
;;;; org-capture related code
(require 'org-capture)

(defvar org-project-root-dir nil)
(defvar org-project-templates nil)
\f
(defvar org-project-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map [remap org-capture-finalize] #'org-project-finalize)
    (define-key map [remap org-capture-kill] #'org-project-kill)
    (define-key map [remap org-capture-refile] #'ignore) ;; be on the safe side
    map)
  "Keymap for `org-project-mode', a minor mode.
Use this map to set additional keybindings for when Org mode is used
for a project buffer.")

(define-minor-mode org-project-mode
  "Minor mode to use in org-project-capture buffer."
  :lighter " Prj"
  (setq-local header-line-format
              (substitute-command-keys
               "\\<org-capture-mode-map>Capture buffer.  Finish \
`\\[org-capture-finalize]', abort `\\[org-capture-kill]'.")))

(defun org-project-finalize (&optional stay-with-capture)
  "Finalize the capture process.
With prefix argument STAY-WITH-CAPTURE, jump to the location of the
captured item after finalizing."
  (interactive "P")
  (org-capture-finalize stay-with-capture)
  (let* ((desc (org-capture-get :description))
         (func (or (org-capture-get :project-hook)
                   (intern-soft (org-template-desc-to-func-name desc)))))
    (when (fboundp func)
      (funcall func))))

(defun org-project-kill ()
  "Abort the current capture process."
  (interactive)
  (let ((org-note-abort t)
        (org-capture-before-finalize-hook nil)
        (org-capture-after-finalize-hook
         `(lambda nil (delete-directory ,default-directory t)
            (kill-buffer ,(org-capture-get :buffer)))))
    (org-capture-finalize)))
\f
;;;; commands
(defun org-project-new-project ()
  (interactive)
  (let ((org-capture-templates org-project-templates)
        (org-capture-mode-hook (lambda () (org-project-mode 1))))
    (org-capture)))

(define-key global-map (kbd "C-S-n") #'org-project-new-project)
\f
;;;; hooks
(defun org-project-new ()
  "Interactively create new directory for a project.

Directory should not exist prior to call to this function."
  (let ((project-path (read-file-name "Project name: "
                                      org-project-root-dir
                                      nil nil nil)))
    (cond ((not (file-directory-p project-path))
           (make-directory project-path)
           (let ((file-name
                  (format "%s.org"
                          (car
                           (last
                            (split-string project-path "/" t))))))
             (find-file (expand-file-name file-name project-path))
             (goto-char (point-min))))
          (t (message "Directory %s already exists." project-path))))
  (org-project-mode 1))

(defun org-template-desc-to-func-name (phrase)
  "Return string PHRASE as a Lisp symbol suitable to call as a function."
  (with-temp-buffer
    (insert phrase)
    (downcase-region 1 (point-max))
    (goto-char 1)
    (while (re-search-forward "[ ]+" nil t)
      (replace-match "-"))
    (buffer-substring-no-properties 1 (point-max))))
\f
;;;; Test related
(setq org-project-root-dir "~/repos/")

(setq org-project-templates
      `(("w" "Web Projects")
        ("wb" "Bootstrap Project" plain
         (function org-project-new)
         "A Bootstrap Project" :project-hook my-bootstrap-hook)
        ("c" "C/C++ Projects")
        ("cc" "C Console Project" plain
         (function org-project-new)
         "A Command Line Project with C")))

;; explicit hook trumps name-based hook
(defun bootstrap-project ()
  (message "THIS SHOULD NOT PRINT"))

(defun my-bootstrap-hook ()
  (message "MY BOOSTRAP HOOK"))

;; use name-based hook
(defun c-console-project ()
  (message "MY C CONSOLE PROJECT"))

(provide 'org-project)
;;; org-project.el ends here

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-03-01  3:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-02-26 16:23 bug#61817: 30.0.50; Project.el finds incorrect project roots in git worktrees Arthur Miller
2023-02-26 18:03 ` Dmitry Gutov
2023-02-27  7:32   ` Arthur Miller
2023-02-27 11:51     ` Dmitry Gutov
2023-02-27 14:15       ` Arthur Miller
2023-02-27 22:39         ` Dmitry Gutov
2023-02-28  0:34           ` Arthur Miller
2023-02-28 23:51             ` Dmitry Gutov
2023-03-01  3:03               ` Arthur Miller

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).