joaotavora / yasnippet

A template system for Emacs
http://joaotavora.github.io/yasnippet/
2.81k stars 311 forks source link

[Question] How not to be shown a list of candidates when a single snippet has been found? #1199

Closed rodrigomorales1 closed 6 months ago

rodrigomorales1 commented 6 months ago

I am using the default value of yas-prompt-functions which is (yas-dropdown-prompt yas-completing-prompt yas-maybe-ido-prompt yas-no-prompt).

Whenever I insert a snippet, the prompt Choose a snippet is shown in the minibuffer. This prompt is shown even when the inserted keys correspond to a single snippet, this is redundant.

A workaround to that problem is setting (setq yas-prompt-functions '(yas-no-prompt)). However, this causes yas-insert-snippet to insert a snippet immediately (i.e. it doesn't show the completion list anymore.) I sometimes want to insert snippets through yas-insert-snippet, but at the same time I want that the completion list not to be shown when there's a single candidate. How to accomplish this behavior?

System information

rodrigomorales1 commented 6 months ago

It seems that the problem has to do with my personal configuration.

I created a simple snippets in the directory ~/.config/emacs/snippets

$ find ~/.config/emacs/snippets
/home/rodrigo/.config/emacs/snippets
/home/rodrigo/.config/emacs/snippets/org-mode
/home/rodrigo/.config/emacs/snippets/org-mode/foo
/home/rodrigo/.config/emacs/snippets/org-mode/bar
$ find ~/.config/emacs/snippets -type f | while read -r line; do echo "-> $line"; cat "$line"; done
-> /home/rodrigo/.config/emacs/snippets/org-mode/foo
# -*- mode: snippet -*-
# name: foo
# key: foo
# --
foofoo-> /home/rodrigo/.config/emacs/snippets/org-mode/bar
# -*- mode: snippet -*-
# name: bar
# key: bar
# --
barbar%

I started emacs -Q and evaluated

