mylisp

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

Practical Common Lisp

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")))

Comments

comments powered by Disqus