Emacs Lisp
Table of Contents
- Elisp
.el
Dialect of Lisp used specifically to configure, extend, and program the GNU Emacs text editor
They are byte complied into .elc file,
and native compiled into .eln file.
"TAB" is ^I and "<tab>" is tab key.
1. Syntax
Symbol
Symbol is an object that represent a variable or function. quote or ' wraps the variable as a symbol.
It consists of four parts: name, value, function value, property list. They can be accessed with symbol-name, symbol-value,
symbol-function, symbol-plist respectively.
fsetsets the function value of the variable. It can be set to a raw function or a symbol as a indirection.- Keywords, of the form
:keyword, are special symbols whose symbol-value is itself.
Dynamically bound functions expands the scope when it is not bound locally, but lexically bound variable does not.
defvarmakes the variable dynamically bound.- Lexical binding is preferred these days.
boundpchecks if a symbol is bound to a value or void.setfis likesetqbut operates on any cell and variables.(let ((var val), ...) (statement))it binds local variable, dynamically on dynamic variable, lexically on free variable.let*defines them sequencially
(setq var val var val ...)- The variable is bound to the value.
- The
qis for quoted, which means thevardoes not need to be quoted
(defvar var val "optional documentation")- It marks the variable as special, so that it is always dynamically bound.
- The variable is not overrode, and
setqcan change the value, it is seen globally - It allows doc string.
- There are various types of primitive data, printed as
#<buffer>,#<marker>,#<frame>. - value can be a closure and it can be called with
funcall #'can be used to explicitly tell it to use the function value.#1=and#1#can be used to create a reference and refer back to it.
List The basic unit of a list is cons cell.
- It consists of two parts
carandcdr, that can contain value or reference. CAR and CDR - Wikipedia consor.form a cons cell out of two values.listis a series of cons cell that reference the next cons cell and ends innil
A list is a series of cons cells called nodes (CAR CDR) -> (CAR CDR) -> ..., with data in CAR and pointer
to the next node in CDR. CDR also be used to store value instead of the pointer to
the next node via (cons VAR1 VAR2), or equivalently (VAR1 . VAR2).
The Lisp reader (parser) reads the list and evaluate it if it is not quoted with (quote LIST) or equivalently 'LIST.
The the function slot in the first element in the list is evaluated with the variable slot in the remaining elements as arguments.
`(... ,a ...)backquote can be used to evaluate only certain part of expression.`(... ,@a ...)can be used instead, to unwrap the result ofa.
There are named form of list: alist and plist.
Alist, short for association list, is a list of cons cells that associate or map
car to cdr:
(setq alist '((apple . 10) (banana . 5) (peach . 17)))
Plist, short for property list, is a list of alternating keywords and values:
(setq plist '(:name "Bob" :age 29 :smart t))
Array
String "abc" , Vector [a b c] are array,
which is a special type of list.
Function
(defun funcname (arguments)
"optional documentation"
(interactive "optional-argument-passing-info")
(body))
Function that is defined interactively with (interactive OPTION) is a command, which can be bound
(require 'cl-lib) ;; Common Lisp library
(cl-defun funcname (a &key (b "Default B") (c 42))
"A function with keyword arguments."
(message "A is %s, B is %s, C is %s" a b c))
(funcname "Hello" :c 99)
A is Hello, B is Default B, C is 99
Package
(provide 'PACKAGE) specified in the end of the package file. Later (require 'PACKAGE) is used to retrieve it.
Mode
Simple mode defined as follow can be activated by M-x generic-mode
(define-generic-mode 'phits-mode
'("#") ;; comment character
'("icntl") ;; keywords
'(("^\\[.*\\]" . 'font-lock-constant-face)) ;; font lock regex
'("\\.inp\\'") ;; file extenstion
nil ;; list of functions to run
"Genetic mode for phits input file")
(define-minor-mode MODE :init-value nil :lighter INDICATOR :global nil BODY)
(defcustom var val "documentation" :type TYPE) it specify a variable that customize can control
2. Functions
2.1. Interactive Function
- These are precisely the commands
Command is defined with (interactive OPTIONS) within the function defition.
The option can be nil, string, or lisp code. String option includes
a sequence of code character and prompt string pairs separated by \n,
with each user response assigned to the arguments of the function in order.
nnumbersany string- the input is terminated by
C-jorRET
- the input is terminated by
ccharacterffilenameFfile does not need to exist
bbuffer nameBbuffer does not need to exist
Ddirectoryrregion- take the start and end point of the region as the two argument.
The full list can be found here.
2.2. Build-in Functions
If the name ends in p, it is a predicate.
If it ends in q, some of the arguments are quoted by default.
List
(setcar CELL NEWCAR),(setcdr CELL NEWCDR)modify the cons cell(assoc KEY ALIST &optional TESTFN)return the key-value pair matchingKEYwithin a alist as a reference.(alist-get KEY ALIST &optional DEFAULT REMOVE TESTFN)similar toassoc, but create if there is no matching key.(append LIST1 LIST2)produces the new concatenated list- Sequence Functions (GNU Emacs Lisp Reference Manual)
(copy-sequence LIST)copy the outer most sequence(copy-alist LIST),(copy-tree LIST)are also available for deep copy.
String
(concat STR1 STR2)concatenate into one string(format FORMAT_STR VAR)(substring STR START_INDEX [END_INDEX])zero-based end-excluded substring.
Point
(point)return current point position(goto-char NUM)move point to the positionNUM(forward-char &optional NUM),(backward-char &optional NUM)move point(beginning-of-buffer),(end-of-buffer)move point- Common motion command, such as
(forward-word),(forward-sentence)are also available. (point-min),(point-max)return possible point position while taking narrowing into account(save-excursion ...)save the point position, and allow point motions to be contained within the scope
Buffer
- Get/Set Buffer
(current-buffer)get the buffer object currented being edited#<buffer>(get-buffer BUFFER-OR-NAME)get buffer by name(get-file-buffer FILENAME)get buffer by file path(get-buffer-create BUFFER-OR-NAME)get buffer while creating it when it does not exists.(set-buffer BUFFER-OR-NAME)set current (editing) buffer toBUFFER(with-current-buffer BUF ...)set the current buffer within the scope(with-temp-buffer "CONTENT" ...)create a temporary buffer with given content
- Buffer File
(buffer-file-name)the file path of the current buffer. It isnilif not applicable.(find-file-noselect FILENAME) => BUFopen a file into a buffer without displaying it(save-buffer)save to buffer file
- Buffer Text
(char-after NUM)return the character at the position(thing-at-point THING &optional NO-PROPERTIES)theTHINGcan be'word,'sentence,'urland others(search-forward STRING &optional BOUND NOERROR COUNT),(search-backward STRING)move the point after/before the (first) match(buffer-substring START END)return string at the given range within current buffer(buffer-substring-no-properties START END)
(insert STR)insert at point(insert-file-contents-literally PATH)(delete-region START END)delete the text within
- Buffer positioning
(display-buffer-alist)set the rules for displaying buffers.
Window
(selected-window)return the active window object#<window>(window-paramters &optional WINDOW)return alist of window parameters(with-selected-window WINDOW ...)run within a given window and return to original window
Frame
(selected-frame)return the active frame object#<frame>(frame-paramters &optional FRAME)return alist of frame parameters(with-selected-frame FRAME ...)run within a given frame and return original frame
Command
(this-command)return the object that represent the last executed command
External Command
(shell-command COMMAND)xdg-opencan be used to open a file externally.
(shell-command-to-string COMMAND)insert the result of shell command(call-process ...)(start-process ...)
Hook
(add-hook HOOK FUNCTION)(run-hook-with-args-until-success HOOK &rest ARGS)runs hooks sequenctially until one of them returnst.(with-eval-after-load PKG BODY)
Interactive
(y-or-n p PROMPT),(yes-or-no-p PROMPT)ask yes or no and returntornil(message STRING)echo in the minibuffer(message "message" optional-format-vars)print message to the echo area%s,%dcan be used to format the string
(read-buffer PROMPT),(read-file-name PROMPT),(read-char &optional PROMPT)
3. Flow Control
Conditionals
(if (test) (if-true) (if-false))(when (condition) (if-ture) (if-ture) ...)(unless (condition) (if-false) (if-false) ...)(cond (condition1 if-true) (condition2 if-true) ...)it is similar to theswitchin C.
Repetition Loop Facility:
(loop NAME_CLAUSE(named)
VARIABLE_CLAUSE(initially, finally, for, as, with)
MAIN_CLAUSE(do, when, collect, append,...)) ;; similar for cl-loop
4. Macro and Special Form
defmacrodefines a macro that interprets expression differently, that it may not evaluate the expression.- Special form is similar to macro and it is often the language feature.
(progn EXPRESSIONS)execute the expressions in order
5. Packages
5.1. cl-lib
(cl-loop VAR_DEFINE(for, with, ...) BODY(if, repeat, collect, append, return, ...)
6. Byte Compilation
- A lisp file from a package is byte compiled on installation. It needs to be recompiled via
package-recompileto load the code.
7. History
The original Lisp came about in 1960 by John McCarthy. It diverged into several dialect in 1970s and unified with Common Lisp in 1980s. The ANSI standard was also established in 1990s.
It was a niche programming language among industry and academia and soon got outnumbered by other languages due to its low performance and lact of libraries. Java at work, Python at academia replaced them.
The Rise & Fall of LISP - Too Good For The Rest Of the World - YouTube