1

I am trying to understand, what some functions are doing, in order to code something similar.

The following example was copied from the file acro.el from the AUCTeX package. This is just a random example, as any other style-file from AUCTeX will do.

In acro.el you will find

...
 (TeX-add-symbols
    ;; Creating New Acronyms
    '("DeclareAcronym" LaTeX-arg-define-acro-acronym
      (LaTeX-arg-acro-key-val "Definition of acronym (k=v)"
                  LaTeX-acro-declareacronym-keys))
...)

I do interpret this, that if you want to insert the macro \DeclareAcronym into your LaTeX-buffer, (by running the command TeX-insert-macro, bound to CTRL-cCTRL-m) AUCTeX will first run the function LaTeX-arg-define-acro-acronym.

This---in return---is defined this way:

(defun LaTeX-arg-define-acro-acronym (optional &optional prompt)
  "Prompt for an acronym completing with known acronyms.
If OPTIONAL is non-nil, insert the resulting value as an optional
argument, otherwise as a mandatory one.  Use PROMPT as the prompt
string."
  (LaTeX-arg-acro-acronym optional prompt t))

As far, as I have understood LISP, the function LaTeX-arg-define-acro-acronym has to be called with one mandatory argument. You may also give it a second, optional argument.

Therefore, calls as this

(LaTeX-arg-define-acro-acronym t)
(LaTeX-arg-define-acro-acronym t "Acronym to define: ")

should be correct. In fact, I can execute those commands in the scratch buffer without error.

But, as you saw above, the function is called without the mandatory argument and even without the parentheses ():

LaTeX-arg-define-acro-acronym

Can someone explain to me, why this is working and why emacs is not throwing an error? When I try this in the *scratch*-buffer, I get an error

Symbol's value as variable is void

When I add parentheses, I get this error message in the minibuffer

Wrong number of arguments

Digging further into the code, I found, that LaTeX-arg-define-acro-acronym calls the function LaTeX-arg-acro-acronym. This time, the mandatory OPTIONAL and both optional arguments PROMPT and DEFINITION are handed over. Again, copied from acro.el:

(LaTeX-arg-acro-acronym optional prompt t)

This time the parentheses () are used.

I am asking myself, what value OPTIONAL, PROMPT and DEFINITION do get, as they haven't been defined (as far as I can see). (Are there any defaults, I have missed?)

4

The answer to your question is actually in AUCTeX manual; it may sound cryptic when you read it for the first time, but it is quite accurate:

Function: TeX-add-symbols symbol ...

Add each symbol to the list of known symbols. Each argument to TeX-add-symbols is a list describing one symbol. The head of the list is the name of the symbol, the remaining elements describe each argument. [...]
You can use the following types of specifiers for arguments: [...]

other symbols: Call the symbol as a function. You can define your own hook, or use one of the predefined argument hooks.

list: If the car is a string, insert it as a prompt and the next element as initial input. Otherwise, call the car of the list with the remaining elements as arguments.

vector: Optional argument. If it has more than one element, parse it as a list, otherwise parse the only element as above. Use square brackets instead of curly braces, and is not inserted on empty user input.

[...] The first argument to all hooks is a flag indicating if it is an optional argument. It is up to the hook to determine what to do with the remaining arguments, if any.

The last part means: all hooks must have a first mandatory argument optional which will be passed to the function by AUCTeX itself depending on being inside square brackets [ ] (see vector item above) and not by the style author. The author has to deal with the remaining arguments, if any.

In the style file acro.el, you have:

(TeX-add-symbols
  ;; Creating New Acronyms
  '("DeclareAcronym" LaTeX-arg-define-acro-acronym
     (LaTeX-arg-acro-key-val "Definition of acronym (k=v)"
                             LaTeX-acro-declareacronym-keys)) )

The head of the list is the string "DeclareAcronym", the name of the macro provided by the LaTeX package. Next element is LaTeX-arg-define-acro-acronym. This element is parsed as symbol and called as function. It is defined as:

(defun LaTeX-arg-define-acro-acronym (optional &optional prompt)
  "Prompt for an acronym completing with known acronyms.
If OPTIONAL is non-nil, insert the resulting value as an optional
argument, otherwise as a mandatory one.  Use PROMPT as the prompt
string."
  (LaTeX-arg-acro-acronym optional prompt t))

It has one mandatory argument optional, prompt is &optional and omitted in the call. Now, when you invoke C-c C-m DeclareAcronym RET, AUCTeX runs:

(LaTeX-arg-define-acro-acronym nil)

which will then run:

(LaTeX-arg-acro-acronym nil nil t)

which is defined as:

