minad / cape

🦸cape.el - Completion At Point Extensions
GNU General Public License v3.0
584 stars 20 forks source link

cape-abbrev parent tables #19

Closed tpeacock19 closed 2 years ago

tpeacock19 commented 2 years ago

I've been working on porting over yasnippet-snippets to Skempo and have noticed that cape-abbrev currently does not pick up from any parent tables. I made the below changes to make that work for me. If you have any interest to include it. It also amends the annotation function (which never worked for me anyway) to show which abbrev table the candidate comes from.

diff --git a/cape.el b/cape.el
index 63fa989..305cbef 100644
--- a/cape.el
+++ b/cape.el
@@ -683,16 +683,20 @@ is nil the function acts like a capf." method method)

 (defun cape--abbrev-list ()
   "Abbreviation list."
-  (delete "" (nconc (all-completions "" global-abbrev-table)
-                    (all-completions "" local-abbrev-table))))
+  (delete "" (apply #'append
+                    (mapcar (lambda (table)
+                              (all-completions "" table))
+                            (nreverse (abbrev--suggest-get-active-tables-including-parents))))))

 (defun cape--abbrev-annotation (abbrev)
   "Annotate ABBREV with expansion."
   (concat " "
           (truncate-string-to-width
-           (symbol-value
-            (or (abbrev--symbol abbrev local-abbrev-table)
-                (abbrev--symbol abbrev global-abbrev-table)))
+           (cl-some (lambda (table)
+                      (when (abbrev--symbol abbrev table)
+                        (string-remove-suffix "-abbrev-table"
+                                              (symbol-name (abbrev-table-name table)))))
+                    (nreverse (abbrev--suggest-get-active-tables-including-parents)))
            30 0 nil t)))

 (defun cape--abbrev-exit (_str status)
minad commented 2 years ago

Thanks! I added the fix in a slightly modified form since we cannot rely on the Emacs 28 function just yet.

I also stumbled over the reddit discussion regarding Corfu/Yasnippet/Tempo/Skeleton/Skempo: From my perspective Tempo is a pretty good system, even if it is fairly basic. I made a slightly modernized Tempo implementation in https://github.com/minad/tempel. Originally I based my small package on Tempo, but I dropped the dependency after a while. I wanted to make it a little more fancy in the style of Tempo-Snippet, where you can edit multiple fields at the same time directly in the buffer with overlays. The package is still tiny and it supports the same syntactic elements as Tempo. Then one doesn't have to take the detour via abbrev. To be honest the abbrev mechanism feels legacy to me - the way it is implemented with obarrays instead of hashtables etc and parts implemented in C.

tpeacock19 commented 2 years ago

Ah right, I had not checked that it was an Emacs 28 only function. However there is a typo here:

diff --git a/cape.el b/cape.el
index a0b6911..68426ac 100644
--- a/cape.el
+++ b/cape.el
@@ -686,7 +686,7 @@ is nil the function acts like a capf." method method)
   ;; Emacs 28: See abbrev--suggest-get-active-tables-including-parents.
   (let ((tables (abbrev--active-tables)))
     (append tables (cl-loop for table in tables
-                            append (abbrev-table-get table :parent)))))
+                            append (abbrev-table-get table :parents)))))

 (defun cape--abbrev-list ()
   "Abbreviation list."

Also, I'm still unsure what your annotation function is supposed to display. It never returns anything for me.

I made a slightly modernized Tempo implementation in https://github.com/minad/tempel

Perhaps I will make the bulk of the templates for this then. I have some free time over this week and am looking to stay busy. Do you think it'd be useful to have a default (or suggested) library of templates? I may have another question specific to tempel re inheritance but i'll open an issue there after I explore for a bit.

minad commented 2 years ago

Ah right, I had not checked that it was an Emacs 28 only function. However there is a typo here:

Thanks. Fixed.

Also, I'm still unsure what your annotation function is supposed to display. It never returns anything for me.

It displays the symbol value. For example if I add an abbreviation with C-x a + then the value is displayed as annotation. I am not very familiar with the abbrev mechanisms and its weird symbol indirections. Maybe you use it in another way and set the symbol-function instead? The annotation function could check both symbol-value and symbol-function or fall back to the abbrev table name as you proposed.

Perhaps I will make the bulk of the templates for this then. I have some free time over this week and am looking to stay busy. Do you think it'd be useful to have a default (or suggested) library of templates?

Yes, this will be useful! Maybe one could also simply convert a bulk of the existing yasnippets. However I am not sure of the value of all these trivial snippets like pt -> (point), since we also have the capf completion mechanism.

I may have another question specific to tempel re inheritance but i'll open an issue there after I explore for a bit.

Please go ahead. But note that Tempel is a very basic package right now. It didn't see a lot of testing. One could consider extending the Tempo syntax slightly or even invent a special syntax entirely. But there is probably some value in Tempo interop at least such that Tempo templates can be used in Tempel. I haven't found snippet libraries however. I assume the only substantial ones in existence target yasnippet.

tpeacock19 commented 2 years ago

Maybe you use it in another way and set the symbol-function instead?

Yep, that was it. I had to wrap the cl-loop in (symbol-value (symbol-function.... Though its not very pretty with snippets that are longer than 30 characters. I do think it'd be useful to have the parent as a fallback. But either way if i choose to stick with Skempo/Abbrev I can easily modify this

Yes, this will be useful! Maybe one could also simply convert a bulk of the existing yasnippets.

I'm going to work my way through the yasnippet snippets and try to distill the most useful/impactful ones and I'll let you know of any progress made.