`

Learn #Emacs Lisp in 15 minutes

    博客分类:
  • lisp
 
阅读更多
原文链接:http://bzg.fr/learn-emacs-lisp-in-15-minutes.html

I was surprised not to find an introduction to Emacs Lisp on http://learnxinyminutes.com so I created one. I sent a pull request to the github repository, hopefully this will be merged at some point.

In the meantime, comments and feedback are very welcome.

Thanks to @squintar who kept encouraging me to write this for her own needs. Enjoy!

;; This gives an introduction to Emacs Lisp in 15 minutes (v0.2c)
;;
;; First make sure you read this text by Peter Norvig:
;; http://norvig.com/21-days.html
;;
;; Then install GNU Emacs 24.3:
;;
;; Debian: apt-get install emacs (or see your distro instructions)
;; MacOSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
;;
;; More general information can be found at:
;; http://www.gnu.org/software/emacs/#Obtaining

;; Important warning:
;;
;; Going through this tutorial won't damage your computer unless
;; you get so angry that you throw it on the floor.  In that case,
;; I hereby decline any responsability.  Have fun!

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Fire up Emacs.
;;
;; Hit the `q' key to dismiss the welcome message.
;;
;; Now look at the gray line at the bottom of the window:
;;
;; "*scratch*" is the name of the editing space you are now in.
;: This editing space is called a "buffer".
;;
;; The scratch buffer is the default buffer when opening Emacs.
;; You are never editing files: you are editing buffers that you
;; can save to a file.
;;
;; "Lisp interaction" refers to a set of commands available here.
;;
;; Emacs has a built-in set of commands available in every buffer,
;; and several subsets of commands available when you activate a
;; specific mode.  Here we use the `lisp-interaction-mode', which
;; comes with commands to evaluate and navigate within Elisp code.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Semi-colons start comments anywhere on a line.
;;
;; Elisp programs are made of symbolic expressions ("sexps"):
(+ 2 2)

;; This symbolic expression reads as "Add 2 to 2".

;; Sexps are enclosed into parentheses, possibly nested:
(+ 2 (+ 1 1))

;; A symbolic expression contains atoms or other symbolic
;; expressions.  In the above examples, 1 and 2 are atoms,
;; (+ 2 (+ 1 1)) and (+ 1 1) are symbolic expressions.

;; From `lisp-interaction-mode' you can evaluate sexps.
;; Put the cursor right after the closing parenthesis then
;; hold down the control and hit the j keys ("C-j" for short).

(+ 3 (+ 1 2))
;;           ^ cursor here
;; `C-j' => 6

;; `C-j' inserts the result of the evaluation in the buffer.

;; `C-xC-e' displays the same result in Emacs bottom line,
;: called the "minibuffer".  We will generally use `C-xC-e',
;; as we don't want to clutter the buffer with useless text.

;; `setq' stores a value into a variable:
(setq my-name "Bastien")
;; `C-xC-e' => "Bastien" (displayed in the mini-buffer)

;; `insert' will insert "Hello!" where the cursor is:
(insert "Hello!")
;; `C-xC-e' => "Hello!"

;; We used `insert' with only one argument "Hello!", but
;; we can pass more arguments -- here we use two:

(insert "Hello" " world!")
;; `C-xC-e' => "Hello world!"

;; You can use variables instead of strings:
(insert "Hello, I am " my-name)
;; `C-xC-e' => "Hello, I am Bastien"

;; You can combine sexps into functions:
(defun hello () (insert "Hello, I am " my-name))
;; `C-xC-e' => hello

;; You can evaluate functions:
(hello)
;; `C-xC-e' => Hello, I am Bastien

;; The empty parentheses in the function's definition means that
;; it does not accept arguments.  But always using `my-name' is
;; boring, let's tell the function to accept one argument (here
;; the argument is called "name"):

(defun hello (name) (insert "Hello " name))
;; `C-xC-e' => hello

;; Now let's call the function with the string "you" as the value
;; for its unique argument:
(hello "you")
;; `C-xC-e' => "Hello you"