(defun LaTeX-arg-acro-acronym (optional &optional prompt definition)
  "Prompt for an acronym completing with known acronyms.
If OPTIONAL is non-nil, insert the resulting value as an optional
argument, otherwise as a mandatory one.  Use PROMPT as the prompt
string.  If DEFINITION is non-nil, add the chosen acronym to the
list of defined acronyms."
  (let ((acronym (completing-read (TeX-argument-prompt optional prompt "Acronym")
                  (LaTeX-acro-acronym-list) nil nil nil
                  'LaTeX-acro-acronym-history)))
    (if (and definition (not (string-equal "" acronym)))
    (LaTeX-add-acro-acronyms acronym))
    (TeX-argument-insert acronym optional optional)))

The argument optional (here nil) is ultimately passed to TeX-argument-prompt and TeX-argument-insert with the effect that in mini-buffer, AUCTeX does not prefix the prompt Acronym: with (Optional) and insert user input in braces {} and not in brackets [].

The next part:

(LaTeX-arg-acro-key-val "Definition of acronym (k=v)"
                         LaTeX-acro-declareacronym-keys)

is a list. Since the car of the list is not string, AUCTeX calls the car as a function with rest as arguments. LaTeX-arg-acro-key-val is defined as:

(defun LaTeX-arg-acro-key-val (optional prompt key-val-alist)
  "Prompt for keys and values in KEY-VAL-ALIST.
<SPC> key binding in minibuffer is removed temporarily.  Insert
the given value as a TeX macro argument.  If OPTIONAL is non-nil,
insert it as an optional argument.  Use PROMPT as the prompt
string.  KEY-VAL-ALIST is an alist.  The car of each element
should be a string representing a key and the optional cdr should
be a list with strings to be used as values for the key."
  (let ((crm-local-completion-map
         (remove (assoc 32 crm-local-completion-map) crm-local-completion-map)))
    (TeX-arg-key-val optional key-val-alist prompt)))

It takes 3 mandatory arguments where only 2 are supplied in the hook. Again, AUCTeX feeds the function with optional (here nil) itself so you don't have to cater for it.

If you want to dive into details, check the functions TeX-parse-macro, TeX-parse-arguments and TeX-parse-argument.

  • Arash, I Owe you so much. I have read the AUCTeX-Manual several times. Your explanation makes a lot clear to me. You are right: it is correct but also confusing. (At least, still to me!) But it feels great. It remembers me of the time on university, when I had enough spare time, to play with Emacsen and Lisp. :-) – Jan Mar 17 '17 at 9:13
3

You're correct about what required and optional arguments are. I think that you've missed a key detail about that first snippet of code, which I reproduce here:

(TeX-add-symbols
  ;; Creating New Acronyms
  '("DeclareAcronym" LaTeX-arg-define-acro-acronym
    (LaTeX-arg-acro-key-val "Definition of acronym (k=v)"
                LaTeX-acro-declareacronym-keys))

This starts with a call to the function TeX-add-symbols, passing it one argument. That argument is a quoted list (it looks like '(...)). When you quote something in a lisp, you're telling the compiler not to evaluate it, but instead to keep it around as a data structure. This means that the LaTeX-arg-define-acro-acronym that you see there is not a call to that function at all; it's just the name of the function. The function TeX-add-symbols must use that name in one way or another, probably by looking up what function is assigned to it, then calling that function at the necessary time.

Another detail you might be missing is that Emacs Lisp is what is called a "Lisp-2". In a "Lisp-2", all names can have two values. One value is used when the name is used in a function call, and the other value is used when the name is used as a variable. (Other Lisp languages are called "Lisp-1" because ever variable can have only one value, either a function value or a "normal" value.) For example, take a look at this code:

(defvar foo 42)
(defun foo () (message "function foo was called"))

Here we define a variable called foo with a value of 42. Then we define a function called foo, and have it display a message. If you evaluate these in your scratch buffer, then evaluate foo, you'll get the 42 back. If you evaluate (foo), on the other hand, it will call the function and display the message. This is why, when you evaluated LaTeX-arg-define-acro-acronym you got an error saying that the variable was undefined. You can use the functions symbol-value and symbol-function to access these two values in an explicit way; they both take a single symbol as an argument: (symbol-value 'foo) gives 42, while symbol-function 'foo) gives a lambda expression.

Finally, you found some code that makes a call to this function, which looks like (LaTeX-arg-acro-acronym optional prompt t). You asked about optional and propmt here, because they didn't seem to be defined. These are likely local variables, only defined inside the scope of the code you were looking at. They could be passed in as arguments to the function, or defined as a variable using let or let*, or even one of the less common facilities that introduce local variables such as dolist.

Given your questions here, I'd say it's time you started reading the Elisp Manual. It goes into quite a lot of detail that you'll eventually need, in addition to covering the basics. (For example, it also tells you about the other two components that are associated with every variable name, aside from the value and the function.) Luckily, this manual (and many others), is included with Emacs. You can open up the list of manuals by typing C-h i. Navigate down to the Elisp manual and hit enter (you could also type m at this point to jump to a menu item by name, with autocompletion) to follow the link.

  • Thank you very much, Daniel, for this answer. I started Emacsen in 1994 on university, but afterwards, most of the knowledge got lost :-(. I forgot the meaning of the 'and that LISP could have two meanings. So you helped my a lot on my way to understand the problem. There are still some black spots, but some brightened up by your answer a lot. Thank you very much. – Jan Mar 17 '17 at 8:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.