reddit / emacs

Shouldn't a function called in the body of another ignore the value of `current-prefix-arg`?

graduale · 2022-11-01 03:14
I'm trying to understand the behavior of the variable `current-prefix-arg`. In particular, I'm trying to understand whether if I pass a prefix argument to `func`, and `other-func` is called by `func`, `other-func` should be ignoring that prefix argument. Consider the following four functions: (defun f1 (arg) (interactive "P") (when arg "Non-nil")) (defun f2 (arg) (interactive "P") (when current-prefix-arg "Non-nil")) (defun g1 (arg) (interactive "P") (message "%s, %s" current-prefix-arg (f1 nil))) (defun g2 (arg) (interactive "P") (message "%s, %s" current-prefix-arg (f2 nil))) I would have thought that both `g1` and `g2` would behave the same. But if I call `g1` with the `C-u` prefix key, I get `"(4), nil"`, whereas if I call `g2` with the `C-u` prefix key, I get `"(4), non-nil"`. Is this as it should be? I understand I can bind `current-prefix-arg` to nil before calling `f2`, i.e. I could just call `f2` inside the scope of a `let` expression, binding `current-prefix-arg` to `nil`. But is there a cleaner way to do this? Looking at the manual section on [prefix command arguments](https://www.gnu.org/software/emacs/manual/html_node/elisp/Prefix-Command-Arguments.html) hasn't helped me figure this out, so I'm hoping someone here may be able to help. (I'm not clear on what is meant there by "the *next* editing command. At first I thought `prefix-arg` would be passed on to functions in the scope of another, but `current-prefix-arg` would not; now I'm not sure anymore.)
7890yuiop · 2022-11-01 03:18
`current-prefix-arg` has dynamic scope/extent, so the binding lasts until the end of that dynamic scope. You want to read about dynamic vs lexical binding in the manual. > I would have thought that both g1 and g2 would behave the same. You've explicitly passed `nil` to `f1` so of course it reports `nil` for the value of its `arg`. Note that as you are not calling `f1` or `f2` interactively, their `interactive` specs are not relevant. > I'm not clear on what is meant there by "the next editing command. The next trip around the command loop: `C-h i g (elisp)Command Loop`
graduale · 2022-11-01 12:14
Thanks! I thought if the issue had to do with dynamic vs lexical binding, enabling lexical binding in the buffer would've mad a difference, but it hadn't, so I jumped to the conclusion that this wasn't it. My bad. [**EDIT**: I now see that `(special-variable-p 'current-prefix-arg)` returns `t`, which implies(right?) that `current-prefix-arg` will take dynamic scope no matter what.] So am I right in thinking that in e.g. this function: (defun func () (interactive "P") (message "%s" current-prefix-arg)) `current-prefix-arg` is only bound when called interactively? (I also tried calling `f2` using `call-interactively` instead, but that didn't make a difference.) Will look at the nodes you point to. Thanks again.
7890yuiop · 2022-11-01 12:53
`C-u` and the like are bound to commands which manipulate the value of `prefix-arg` (maybe repeatedly), and then `current-prefix-arg` usually gets set by `command-execute` based on whatever `prefix-arg` was set to. Commands which manipulate the prefix arg have some special handling associated with that, but they're all just commands -- have a poke around the code and you'll get the idea.