;; Yeah!

;; Take a breath.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Now switch to a new buffer named "*test*" in another window:

(switch-to-buffer-other-window "*test*")
;; `C-xC-e'
;: => [screen has two windows and cursor is in the *test* buffer]

;; Mouse over the top window and left-click to go back.  Or you can
;; use `C-xo' (i.e. hold down control-x and hit o) to go to the other
;; window interactively.

;; You can combine several sexps with `progn':
(progn
  (switch-to-buffer-other-window "*test*")
  (hello "you"))
;; `C-xC-e'
;: => [The screen has two windows and cursor is in the *test* buffer]

;; Now if you don't mind, I'll stop asking you to hit `C-xC-e': do it
;; for every sexp that follows.

;; Always go back to the *scratch* buffer with the mouse or `C-xo'.

;; It's often useful to erase the buffer:
(progn
  (switch-to-buffer-other-window "*test*")
  (erase-buffer)
  (hello "there"))

;; Or to go back to the other window:
(progn
  (switch-to-buffer-other-window "*test*")
  (erase-buffer)
  (hello "you")
  (other-window 1))

;; You can bind a value to a local variable with `let':
(let ((local-name "you"))
  (switch-to-buffer-other-window "*test*")
  (erase-buffer)
  (hello local-name)
  (other-window 1))

;; No need to use `progn' in that case, since `let' also combines
;; several sexps.

;; Let's format a string:
(format "Hello %s!\n" "visitor")

;; %s is a place-holder for a string, replaced by "Alice".
;; \n is the newline character.

;; Let's refine our function by using format:
(defun hello (name)
  (insert (format "Hello %s!\n" name)))

(hello "you")

;; Let's create another function which uses `let':
(defun greeting (name)
  (let ((your-name "Bastien"))
    (insert (format "Hello %s!\n\nI am %s."
                    name       ; the argument of the function
                    your-name  ; the let-bound variable "Bastien"
                    ))))

;; And evaluate it:
(greeting "you")

;; Some function are interactive:
(read-from-minibuffer "Enter your name: ")

;; Evaluating this function returns what you entered at the prompt.

;; Let's make our `greeting' function prompt for your name:
(defun greeting (from-name)
  (let ((your-name (read-from-minibuffer "Enter your name: ")))
    (insert (format "Hello!\n\nI am %s and you are %s."
                    from-name ; the argument of the function
                    your-name ; the let-bound var, entered at prompt
                    ))))

(greeting "Bastien")

;; Let's complete it by displaying the results in the other window:
(defun greeting (from-name)
  (let ((your-name (read-from-minibuffer "Enter your name: ")))
    (switch-to-buffer-other-window "*test*")
    (erase-buffer)
    (insert (format "Hello %s!\n\nI am %s." your-name from-name))
    (other-window 1)))

;; Now test it:
(greeting "Bastien")

;; Take a breath.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Let's store a list of names:
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))

;; Get the first element of this list with `car':
(car list-of-names)

;; Get a list of all but the first element with `cdr':
(cdr list-of-names)

