Simulating `C-u` args to lambda-wrapped functions

Table of Contents

I build hydras for common functions in my use-pattern; sometimes it’s the C-u version that I want in my hydra. Usually this is easily done by passing a '(4) to the function. However, I have one fn that is failing at this:

  ("<f11>" (lambda () (interactive) (flyspell-correct-wrapper '(4))) "spell correct")
;; eval: Wrong number of arguments: (0 . 0), 1

The reason for this failure is that it turns out emacs has two ways of calling fns with prefix args. Interactively, both of these ways are done by pressing C-u before you call the function. When calling them in code, though, they behave differently: the reason most of my fns work with the wrapper above is because those fns take an optional numeric arg and check to see if it’s '(4) (that’s one press of C-u), '(16) (two presses), etc. The flyspell-correct-wrapper function, though, is not using this numeric-arg method; instead, it is a 0-arg method which checks the value of a global variable current-prefix-arg that is set upon function invocation – something not set when you call the fn through a function. Yes, I know – global variables instead of args YUCK! But it is what it is (props to anyone who can give a good reason for this yuckiness). Here’s how we work around it:

   (defun tsa/correct-all () 
     (interactive)
     (let ((current-prefix-arg '(4))) ;; set the global in dynamic scope
          (call-interactively 'flyspell-correct-wrapper)))

;;; ... and then our hydra lines becomes:
("<f11>" tsa/correct-all "spell correct")

EDIT As pointed out in the comments, you can implement emacs’ idiomatic dynamic scope instead of tweaking globals by using a let instead of a setq, which I’ve updated the example with above.

Tory Anderson avatar
Tory Anderson
Full-time Web App Engineer, Digital Humanist, Researcher, Computer Psychologist