* bug#50297: 28.0.50; Aggregate project functions for project.el @ 2021-08-31 12:47 Philip Kaludercic 2021-09-01 1:07 ` Dmitry Gutov 2021-09-22 0:31 ` Dmitry Gutov 0 siblings, 2 replies; 21+ messages in thread From: Philip Kaludercic @ 2021-08-31 12:47 UTC (permalink / raw) To: 50297; +Cc: Dmitry Gutov [-- Attachment #1: Type: text/plain, Size: 527 bytes --] The following patch introduces a few functions for aggregate project maintenance: - project-find-projects-under Select a directory with projects to index all at once. - project-remove-zombie-projects Check if all known projects still exist and remove those that don't anymore - project-remove-projects-under Remove all projects in a directory (inverse of project-find-projects-under). Especially the last two are useful to maintain a clean project list without having to manually remove every project one by one. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Add-aggregate-project-discovery-and-maintenance-func.patch --] [-- Type: text/x-diff, Size: 3036 bytes --] From 3431a9123753d769f10621d2f5f6ef72ab0e2f3a Mon Sep 17 00:00:00 2001 From: Philip Kaludercic <philipk@posteo.net> Date: Tue, 31 Aug 2021 14:12:13 +0200 Subject: [PATCH] Add aggregate project discovery and maintenance functions * project.el (project-remember-project): Add optional no-write argument (project-find-projects-under): Add command (project-remove-zombie-projects): Add command (project-remove-known-projects): Add command --- lisp/progmodes/project.el | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index ae9bf03571..2f251393e2 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1261,9 +1261,10 @@ project--write-project-list (write-region nil nil filename nil 'silent)))) ;;;###autoload -(defun project-remember-project (pr) +(defun project-remember-project (pr &optional no-write) "Add project PR to the front of the project list. -Save the result in `project-list-file' if the list of projects has changed." +Save the result in `project-list-file' if the list of projects +has changed, and NO-WRITE is nil." (project--ensure-read-project-list) (let ((dir (project-root pr))) (unless (equal (caar project--list) dir) @@ -1271,7 +1272,8 @@ project-remember-project (when (equal dir (car ent)) (setq project--list (delq ent project--list)))) (push (list dir) project--list) - (project--write-project-list)))) + (unless no-write + (project--write-project-list))))) (defun project--remove-from-project-list (project-root report-message) "Remove directory PROJECT-ROOT of a missing project from the project list. @@ -1325,6 +1327,35 @@ project-execute-extended-command (let ((default-directory (project-root (project-current t)))) (call-interactively #'execute-extended-command))) +(defun project-find-projects-under (dir) + "Index all projects below a directory DIR." + (interactive "DDirectory: ") + (let ((count 0)) + (dolist (subdir (directory-files dir t nil t)) + (when-let (pr (project--find-in-directory subdir)) + (project-remember-project pr t) + (message "Found %s..." (project-root pr)) + (setq count (1+ count)))) + (if (zerop count) + (message "No projects found") + (project--write-project-list) + (message "%d project%s found" + count (if (= count 1) "" "s"))))) + +(defun project-remove-zombie-projects () + "Remove all known projects that don't exist any more." + (interactive) + (dolist (proj (project-known-project-roots)) + (unless (file-exists-p proj) + (project-remove-known-project proj)))) + +(defun project-remove-known-projects (dir) + "Remove all known projects below a directory DIR." + (interactive "DDirectory: ") + (dolist (proj (project-known-project-roots)) + (when (file-in-directory-p proj dir) + (project-remove-known-project proj)))) + \f ;;; Project switching -- 2.30.2 [-- Attachment #3: Type: text/plain, Size: 6809 bytes --] In GNU Emacs 28.0.50 (build 7, x86_64-pc-linux-gnu, X toolkit, cairo version 1.16.0, Xaw scroll bars) of 2021-08-26 built on icterid Repository revision: b74afe63d02f126127d9211c0d1c1dc2cf5dd5bb Repository branch: master Windowing system distributor 'The X.Org Foundation', version 11.0.12011000 System Description: Debian GNU/Linux 11 (bullseye) Configured using: 'configure LDFLAGS=-flto 'CFLAGS=-O2 -march=native -mtune=native -pipe' --with-native-compiler' Configured features: ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY INOTIFY PDUMPER PNG SECCOMP SOUND THREADS TIFF TOOLKIT_SCROLL_BARS X11 XDBE XIM XPM LUCID ZLIB Important settings: value of $EMACSLOADPATH: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Git-Log-View Minor modes in effect: TeX-PDF-mode: t global-git-commit-mode: t magit-auto-revert-mode: t shell-dirtrack-mode: t icomplete-mode: t rcirc-track-minor-mode: t display-time-mode: t winner-mode: t windmove-mode: t electric-pair-mode: t recentf-mode: t save-place-mode: t savehist-mode: t show-paren-mode: t tooltip-mode: t global-eldoc-mode: t electric-indent-mode: t mouse-wheel-mode: t tab-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t temp-buffer-resize-mode: t buffer-read-only: t line-number-mode: t indent-tabs-mode: t transient-mark-mode: t Load-path shadows: /home/philip/.config/emacs/elpa/transient-0.3.6/transient hides /home/philip/Code/src/emacs/lisp/transient ~/.config/emacs/site-lisp/autoload hides /home/philip/Code/src/emacs/lisp/emacs-lisp/autoload Features: (shadow emacsbug tramp-archive tramp-gvfs tramp-cache zeroconf tramp tramp-loaddefs trampver tramp-integration files-x tramp-compat ls-lisp flymake-cc macrostep-c cmacexp macrostep preview tex-buf tex-fold reftex-dcr reftex-auc reftex reftex-loaddefs reftex-vars font-latex latex latex-flymake tex-ispell tex-style tex texmathp tex-mode latexenc apropos eieio-opt speedbar ezimage dframe shortdoc vc-annotate help-at-pt gnus-fun cl-print debug backtrace pulse find-func rect markdown-mode shell-command+ rng-xsd xsd-regexp rng-cmpct rng-nxml rng-valid rng-loc rng-uri rng-parse nxml-parse rng-match rng-dt rng-util rng-pttrn nxml-ns nxml-mode nxml-outln nxml-rap nxml-util nxml-enc xmltok xref find-dired grep mhtml-mode css-mode smie eww xdg url-queue mm-url color js cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs sgml-mode facemenu whitespace make-mode dired-aux ffap avy magit-extras bug-reference face-remap magit-submodule magit-obsolete magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit magit-sequence magit-notes magit-worktree magit-tag magit-merge magit-branch magit-reset magit-files magit-refs magit-status magit magit-repos magit-apply magit-wip magit-log which-func imenu magit-diff git-commit log-edit add-log magit-core magit-autorevert autorevert filenotify magit-margin magit-transient magit-process with-editor term ehelp eshell esh-cmd esh-ext esh-opt esh-proc esh-io esh-arg esh-module esh-groups esh-util shell pcomplete server magit-mode transient format-spec magit-git magit-section magit-utils dash vc-fossil vc-mtn vc-hg vc-git vc-bzr vc-src vc-sccs vc-svn vc-cvs vc-rcs icomplete project memory-report char-fold misearch multi-isearch mailalias bbdb-pgp url-http url-gw url-cache url-auth cus-edit pp cus-start finder-inf bbdb-message autocrypt-message smerge-mode diff-mode jka-compr mule-util smiley gnus-cite flow-fill mm-archive mail-extr gnus-async gnus-bcklg qp sort gnus-ml disp-table autocrypt-gnus autocrypt nndraft nnmh epa-file gnutls network-stream nsm nnmaildir nnfolder vc-backup log-view pcvs-util vc vc-dispatcher diff time-stamp bbdb-gnus bbdb-mua bbdb-com crm nnnil gnus-agent gnus-srvr gnus-score score-mode nnvirtual gnus-msg gnus-art mm-uu mml2015 mm-view mml-smime smime dig nntp gnus-cache gnus-sum shr kinsoku svg dom gnus-group gnus-undo gnus-start gnus-dbus dbus xml gnus-cloud nnimap nnmail mail-source utf7 netrc nnoo gnus-spec gnus-int gnus-range message rmc puny rfc822 mml mml-sec epa mm-decode mm-bodies mm-encode mailabbrev gmm-utils mailheader gnus-win modus-vivendi-theme paredit checkdoc flymake-proc flymake warnings thingatpt flyspell ispell noutline outline easy-mmode gnus-dired dired-x dired dired-loaddefs rcirc parse-time iso8601 rx time bbdb bbdb-site timezone sendmail gnus nnheader gnus-util rmail rmail-loaddefs time-date mail-utils hippie-exp winner windmove elec-pair recentf tree-widget wid-edit saveplace savehist paren modus-operandi-theme modus-themes holidays hol-loaddefs cal-menu calendar cal-loaddefs cus-load setup load compile text-property-search comint ansi-color autoload lisp-mnt mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr tex-site geiser-impl help-fns radix-tree geiser-custom geiser-base ring slime-autoloads info package let-alist derived edmacro kmacro pcase cl-extra help-mode browse-url url url-proxy url-privacy url-expand url-methods url-history url-cookie url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs password-cache json map url-vars seq byte-opt gv bytecomp byte-compile cconv epg epg-config subr-x cl-loaddefs cl-lib iso-transl tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type 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 elisp-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 cl-generic 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 charscript charprop case-table epa-hook jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice button loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote threads dbusbind inotify dynamic-setting system-font-setting font-render-setting cairo x-toolkit x multi-tty make-network-process emacs) Memory information: ((conses 16 1167755 519125) (symbols 48 100287 1576) (strings 32 294014 1164412) (string-bytes 1 10068553) (vectors 16 85242) (vector-slots 8 1729184 892975) (floats 8 776 1974) (intervals 56 55886 9874) (buffers 992 65)) -- Philip K. ^ permalink raw reply related [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-08-31 12:47 bug#50297: 28.0.50; Aggregate project functions for project.el Philip Kaludercic @ 2021-09-01 1:07 ` Dmitry Gutov 2021-09-02 13:30 ` Philip Kaludercic 2021-09-22 0:31 ` Dmitry Gutov 1 sibling, 1 reply; 21+ messages in thread From: Dmitry Gutov @ 2021-09-01 1:07 UTC (permalink / raw) To: Philip Kaludercic, 50297 Hi! On 31.08.2021 15:47, Philip Kaludercic wrote: > > The following patch introduces a few functions for aggregate project > maintenance: > > - project-find-projects-under > Select a directory with projects to index all at once. I wonder how popular this is going to be. Do you have a flat directory with projects which you only want scanned one time? Another issue, is that it's not going to find nested projects (and project.el does support those). Suppose we do add it, how about the name 'project-remember-projects-under'? By analogy with 'project-remember-project'. Adding a new arg for the latter is fine by me either way. > - project-remove-zombie-projects > Check if all known projects still exist and remove those > that don't anymore Perhaps we should rename 'project-remove-known-project' to 'project-forget-known-project'? That would make for a nice symmetry. Then this function could be called 'project-forget-zombie-projects'. I'm thinking about this about the slight connotation of 'remove' which can mean removing from disk. Another approach would be to call this or similar code automatically before saving the list (and cap the number of remembered projects), but that comes with its own tradeoffs. > - project-remove-projects-under > Remove all projects in a directory (inverse of > project-find-projects-under). Similar question about popularity, but this one won't have a problem with semantics, at least (recursive-vs-non-recursive). > Especially the last two are useful to maintain a clean project list > without having to manually remove every project one by one. What if the goal was to maintain a clean project list but minimize the manual management of it by the user? Can you imagine a solution for that? What would be the downsides, compared to the present proposal? ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-01 1:07 ` Dmitry Gutov @ 2021-09-02 13:30 ` Philip Kaludercic 2021-09-02 14:45 ` Philip Kaludercic 2021-09-03 0:55 ` Dmitry Gutov 0 siblings, 2 replies; 21+ messages in thread From: Philip Kaludercic @ 2021-09-02 13:30 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297 Dmitry Gutov <dgutov@yandex.ru> writes: > Hi! > > On 31.08.2021 15:47, Philip Kaludercic wrote: >> The following patch introduces a few functions for aggregate project >> maintenance: >> - project-find-projects-under >> Select a directory with projects to index all at once. > > I wonder how popular this is going to be. Do you have a flat directory > with projects which you only want scanned one time? I clone most code into a directory, and I have seen others do so too. That being said, it might just be something unusual in the big picture. > Another issue, is that it's not going to find nested projects (and > project.el does support those). My first implementation of the command tried to so something like that, but it was rather slow (even if I currently only have 20 projects checked out), and indexed a lot of projects that I wasn't interested in. Maybe I can look into how it can be accelerated or only search for nested projects when a prefix argument is supplied/not supplied. > Suppose we do add it, how about the name > 'project-remember-projects-under'? By analogy with > 'project-remember-project'. I like it. > Adding a new arg for the latter is fine by me either way. > >> - project-remove-zombie-projects >> Check if all known projects still exist and remove those >> that don't anymore > > Perhaps we should rename 'project-remove-known-project' to > 'project-forget-known-project'? That would make for a nice symmetry. > > Then this function could be called 'project-forget-zombie-projects'. This also make sense. Initially I wanted to name the command that way, but then decided to go with "remove" to keep the naming consistent. > I'm thinking about this about the slight connotation of 'remove' which > can mean removing from disk. > > Another approach would be to call this or similar code automatically > before saving the list (and cap the number of remembered projects), > but that comes with its own tradeoffs. I can try it out, but I fear it might lead to annoying pauses, especially when a project was indexed via TRAMP. >> - project-remove-projects-under >> Remove all projects in a directory (inverse of >> project-find-projects-under). > > Similar question about popularity, but this one won't have a problem > with semantics, at least (recursive-vs-non-recursive). > >> Especially the last two are useful to maintain a clean project list >> without having to manually remove every project one by one. > > What if the goal was to maintain a clean project list but minimize the > manual management of it by the user? > > Can you imagine a solution for that? What would be the downsides, > compared to the present proposal? I can imagine zombie projects being cleaned up automatically, but the motivation to write project-remove-projects-under was to remove projects that were falsely indexed. An entirely different approach might be to implement a tabulated list major mode to manage projects, comparable to package-list. -- Philip Kaludercic ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-02 13:30 ` Philip Kaludercic @ 2021-09-02 14:45 ` Philip Kaludercic 2021-09-02 15:56 ` Juri Linkov 2021-09-03 1:02 ` Dmitry Gutov 2021-09-03 0:55 ` Dmitry Gutov 1 sibling, 2 replies; 21+ messages in thread From: Philip Kaludercic @ 2021-09-02 14:45 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297 [-- Attachment #1: Type: text/plain, Size: 382 bytes --] Philip Kaludercic <philipk@posteo.net> writes: > An entirely different approach might be to implement a tabulated list > major mode to manage projects, comparable to package-list. For the sake of it, it tried it out how this might look like. It feels clunky as of now, doesn't implement everything that it should and it might make more sense to provide as an additional package. [-- Attachment #2: Type: text/plain, Size: 3793 bytes --] diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index e420a4ccca..b438249b95 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1327,6 +1327,102 @@ project-execute-extended-command (let ((default-directory (project-root (project-current t)))) (call-interactively #'execute-extended-command))) +\f +;;; Project managment + +(defun project-list-generate-list () + "Generate a list of projects for `tabulated-list-mode'." + (let (entries) + (dolist (root (project-known-project-roots)) + (when-let* ((proj (project--find-in-directory root)) + (root (project-root proj)) + ;; XXX: Name and Type are just to keep the buffer + ;; from looking too empty. + (name (capitalize + (file-name-nondirectory + (directory-file-name root)))) + (type (if (consp proj) (format "%S" (car proj)) "??")) + (data (vector name type root))) + (push (list root data) entries))) + entries)) + +(defun project-list-select () + "Select the project at point." + (interactive) + (project-switch-project (tabulated-list-get-id))) + +(defun project-list-mark-forget () + "Mark the project at point to be forgotten." + (interactive) + (save-mark-and-excursion + (save-restriction + (narrow-to-region (region-beginning) (region-end)) + (goto-char (point-min)) + (while (not (eobp)) + (tabulated-list-put-tag "F" t))))) + +(defun project-list-forget-zombies () + "Mark the project at point to be forgotten." + (interactive) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (unless (file-exists-p (tabulated-list-get-id)) + (tabulated-list-put-tag "F" t))))) + +(defun project-list-unmark () + "Unmark the project at point." + (save-mark-and-excursion + (save-restriction + (narrow-to-region (region-beginning) (region-end)) + (goto-char (point-min)) + (while (not (eobp)) + (tabulated-list-put-tag " " t))))) + +(defun project-list-execute () + "Preform marked actions on the project list." + (interactive) + (let (forget-list) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (when (eq (char-after) ?F) + (push (tabulated-list-get-id) forget-list)) + (forward-line))) + (when (yes-or-no-p (format "Forget %d projects? " (length forget-list))) + (mapc #'project-remove-known-project forget-list) + (tabulated-list-clear-all-tags) + (tabulated-list-print)))) + +(defvar project-list-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") #'project-list-select) + (define-key map (kbd "f") #'project-list-mark-forget) + (define-key map (kbd "d") #'project-list-mark-forget) + (define-key map (kbd "z") #'project-list-forget-zombies) + (define-key map (kbd "u") #'project-list-unmark) + (define-key map (kbd "x") #'project-list-execute) + map)) + +(define-derived-mode project-list-mode tabulated-list-mode "Project List" + "Major mode for browsing the list of known projects." + (setq tabulated-list-format [("Name" 16 t) + ("Type" 4 nil) + ("Path" 0 t)] + tabulated-list-entries #'project-list-generate-list + tabulated-list-padding 2) + (tabulated-list-init-header) + (tabulated-list-print)) + +;;;###autoload +(defun project-list-projects () + "Display a list of all known projects." + (interactive) + (project--ensure-read-project-list) + (with-current-buffer (get-buffer-create "*Projects*") + (project-list-mode) + (pop-to-buffer-same-window (current-buffer)))) + \f ;;; Project switching [-- Attachment #3: Type: text/plain, Size: 24 bytes --] -- Philip Kaludercic ^ permalink raw reply related [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-02 14:45 ` Philip Kaludercic @ 2021-09-02 15:56 ` Juri Linkov 2021-09-03 1:02 ` Dmitry Gutov 1 sibling, 0 replies; 21+ messages in thread From: Juri Linkov @ 2021-09-02 15:56 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 50297, Dmitry Gutov >> An entirely different approach might be to implement a tabulated list >> major mode to manage projects, comparable to package-list. > > For the sake of it, it tried it out how this might look like. It feels > clunky as of now, doesn't implement everything that it should and it > might make more sense to provide as an additional package. This is like music players that provide an option to scan a folder for music files, then allow to manage found files in a list. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-02 14:45 ` Philip Kaludercic 2021-09-02 15:56 ` Juri Linkov @ 2021-09-03 1:02 ` Dmitry Gutov 1 sibling, 0 replies; 21+ messages in thread From: Dmitry Gutov @ 2021-09-03 1:02 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 50297 On 02.09.2021 17:45, Philip Kaludercic wrote: > For the sake of it, it tried it out how this might look like. It feels > clunky as of now, doesn't implement everything that it should and it > might make more sense to provide as an additional package. I like it as an idea, but probably wouldn't use the UI itself much. At this point it's up to you which of the approaches to put forward, though. I was also thinking that the "read project" prompt itself could serve like such a listing which could be edited by the user on-the-fly. But that would require some extension of the completing-read facility. The closest analogy is how icomplete-fido-kill (C-k) can delete a file if it's called during file name completion. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-02 13:30 ` Philip Kaludercic 2021-09-02 14:45 ` Philip Kaludercic @ 2021-09-03 0:55 ` Dmitry Gutov 1 sibling, 0 replies; 21+ messages in thread From: Dmitry Gutov @ 2021-09-03 0:55 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 50297, Theodor Thornhill On 02.09.2021 16:30, Philip Kaludercic wrote: >>> - project-find-projects-under >>> Select a directory with projects to index all at once. >> >> I wonder how popular this is going to be. Do you have a flat directory >> with projects which you only want scanned one time? > > I clone most code into a directory, and I have seen others do so > too. That being said, it might just be something unusual in the big > picture. I think it's usual enough, but since we try to enable all kinds of practices, we should try to handle as many as feasible. I'm mostly worried about the semantics here: we say we scan all the projects in said directory, but we can miss some (or many). That can be fixed with an edit to the docstring, of course (e.g. "directly below"). >> Another issue, is that it's not going to find nested projects (and >> project.el does support those). > > My first implementation of the command tried to so something like that, > but it was rather slow (even if I currently only have 20 projects > checked out), and indexed a lot of projects that I wasn't interested > in. Maybe I can look into how it can be accelerated or only search for > nested projects when a prefix argument is supplied/not supplied. It might be fine as it is, behavior-wise. It never occurred to me to ask or search for such functionality, though, so me might want to wait for others to chime in (who will want to use this). I'm usually fine with 'C-x C-f' when visiting a project the first time. >> Suppose we do add it, how about the name >> 'project-remember-projects-under'? By analogy with >> 'project-remember-project'. > > I like it. > >> Adding a new arg for the latter is fine by me either way. >> >>> - project-remove-zombie-projects >>> Check if all known projects still exist and remove those >>> that don't anymore >> >> Perhaps we should rename 'project-remove-known-project' to >> 'project-forget-known-project'? That would make for a nice symmetry. >> >> Then this function could be called 'project-forget-zombie-projects'. > > This also make sense. Initially I wanted to name the command that way, > but then decided to go with "remove" to keep the naming consistent. We might encounter some resistance (the command has been with us for half a year), but let's try it, at least. We can also ask Theodor whether he has already used the current name, project-remove-known-project, in some Lisp code. >> I'm thinking about this about the slight connotation of 'remove' which >> can mean removing from disk. >> >> Another approach would be to call this or similar code automatically >> before saving the list (and cap the number of remembered projects), >> but that comes with its own tradeoffs. > > I can try it out, but I fear it might lead to annoying pauses, > especially when a project was indexed via TRAMP. We could skip remote projects entirely in that function (leaving it to the user to 'forget' them manually), or only do it for already connected hosts. The latter could still take some time, though. Do you expect project-forget-zombie-projects to be useful to remote hosts as well? Do you also have directories on remote hosts that contain many projects? >>> Especially the last two are useful to maintain a clean project list >>> without having to manually remove every project one by one. >> >> What if the goal was to maintain a clean project list but minimize the >> manual management of it by the user? >> >> Can you imagine a solution for that? What would be the downsides, >> compared to the present proposal? > > I can imagine zombie projects being cleaned up automatically, but > the motivation to write project-remove-projects-under was to remove > projects that were falsely indexed. Could you elaborate? Falsely meaning projects you simply don't want to return to? A whole directory of them? > An entirely different approach might be to implement a tabulated list > major mode to manage projects, comparable to package-list. I don't object to supporting this approach, built-in or in a third-party package, as long as we're reasonably sure there is no low-touch, automatic solution we can use with a similar success for the problem in question. If there's none, or if we found such, and then figured that some manual management on top of it can still be useful, that is fine. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-08-31 12:47 bug#50297: 28.0.50; Aggregate project functions for project.el Philip Kaludercic 2021-09-01 1:07 ` Dmitry Gutov @ 2021-09-22 0:31 ` Dmitry Gutov 2021-09-22 7:15 ` Philip Kaludercic ` (2 more replies) 1 sibling, 3 replies; 21+ messages in thread From: Dmitry Gutov @ 2021-09-22 0:31 UTC (permalink / raw) To: Philip Kaludercic, 50297 On 31.08.2021 15:47, Philip Kaludercic wrote: > The following patch introduces a few functions for aggregate project > maintenance: > > - project-find-projects-under > Select a directory with projects to index all at once. > - project-remove-zombie-projects > Check if all known projects still exist and remove those > that don't anymore > - project-remove-projects-under > Remove all projects in a directory (inverse of > project-find-projects-under). > > Especially the last two are useful to maintain a clean project list > without having to manually remove every project one by one. OK, so I have done the rename: we now have project-forget-project. While I'm not necessarily a fan of the tabulated list approach, the above list looks sensible. Let's just name them to fit the current scheme better: project-remember-projects-under project-forget-projects-under project-forget-zombie-projects And whatever ambiguities about recursive search can be solved through better descriptions in docstrings. We could also add a hook like project-after-read-list-hook, which people would be able to use for cleanup, e.g. adding project-forget-zombie-projects to it. Not sure whether to add it there by default, though. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 0:31 ` Dmitry Gutov @ 2021-09-22 7:15 ` Philip Kaludercic 2021-09-22 12:13 ` Dmitry Gutov 2021-09-22 16:00 ` Juri Linkov 2021-09-22 18:55 ` Philip Kaludercic 2 siblings, 1 reply; 21+ messages in thread From: Philip Kaludercic @ 2021-09-22 7:15 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297 Dmitry Gutov <dgutov@yandex.ru> writes: > On 31.08.2021 15:47, Philip Kaludercic wrote: >> The following patch introduces a few functions for aggregate project >> maintenance: >> - project-find-projects-under >> Select a directory with projects to index all at once. >> - project-remove-zombie-projects >> Check if all known projects still exist and remove those >> that don't anymore >> - project-remove-projects-under >> Remove all projects in a directory (inverse of >> project-find-projects-under). >> Especially the last two are useful to maintain a clean project list >> without having to manually remove every project one by one. > > OK, so I have done the rename: we now have project-forget-project. > > While I'm not necessarily a fan of the tabulated list approach, the > above list looks sensible. Let's just name them to fit the current > scheme better: > > project-remember-projects-under > project-forget-projects-under > project-forget-zombie-projects It is also my impression that the tabulated list doesn't make too much sense (for now). > And whatever ambiguities about recursive search can be solved through > better descriptions in docstrings. Ok, I will update the patches and refine the documentation. My plan would be to be non-recursive by default, and recurse if a prefix argument is given. > We could also add a hook like project-after-read-list-hook, which > people would be able to use for cleanup, e.g. adding > project-forget-zombie-projects to it. Not sure whether to add it there > by default, though. The question is does it make sense to not always forget zombies? This depends on the real-world performance. If it is a noticeable burden (at least on some systems), users might prefer adding the function to kill-emacs-hook instead of a project-after-read-list-hook. -- Philip Kaludercic ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 7:15 ` Philip Kaludercic @ 2021-09-22 12:13 ` Dmitry Gutov 0 siblings, 0 replies; 21+ messages in thread From: Dmitry Gutov @ 2021-09-22 12:13 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 50297 On 22.09.2021 10:15, Philip Kaludercic wrote: >> And whatever ambiguities about recursive search can be solved through >> better descriptions in docstrings. > > Ok, I will update the patches and refine the documentation. My plan > would be to be non-recursive by default, and recurse if a prefix > argument is given. If you like. No recursive option seems also okay. >> We could also add a hook like project-after-read-list-hook, which >> people would be able to use for cleanup, e.g. adding >> project-forget-zombie-projects to it. Not sure whether to add it there >> by default, though. > > The question is does it make sense to not always forget zombies? This > depends on the real-world performance. FWIW, speaking of Tramp, we can either avoid cleaning remote dirs, or at least make sure the connection is on before checking (and skip those where it is not). And another way to limit the performance impact is to cap the number of projects in history. > If it is a noticeable burden (at > least on some systems), users might prefer adding the function to > kill-emacs-hook instead of a project-after-read-list-hook. kill-emacs-hook is also a good place to use it indeed. Maybe we don't need the other hook. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 0:31 ` Dmitry Gutov 2021-09-22 7:15 ` Philip Kaludercic @ 2021-09-22 16:00 ` Juri Linkov 2021-09-22 16:44 ` Philip Kaludercic 2021-09-22 18:55 ` Philip Kaludercic 2 siblings, 1 reply; 21+ messages in thread From: Juri Linkov @ 2021-09-22 16:00 UTC (permalink / raw) To: Dmitry Gutov; +Cc: Philip Kaludercic, 50297 > While I'm not necessarily a fan of the tabulated list approach, the above > list looks sensible. We already have a lot of 'list-*' commands for everything like 'list-packages', 'list-timers', etc. So sooner or later 'list-projects' will need to be added anyway, with the minimal requirement of using that list for quicker and more visual project switching with 'RET' like in 'list-buffers', and also for issuing commands on a group of selected projects, etc. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 16:00 ` Juri Linkov @ 2021-09-22 16:44 ` Philip Kaludercic 2021-09-22 17:34 ` Dmitry Gutov 0 siblings, 1 reply; 21+ messages in thread From: Philip Kaludercic @ 2021-09-22 16:44 UTC (permalink / raw) To: Juri Linkov; +Cc: Philip Kaludercic, 50297, Dmitry Gutov Juri Linkov <juri@linkov.net> writes: >> While I'm not necessarily a fan of the tabulated list approach, the above >> list looks sensible. > > We already have a lot of 'list-*' commands for everything like > 'list-packages', 'list-timers', etc. So sooner or later > 'list-projects' will need to be added anyway, with the minimal > requirement of using that list for quicker and more visual > project switching with 'RET' like in 'list-buffers', and > also for issuing commands on a group of selected projects, etc. I think it would make sense to have some kind of a way to name projects, either by extracting the information from the VCS or via an alias. When I tried implementing something like this, the only two columns I could come up with to present were type (that isn't to interesting to begin with) and project root. This seems a too meagre to warren a list-projects function. -- Philip Kaludercic ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 16:44 ` Philip Kaludercic @ 2021-09-22 17:34 ` Dmitry Gutov 2021-09-22 18:06 ` Philip Kaludercic 0 siblings, 1 reply; 21+ messages in thread From: Dmitry Gutov @ 2021-09-22 17:34 UTC (permalink / raw) To: Philip Kaludercic, Juri Linkov; +Cc: 50297 On 22.09.2021 19:44, Philip Kaludercic wrote: > I think it would make sense to have some kind of a way to name projects, > either by extracting the information from the VCS or via an > alias. If we add this feature, I think most of the names will be more or less equal to project root's base name. So it's not like this will add much in the way of variety to the table. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 17:34 ` Dmitry Gutov @ 2021-09-22 18:06 ` Philip Kaludercic 2021-09-22 18:25 ` Dmitry Gutov 0 siblings, 1 reply; 21+ messages in thread From: Philip Kaludercic @ 2021-09-22 18:06 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297, Juri Linkov Dmitry Gutov <dgutov@yandex.ru> writes: > On 22.09.2021 19:44, Philip Kaludercic wrote: >> I think it would make sense to have some kind of a way to name projects, >> either by extracting the information from the VCS or via an >> alias. > > If we add this feature, I think most of the names will be more or less > equal to project root's base name. So it's not like this will add much > in the way of variety to the table. Currently yes. But if we were to store more metadata about a project (nickname, first access, last access, etc.) maybe it might make more sense. -- Philip Kaludercic ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 18:06 ` Philip Kaludercic @ 2021-09-22 18:25 ` Dmitry Gutov 2021-09-22 18:53 ` Philip Kaludercic 0 siblings, 1 reply; 21+ messages in thread From: Dmitry Gutov @ 2021-09-22 18:25 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 50297, Juri Linkov On 22.09.2021 21:06, Philip Kaludercic wrote: > Currently yes. But if we were to store more metadata about a project > (nickname, first access, last access, etc.) maybe it might make more > sense. That's possible, yes. We could start storing access times right now, if you like. I don't know where else we would use them, though. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 18:25 ` Dmitry Gutov @ 2021-09-22 18:53 ` Philip Kaludercic 0 siblings, 0 replies; 21+ messages in thread From: Philip Kaludercic @ 2021-09-22 18:53 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297, Juri Linkov Dmitry Gutov <dgutov@yandex.ru> writes: > On 22.09.2021 21:06, Philip Kaludercic wrote: >> Currently yes. But if we were to store more metadata about a project >> (nickname, first access, last access, etc.) maybe it might make more >> sense. > > That's possible, yes. > > We could start storing access times right now, if you like. I don't > know where else we would use them, though. I don't think there is any use for that either right now, so I wouldn't argue that it should be added immediately. -- Philip Kaludercic ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 0:31 ` Dmitry Gutov 2021-09-22 7:15 ` Philip Kaludercic 2021-09-22 16:00 ` Juri Linkov @ 2021-09-22 18:55 ` Philip Kaludercic 2021-09-23 2:44 ` Dmitry Gutov 2 siblings, 1 reply; 21+ messages in thread From: Philip Kaludercic @ 2021-09-22 18:55 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297 [-- Attachment #1: Type: text/plain, Size: 72 bytes --] Here is the updated patch, with the new names and optional recursion: [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Add-aggregate-project-discovery-and-maintenance-func.patch --] [-- Type: text/x-diff, Size: 4642 bytes --] From 4779aae9d1c18cd2dc2b8f54322b48b0e11ac5fb Mon Sep 17 00:00:00 2001 From: Philip Kaludercic <philipk@posteo.net> Date: Tue, 31 Aug 2021 14:12:13 +0200 Subject: [PATCH] Add aggregate project discovery and maintenance functions * project.el (project-remember-project): Add optional no-write argument (project-remember-projects-under): Add command (project-forget-zombie-projects): Add command (project-forget-known-projects): Add command --- lisp/progmodes/project.el | 72 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index ebd21d4b60..977b1ae185 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1290,9 +1290,10 @@ project--write-project-list (write-region nil nil filename nil 'silent)))) ;;;###autoload -(defun project-remember-project (pr) +(defun project-remember-project (pr &optional no-write) "Add project PR to the front of the project list. -Save the result in `project-list-file' if the list of projects has changed." +Save the result in `project-list-file' if the list of projects +has changed, and NO-WRITE is nil." (project--ensure-read-project-list) (let ((dir (project-root pr))) (unless (equal (caar project--list) dir) @@ -1300,7 +1301,8 @@ project-remember-project (when (equal dir (car ent)) (setq project--list (delq ent project--list)))) (push (list dir) project--list) - (project--write-project-list)))) + (unless no-write + (project--write-project-list))))) (defun project--remove-from-project-list (project-root report-message) "Remove directory PROJECT-ROOT of a missing project from the project list. @@ -1357,6 +1359,70 @@ project-execute-extended-command (let ((default-directory (project-root (project-current t)))) (call-interactively #'execute-extended-command))) +(defun project-remember-projects-under (dir &optional recursive) + "Index all projects below a directory DIR. +If RECURSIVE is non-nil, recurse into all subdirectories to find +more projects. After finishing, a message is printed summarizing +the progress. The function returns the number of detected +projects." + (interactive "DDirectory: \nP") + (project--ensure-read-project-list) + (let ((queue (directory-files dir t nil t)) (count 0) + (known (make-hash-table + :size (* 2 (length project--list)) + :test #'equal ))) + (dolist (project (mapcar #'car project--list)) + (puthash project t known)) + (while queue + (when-let ((subdir (pop queue)) + ((file-directory-p subdir)) + ((not (gethash subdir known)))) + (when-let (pr (project--find-in-directory subdir)) + (project-remember-project pr t) + (message "Found %s..." (project-root pr)) + (setq count (1+ count))) + (when (and recursive (file-symlink-p subdir)) + (setq queue (nconc (directory-files subdir t nil t) queue)) + (puthash subdir t known)))) + (unless (eq recursive 'in-progress) + (if (zerop count) + (message "No projects were found") + (project--write-project-list) + (message "%d project%s were found" + count (if (= count 1) "" "s")))) + count)) + +(defun project-forget-zombie-projects () + "Forget all known projects that don't exist any more." + (interactive) + (dolist (proj (project-known-project-roots)) + (unless (file-exists-p proj) + (project-remove-known-project proj)))) + +(defun project-forget-known-projects (dir &optional recursive) + "Forget all known projects below a directory DIR. +If RECURSIVE is non-nil, recurse into all subdirectories to +remove all known projects. After finishing, a message is printed +summarizing the progress. The function returns the number of +forgotten projects." + (interactive "DDirectory: \nP") + (let ((count 0)) + (if recursive + (dolist (proj (project-known-project-roots)) + (when (file-in-directory-p proj dir) + (project-remove-known-project proj) + (setq count (1+ count)))) + (dolist (proj (project-known-project-roots)) + (when (file-equal-p (file-name-directory proj) dir) + (project-remove-known-project proj) + (setq count (1+ count))))) + (if (zerop count) + (message "No projects were forgotten") + (project--write-project-list) + (message "%d project%s were forgotten" + count (if (= count 1) "" "s"))) + count)) + \f ;;; Project switching -- 2.30.2 [-- Attachment #3: Type: text/plain, Size: 24 bytes --] -- Philip Kaludercic ^ permalink raw reply related [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-22 18:55 ` Philip Kaludercic @ 2021-09-23 2:44 ` Dmitry Gutov 2021-09-23 10:46 ` Philip Kaludercic 0 siblings, 1 reply; 21+ messages in thread From: Dmitry Gutov @ 2021-09-23 2:44 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 50297 On 22.09.2021 21:55, Philip Kaludercic wrote: > + (project-remove-known-project proj)))) This one is called 'project-forget-project' now. > +(defun project-forget-known-projects (dir &optional recursive) And let's call this one 'project-forget-projects-under'. Looks good otherwise, thanks. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-23 2:44 ` Dmitry Gutov @ 2021-09-23 10:46 ` Philip Kaludercic 2021-09-23 11:56 ` Dmitry Gutov 0 siblings, 1 reply; 21+ messages in thread From: Philip Kaludercic @ 2021-09-23 10:46 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297 [-- Attachment #1: Type: text/plain, Size: 454 bytes --] Dmitry Gutov <dgutov@yandex.ru> writes: > On 22.09.2021 21:55, Philip Kaludercic wrote: >> + (project-remove-known-project proj)))) > > This one is called 'project-forget-project' now. > >> +(defun project-forget-known-projects (dir &optional recursive) > > And let's call this one 'project-forget-projects-under'. > > Looks good otherwise, thanks. Sorry about that, forgot to byte-compile before preparing the patch. This should fix the issues: [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Add-aggregate-project-discovery-and-maintenance-func.patch --] [-- Type: text/x-diff, Size: 4624 bytes --] From 45492ec9fb9f2706f6ac0e7317ec1b0f7ce25091 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic <philipk@posteo.net> Date: Tue, 31 Aug 2021 14:12:13 +0200 Subject: [PATCH] Add aggregate project discovery and maintenance functions * project.el (project-remember-project): Add optional no-write argument (project-remember-projects-under): Add command (project-forget-zombie-projects): Add command (project-forget-projects-under): Add command --- lisp/progmodes/project.el | 72 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 9b63f4b1bc..57a961c260 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1296,9 +1296,10 @@ project--write-project-list (write-region nil nil filename nil 'silent)))) ;;;###autoload -(defun project-remember-project (pr) +(defun project-remember-project (pr &optional no-write) "Add project PR to the front of the project list. -Save the result in `project-list-file' if the list of projects has changed." +Save the result in `project-list-file' if the list of projects +has changed, and NO-WRITE is nil." (project--ensure-read-project-list) (let ((dir (project-root pr))) (unless (equal (caar project--list) dir) @@ -1306,7 +1307,8 @@ project-remember-project (when (equal dir (car ent)) (setq project--list (delq ent project--list)))) (push (list dir) project--list) - (project--write-project-list)))) + (unless no-write + (project--write-project-list))))) (defun project--remove-from-project-list (project-root report-message) "Remove directory PROJECT-ROOT of a missing project from the project list. @@ -1363,6 +1365,70 @@ project-execute-extended-command (let ((default-directory (project-root (project-current t)))) (call-interactively #'execute-extended-command))) +(defun project-remember-projects-under (dir &optional recursive) + "Index all projects below a directory DIR. +If RECURSIVE is non-nil, recurse into all subdirectories to find +more projects. After finishing, a message is printed summarizing +the progress. The function returns the number of detected +projects." + (interactive "DDirectory: \nP") + (project--ensure-read-project-list) + (let ((queue (directory-files dir t nil t)) (count 0) + (known (make-hash-table + :size (* 2 (length project--list)) + :test #'equal ))) + (dolist (project (mapcar #'car project--list)) + (puthash project t known)) + (while queue + (when-let ((subdir (pop queue)) + ((file-directory-p subdir)) + ((not (gethash subdir known)))) + (when-let (pr (project--find-in-directory subdir)) + (project-remember-project pr t) + (message "Found %s..." (project-root pr)) + (setq count (1+ count))) + (when (and recursive (file-symlink-p subdir)) + (setq queue (nconc (directory-files subdir t nil t) queue)) + (puthash subdir t known)))) + (unless (eq recursive 'in-progress) + (if (zerop count) + (message "No projects were found") + (project--write-project-list) + (message "%d project%s were found" + count (if (= count 1) "" "s")))) + count)) + +(defun project-forget-zombie-projects () + "Forget all known projects that don't exist any more." + (interactive) + (dolist (proj (project-known-project-roots)) + (unless (file-exists-p proj) + (project-forget-project proj)))) + +(defun project-forget-projects-under (dir &optional recursive) + "Forget all known projects below a directory DIR. +If RECURSIVE is non-nil, recurse into all subdirectories to +remove all known projects. After finishing, a message is printed +summarizing the progress. The function returns the number of +forgotten projects." + (interactive "DDirectory: \nP") + (let ((count 0)) + (if recursive + (dolist (proj (project-known-project-roots)) + (when (file-in-directory-p proj dir) + (project-forget-project proj) + (setq count (1+ count)))) + (dolist (proj (project-known-project-roots)) + (when (file-equal-p (file-name-directory proj) dir) + (project-forget-project proj) + (setq count (1+ count))))) + (if (zerop count) + (message "No projects were forgotten") + (project--write-project-list) + (message "%d project%s were forgotten" + count (if (= count 1) "" "s"))) + count)) + \f ;;; Project switching -- 2.30.2 [-- Attachment #3: Type: text/plain, Size: 24 bytes --] -- Philip Kaludercic ^ permalink raw reply related [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-23 10:46 ` Philip Kaludercic @ 2021-09-23 11:56 ` Dmitry Gutov 2021-09-23 12:08 ` Philip Kaludercic 0 siblings, 1 reply; 21+ messages in thread From: Dmitry Gutov @ 2021-09-23 11:56 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 50297 On 23.09.2021 13:46, Philip Kaludercic wrote: > Sorry about that, forgot to byte-compile before preparing the > patch. This should fix the issues: Thanks. You can go ahead and install. Just add NEWS entries for the commands. ^ permalink raw reply [flat|nested] 21+ messages in thread
* bug#50297: 28.0.50; Aggregate project functions for project.el 2021-09-23 11:56 ` Dmitry Gutov @ 2021-09-23 12:08 ` Philip Kaludercic 0 siblings, 0 replies; 21+ messages in thread From: Philip Kaludercic @ 2021-09-23 12:08 UTC (permalink / raw) To: Dmitry Gutov; +Cc: 50297-done Dmitry Gutov <dgutov@yandex.ru> writes: > On 23.09.2021 13:46, Philip Kaludercic wrote: >> Sorry about that, forgot to byte-compile before preparing the >> patch. This should fix the issues: > > Thanks. You can go ahead and install. > > Just add NEWS entries for the commands. Done and pushed. -- Philip Kaludercic ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2021-09-23 12:08 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-08-31 12:47 bug#50297: 28.0.50; Aggregate project functions for project.el Philip Kaludercic 2021-09-01 1:07 ` Dmitry Gutov 2021-09-02 13:30 ` Philip Kaludercic 2021-09-02 14:45 ` Philip Kaludercic 2021-09-02 15:56 ` Juri Linkov 2021-09-03 1:02 ` Dmitry Gutov 2021-09-03 0:55 ` Dmitry Gutov 2021-09-22 0:31 ` Dmitry Gutov 2021-09-22 7:15 ` Philip Kaludercic 2021-09-22 12:13 ` Dmitry Gutov 2021-09-22 16:00 ` Juri Linkov 2021-09-22 16:44 ` Philip Kaludercic 2021-09-22 17:34 ` Dmitry Gutov 2021-09-22 18:06 ` Philip Kaludercic 2021-09-22 18:25 ` Dmitry Gutov 2021-09-22 18:53 ` Philip Kaludercic 2021-09-22 18:55 ` Philip Kaludercic 2021-09-23 2:44 ` Dmitry Gutov 2021-09-23 10:46 ` Philip Kaludercic 2021-09-23 11:56 ` Dmitry Gutov 2021-09-23 12:08 ` Philip Kaludercic
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).