Skip to content
This repository

Update smex after function calls that are likely to define new commands. #4

Open
wants to merge 5 commits into from

2 participants

Ryan Thompson nonsequitur
Ryan Thompson

I got tired of periodic smex auto updates, especially since every time I loaded a file or defined a new function, I would have to manually update smex anyway, since I immediately wanted access to the new functions that I just loaded. So I figured out which functions are involved in the definitions of vast majority of commands, and I wrapped them in advice that updates smex immediately after them. Now when you load a file or press C-j in *scratch*, your new stuff is available with no waiting.

Ryan Thompson

For general consumption, it might be best to refactor this into a modifiable custom variable.

Ryan Thompson

Do you have any interest in merging this? I've been using it for a long time (at least a year), and it has completely eliminated the need for periodic auto-updates.

Ryan Thompson

By the way, the two commits in this pull request are completely independent. I probably should have submitted them separately. So feel free to cherry-pick just one or the other.

Ryan Thompson

I just fixed a missing paren on this pull request and rebased on top of your latest master branch.

nonsequitur
Owner

Thanks! In the early stages, I did some experiments using exact same approach.
It turned out to not work reliably enough for me. For example, commands defined via fset won't get caught; and fset can't be advised.
I'll leave this open - quickly capturing new commands is still an unsolved problem.

Ryan Thompson

With the code in this pull request, I've never run into a case where a new command was defined and smex didn't immediately pick it up. Yes, calls fset (and defun, and defmacro, etc.) will be missed, but that doesn't matter because it's nearly impossible to call any of those without using one of the functions listed in:

(smex-auto-update-after load eval-last-sexp eval-buffer eval-region eval-expression)

(Yes, I just added eval-expression to that list two seconds ago.) So in practice the only time any new functions will be missed is if you were deliberately trying to evade the auto-updating by using some obscure method of evaluating elisp.

Can you provide a method of defining a function that doesn't use one of the five functions listed above? I can't think of any.

Ryan Thompson Update smex after function calls that are likely to define new commands. aa7dd29
Ryan Thompson Code cleanups
* Add new function `smex-update-if-needed` and use it where
  appropriate

* Rename `update-smex-after` to `smex-auto-update-after`

* Advice defined by `smex-auto-update-after` now only works when
  `smex-auto-update' is set to t.

* Other minor cleanups

These are all in one commit because they all affect overlapping lines,
so separating them out would have been quite difficult.
f156f90
Ryan Thompson Update smex after "eval-region" 655bece
Ryan Thompson Ensure that advice never gives errors
Since this advice is attached to important emacs functions, it should
prefer to just do nothing rather than throw an error.
4593f66
Ryan Thompson Update smex after "eval-expression"
This is normally bound to "M-S-:".
146403c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 5 unique commits by 1 author.

Sep 03, 2012
Ryan Thompson Update smex after function calls that are likely to define new commands. aa7dd29
Ryan Thompson Code cleanups
* Add new function `smex-update-if-needed` and use it where
  appropriate

* Rename `update-smex-after` to `smex-auto-update-after`

* Advice defined by `smex-auto-update-after` now only works when
  `smex-auto-update' is set to t.

* Other minor cleanups

These are all in one commit because they all affect overlapping lines,
so separating them out would have been quite difficult.
f156f90
Ryan Thompson Update smex after "eval-region" 655bece
Ryan Thompson Ensure that advice never gives errors
Since this advice is attached to important emacs functions, it should
prefer to just do nothing rather than throw an error.
4593f66
Ryan Thompson Update smex after "eval-expression"
This is normally bound to "M-S-:".
146403c
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 24 additions and 5 deletions. Show diff stats Hide diff stats

  1. 29  smex.el
29  smex.el
@@ -89,9 +89,7 @@ Set this to nil to disable fuzzy matching."
89 89
     (smex-initialize))
90 90
   (if (smex-already-running)
91 91
       (smex-update-and-rerun)
92  
-    (and smex-auto-update
93  
-         (smex-detect-new-commands)
94  
-         (smex-update))
  92
+    (and smex-auto-update (smex-update-if-needed))
95 93
     (smex-read-and-run smex-ido-cache)))
96 94
 
97 95
 (defsubst smex-already-running ()
@@ -217,11 +215,13 @@ Set this to nil to disable fuzzy matching."
217 215
     (unless (= i smex-command-count)
218 216
       (setq smex-command-count i))))
219 217
 
  218
+(defun smex-update-if-needed ()
  219
+  (if (smex-detect-new-commands) (smex-update)))
  220
+
220 221
 (defun smex-auto-update (&optional idle-time)
221 222
   "Update Smex when Emacs has been idle for IDLE-TIME."
222 223
   (unless idle-time (setq idle-time 60))
223  
-  (run-with-idle-timer idle-time t
224  
-                       '(lambda () (if (smex-detect-new-commands) (smex-update)))))
  224
+  (run-with-idle-timer idle-time t 'smex-update-if-needed))
225 225
 
226 226
 (defun smex-detect-legacy-save-file ()
227 227
   "The default value of `smex-save-file' was changed in between releases.
@@ -488,5 +488,24 @@ sorted by frequency of use."
488 488
     (set-buffer-modified-p nil)
489 489
     (goto-char (point-min))))
490 490
 
  491
+(defmacro smex-auto-update-after (&rest functions)
  492
+  "Advise each of FUNCTIONS to execute smex-update upon completion."
  493
+  (cons
  494
+   'progn
  495
+   (mapcar (lambda (fun)
  496
+             `(defadvice ,fun (after smex-update activate)
  497
+                "Run smex-update upon completion"
  498
+                (ignore-errors
  499
+                  (when (bound-and-true-p smex-auto-update)
  500
+                    (smex-update-if-needed)))))
  501
+           ;; Defining advice on `eval' causes infinite recursion, so
  502
+           ;; don't allow that.
  503
+           (delete-if (apply-partially 'equal 'eval)
  504
+                      functions))))
  505
+
  506
+;; If you call `smex-update' after every invocation of just these few
  507
+;; functions, you almost never need any other updates.
  508
+(smex-auto-update-after load eval-last-sexp eval-buffer eval-region eval-expression)
  509
+
491 510
 (provide 'smex)
492 511
 ;;; smex.el ends here
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.