(require 'yasnippet)
(yas-global-mode)
(find-file "/tmp/a.org")

I wrote foo and pressed C-i, the candidate list was not shown and the text changed to foofoo. I wrote bar and pressed C-i, the candidate list was not shown and the text changed to barbar. I then called yas-insert-snippet and the candidate list was shown.

karta0807913 commented 6 months ago

did you try the function yas-expand? I think this function won't show the list by default.

rodrigomorales1 commented 6 months ago

I investigated more on this and I think I have found the root cause: Snippets that belong to the directory fundamental-mode are found twice. It seems that this issue has been fixed in e23a80177a9c434174ed8a5955c296d7828a1060 so I just need to update.

The following sections explain how I found this out.

Experiment 1

I created the following snippets

find ~/.config/emacs/snippets -type f | while read -r line; do echo "-> $line"; cat "$line"; done
-> /home/rodrigo/.config/emacs/snippets/fundamental-mode/foo
# -*- mode: snippet -*-
# name: name foo
# key: foo
# --
this is snippet foo
-> /home/rodrigo/.config/emacs/snippets/fundamental-mode/bar
# -*- mode: snippet -*-
# name: name bar
# key: bar
# --
this is snippet bar

I launched emacs -Q and evaluated the following sexps (see results of evaluation in M-x ielm in the second code block below)

(progn
  (require 'yasnippet)
  (setq yas-snippet-dirs '("/home/rodrigo/.config/emacs/snippets"))
  (yas-recompile-all)
  (yas-reload-all)
  (yas-global-mode)
  (with-current-buffer (find-file-noselect "/tmp/a")
    (insert "foo")
    (yas--templates-for-key-at-point)))
*** Welcome to IELM ***  Type (describe-mode) or press C-h m for help.
ELISP> (progn
  (require 'yasnippet)
  (setq yas-snippet-dirs '("/home/rodrigo/.config/emacs/snippets"))
  (yas-recompile-all)
  (yas-reload-all)
  (yas-global-mode)
  (with-current-buffer (find-file-noselect "/tmp/a")
    (insert "foo")
    (yas--templates-for-key-at-point)))
((("name foo" . #s(yas--template :key "foo" :content "this is snippet foo
" :name "name foo" :condition nil :expand-env nil :load-file "/home/rodrigo/.config/emacs/snippets/fundamental-mode/foo" :save-file nil :keybinding nil :uuid "name foo" :menu-binding-pair
((menu-item "name foo"
        (lambda nil
          (interactive)
          (yas--expand-or-visit-from-menu 'fundamental-mode "name foo"))
        :keys "foo =>"))
:group nil :perm-group nil :table #s(yas--table :name "fundamental-mode" :hash #<hash-table equal 2/65 0x909893> :uuidhash #<hash-table equal 2/65 0xa6a3b1> :parents nil :direct-keymap
                         (keymap))))
  ("name foo" . #s(yas--template :key "foo" :content "this is snippet foo
" :name "name foo" :condition nil :expand-env nil :load-file "/home/rodrigo/.config/emacs/snippets/fundamental-mode/foo" :save-file nil :keybinding nil :uuid "name foo" :menu-binding-pair
((menu-item "name foo"
        (lambda nil
          (interactive)
          (yas--expand-or-visit-from-menu 'fundamental-mode "name foo"))
        :keys "foo =>"))
:group nil :perm-group nil :table #s(yas--table :name "fundamental-mode" :hash #<hash-table equal 2/65 0x909893> :uuidhash #<hash-table equal 2/65 0xa6a3b1> :parents nil :direct-keymap
                         (keymap)))))
 1 4)

ELISP> 

Note that two snippets were found.

Experiment 2

I removed all snippets from ~/.config/emacs/snippets and I created some simple snippets in the directory python-mode.

find ~/.config/emacs/snippets -type f | while read -r line; do echo "-> $line"; cat "$line"; done
-> /home/rodrigo/.config/emacs/snippets/python-mode/foo
# -*- mode: snippet -*-
# name: name foo
# key: foo
# --
this is snippet foo
-> /home/rodrigo/.config/emacs/snippets/python-mode/bar
# -*- mode: snippet -*-
# name: name bar
# key: bar
# --
this is snippet bar

I launched emacs -Q and evaluated the following sexps (see results of evaluation in M-x ielm in the second code block below)

(progn
  (require 'yasnippet)
  (setq yas-snippet-dirs '("/home/rodrigo/.config/emacs/snippets"))
  (yas-recompile-all)
  (yas-reload-all)
  (yas-global-mode)
  (with-current-buffer (find-file-noselect "/tmp/a.py")
    (insert "foo")
    (yas--templates-for-key-at-point)))
*** Welcome to IELM ***  Type (describe-mode) or press C-h m for help.
ELISP> (progn
  (require 'yasnippet)
  (setq yas-snippet-dirs '("/home/rodrigo/.config/emacs/snippets"))
  (yas-recompile-all)
  (yas-reload-all)
  (yas-global-mode)
  (with-current-buffer (find-file-noselect "/tmp/main.py")
    (insert "foo")
    (yas--templates-for-key-at-point)))
((("name foo" . #s(yas--template :key "foo" :content "this is snippet foo
" :name "name foo" :condition nil :expand-env nil :load-file "/home/rodrigo/.config/emacs/snippets/python-mode/foo" :save-file nil :keybinding nil :uuid "name foo" :menu-binding-pair
((menu-item "name foo"
        (lambda nil
          (interactive)
          (yas--expand-or-visit-from-menu 'python-mode "name foo"))
        :keys "foo =>"))
:group nil :perm-group nil :table #s(yas--table :name "python-mode" :hash #<hash-table equal 2/65 0x7e3393> :uuidhash #<hash-table equal 2/65 0x7e35c1> :parents nil :direct-keymap
                         (keymap)))))
 1 4)

ELISP> 

Note that a single snippet was found.

monnier commented 6 months ago

I investigated more on this and I think I have found the root cause: Snippets that belong to the directory fundamental-mode are found twice. It seems that this issue has been fixed in e23a80177a9c434174ed8a5955c296d7828a1060 so I just need to update.

Thanks for tracking it down. If the update doesn't fix your problem, let us know.

rodrigomorales1 commented 6 months ago

Updating solved the problem.

monnier commented 6 months ago

Updating solved the problem.

Thanks for the confirmation!