[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
package-autosuggest
From: |
Philip Kaludercic |
Subject: |
package-autosuggest |
Date: |
Wed, 30 Aug 2023 19:26:38 +0000 |
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Philip Kaludercic <philipk@posteo.net>
>> Cc: monnier@iro.umontreal.ca, stefankangas@gmail.com, yandros@gmail.com,
>> bozhidar@batsov.dev, dmitry@gutov.dev, rms@gnu.org,
>> danny@dfreeman.email, emacs-devel@gnu.org, manuel.uberti@inventati.org
>> Date: Wed, 30 Aug 2023 12:25:20 +0000
>>
>> Are there any other examples, where we would want to have minor modes
>> for specific file types? These sorts of entries would probably have to
>> be added manually.
>
> I don't know, maybe someone else has an idea.
>
>> I am glad to see that there is interest in this proposal. I can try and
>> create an example of how this could work, and push it to a feature
>> branch for further review, some time soon.
>
> I think this could be useful, yes.
Here is a quick and rough draft of how this feature could look like:
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index e1172d69bf0..723900318c5 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -4534,6 +4534,116 @@ package-get-version
(or (lm-header "package-version")
(lm-header "version")))))))))
+
+;;;; Autosuggest
+
+(defvar package-autosuggest-database
+ '((sml-mode auto-mode-alist "\\.sml\\'")
+ (lua-mode auto-mode-alist "\\.lua\\'" )
+ (ada-mode auto-mode-alist "\\.ada\\'")
+ ;; ...
+ ;;
+ ;; this is just for testing, in practice I think this data should
+ ;; be generated and bundled with Emacs, and would ideally be
+ ;; loaded in at compile-time. When the "archive-contents" file
+ ;; format is updated, we can include more information in there
+ ;; that would be added to this database.
+ )
+ "Database of hints for packages to suggest installing.")
+
+(define-minor-mode package-autosuggest-mode
+ "Enable the automatic suggestion and installation of packages."
+ :init-value 'message :global t
+ (funcall (if package-autosuggest-mode #'add-hook #'remove-hook)
+ 'after-change-major-mode-hook
+ #'package--autosuggest-after-change-mode))
+
+(defun package--suggestion-applies-p (pkg-sug)
+ "Check if a suggestion PKG-SUG is applicable to the current buffer."
+ (pcase pkg-sug
+ (`(,(pred package-installed-p) . _) nil)
+ ((or `(,_ auto-mode-alist ,ext _)
+ `(,_ auto-mode-alist ,ext))
+ (and (string-match-p ext (buffer-name)) t))
+ ((or `(,_ magic-mode-alist ,mag _)
+ `(,_ magic-mode-alist ,mag))
+ (save-restriction
+ (widen)
+ (save-excursion
+ (goto-char (point-min))
+ (looking-at-p mag))))
+ ((or `(,_ interpreter-mode-alist ,magic _)
+ `(,_ interpreter-mode-alist ,magic))
+ (save-restriction
+ (widen)
+ (save-excursion
+ (goto-char (point-min))
+ (and (looking-at auto-mode-interpreter-regexp)
+ (string-match-p
+ (concat "\\`" (file-name-nondirectory (match-string 2)) "\\'")
+ magic)))))))
+
+(defun package--autosuggest-find-candidates ()
+ "Return a list of packages that might be interesting the current buffer."
+ (and package-autosuggest-mode
+ (let (suggetions)
+ (dolist (sug package-autosuggest-database)
+ (when (package--suggestion-applies-p sug)
+ (push sug suggetions)))
+ suggetions)))
+
+(defun package--autosuggest-install-and-enable (pkg-sug)
+ "Install and enable a package suggestion PKG-ENT.
+PKG-SUG has the same form as an element of
+`package-autosuggest-database'."
+ (package-install (car pkg-sug))
+ (with-demoted-errors "Failed to enable: %S"
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (when (and (eq major-mode 'fundamental-mode) (buffer-file-name)
+ (package--suggestion-applies-p pkg-sug))
+ (funcall-interactively (or (cadddr pkg-sug) (car pkg-sug))))))))
+
+(defvar package--autosuggest-suggested '()
+ "List of packages that have already been suggested.")
+
+(defun package--autosuggest-after-change-mode ()
+ "Hook function to suggest packages for installation."
+ (when-let ((avail (seq-difference (package--autosuggest-find-candidates)
+ package--autosuggest-suggested))
+ (pkgs (mapconcat #'symbol-name
+ (delete-dups (mapcar #'car avail))
+ ", ")))
+ (pcase package-autosuggest-mode
+ ('always
+ (when (yes-or-no-p (format "Install suggested packages (%s)?" pkg))
+ (mapc #'package--autosuggest-install-and-enable avail)))
+ ('once
+ (when (yes-or-no-p (format "Install suggested packages (%s)?" pkg))
+ (mapc #'package--autosuggest-install-and-enable avail))
+ (setq package--autosuggest-suggested (append avail
package--autosuggest-suggested)))
+ ('message
+ (message
+ (substitute-command-keys
+ (format "Found suggested packages: %s. Install using
\\[package-autosuggest]"
+ pkgs)))))))
+
+(defun package-autosuggest ()
+ "Prompt the user for suggested packages."
+ (interactive)
+ (let* ((avail (or (package--autosuggest-find-candidates)
+ (user-error "No suggestions found")))
+ (pkgs (completing-read-multiple
+ "Install suggested packages: " avail
+ nil t
+ (mapconcat #'symbol-name
+ (delete-dups (mapcar #'car avail))
+ ",")))
+ (choice (concat "\\`" (regexp-opt pkgs) "\\'")))
+ (dolist (ent avail)
+ (when (string-match-p choice (symbol-name (car ent)))
+ (package--autosuggest-install-and-enable ent)))))
+
;;;; Quickstart: precompute activation actions for faster start up.
The documentation is obviously lacking and incomplete, I just wanted to
have a POC to discuss the idea.
I am not sure if the default option 'message is still too aggressive, as
opinions differ on how and who should print messages in the echo area.
- Re: Clojure mode, (continued)
- Re: Clojure mode, Stefan Kangas, 2023/08/29
- Re: Clojure mode, Philip Kaludercic, 2023/08/29
- Re: Clojure mode, Stefan Kangas, 2023/08/29
- Re: Clojure mode, Philip Kaludercic, 2023/08/30
- Re: Clojure mode, Stefan Kangas, 2023/08/30
- Re: Clojure mode, Eli Zaretskii, 2023/08/30
- Re: Clojure mode, Philip Kaludercic, 2023/08/30
- Re: Clojure mode, Eli Zaretskii, 2023/08/30
- Re: Clojure mode, Philip Kaludercic, 2023/08/30
- Re: Clojure mode, Eli Zaretskii, 2023/08/30
- package-autosuggest,
Philip Kaludercic <=
- Re: package-autosuggest, Stefan Monnier, 2023/08/30
- Re: package-autosuggest, Philip Kaludercic, 2023/08/31
- Re: package-autosuggest, Stefan Monnier, 2023/08/31
- Re: package-autosuggest, Eshel Yaron, 2023/08/31
- Re: package-autosuggest, Stefan Monnier, 2023/08/31
- Re: package-autosuggest, Eshel Yaron, 2023/08/31
- Re: package-autosuggest, Stefan Kangas, 2023/08/31
- Re: Clojure mode, Eli Zaretskii, 2023/08/29
- Re: Clojure mode, Richard Stallman, 2023/08/30
- Re: Clojure mode, Gregor Zattler, 2023/08/31