Where does this Emacs Lisp hook function get its argument from? - emacs

I'm just learning emacs and came across a configuration that demonstrates quite a bit of the functionality I want in my own configuration. It uses init.el as an entry point to an org file that handles the bulk of the configuration with extensive documentation. I am confused by the following function:
(put 'after-save-hook 'safe-local-variable
(lambda (value) (equal value '(org-babel-tangle t))))
What I think I understand is that this puts the value of the lambda expression into the property list of after-save-hook under the property name safe-local-variable, and that a value is safe if, when passed to the safe-local-variable-p function it returns a non-nil value. This lambda then appears to do an equality comparison between value and the list (org-babel-tangle t), so presumably this means that value is safe only when it's equal to the list (org-babel-tangle t)?
What I am having trouble understanding is twofold. First, where is the lambda getting value from? Second, what is this all actually doing? Neither the documentation I could find on after-save-hook nor org-babel-tangle clarified this for me. The author's comments say "Mark safe variables early so that tangling won't break," but I still don't get it.

The anonymous function with argument value gets its arg from the value of after-save-hook.
after-save-hook is a variable. Its value is a list of hooks.
This code puts the anonymous function as the safe-local-variable property value of symbol after-save-hook, so that when after-save-hook is processed as to see if it is a safe local variable, that function is called. The function is called on the current value of the variable, after-save-hook.
See the Elisp manual, node File Local Variables.

The reason for this is that the file DESKTOP.org starts with this line:
# -*- after-save-hook: (org-babel-tangle t); -*-
That is, when you open that file in Emacs, the local value of after-save-hook becomes (org-babel-tangle t). So whenever you save that file, it's going to call the function org-babel-tangle without any arguments, in order to generate a few shell scripts, e.g. scripts/screenshot.region.sh. The value t in a hook variable means that after calling all the functions in the local value of the hook variable, run-hooks is going to look at the global value of after-save-hook and call any functions listed there as well.
Obviously, allowing any file to specify arbitrary Lisp code to be run would be a security hole equaled only by Microsoft Word macros, so by default file-local settings for risky variables are ignored. Since we know this particular value is safe,* we use the safe-local-variable trick you're asking about. As per the documentation:
You can specify safe values for a variable with a
‘safe-local-variable’ property. The property has to be a function of
one argument; any value is safe if the function returns non-‘nil’ given
that value.
So that's what we have here:
(lambda (value) (equal value '(org-babel-tangle t)))
It is a function that takes one argument, and checks that the argument is equal to the specific value we want to allow. safe-local-variable-p is going to call this function on the specified file-local value, and only allow it if the function returns non-nil. Thus, value is going to be the value that is about to be assigned to after-save-hook. We can see that in action in M-x ielm:
*** Welcome to IELM *** Type (describe-mode) for help.
ELISP> (setq my-function (lambda (value) (equal value '(org-babel-tangle t))))
(lambda
(value)
(equal value
'(org-babel-tangle t)))
ELISP> (funcall my-function '(org-babel-tangle t))
t
ELISP> (funcall my-function 'something-else)
nil
* Is this safe, though?... If an attacker can get you to download a specially crafted file and run org-babel-tangle on it, they can overwrite arbitrary files in the file system using the privileges of your user. It's not what's happening in this case, just something to be aware of.

Related

Emacs customizable variable with dynamic set of possible values

I want to define a customizable variable in Emacs Lisp whose possible values are restricted to a certain list, but the list should be dynamically created by a function each time the user opens the customization buffer. Thus, something similar to
(defcustom my-variable
[...]
:type '(choice [...])
but choice seems to support only a static set of values. What I want is something like
(defcustom my-variable
[...]
:type '(choice my-function)
where my-function is a function that returns the list of possible values, and is evaluated each time the customization buffer is created.
Is that possible?
(defun my-function ()
"..."
'(42 "a" b (x y) "c"))
(defcustom foo 42
"..."
:group 'convenience
:type '(restricted-sexp
:match-alternatives ((lambda (x)
(car (member x (my-function)))))))
Function my-function could provide a different list of possibilities each time (or whenever, based on whatever).
This simple example doesn't provide much in the way of feedback (and no doc strings).
But the idea is this: restricted-sexp is the most general defstruct type-defining construct. This is what the Elisp manual, node Composite Types says:
(restricted-sexp :match-alternatives CRITERIA)
This is the most general composite type construct. The value may
be any Lisp object that satisfies one of CRITERIA. CRITERIA should
be a list, and each element should be one of these possibilities:
A predicate—that is, a function of one argument that returns
either nil or non-nil according to the argument. Using a
predicate in the list says that objects for which the
predicate returns non-nil are acceptable.
A quoted constant—that is, 'OBJECT. This sort of element in
the list says that OBJECT itself is an acceptable value.
For example,
(restricted-sexp :match-alternatives
(integerp 't 'nil))
allows integers, t and nil as legitimate values.
The customization buffer shows all legitimate values using their
read syntax, and the user edits them textually.
In the example I gave, the list of CRITERIA is a singleton, with just this function:
(lambda (x) (car (member x (my-function))))
That function ensures that the value you use for the option is a member of the list that function my-function returns. (And it makes the value be the car of what member returns, i.e., the particular member of the list that the user enters.
When using M-x customize-option you won't be able to set a new value if it isn't one of the values returned by my-function.
Instead of seeing feedback that the value was set to what you entered, you continue to see this help text:
EDITED, shown value does not take effect until you set or save it.
If you provide a valid value then you get confirmation that the value was set.
Admittedly, what you might really want is to provide for completion etc. in the editing field. For that, you would need to use/define an appropriate widget, because Customize, out of the box, provides for completion only for a limited set of defcustom type constructs (files, colors, etc.). You can see which ones by searching for completion starting in node Simple Types.
restricted-sexp is really a wonderful thing. It should be improved by Emacs to be more useful. But even as it is it should be used more, to provide more-specific type checking. Too many users defining defcustoms are a bit lazy, IMO, not bothering to provide a specific type definition even when that might be as simple as using choice. (Too many just use a type of sexp.)
I found a solution: I defined my-variable with type choice and only one default entry, then I wrote a function that updates the choice entries dynamically, and added that function to 'Custom-mode-hook. This hook is called each time Custom mode is entered. Thus, whenever the user is about to customize my-variable, the choice entries are updated before. Here is a sketch of code:
(defcustom my-variable
"None"
:type '(choice (const :tag "None" "None")))
(defun my-function ()
;; Function that provides the possible values of my-variable
)
(defun my-update-variable-allowed-values ()
(let* ( (choices '((const :tag "None" "None"))) )
(dolist (val (my-function))
(setq choices (cons (list 'const ':tag val val) choices)))
(setq choices (cons 'choice choices))
(put 'my-variable 'custom-type choices)))
(add-hook 'Custom-mode-hook 'my-update-variable-allowed-values)

What is the difference between using "setq" or not to set an Emacs setting?

Very simple question but confuse me for some time:
(setq visible-bell t)
and
(visible-bell t)
both seem work.
But
(desktop-save-mode 1)
works, while
(setq desktop-save-mode 1)
not.
May I ask why is this?
They're different because they're different :)
(setq visible-bell t)
is assigning the value t to a variable named visible-bell.
(visible-bell t)
is calling a function1 named visible-bell (and passing the value t as a parameter).
(Although FYI there is no visible-bell function by default in current versions of Emacs, so it's not obvious to me that this is actually working the way you think? However, assuming for the moment that you do indeed have such a function...)
Emacs Lisp is a 'Lisp-2' meaning it has separate name spaces for variables and functions, and therefore you can -- and commonly do -- have a variable and a function with the same name. Which one is being referred to is always implicit in the context of the code (e.g. setq always refers to a variable).
In short, the two pieces of code are doing very different things. This doesn't mean they couldn't have an equivalent effect (e.g. the function might simply set the value of the variable); but whether or not that's actually the case is entirely up to the definition of the function.
1 In fact the first line of code is also calling a function2: it's calling setq and passing it two parameters visible-bell and t, and setq then sets the value in accordance with its parameters. Hopefully you're now starting to see how lisp syntax works?
2 Strictly speaking, setq is actually a "special form" rather than a function, and special forms are closer to macros than to functions; but these distinctions are not important for this Q&A.
Others have told you the basic points about what setq does and about variables versus functions.
Wrt visible-bell itself:
There is no function visible-bell delivered with Emacs, in any Emacs version I know of, and there never has been. (I've checked back through Emacs 20, and by memory I believe the same was true from the beginning. There is only the variable visible-bell.
So as #phils suggested, is not clear that what you said is true: "both seem to work". Unless some extra code you are loading defines a function of that name (and then there is no way for us to comment on it, not having it to see), evaluating (visible-bell t) raises an undefined (void) function error.
Variable visible-bell is not just a variable. It is a user option, and it has been, again, since at least Emacs 20.
You should not, in general, just use setq to change the value of a user option. In many cases you won't get into trouble if you do that, but sometimes you will, and it is not a good habit to get into.
setq does not perform any special initialization or updating actions that might be appropriate for a given user option. It is not intended for user options. Or rather, user options are not intended for setq - they can be more complex than what setq can offer.
What you should use instead of setq is Customize. Either interactively (M-x customize-option RET visible-bell RET, or C-h v RET visible-bell RET followed by clicking the customize link) or using Lisp code in your init file.
If you use Lisp code then use one of these functions (not setq):
customize-set-variable
customize-set-value
custom-set-variables
Use C-h f followed by each of those function names, to see what (minor) differences there are.
There are 3 issues here.
In Emacs Lisp, the same symbol can be both variable and function.
in the case of desktop-save-mode, it's a function but also a variable.
Because it's a function, so you can call
(desktop-save-mode 1)
Because it's a variable, so you set value to it
(setq desktop-save-mode t)
You can define your own function and also a variable of the same name to test it.
Note: exactly what a function's arguments should be or what the value of a variable makes sense depends on the function or variable.
Now, a second issue. In general, for function (commands) to activate a minor mode, the convention is that a positive integer should mean to turn it on, and otherwise turn off.
Also, for command to activate a minor mode, typically there's a variable of the same name, with value of t or nil, to indicate if the mode is on.
Now, there's third issue. For command to activate the mode, before emacs 24 or so, by convention, if no arg is given, the command toggle current state.
Because all of the above, the issue is confusing. You might see in init things like this:
(desktop-save-mode 1) ; correct. To turn on.
(desktop-save-mode) ; Confusing. Should take value 1 to turn on. Usually works because by default it's off.
(desktop-save-mode t) ; wrong. Take value of positive integer to turn on.
(desktop-save-mode nil) ; Confusing. Value should be integer
(setq desktop-save-mode t) ; wrong. Shoud call function instead
(setq desktop-save-mode nil) ; wrong. Shoud call function instead
(setq desktop-save-mode 1) ; wrong. Shoud call function instead. Besides, only t and nil make sense
So, there's a lot confusion. In emacs 24 (or 23.x), the convention changed so that, if it receives no value, it will turn on, if called in elisp code. (when called interactively as command, it toggles.)
In the end, always call describe-function or describe-variable to read the doc.
Well setq (which is "set" with an auto-quoting feature) is used in assigning a value to a variable. In this example, it's obviously not required because as you mentioned, omitting it works for the first set of examples.
Basically, visible-bell is a variable, and you assign it the value "t" to enable visible bells.
However, desktop-save-mode is an interactive function, so you don't use setq to assign it a value, you call it with parameters.
One good thing to do when you're not sure what something is, is to use the built-in help function:
C-h v visible-bell RET
This will return the information for visible bell -- notice the "v" in the command is because it's a variable. If you wanted to search for information on a function, you would do this:
C-h f desktop-save-mode RET
Incidentally in this case, desktop-save-mode is also a variable, but it's a read-only variable to determine whether or not desktop-save-mode is enabled, so trying to alter it will not work.

Why a parameter of an Emacs lisp function is not evaluated?

I want to define a list of accumulators with Emacs Lisp and write the following code, but I got a error saying that initV is a void variable. It seems initV is not evaluated in the function define-accum. Where is I make a mistake? (I just want to know why although I know there is other ways to reach my target.)
(defun define-accum (name initV)
(defalias name (lambda (v) (+ v initV))))
(setq accums '((myadd1 . 1)
(myadd2 . 2)))
(dolist (a accums)
(define-accum (car a) (cdr a)))
(message "result = %d" (+ (myadd1 1) (myadd2 1)))
You need to use backquotes properly. This would work for you, for instance:
(defun define-accum (name initV)
(defalias name `(lambda (v) (+ v ,initV))))
See here for an explanation
Apart from using backquotes, you can activate lexical binding (if you're using Emacs 24 or newer). For example, if I put your code in a .el file and put this on the first line:
;; -*- lexical-binding: t -*-
then I get the output:
result = 5
This works because the lambda function in define-accum will reference the initV in the environment where it's being defined (thus picking the variable in the argument list), and create a closure over this variable. With dynamic binding (the default), the function would look for initV in the environment where it's being called.
To add a little to what others have said -
If the variable (initV) is never actually used as a variable, so that in fact its value at the time the accumulator is defined is all that is needed, then there is no need for the lexical closure that encapsulates that variable and its value. In that case, the approach described by #juanleon is sufficient: it uses only the value at definition time - the variable does not exist when the function is invoked (as you discovered).
On the other hand, the lexical-closure approach lets the function be byte-compiled. In the backquote approach, the function is simply represented at runtime by a list that represents a lambda form. If the lambda form represents costly code then it can make sense to use the lexical-closure approach, even though (in this case) the variable is not really needed (as a variable).
But you can always explicitly byte-compile the function (e.g. ##NAME## in your define-accum. That will take care of the inefficiency mentioned in #2, above.

Elisp interactive function name

I'm trying to use the interactive function name feature. On emacs lisp manual it says:
‘a’
A function name (i.e., a symbol satisfying fboundp). Existing, Completion, Prompt.
So I tried it with a small test code:
(defun testfun1 ()
(message "hello, world!"))
(defun test (abcd)
(interactive "aTheme name: ")
(abcd))
Emacs gives an error saying,
test: Symbol's function definition is void: abcd
I tried to test abcd with fboundp, it returns t. So I'm quite confused about how to use the 'a' option in interactive.
Any body can give some hints?
Your function test receives its argument abcd as a function, but you can't just invoke a function by putting a symbol referencing it in the first position of a list to be evaluated. Since Emacs Lisp is a Lisp-2, the reference to the function provided to the interactive query is stored in symbol abcd's value slot, not its function slot. The evaluation rules for a list like
(abcd)
involve looking in the first object's function slot if that object is a symbol, which it is in your case. If instead you wish to invoke a function referenced in a symbol's value slot, you need the funcall function:
(funcall abcd)
That says, "Take abcd, grab the value out of its value slot, and, provided it's a function, call it here, just as we would have if that function had been referenced in the list's first position either in a symbol's function slot or by a direct reference to the function object."
Here's an answer to a similar question with references useful to allow you probe further.
This should do this trick:
(defun test (abcd)
(interactive "aTheme name: ")
(call-interactively abcd))

Unable to understand a line of Emacs Lisp

The line is
function info() {
emacs -eval "(progn (setq Man-notify-method 'bully) (info \"$1\"))"
}
I know from manuals that
Progn
progn is a special form in `C source
code'.
Setq
setq is a special form in `C source
code'. (setq SYM VAL SYM VAL ...)
Set each SYM to the value of its VAL.
The symbols SYM are variables; they
are literal (not evaluated). The
values VAL are expressions; they are
evaluated. Thus, (setq x (1+ y)) sets
x' to the value of(1+ y)'. The
second VAL is not computed until after
the first SYM is set, and so on; each
VAL can use the new value of variables
set earlier in the setq'. The return
value of thesetq' form is the value
of the last VAL.
$1 seems to a reference to the first parameter after the command man which the user gives.
'bully seems to be a random variable.
Man-notify-method seems to be an action function which is run when man command is executed.
-eval seems to be an evalutian statemant which tells Emacs to run the statement which follows it.
However, I am not completely sure about the function.
I need to understand the function, since I want to bind a bash code of mine to the action function of man. Man-notify-method seems to be that action function, at least in Emacs.
How do you understand the line of Emacs Lisp?
The code you posted is a combination of shell script and elisp.
function info()
{
emacs -eval "(progn (setq Man-notify-method 'bully) (info \"$1\"))"
}
This defines a shell script function named info. It takes 1 parameter, named $1. When you call this function (say, from another shell script), the value of the argument gets substituted in for $1, and it runs the commands specified in sequence. So, if you were to call it like this:
info("something")
The shell would execute this command:
emacs -eval "(progn (setq Man-notify-method 'bully) (info \"something\"))"
This invokes the emacs executable with two arguments, -eval and the command string, which contains embedded escaped quotes. This is asking emacs to invoke the following elisp code:
(progn (setq Man-notify-method 'bully) (info "something"))
progn is a special form. Special forms evaluate their arguments differently than normal function calls. You can find the documentation for progn in chapter 10.1 of the GNU Emacs Lisp Reference Manual. progn is a simple construct for executing a sequence of statements in order. The reason you may need to do this is for cases when you want to execute multiple statements, but the context that you're in only expects a single statement.
For example, an if statement takes 3 (or more) arguments: the condition to evaluate, the expression to evaluate if true, and the expression to evaluate if false. If more than 3 arguments are provided, the subsequent arguments are part of the else branch. If you want to use more than one statement in the true branch, you have to use progn:
(if condition
(progn first-statement-if-true
second-statement-if-true)
first-statement-if-false
second-statement-if-false
)
In this case, if condition is true, then first-statement-if-true and second-statement-if-true will be evaluated. Otherwise, first-statement-if-false and second-statement-if-false will be evaluated.
Thus, your code will simply evaluate the two statements (setq Man-notify-method 'bully) and (info "something") in order.
setq is another special form. See chapter 11.8 for its documentation. It simply sets a variable, named by the first parameter, to the value of the second parameter. The first parameter is not evaluated -- it is taken literally.
A value preceded by a single quote (such as 'bully) is not evaluated. See chapter 9.3 for details on quoting. Hence, (setq Man-notify-method) sets a variable named Man-notify-method to the literal token bully (which is a data type called a symbol, which is distinct from the string "bully").
I can't find the documentation on the info function online, you can get help on any given function in emacs by typing C-h f function-name. So, by typing C-h f info, I got this:
info is an interactive autoloaded Lisp function in `info'.
[Arg list not available until function definition is loaded.]
Enter Info, the documentation browser.
Optional argument FILE specifies the file to examine;
the default is the top-level directory of Info.
Called from a program, FILE may specify an Info node of the form
`(FILENAME)NODENAME'.
In interactive use, a prefix argument directs this command
to read a file name from the minibuffer.
The search path for Info files is in the variable `Info-directory-list'.
The top-level Info directory is made by combining all the files named `dir'
in all the directories in that path.
The online reference manual is very useful, and emacs' interactive help is also indispensible. If you don't understand what a particular function does, just C-h f it.
PROGN simply evaluates the expressions in order, returning the return value of the last one.
SETQ is the basic assignment operator.
INFO enters the emacs info browser.
So, what this does is first assign the symbol 'bully to the variable Man-notify-method, then enter the info browser. 'bully is likely the name of a function, and Man-notify-method a place where the info browser looks up a function to call for some notification (Warning: I am just guessing here).
I guess that you will have to define your own function that calls your shell command like this:
(defun my-cmd ()
(call-process ; Look up the syntax in the emacs lisp manual
))
Then assign its symbol to Man-notify-method:
(setq Man-notify-method 'my-cmd)