General
- Apparently, there is no built-in function composition.
- Comments: Starts with
; progn: evaluate each statement in body sequentially and return value from last statement.- Kind of like comma operator in C.
- https://www.gnu.org/software/emacs/manual/html_node/eintr/progn.html
(1- x)is same as(- x 1). Former form is considered better style.- Invoke shell commands:
(shell-command "cmd") - Search text with regex:
(re-search-forward "^* The specific heading") - Write text to current buffer:
(insert "text") (file-name-nondirectory arg): get filename and extension- Remove everything after last slash
(name)is a function (as inname()in C), butnameis a valueletis normal let,let*is likeletrec- elisp has vectors
(signal ..)and(error ..): ways to indicate errors programmatically- Emacs:
M-x pp-buffer: pretty-print a buffer with lisp code
Temporary files and buffers
- Create a temporary file:
(make-temp-file "foo")- By default, Creates a file with
"foo"prefix in/tmp/and returns its path as string. - https://www.gnu.org/software/emacs/manual/html_node/elisp/Unique-File-Names.html
- DBT: Would this file get deleted automatically after use ??
- By default, Creates a file with
(with-temp-file outfile body): create new buffer, evaluate body there and write to outfile ??
Regions
(use-region-p): returnstif a region is active(region-beginning): integer representing start of current region(region-end): integer representing end of current region
Type conversions
Check value of a type:
(integerp v): returntifvis an integer(sequencep '(1 2)) ;; t: check if value is a sequence(sequencep (make-hash-table)) ;; nil
(hash-table-p v): hash tables
Type conversions:
- String to number:
(+ 2 (string-to-number "3")) ;; 5- https://www.gnu.org/software/emacs/manual/html_node/elisp/String-Conversion.html
funcall and apply
- Quite similar.
funcall f args: calls functionfwithargsas argumentsapplytakesargsas a list, but they are passed tofas separate args- https://www.gnu.org/software/emacs/manual/html_node/elisp/Calling-Functions.html
(funcall '+ 2 3)
; 5
(apply '+ '(2 3))
; 5
Emacs terminology
- Printed representation and read syntax
Point
https://www.gnu.org/software/emacs/manual/html_node/elisp/Point.html
- org narrow => point is restricted to accessible region
- Excursion: Temporarily change point position
- Eg: with
(save-excursion)
- Eg: with
Associated functions:
(point): current value of point in buffer(point-min)/(point-max): minimum/maximum accessible value of point in buffer
Kill ring
- Kill: cut
- Yank: paste
- Kill ring holds a list of recently killed text
- This list is
(kill-ring)??
- This list is
(kill-ring-max)maximum size of kill ring
See:
- https://www.gnu.org/software/emacs/manual/html_node/elisp/The-Kill-Ring.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Internals-of-Kill-Ring.html
Single characters
Preceded by a ? for syntax.
; ?a is like 'a' in C
?a
97
See:
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Char-Syntax.html#Basic-Char-Syntax
- https://emacs.stackexchange.com/questions/30392/what-are-the-symbols-in-emacs-lisp
Lists
mapcar: map function over a sequence like listsseq-uniq: Get unique elements in a list(seq-uniq '(1 2 2 2 2)) ;; (1 2)
nth element of a list
(nth idx lst): getn-th element oflst(nthcdr n lst): Like callingcdrntimes onlst
(nth 0 '(0 1 2 3 4 5))
0
(nth 3 '(0 1 2 3 4 5))
3
(nthcdr 3 '(0 1 2 3 4 5))
(3 4 5)
(nthcdr 10 '(0 1 2 3 4 5))
nil
https://www.gnu.org/software/emacs/manual/html_node/eintr/nth.html
car and cdr
- Head and tail functions for lists.
- Name is due to historical reasons: IBM 704.
- https://www.gnu.org/software/emacs/manual/html_node/eintr/Strange-Names.html
- car: contents of address part of register
- cdr (pronounced 'could-er'): contents of decrement part of register
- https://www.gnu.org/software/emacs/manual/html_node/eintr/Strange-Names.html
–
car: get head element of a listcdr: get tail of a list
(car '("a" "b" "c"))
; "a"
(car '(0 1 2))
; 0
(car '())
; nil
(cdr '("a" "b" "c"))
; ("b" "c")
(cdr '(0 1 2))
; (1 2)
(cdr '())
; nil
https://www.gnu.org/software/emacs/manual/html_node/eintr/car-_0026-cdr.html
Strings
- Find length of a string:
string-width- Note:
'\n'is not counted in this function (string-width "hi") ; 2(string-width "\n") ; 0
- Note:
- Make a string from a char:
(string ?a) ; "a" - Repeat a character n times
(make-string <count> <char>)(make-string 2 ?a) ; "aa"
- String concatenations:
(concat str1 str2) - Concatenate list of strings:
string-join(string-join '("hi " "how are" " you?")) ;; "hi how are you?"
- Looks like numbers are integers by default in elisp.
(/ 3 2)is 1(/ (float 3) 2)is 1.5(/ 3 2.0)is 1.5
See:
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Strings.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Shell-Arguments.html
Uppercase and lowercase
- Convert string/char to lowercase: downcase
- Convert string/char to uppercase: upcase
If argument is char, return value is int for both downcase and upcase.
Splitting a string
split-string
- Note: Second argument is a regex
(split-string "1.2.3" "\\.")
; ("1" "2" "3")
(split-string "a-b c" "-")
; ("a" "b c")
Functions
defun foo () (5)
(foo) ;5
(defun fact (a) (cond
((= a 0) 1)
(t (* a
(fact (- a 1))
)
)))
(fact 5) ; 120
(defun gcd (a b)
(cond
((< a b) (gcd b a))
((= (% a b) 0) b)
(t (gcd b (% a b)))
))
(gcd 1000 10) ; 10
(atom 1) ; t
(atom (list 1 2)) ; nil
;; NOT WORKING
; find sqrt of a.
; x is starting value
; e is permissible error
(defun sqrt_nr (a x e)
(cond
((< (abs (- (* x x) a)) e) x)
(t (sqrt_nr a (* (/ 1 2) (+ x (/ a x))) e))
))
Plist (Property list)
- Paired list of elements
- Effectively just list which can be treated specially
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Plists-and-Alists.html
Functions:
- plist-put: add new key-element pair
- plist-get: add element given a key
- plist-member: check membership for a key
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Plist-Access.html
—
In:
(pine cones numbers (1 2 3) color "blue")
it's like:
- (pine,cones)
- (numbers, (1 2 3))
- (color, "blue")
—
Examples:
(setq-local myplist '("pine" "cones" "numbers" (1 2 3) "color" "blue"))
; ("pine" "cones" "numbers" (1 2 3) "color" "blue")
(setq-local myplist (plist-put myplist "vive" "la"))
; ("pine" "cones" "numbers" (1 2 3) "color" "blue" "vive" "la")
(setq-local l myplist)
; ("pine" "cones" "numbers" (1 2 3) "color" "blue" "vive" "la")
(plist-get '(foo 4) 'foo)
; 4Alist (Association list)
- Similar to plists
- Syntax:
(key . value) - https://www.gnu.org/software/emacs/manual/html_node/elisp/Association-Lists.html
- Just a fancy list?? Allows multiple entries with same 'key'
(setq-local myalist
'(("name" . "joe")
("age" . 50)
("planet" . "earth")))
; (("name" . "joe") ("age" . 50) ("planet" . "earth"))Functions:
(assq key alist): return element of alist whosecariskey
—
Folding over an alist (courtesy of chatgpt):
(require 'cl-lib)
(setq-local my-alist '((a . 1) (b . 2) (c . 3)))
((a . 1) (b . 2) (c . 3))
(cl-reduce (lambda (acc pair)
(+ acc (cdr pair))) ;; Accumulate the values (cdr of each pair)
my-alist
:initial-value 0)
; 6
Hash table
- Kind of like a faster alist
- ie, like python dictionary
- https://www.gnu.org/software/emacs/manual/html_mono/elisp.html#Hash-Tables
Creating hash tables
make-hash-table:testargument specifies how hashing would be done- Default
:testmethod iseql
- Can also be made using read syntax
#s(hash-table size 50 data (key1 val1) (key2 (val2)
#s(hash-table data (key1 val1 key2 300))
; #s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8125 data (key1 val1 key2 300 ...))
#s(hash-table (key1 val1 key2 300))
; #s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8125 data ( ...))
#s(key1 val1 key2 300)
; #s(key1 val1 key2 300)Example usage:
(make-hash-table)
; #s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8125 data ( ...))
#s(hash-table size 30 data (key1 val1 key2 300))
; #s(hash-table size 30 test eql rehash-size 1.5 rehash-threshold 0.8125 data (key1 val1 key2 300 ...))
(setq-local myht #s(hash-table size 30 data ("a" 10 "b" 20)))
; #s(hash-table size 30 test eql rehash-size 1.5 rehash-threshold 0.8125 data ("a" 10 "b" 20 ...))Functions
gethash key tableputhash key tableremhash key tableclrhash table: empty the hash tablemaphash function table: in-place map over hashtablehash-table-keys table: get all keys of hashtable
https://www.gnu.org/software/emacs/manual/html_mono/elisp.html#Hash-Access
(hash-table-keys #s(hash-table data ("a" 1 "b" 2)))
; ("a" "b")
; No unique keys ???
(hash-table-keys #s(hash-table data ("a" 1 "b" 2 "a" 3)))
; ("a" "b" "a")
(hash-table-p #s("a" 1))
; nil
(hash-table-p #s(hash-table "a" 1))
; t
(hash-table-p (make-hash-table))
; t
Text properties in strings
https://www.gnu.org/software/emacs/manual/html_mono/elisp.html#Text-Props-and-Strings
For example, the following means:
#("foo bar" 0 3 (face bold) 3 4 nil 4 7 (face italic))
| Part of string | Slice | Property |
|---|---|---|
| "foo" | str[0: 3] | bold |
| " " | str[3: 4] | NA |
| "bar" | str[4: 7] | italic |
Conditionals
ifstatement:(if (condition) (then-clause) (else-clause))when: likeifwithout elseunless: likeifwith only else
Equality check
- eq: equal only both args are the same object
- eql: For non-atomic types, looks inside for
eq-style equality ??- ie, not too strict at top level, but is like
eqfor looking at internal structure ??
- ie, not too strict at top level, but is like
- equal
See:
- https://stackoverflow.com/questions/547436/whats-the-difference-between-eq-eql-equal-and-equalp-in-common-lisp
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Equality-Predicates.html
eq
(setq-local a 3)
(setq-local b 3)
(eq 'a 'a)
; t
(eq 'a 'b)
; nil
(eq 'a '3)
; nil
equal
(eq "2" "2")
; nil
(equal "2" "2")
; t
(equal 2 2)
; nil
Built-in functions
Math functions:
abs: absolute valuesqrt: square root
Advising functions
https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html
Change the default behaviour of an existing function ('by giving some advice') rather than redefining the whole function.
Codes for interactive prompts
First character of argument of (interactive).
https://www.gnu.org/software/emacs/manual/html_node/elisp/Interactive-Codes.html
(interactive): function can be called withM-xas well- What does
(interactive "p")mean?: See this
- What does
Read input from user interactively:
| Function | Description |
|---|---|
read-char |
Reads a character. Returns int |
read-int |
Reads int |
read-string |
Reads string |
read-key |
|
read-char-choice |
|
yes-or-no-p |
Ask a yes/no answer |
y-or-n-p |
Ask a y/n answer |
dotimes and dolist
dotimes (counter limit result) body
counterstarts from 0.bodyis the loop body- Resultant value is
result.- If no value for result is given,
nilis returned.
- If no value for result is given,
dolist is looping on a list.
(dolist list-name
(operation list-elem)
is like the following python:
for list_elem in list_name:
operation(list_elem)
Write part of a buffer to a file
; Overwrite
(write-region (point-min) (point-max) "outfilename")
; Append
(write-region (point-min) (point-max) "outfilename" t)
(write-region (point-min) (point-max) "outfilename" 'append)
Append a string to a file with write-region:
(write-region <string> nil <filename> 'append)
Run an external command and get its output
shell-command-to-string: run a command and gets its output as a stringshell-command: just run the command. Don't use its outputasync-shell-command
(message (shell-command-to-string "/bin/echo -n hello"))
; Output: hello
True and false
- There is no boolean type in elisp
- Following can stand in:
- True:
t - False:
nilor empty list
- True:
(and t nil)
; nil
(or t nil)
; t
(if '() "T" "F")
; "F"
(if () "T" "F")
; "F"
Managing parenthesis
- Find unbalanced parenthesis (vanilla emacs):
M-x check-parens - Third party packages: paredit, lispy
See:
- https://www.gnu.org/software/emacs/manual/html_node/emacs/Parentheses.html
- Stuff available in vanilla emacs itself: http://web.archive.org/web/20160712150651/https://cl-cookbook.sourceforge.net/emacs-ide.html
- https://www.emacswiki.org/emacs/NavigatingParentheses
Handling time and date
(current-time)
; (26423 47784 405993 901000)
(decode-time)
; (42 48 2 16 11 2024 6 nil 19800)- format-time-string: formats current datetime if no datetime argument is given
(format-time-string "%Y-%m-%d")
"2024-11-16"
(format-time-string "%Y-%m-%d" (decode-time))
"1970-01-07"(decode-time)
; (59 6 3 16 11 2024 6 nil 19800)
(encode-time (decode-time))
; (26423 48961)
(format-time-string "%Y-%m-%d" (encode-time (decode-time)))
; "2024-11-16"See:
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Time-of-Day.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Time-Parsing.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Time-Calculations.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Time-Conversion.html
car and cdr
car: head of listcarof empty list givesnil
cdr: tail of list
(car '(0 1 2 3))
; 0
(car nil)
; nil
(cdr '(0 1 2 3))
; (1 2 3)
(cdr (cdr '(0 1 2 3)))
; (2 3)nthcdrrepeatscdrfunctionntimes
nth element in a list/tuple
- Indexing starts from zero.
(nth 2 '(1 2 3))
; 3File paths
(file-name-directory "/home/user/Desktop/file.ext")
; "/home/user/Desktop/"
(file-name-nondirectory "/home/user/Desktop/file.ext")
; "file.ext"
(file-name-extension "/home/user/Desktop/file.ext")
; "ext"
; Change extension
(file-name-with-extension "/home/user/Desktop/file.oldext" "newext")
; "/home/user/Desktop/file.newext"
; Path without extension
(file-name-sans-extension "/home/user/Desktop/file.ext")
; "/home/user/Desktop/file"
See:
- https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Name-Components.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Directory-Names.html
let expressions
See: https://www.gnu.org/software/emacs/manual/html_node/eintr/let.html
let
(let
((x 1)
(y 2))
(message (format "x=%d, y=%d" x y)))
; x=1, y=2
Each binding should be defined independent of the other.
Otherwise it will give error. For example:
(let
((x 1)
(y (+ x 2)))
(message (format "x=%d, y=%d" x y)))
; Debugger entered--Lisp error: (void-variable x)
; (+ x 2)
; (let ((x 1) (y (+ x 2))) (message (format "x=%d, y=%d" x y)))
; eval((let ((x 1) (y (+ x 2))) (message (format "x=%d, y=%d" x y))) t)
; eval-expression((let ((x 1) (y (+ x 2))) (message (format "x=%d, y=%d" x y))) nil nil 127)
; funcall-interactively(eval-expression (let ((x 1) (y (+ x 2))) (message (format "x=%d, y=%d" x y))) nil nil 127)
; call-interactively(eval-expression nil nil)
; command-execute(eval-expression)
let*
Unlike let, bindings can be defined dependent on other values mentioned in the same let* expression.
(let*
((x 1)
(y (+ x 2)))
(message (format "x=%d, y=%d" x y)))
; x=1, y=3
https://emacs.stackexchange.com/questions/42449/what-does-let-let-asterisk-mean-in-elisp
Copy whole buffer
These functions update the kill ring. To just delete text without disturbing kill ring use functions that start with kill-.
- Copy without deleting:
(copy-region-as-kill (point-min) (point-max)) - Copy with deleting:
(kill-region (point-min) (point-max))
https://www.gnu.org/software/emacs/manual/html_node/elisp/Kill-Functions.html
Writing to file
https://www.gnu.org/software/emacs/manual/html_node/elisp/Writing-to-Files.html
Lisp interaction mode
Handy to try out lisp snippets. Maybe in *scratch* buffer.
- Enable mode:
M-x lisp-interaction-mode C-j: Evaluate last line
https://www.gnu.org/software/emacs/manual/html_node/emacs/Lisp-Interaction.html
References:
- https://www.csie.ntu.edu.tw/~course/10420/Resources/lp/node34.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Iteration.html
Common lisp
May not be true for elisp.
- Complex numbers??
#c(2 3)means2+3i- Apparently not available in elisp
elisp libraries
- dash: like a bettern cl.el ??
- s.el: string manipulation
File system management
(directory-files "/foo" nil directory-files-no-dot-files-regexp)
https://www.gnu.org/software/emacs/manual/html_node/elisp/Contents-of-Directories.html
References
- An elisp style guide
- Emacs common lisp emulation: https://www.gnu.org/software/emacs/manual/html_node/cl/
- https://www.gnu.org/software/emacs/manual/pdf/eintr.pdf
Common lisp
- Run lisp from a file:
sbcl --script inp.lisp - Load lisp from file and start repl:
sbcl --load inp.lisp (print): print strings