;; Add an element to the beginning of a list with `push':
(push "Stephanie" list-of-names)

;; NOTE: `car' and `cdr' don't modify the list, but `push' does.
;; This is an important difference: some functions don't have any
;; side-effects (like `car') while others have (like `push').

;; Let's call `hello' for each element in `list-of-names':
(mapcar 'hello list-of-names)

;; Refine `greeting' to say hello to everyone in `list-of-names':
(defun greeting ()
    (switch-to-buffer-other-window "*test*")
    (erase-buffer)
    (mapcar 'hello list-of-names)
    (other-window 1))

(greeting)

;; Remember the `hello' function we defined above?  It takes one
;; argument, a name.  `mapcar' calls `hello', successively using each
;; element of `list-of-names' as the argument for `hello'.

;; Now let's arrange a bit what we have in the displayed buffer:

(defun replace-hello-by-bonjour ()
    (switch-to-buffer-other-window "*test*")
    (goto-char (point-min))
    (while (search-forward "Hello")
      (replace-match "Bonjour"))
    (other-window 1))

;; (goto-char (point-min)) goes to the beginning of the buffer.
;; (search-forward "Hello") searches for the string "Hello".
;; (while x y) evaluates the y sexp(s) while x returns something.
;; If x returns `nil' (nothing), we exit the while loop.

(replace-hello-by-bonjour)

;; You should see all occurrences of "Hello" in the *test* buffer
;; replaced by "Bonjour".

;; You should also get an error: "Search failed: Hello".
;;
;; To avoid this error, you need to tell `search-forward' whether it
;; should stop searching at some point in the buffer, and whether it
;; should silently fail when nothing is found:

;; (search-forward "Hello" nil t) does the trick:

;; The `nil' argument says: the search is not bound to a position.
;; The `t' argument says: silently fail when nothing is found.

;; We use this sexp in the function below, which doesn't throw an error:

(defun hello-to-bonjour ()
    (switch-to-buffer-other-window "*test*")
    (erase-buffer)
    ;; Say hello to names in `list-of-names'
    (mapcar 'hello list-of-names)
    (goto-char (point-min))
    ;; Replace "Hello" by "Bonjour"
    (while (search-forward "Hello" nil t)
      (replace-match "Bonjour"))
    (other-window 1))

(hello-to-bonjour)

;; Let's colorize the names:

(defun boldify-names ()
    (switch-to-buffer-other-window "*test*")
    (goto-char (point-min))
    (while (re-search-forward "Bonjour \\(.+\\)!" nil t)
      (add-text-properties (match-beginning 1)
                           (match-end 1)
                           (list 'face 'bold)))
    (other-window 1))

;; This functions introduces `re-search-forward': instead of
;; searching for the string "Bonjour", you search for a pattern,
;; using a "regular expression" (abbreviated in the prefix "re-").

;; The regular expression is "Bonjour \\(.+\\)!" and it reads:
;; the string "Bonjour ", and
;; a group of           | this is the \\( ... \\) construct
;;   any character      | this is the .
;;   possibly repeated  | this is the +
;; and the "!" string.

;; Ready?  Test it!

(boldify-names)

;; `add-text-properties' adds... text properties, like a face.

;; OK, we are done.  Happy hacking!

;; If you want to know more about a variable or a function:
;;
;; C-h v a-variable RET
;; C-h f a-function RET
;;
;; To read the Emacs Lisp manual with Emacs:
;;
;; C-h i m elisp RET
;;
;; To read an online introduction to Emacs Lisp:
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html

;; Thanks to these people for their feedback and suggestions:
;; - Wes Hardaker
;; - notbob
;; - Kevin Montuori
;; - Arne Babenhauserheide
;; - Alan Schmitt
分享到:
评论

相关推荐

    An Introduction to Programming in Emacs Lisp

    - **标题**:“An Introduction to Programming in Emacs Lisp”(Emacs Lisp编程入门) - **描述**:该资源是基于Emacs官方文档的重编版本,旨在提供更易阅读的字体样式。 #### 知识点详解 ##### 1. Emacs Lisp...

    Programming in Emacs Lisp

    Programming in Emacs Lisp英文版

    GNU Emacs Lisp 编程入门

    GNU Emacs Lisp 编程入门是一本非常专业的编程书籍,它详细地介绍了如何使用GNU Emacs Lisp这种编程语言来编写程序。GNU Emacs Lisp是一种用于GNU Emacs编辑器的编程语言,它是一种功能强大且灵活的编程工具,广泛...

    An Introduction to Programming in Emacs Lisp Second Edition

    15. **准备图表(Readying a Graph)**:介绍了如何在Emacs Lisp中生成图表。 16. **您的.emacs文件(Your ‘.emacs’ File)**:讲述了如何定制个人的Emacs配置文件。 17. **调试(Debugging)**:提供了调试技巧和...

    GNU Emacs Lisp编程入门

    GNU Emacs Lisp编程入门 GNU Emacs是一款著名的开源文本编辑器,以其高度可定制性和扩展性而闻名。Emacs的内核由C语言编写,但它的强大之处在于其内置的Lisp方言——Emacs Lisp(简称Elisp)。Elisp使得用户能够...

    GNU Emacs Lisp Reference Manual For Emacs Version 22.1 Revision 2.9, April 2007

    ### GNU Emacs Lisp 参考手册知识点总结 #### 1. 引言 GNU Emacs Lisp 参考手册为Emacs版本22.1提供了详细的指导,该版本为修订版2.9,发布于2007年4月。该手册由Bil Lewis、Dan LaLiberte、Richard Stallman以及...

    Atom-language-emacs-lisp,emacs lisp和yasnippet支持atom和github。.zip

    在“Atom-language-emacs-lisp.zip”这个压缩包中,主要关注的是对Emacs Lisp的支持。Emacs Lisp是一种用于扩展和定制GNU Emacs编辑器的Lisp方言。它提供了丰富的API和交互式编程环境,使得开发者可以编写自定义的...

    GNU Emacs Lisp编程入门(文本org)

    Programming in Emacs Lisp: An Introduction (美)Robert J.Chassell 著 毛文涛、吕芳 译 洪峰 审校 本书的作者罗伯特·卡塞尔是自由软件基金会的合创人之一,也是理查德·斯托曼博士青年时期结交的挚友,他...

    Robert Chassell:An Introduction to Programming in Emacs Lisp

    ### Robert Chassell:An Introduction to Programming in Emacs Lisp #### 知识点概览 - **Lisp Lists**: 介绍Lisp列表的概念及其在Emacs Lisp中的应用。 - **Lisp Atoms**: 解释Lisp原子的基本概念以及它们在...

    GNU EMACS lisp编程入门.djvu

    GNU EMACS lisp编程入门.djvuGNU EMACS lisp编程入门.djvuGNU EMACS lisp编程入门.djvuGNU EMACS lisp编程入门.djvuGNU EMACS lisp编程入门.djvuGNU EMACS lisp编程入门.djvuGNU EMACS lisp编程入门.djvu

    emacs lisp函数手册,版本24.3

    ### Emacs Lisp 函数手册知识点概览 #### 一、引言 Emacs Lisp(简称Elisp)是Emacs文本编辑器内置的一种高级编程语言。它不仅支持编辑文档时的脚本化操作,还具备完整的编程功能,使得用户可以扩展Emacs的功能。本...

    emacs lisp reference manual

    ### Emacs Lisp 参考手册知识点概述 #### 一、引言 Emacs Lisp(简称Elisp)是Emacs文本编辑器内置的一种高级编程语言。它不仅支持文本编辑操作,还能进行复杂的程序设计工作。Emacs Lisp参考手册为用户提供了一个...

    emacs lisp introduction

    ### Emacs Lisp介绍与编程基础 #### 一、Emacs Lisp概览 Emacs Lisp(简称Elisp)是一种专为Emacs文本编辑器设计的高级动态编程语言。它不仅支持Emacs的功能扩展,还允许用户根据自己的需求定制和开发新的功能。...

    Lisp参考

    ### Lisp参考:深入理解Emacs Lisp编程语言 #### 引言 Emacs Lisp,作为GNU Emacs文本编辑器的核心编程语言,不仅为用户提供了强大的编辑功能,还赋予了开发者无限的扩展可能。它远非仅仅是一种“扩展语言”,实际...

    emacs-lisp编程入门

    Emacs Lisp(简称Elisp)是GNU Emacs编辑器的核心编程语言,它允许用户自定义、扩展和控制这个功能丰富的文本编辑器。作为一个强大的脚本语言,Elisp在程序员和Emacs爱好者中广受欢迎,不仅适合初学者,也满足高级...

Global site tag (gtag.js) - Google Analytics