jwiegley / use-package

A use-package declaration for simplifying your .emacs
https://jwiegley.github.io/use-package
GNU General Public License v3.0
4.42k stars 260 forks source link

Completion for use-package macro (e.g., within :custom) #1077

Open leinfink opened 4 months ago

leinfink commented 4 months ago

I would like to have completion-at-point for use-package. In particular, it would be great if there was a way to let emacs know that inside :custom, it should expect variables, not functions, even though point might look as if it was in a funcall position. If not easily fixable, could someone guide me in the correct direction to work on this?

277 apparently tried to do something like this, but it didn't seem to lead anywhere.

montchr commented 4 months ago

I also would like to have improved completion candidates for use-package. I actually switched away from using use-package primarily for this reason. IMHO, calling the underlying functions and macros (e.g. setopt, add-hook) provide a much better sense of discoverability and even (counterintuitively?) save me time and effort because those completions just work. Clearly I rely a lot on completions to help me figure out what I am trying to do :sweat_smile:

I guess a lot of the issue is use-package's extensive use of unquoted lists. But still, even if the lists in :custom, for example, were quoted, you would still get completion candidates for any symbol, not just variables. Callables like setopt and keymap-set offer out-of-the-box completion appropriate to the context, and they don't require everything to be contained in extraneous lists like :custom and :bind.

conao3 commented 4 months ago

Since when, I think Emacs assumes that the :custom symbols are functions, not variables, and makes code jumps. The same issue is happening in leaf and I don't know how to solve this problem. As a work-around, for example, when there is a use-package like this,

(use-package comint
  :custom
  (comint-buffer-maximum-size 20000 “Increase comint buffer size.”)
  (comint-prompt-read-only t “Make the prompt read only.”))
(use-package comint
  :custom
  (a comint-buffer-maximum-size 20000 “Increase comint buffer size.”))
  (comint-prompt-read-only t “Make the prompt read only.”)))

Change it this way, and for comint-buffer-maximum-size, M-. would allow me to jump properly, but it's too bad work-around.

yonta commented 3 months ago

The default capf used in elisp-mode, elisp-completion-at-point, filters completion candidates based on context (variables, functions, ...). The problem is that this filter cannot recognize variables in :custom of use-package.

This is not a complete solution, but I am working around the issue by setting (cape-capf-inside-code #'cape-elisp-symbol) to local variable completion-at-point-function in elisp mode. I distinguish whether a completion candidate is a function or a variable using icon information provided by nerd-icons-corfu. If you are using company, you can achieve the same with company-box.

Here is a part of my init.el and screenshot:

(defun my/elisp-mode-init ()
  "Set completion function to cape"
  (setq-local completion-at-point-functions
              (list (cape-capf-inside-code #'cape-elisp-symbol))))
(add-hook 'emacs-lisp-mode-hook #'my/elisp-mode-init)

image