Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
** Table of Contents
* [[*Audience][Audience]]
* [[*Programming in Emacs Lisp][Programming in Emacs Lisp]]
* [[*After reading this guide][After reading this guide]]
* [[*Trivial basics][Trivial basics]]
* [[*Evaluation][Evaluation]]
* [[*Discoverability][Discoverability]]
* [[*Finding functions of keybindings][Finding functions of keybindings]]
* [[*Getting documentation][Getting documentation]]
* [[*Find all bindings in the current buffer][Find all bindings in the current
buffer]]
* [[*Searching for documentation topics][Searching for documentation topics]]
* [[*Jumping to definition][Jumping to definition]]
* [[*Describe functions][Describe functions]]
* [[*Basic concepts][Basic concepts]]
* [[*Buffers][Buffers]]
* [[*Buffer-local variables][Buffer-local variables]]
* [[*Project-wide buffer-local variables][Project-wide buffer-local variables]]
* [[*The point][The point]]
* [[*The region][The region]]
* [[*Text properties][Text properties]]
* [[*Debugging][Debugging]]
* [[*Editing][Editing]]
* [[*Paredit][Paredit]]
* [[*Manipulating the buffer][Manipulating the buffer]]
* [[*Navigating the buffer][Navigating the buffer]]
* [[*Querying the buffer][Querying the buffer]]
* [[*Temporary buffers][Temporary buffers]]
* [[*Defining interactive functions][Defining interactive functions]]
* [[*Defining your own major mode][Defining your own major mode]]
* [[*Defining a minor mode][Defining a minor mode]]
* [[*Markers][Markers]]
* [[*Overlays][Overlays]]
* [[*Standard practices][Standard practices]]
* [[*Alternative sources][Alternative sources]]
** Audience
Programmers who are too busy to read through long tutorials and
manuals, but who want to extend their editor. You don't need to learn
everything from the ground up, just enough knowledge to be
self-sufficient. You've been using Emacs for a while and now it's time
you started making some handy extensions for yourself.
There are a bunch of existing guides, but they don't strike the right
balance of useful and helpful. Some just list functions, others try to
explain Emacs Lisp from the ground up as a language. You don't need to
know everything right away. See the [Alternative sources](#alternative-sources)
section for a list of these.
I'm not going to explain the Emacs Lisp language itself in any detail.
Programming in [[http://en.wikipedia.org/wiki/Emacs_Lisp][Emacs Lisp]] (look at the
Wikipedia page for the academic details)
is similar to programming in Python, Scheme, Common Lisp, JavaScript, Ruby, and
languages like that. Its syntax is funny but otherwise it's an imperative
language with similar data structures.
Like all Lisps, Emacs Lisp has macros which you can
[[https://www.gnu.org/software/emacs/manual/html_node/elisp/Macros.html#Macros]
[read about in the manual at
your leisure]]
I reference the manual throughout the guide by HTML link, but you can
read it inside your Emacs itself. Run: `C-h i m Elisp RET`
** Trivial basics
These are the basics to syntax that you can lookup in any guide or
just by looking at some Emacs Lisp code. I am assuming you're a
programmer who can pick things up like this just by looking at code. I
include these because I use them later:
#+BEGIN_SRC emacs-lisp
(* 2 3)
(concat "a" "b")
(defun func (arg1 arg2)
"Always document your functions."
<function body>)
(defvar var-name <the value>
"Always document your variables.")
(let ((x 1)
(y 2))
...)
#+END_SRC
In Lisp the normal `LET` doesn't let you refer to previous variables,
so you need to use `LET*` for that. This is likely to trip people up,
so I include it here.
#+BEGIN_SRC emacs-lisp
(let* ((x 1)
(y x))
...)
#+END_SRC
To do many things at once in one expression, use `PROGN`:
#+BEGIN_SRC emacs-lisp
(progn do-this
do-that)
#+END_SRC
[[http://www.gnu.org/software/emacs/manual/html_node/elisp/Local-
Variables.html#Local-Variables][See manual]] for details.
#+BEGIN_SRC emacs-lisp
(setq var-name value)
#+END_SRC
** Evaluation
* Use `M-:` to evaluate any Emacs Lisp expression and print the
result. I personally use this constantly.
* Use `C-x C-e` to evaluate the previous s-expression in the
buffer. I personally never use this. See next binding.
* Use `C-M-x` to evaluate the current top-level s-expression. I use
this to re-apply `defvar` and `defun` declarations.
* There is a REPL available by `M-x ielm`. I tend to use `M-:` rather
than the REPL but you might like it.
* Use `M-x eval-buffer` to evaluate the whole buffer of Emacs Lisp
code.
** Discoverability
It is bound to C-p.
Apply FUNCTION to each element of SEQUENCE, and make a list of the results.
The result is a list just as long as SEQUENCE.
SEQUENCE may be a list, a vector, a bool-vector, or a string.
Run `C-h b` to show a massive list of keybindings and the command they
run. You'll see something like, e.g. in `markdown-mode`:
* `M-x apropos`
* `M-x apropos-command`
* `M-x apropos-library`
* `M-x apropos-documentation`
Now you can use `M-.` to jump to the identifer at point and `M-,` to
jump back.
** Basic concepts
*** Buffers
All Emacs Lisp code when run has a current buffer. Operations that
claim to work on "the buffer" work on this current buffer. Some handy
functions, which you can run `C-h f` on to get more info:
See
[[https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffers.html#Buffers]
[Buffers]] in the manual for detailed info.
* major-mode
You can use this variable to see what mode you're in, if you need it.
#+BEGIN_SRC emacs-lisp
(defvar your-variable-name nil "Your documentation here.")
#+END_SRC
Then later on in your code that will run in a given buffer, use:
#+BEGIN_SRC emacs-lisp
(set (make-local-variable 'your-variable-name) <the-value>)
#+END_SRC
See [[http://www.gnu.org/software/emacs/manual/html_node/elisp/Buffer_002dLocal-
Variables.html#Buffer_002dLocal-Variables][manual]] for details.
A handy way to set a buffer local variable for every file that's within a
directory structure is to use
[[https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-
Variables.html][a `.dir-locals.el` file.]]
#+BEGIN_SRC emacs-lisp
((nil . ((indent-tabs-mode . t)
(fill-column . 80)))
(c-mode . ((c-file-style . "BSD")
(subdirs . nil)))
("src/imported"
. ((nil . ((change-log-default-name
. "ChangeLog.local"))))))
#+END_SRC
All Emacs Lisp code has a current point in the current buffer. It's a number.
It refers to where the cursor is. See
[[http://www.gnu.org/software/emacs/manual/html_node/elisp/Point.html][the manual
entry for point]], but here's
the basics:
Sometimes the region can be active, and you can use it in your Emacs Lisp code
to manipulate text specially. See
[[http://www.gnu.org/software/emacs/manual/html_node/elisp/The-Region.html#The-
Region][the manual]] for details. Rundown:
#+BEGIN_SRC emacs-lisp
(defun print-upper-region ()
"Demo to print the uppercased version of the active region."
(interactive)
(when (region-active-p)
(message "%S" (let ((string (buffer-substring (region-beginning)
(region-end))))
(with-temp-buffer
(insert string)
(upcase-region (point-min)
(point-max))
(buffer-substring-no-properties (point-min)
(point-max)))))))
#+END_SRC
To run it, `C-M-x` it, select some text and run `M-x print-upper-region`.
When you manipulate text in Elisp, it can have properties applied to it, and
those properties can be queried. Full details are
[[http://www.gnu.org/software/emacs/manual/html_node/elisp/Text-
Properties.html#Text-Properties][here]] but see the "Manipulating
the buffer" section in this guide for examples.
** Debugging
Run `M-: (setq debug-on-error t) RET` and any errors will open up the
debugger.
I'll write more about using the debugger stepper and breakpoints later.
** Editing
*** Paredit
**** Navigating
* `C-M-u` - Go up a node.
* `)` - Go to the end of the node or the end of the parent node when repeated.
* `C-M-f` - Go to the end of the node.
* `C-M-b` - Go to the start of the node.
**** Killing
`C-k` - Kill everything from here to the end of the line, including
any following lines that are included in the scope of the nodes
being killed. It will also kill inside strings but stop at the end
of the string.
**** Raising
**** Wrapping
**** Splitting
Any other command that inserts things can be called from Emacs Lisp, too.
#+BEGIN_SRC emacs-lisp
(put-text-property start end 'my-property-name <value>)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(set-text-properties start end 'my-property-name <value>)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(get-text-property <point> 'my-property-name)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(propertize "hello" 'my-property-name <value> 'another-prop <value2>)
#+END_SRC
If there's a kind of navigation you want to do that you don't know the function
name for, think of how you would do it with your keyboard and then use `C-h k` on
the commands to find out the functions being run.
Often you want to jump around the buffer to either query or manipulate something,
and then go back to where you were originally. To do this, use:
#+BEGIN_SRC emacs-lisp
(save-excursion ...)
#+END_SRC
For example:
#+BEGIN_SRC emacs-lisp
(save-excursion (beginning-of-line) (looking-at "X"))
#+END_SRC
** Temporary buffers
#+BEGIN_SRC emacs-lisp
(with-temp-buffer
(insert "Hello!"))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(defun foo ()
"Some function."
(interactive)
(do-some-stuff))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(define-key emacs-lisp-mode (kbd "C-c C-f") 'foo)
#+END_SRC
Example:
#+BEGIN_SRC emacs-lisp
(define-derived-mode hypertext-mode
text-mode "Hypertext"
"Major mode for hypertext.
\\{hypertext-mode-map}"
(setq case-fold-search nil))
(define-key hypertext-mode-map
[down-mouse-3] 'do-hyper-link)
#+END_SRC
A dummy example:
#+BEGIN_SRC emacs-lisp
(defvar elisp-guide-mode-map (make-sparse-keymap))
(define-minor-mode elisp-guide-mode "A simple minor mode example."
:lighter " ELGuide"
:keymap elisp-guide-mode-map
(if (bound-and-true-p elisp-guide-mode)
(message "Elisp guide activated!")
(message "Bye!")))
(define-key elisp-guide-mode-map (kbd "C-c C-a") 'elisp-guide-go)
(defun elisp-guide-go ()
(interactive)
(message "Go!"))
#+END_SRC
* [[https://github.com/chrisdone/structured-haskell-
mode/blob/master/elisp/shm.el#L110][structured-haskell-mode]]
* [[https://github.com/emacsmirror/paredit/blob/master/paredit.el#L203][paredit-
mode]]
* [[https://github.com/chrisdone/god-mode/blob/master/god-mode.el#L80..L86][god-
mode]]
** Markers
Markers are handy objects that store a point, and changes to the buffer make the
marker position move along. See
[[http://www.gnu.org/software/emacs/manual/html_node/elisp/Markers.html][the
manual]], which has a good section explaining
it. Their use-case is probably more intermediate than for a tutorial like this,
so I include them only so that you're aware of them.
Here's an example:
#+BEGIN_SRC emacs-lisp
(defun my-indent-region (beg end)
(interactive "r")
(let ((marker (make-marker)))
(set-marker marker (region-end))
(goto-char (region-beginning))
(while (< (point) marker)
(funcall indent-line-function)
(forward-line 1))))
#+END_SRC
You need to store the end of the region before you start changing the
buffer, because the integer position will increase as you start
indenting lines. So you store it in a marker and that marker's value
updates as the buffer's contents changes.
** Overlays
See [[http://www.gnu.org/software/emacs/manual/html_node/elisp/Overlays.html][the
manual on overlays]], these are a handy tool for a special kind of text
that behaves as if separate and above the buffer. This is more advanced, by the
time you want to use overlays you'll be happy reading the manual entry about it.
** Standard practices
*** Namespacing
(defun foo-go ()
"Go!"
...)
(provide 'foo)
To make this easier on your fingers, you can use something like:
#+BEGIN_SRC emacs-lisp
(defun emacs-lisp-expand-clever ()
"Cleverly expand symbols with normal dabbrev-expand, but also
if the symbol is -foo, then expand to module-name-foo."
(interactive)
(if (save-excursion
(backward-sexp)
(when (looking-at "#?'") (search-forward "'"))
(looking-at "-"))
(if (eq last-command this-command)
(call-interactively 'dabbrev-expand)
(let ((module-name (emacs-lisp-module-name)))
(progn
(save-excursion
(backward-sexp)
(when (looking-at "#?'") (search-forward "'"))
(unless (string= (buffer-substring-no-properties
(point)
(min (point-max) (+ (point) (length module-
name))))
module-name)
(insert module-name)))
(call-interactively 'dabbrev-expand))))
(call-interactively 'dabbrev-expand)))
(defun emacs-lisp-module-name ()
"Search the buffer for `provide' declaration."
(save-excursion
(goto-char (point-min))
(when (search-forward-regexp "^(provide '" nil t 1)
(symbol-name (symbol-at-point)))))
#+END_SRC
And then:
#+BEGIN_SRC emacs-lisp
(define-key emacs-lisp-mode-map (kbd "M-/") 'emacs-lisp-expand-clever)
#+END_SRC
Now you can write `(defun -blah M-/` and get `(defun foo-blah`. You
need a `(provide 'foo)` line at the bottom of your file for this to work.
** Alternative sources
* https://github.com/gar3thjon3s/elisp-cheatsheet/blob/master/cheatsheet.md
* http://wikemacs.org/wiki/Emacs_Lisp_Cheat_Sheet
* http://steve-yegge.blogspot.it/2008/01/emergency-elisp.html
* http://lispp.wordpress.com/2009/11/25/emacs-lisp-cheatsheet/
* http://stackoverflow.com/questions/5238245/elisp-programming-whats-the-best-
setup
* http://nic.ferrier.me.uk/blog/2012_07/tips-and-tricks-for-emacslisp
* https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
* http://www.emacswiki.org/emacs/EmacsLispIntro
* http://www.emacswiki.org/emacs/LearnEmacsLisp
* http://bzg.fr/learn-emacs-lisp-in-15-minutes.html
* http://www.delorie.com/gnu/docs/emacs-lisp-intro/emacs-lisp-intro_toc.html
* http://cjohansen.no/an-introduction-to-elisp
* http://emacswiki.org/emacs/ElispCookbook