mylisp
Date and Time
String
(concat "http://us.php.net/" myword)
Array
> (setq v1 (make-array '(3)))
#(NIL NIL NIL)
> (setq v2 (make-array '(4) :initial-element "lisp is good"))
#("lisp is good" "lisp is good" "lisp is good" "lisp is good")
> (setq v3 #(1 2 3 4 "cat" '(99 100)))
#(1 2 3 4 "cat" '(99 100))
The function aref can be used to access any element in an array:
> (aref v3 3) 4 > (aref v3 5)
Lisp Programing
Kill-append and kill-new can put text into kill,
Define Function
01 (defun my-switch-buffer () 02 "Like switch-buffer but in the opposite direction" 03 (interactive "") 04 (other-window -1) 05 )
Anonymous Functions
With the previous method for defining hooks, you often find that you need a new name for a function, with the only reason that the function needs a name is so that you can give it to the add-hook declaration. With an anonymous function you can save time and avoid having to find a name for the function. Anonymous functions are defined with the keyword lambda instead of the keyword defun, as can be seen in the following example:
(add-hook 'c-mode-hook
(lambda ()
(setq fill-column 100)
(turn-on-auto-fill)
))
Code Characters for interactive
Code Characters for interactive
If you need a string input parameter, you can code like this : <#+BEGIN_SRC >
Books
This page contains snippets of code that demonstrate basic elisp programming operations in the spirit of the o’reilly cookbook series of books. For every task addressed, a worked-out solution is presented as a short, focused, directly usable piece of code.
All this stuff can be found elsewhere, but it is scattered about in libraries, manuals, etc. It would be helpful to have here in one spot.
These recipes should be pastable into the *scratch* buffer so that users can hit ‘C-j’ and evaluate them step by step.
There’s going to be some overlap with CategoryCode, obviously. Just link to more elaborate pages when appropriate. Should this page grow too large, we’ll split it up later.
Contents
Strings
Strings vs Buffer Content
Substrings
Processing Characters
Trim Whitespace
Formatting
Numbers
check if string is a valid number
random numbers
put commas in numbers
break up large numbers with commas
incrementing numbers
Dates and Times
get today's date
conversions
formatting dates
timers
Pattern Matching
Finding
Search and Replace
Verifying
Sequences
Lists
Vectors
Hashes
Storing and retrieving keys and values
Sorting Keys
Files
read
write
filter
locking
stat
deleting
copy/move/rename
Directories
traversing
path splitting
Processes
running a program
collecting output from a running program
handling signals
Sockets
TCP client
TCP server
Keyboard Events
Strings
Strings vs Buffer Content
While it is quite common in other programming languages to work on strings contained in variables in Emacs it is even more idiomatic to work on strings in buffers. That’s why the following contains examples of both.
Substrings
(substring "abcdefg" 0 3)
==> "abc"
(substring "abcdefg" -3 -1)
==> "ef"
The TO argument is optional:
(substring "abcdefg" -3)
==> "efg"
Buffers:
(with-temp-buffer
(insert "abcdefg")
(buffer-substring 2 4))
==> "bc"
Processing Characters
Reversing a string:
(string-to-list "foo")
==> (102 111 111)
(reverse (string-to-list "foo"))
==> (111 111 102)
(apply 'string (reverse (string-to-list "foo")))
==> "oof"
See CharacterProcessing and StringModification.
Looking at characters in buffers:
(with-temp-buffer
(insert "abcdefg")
(goto-char (point-min))
(while (not (= (char-after) ?b))
(forward-char))
(point))
==> 2
Trim Whitespace
Trim whitespace from the end of a string:
(setq test-str "abcdefg ")
(when (string-match "[ \t]*$" test-str)
(message (concat "[" (replace-match "" nil nil test-str) "]")))
Trim whitespace from a string with a perl-like chomp function:
(defun chomp (str)
"..."
(let ((s (if (symbolp str)(symbol-name str) str)))
(save-excursion
(while (and
(not (null (string-match "^\\( \\|\f\\|\t\\|\n\\)" s)))
(> (length s) (string-match "^\\( \\|\f\\|\t\\|\n\\)" s)))
(setq s (replace-match "" t nil s)))
(while (and
(not (null (string-match "\\( \\|\f\\|\t\\|\n\\)$" s)))
(> (length s) (string-match "\\( \\|\f\\|\t\\|\n\\)$" s)))
(setq s (replace-match "" t nil s))))
s))
Formatting
Numbers
check if string is a valid number
(defun string-integer-p (string)
(if (string-match "\\`-?[0-9]+\\'" string)
t
nil))
(string-integer-p "1234")
=> t
(string-integer-p "x1234")
=> nil
random numbers
(random 2) ;coin toss (0 or 1)
(+ (random 6) 1) ;dice
put commas in numbers
Using the Common Lisp package:
(require 'cl)
(let ((number (/ (random) (expt 2.0 28))))
(substitute ?\, ?\. (format "%g" number)))
break up large numbers with commas
(This does what I expected the previous recipe to do.)
(progn
(defun commafy (n)
"Put commas in an integer"
(let ((chunks ()))
(do ((chunk (mod (abs n) 1000) (mod rest 1000))
(rest (floor (abs n) 1000) (floor rest 1000)))
((and (zerop chunk) (zerop rest)))
(push (number-to-string chunk) chunks)
(when (< chunk 100) (push "0" chunks))
(when (< chunk 10) (push "0" chunks))
(when (plusp rest) (push "," chunks)))
(while (string= (first chunks) "0") (pop chunks))
(when (minusp n) (push "-" chunks))
(apply 'concat chunks)))
(commafy (random)))
incrementing numbers
See IncrementNumber.
Dates and Times
get today's date
See InsertingTodaysDate.
conversions
See StrPTime.
formatting dates
Use the function format-time-string which is a build in function in both Emacsen and works like strftime:
;; Year-Month-Day:
(insert (format-time-string "%Y-%m-%d"))
;; Hour:Minutes:Seconds
(insert (format-time-string "%H-%M-%S"))
timers
See IdleTimers
Pattern Matching
-Y΄Patterns‘ refers to RegularExpressions.
There’s a set of functions that work in strings, and a set that work in buffers.
Finding
(string-match "foo*" "Fight foo for food!")
==> 6
Buffers:
(with-temp-buffer
(insert "Fight foo for food!")
(goto-char (point-min))
(re-search-forward "foo*")
(point))
==> 10
Alternative without regular expressions: ‘search-forward’.
Note that the functions working on buffers move point to the end of the occurrence found and return it. That’s why the result is 10 instead of 6!
Search and Replace
(replace-regexp-in-string "foo*" "fu" "Fight foo for food!")
==> "Fight fu fur fud!"
Buffers:
(with-temp-buffer
(insert "Fight foo for food!")
(goto-char (point-min))
(while (re-search-forward "foo*" nil t)
(replace-match "fu"))
(buffer-string))
==> "Fight fu fur fud!"
Alternative without regular expressions: ‘search-forward’.
See also StringSearchAndReplace.
Verifying
Sometimes you just want to check whether you’re at the right place:
(with-temp-buffer
(insert "Fight foo for food!")
(goto-char (point-min))
(looking-at "fight"))
==> t
Sequences
Datatypes used to represent sequences of things:
_____________________________________________
| |
| Sequence |
| ______ ________________________________ |
| | | | | |
| | List | | Array | |
| | | | ________ ________ | |
| |______| | | | | | | |
| | | Vector | | String | | |
| | |________| |________| | |
| | ____________ _____________ | |
| | | | | | | |
| | | Char-table | | Bool-vector | | |
| | |____________| |_____________| | |
| |________________________________| |
|_____________________________________________|
Lists
List basics are explained on ListStructure. Lists can shrink and grow, but access to elements towards the end of the list is slow if the list is long.
Use ‘cons’ to append a new element to the front of a list. Use ‘nth’ to access an element of the list.
(let ((words '("fight" "foo" "for" "food!")))
(when (string= "foo" (nth 1 words))
(setq words (cons "bar" words)))
words)
==> ("bar" "fight" "foo" "for" "food!")
See ListModification for more ways of changing a list.
Iteration:
(let ((result))
(dolist (word '("fight" "foo" "for" "food!"))
(when (string-match "o" word)
(setq result (cons word result))))
(nreverse result))
==> ("foo" "for" "food!")
Note how ‘cons’ adds an element to the front of the list, so that usually the list has to be reversed after the loop. ‘nreverse’ is particularly efficient because it does this destructively by swiveling pointers around. See DestructiveOperations for more about this.
Filtering:
Emacs Lisp doesn’t come with a ‘filter’ function to keep elements that satisfy a conditional and excise the elements that do not satisfy it. One can use ‘mapcar’ to iterate over a list with a conditional, and then use ‘delq’ to remove the ‘nil’ values.
(defun my-filter (condp lst)
(delq nil
(mapcar (lambda (x) (and (funcall condp x) x)) lst)))
Therefore,
(my-filter 'identity my-list)
is equivalent to
(delq nil my-list)
For example:
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))
(my-filter 'numberp num-list))
==> (1 2 3 4)
Actually the package cl-seq contains the functions remove-if and remove-if-not. The latter can be used instead of my-filter.
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))
(remove-if-not 'numberp num-list))
==> (1 2 3 4)
(let ((num-list '(1 'a 2 "nil" 3 nil 4)))
(remove-if 'numberp num-list))
==> ((quote a) "nil" nil)
As an example here is the quick sort algorithm:
(defun quicksort (lst)
"Implement the quicksort algorithm."
(if (null lst) nil
(let* ((spl (car lst))
(rst (cdr lst))
(smalp (lambda (x)
(< x spl))))
(append (quicksort (remove-if-not smalp rst))
(list spl)
(quicksort (remove-if smalp rst))))))
(quicksort '(5 7 1 3 -9 8 7 -4 0))
==> (-9 -4 0 1 3 5 7 7 8)
Vectors
Vectors are fixed in size but elements can be accessed in constant time.
(let ((words ["fight" "foo" "for" "food!"]))
(when (string= "foo" (aref words 1))
(aset words 1 "bar"))
words)
==> ["fight" "bar" "for" "food!"]
Hashes
Hashes map keys to values. In a way they are similar to alists, except they are more efficient for a large number of keys.
More info is available on the HashMap page.
Storing and retrieving keys and values
By default, hash tables use ‘eql’ to compare keys. This is not appropriate for strings: (eql "alex" "alex") ⇒ nil. Thus, use ‘equal’ in these cases:
(let ((nick-table (make-hash-table :test 'equal)))
(puthash "kensanata" "Alex Schroeder" nick-table)
(gethash "kensanata" nick-table))
==> "Alex Schroeder"
Iterate:
(let ((nick-table (make-hash-table :test 'equal))
nicks)
(puthash "kensanata" "Alex Schroeder" nick-table)
(puthash "e1f" "Luis Fernandes" nick-table)
(puthash "pjb" "Pascal J. Bourguignon" nick-table)
(maphash (lambda (nick real-name)
(setq nicks (cons nick nicks)))
nick-table)
nicks)
==> ("pjb" "e1f" "kensanata")
Sorting Keys
Use ‘maphash’ to build up a list of keys, sort it, and then loop through the list:
(let ((nick-table (make-hash-table :test 'equal))
nicks)
(puthash "kensanata" "Alex Schroeder" nick-table)
(puthash "e1f" "Luis Fernandes" nick-table)
(puthash "pjb" "Pascal J. Bourguignon" nick-table)
(maphash (lambda (nick real-name)
(setq nicks (cons nick nicks)))
nick-table)
(mapcar (lambda (nick)
(concat nick " => " (gethash nick nick-table)))
(sort nicks 'string<)))
==> ("e1f => Luis Fernandes"
"kensanata => Alex Schroeder"
"pjb => Pascal J. Bourguignon")
Files
read
Processing a file is usually done with a temporary buffer:
(defun process-file (file)
"Read the contents of a file into a temp buffer and then do
something there."
(when (file-readable-p file)
(with-temp-buffer
(insert-file-contents file)
(goto-char (point-min))
(while (not (eobp))
;; do something here with buffer content
(forward-line)))))
write
To write something to a file you can create a temporary buffer, insert the things to write there and write the buffer contents to a file. The following example read a string and a filename (with completion, but doesn’t need to exist, see InteractiveCodeChar? F) and write the string to that file.
(defun write-string-to-file (string file)
(interactive "sEnter the string: \nFFile to save to: ")
(with-temp-buffer
(insert string)
(when (file-writable-p file)
(write-region (point-min)
(point-max)
file))))
filter
locking
stat
An interface to the kernel’s stat(2) is provided by the function file-attributes. The way times are represented may be a bit unexpected, though.
deleting
copy/move/rename
Directories
traversing
(defun walk-path (dir action)
"walk DIR executing ACTION with (dir file)"
(cond ((file-directory-p dir)
(or (char-equal ?/ (aref dir(1- (length dir))))
(setq dir (file-name-as-directory dir)))
(let ((lst (directory-files dir nil nil t))
fullname file)
(while lst
(setq file (car lst))
(setq lst (cdr lst))
(cond ((member file '("." "..")))
(t
(and (funcall action dir file)
(setq fullname (concat dir file))
(file-directory-p fullname)
(walk-path fullname action)))))))
(t
(funcall action
(file-name-directory dir)
(file-name-nondirectory dir)))))
(defun walk-path-visitor (dir file)
"Called by walk-path for each file found"
(message (concat dir file)))
(walk-path "~/" 'walk-path-visitor)
path splitting
Processes
running a program
collecting output from a running program
Again you have to make a difference between capturing the output in a string variable or in a buffer.
shell-command-to-string:
(defun insert-output (command)
(interactive "sCommand: ")
(insert (shell-command-to-string command)))
call-process which can be called with a buffer to insert the output to:
(defun output-to-buffer (buffer command)
(interactive "sBuffer name: \nsCommand: ")
(get-buffer-create buffer)
(call-process command nil buffer)
(switch-to-buffer (get-buffer buffer)))
The function start-process can be used to insert the output of a program into a buffer, too. See e.g. GlobalFF for an example.
XEmacs also comes with exec-to-string:
(defun test-insert-exec-text (command)
"Insert the output of an executable programm at the
current cursorpostion."
(interactive "sEnter command-string: ")
(insert (exec-to-string command)))
handling signals
Sockets
TCP client
TCP server
Perhaps EmacsEchoServer and EmacsDaytimeServer can be useful here.
Keyboard Events
Call function bound to key
(funcall (key-binding (kbd "M-TAB")))
or
(call-interactively (key-binding (kbd "M-TAB")))