Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

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

Open
wants to merge 5 commits into from

2 participants

@DarwinAwardWinner

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.

@DarwinAwardWinner

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

@DarwinAwardWinner

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.

@DarwinAwardWinner

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.

@DarwinAwardWinner

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.

@DarwinAwardWinner

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.

@DarwinAwardWinner DarwinAwardWinner Update smex after function calls that are likely to define new commands. aa7dd29
@DarwinAwardWinner DarwinAwardWinner 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
@DarwinAwardWinner DarwinAwardWinner Update smex after "eval-region" 655bece
@DarwinAwardWinner DarwinAwardWinner 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
@DarwinAwardWinner DarwinAwardWinner 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
Commits on Sep 4, 2012
  1. @DarwinAwardWinner
  2. @DarwinAwardWinner

    Code cleanups

    DarwinAwardWinner authored
    * 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.
  3. @DarwinAwardWinner
  4. @DarwinAwardWinner

    Ensure that advice never gives errors

    DarwinAwardWinner authored
    Since this advice is attached to important emacs functions, it should
    prefer to just do nothing rather than throw an error.
  5. @DarwinAwardWinner

    Update smex after "eval-expression"

    DarwinAwardWinner authored
    This is normally bound to "M-S-:".
This page is out of date. Refresh to see the latest.
Showing with 24 additions and 5 deletions.
  1. +24 −5 smex.el
View
29 smex.el
@@ -89,9 +89,7 @@ Set this to nil to disable fuzzy matching."
(smex-initialize))
(if (smex-already-running)
(smex-update-and-rerun)
- (and smex-auto-update
- (smex-detect-new-commands)
- (smex-update))
+ (and smex-auto-update (smex-update-if-needed))
(smex-read-and-run smex-ido-cache)))
(defsubst smex-already-running ()
@@ -217,11 +215,13 @@ Set this to nil to disable fuzzy matching."
(unless (= i smex-command-count)
(setq smex-command-count i))))
+(defun smex-update-if-needed ()
+ (if (smex-detect-new-commands) (smex-update)))
+
(defun smex-auto-update (&optional idle-time)
"Update Smex when Emacs has been idle for IDLE-TIME."
(unless idle-time (setq idle-time 60))
- (run-with-idle-timer idle-time t
- '(lambda () (if (smex-detect-new-commands) (smex-update)))))
+ (run-with-idle-timer idle-time t 'smex-update-if-needed))
(defun smex-detect-legacy-save-file ()
"The default value of `smex-save-file' was changed in between releases.
@@ -488,5 +488,24 @@ sorted by frequency of use."
(set-buffer-modified-p nil)
(goto-char (point-min))))
+(defmacro smex-auto-update-after (&rest functions)
+ "Advise each of FUNCTIONS to execute smex-update upon completion."
+ (cons
+ 'progn
+ (mapcar (lambda (fun)
+ `(defadvice ,fun (after smex-update activate)
+ "Run smex-update upon completion"
+ (ignore-errors
+ (when (bound-and-true-p smex-auto-update)
+ (smex-update-if-needed)))))
+ ;; Defining advice on `eval' causes infinite recursion, so
+ ;; don't allow that.
+ (delete-if (apply-partially 'equal 'eval)
+ functions))))
+
+;; If you call `smex-update' after every invocation of just these few
+;; functions, you almost never need any other updates.
+(smex-auto-update-after load eval-last-sexp eval-buffer eval-region eval-expression)
+
(provide 'smex)
;;; smex.el ends here
Something went wrong with that request. Please try again.