2

我对 Emacs lisp 编程有一个小时的了解。我对方案有一点经验,所以我总体上了解 lisps 的大局。但是,我只使用了方案的“纯功能”子集,不知道如何完成实际任务。

现在写,我知道这C-x C-e将评估当前光标位置括号中的代码。

我希望从 i = 1 循环到 10 并打印 i 的值。这是怎么做到的?我尝试了以下方法:

(defvar i 1)
(while (< i 11)
  (print "i: " i)
  (setq i (+ i 1)))

Emacs 告诉我:invalid function 0.

  1. 我该如何正确地做到这一点?
  2. 为什么emacs告诉我invalid function 0

随意给我一些关于如何C-x C-e在 emacs 中使用暂存缓冲区(我所知道的只是评估)的提示。感谢所有的帮助!

EDIT1:有人可以告诉我如何打印出i使用 while 循环的顺序值吗?

EDIT2:当我评估代码时,它会打开另一个小缓冲区,i一次显示每个值。但是,它不是一个大缓冲区,仅显示i13 到 19 之间的值。当我尝试进入该缓冲区时,它会立即关闭。我如何“滚动”通过那个微小的缓冲区?注意我通过终端使用emacs 24.3

EDIT3:我发现微小的缓冲区是消息缓冲区。有没有更好的方法来查看我的 elisp 代码的输出?Messages 缓冲区中充满了其他来自评估 emacs 中的东西的垃圾。

4

3 回答 3

3

首先,Options现在从菜单中启用“出错时输入调试器”,然后将(setq debug-on-error t)或添加(custom-set-variables '(debug-on-error t))到您的~/.emacs.el.

然后你会得到一个*Backtrace*缓冲区C-x C-e

Debugger entered--Lisp error: (invalid-function 1)
  1(10)
  print("i: " 1)
  (while (< i 11) (print "i: " i) (setq i (+ i 1)))
  eval((while (< i 11) (print "i: " i) (setq i (+ i 1))) nil)
  eval-last-sexp-1(nil)
  eval-last-sexp(nil)
  call-interactively(eval-last-sexp nil nil)
  command-execute(eval-last-sexp)

这表明错误来自print.

C-h f print RET会告诉你为什么,但结果是你想使用insert而不是在print这里。

于 2013-08-22T22:20:53.200 回答
3

Just as an added note, since you mentioned knowing some scheme -- if you like the interactive REPL that you can use in typical scheme environment, you might like ielm -- I think it probably stands for Interactive Emacs Lisp mode. Not sure. Anyway, M-x ielm RET will open up an emacs lisp REPL. Sometimes it is actually useful -- for example, when you want to inspect the content of a variable with a lot of data in it, ielm will print the whole thing out. Ielm is built in to my Emacs. Not sure when it was added to the standard distribution, but the earliest copyright in the source says 1994, so it is probably in your Emacs.

于 2013-08-23T05:59:46.827 回答
1

*scratch*您可以在相同模式或(我的偏好)在 mode 中的任何其他缓冲区中或任何其他缓冲区中评估 Emacs-Lisp sexps emacs-lisp-mode

In *scratch* you need only hit C-j (newline) after a sexp to evaluate it. In an emacs-lisp-mode buffer you can, as you said, use C-x C-e after a sexp. Or you can use M-x evaluate-region after selecting one or more sexps. As always, C-h m in any mode tells you about it, and usually lists important key bindings.

You can also check a global variable value using C-h v SOME-VAR. And you can evaluate any sexp on the fly from the minibuffer, using M-:. For example: M-: (setq foo (+ 42 (length bar)))

Wrt the debugger:

  • As @sds mentioned, debug-on-error puts you in the debugger when an error is raised. You can also set debug-on-quit and then enter the debugger using C-g to quit (e.g., during a loop).

  • If you know the function you want to debug, you can use M-x debug-on-entry.

  • Step through the debugger using d, or skip to the end of a step using c. Use q to quit the debugger.

  • You can also insert calls to function debug in source code, as debugger entry points: (debug).

The backtrace in the debugger is always more informative if you load the relevant source file e.g., foo.el, instead of the byte-compiled file, e.g., foo.elc. So before you use M-x debug-on-entry use C-h f to find out which file the function is defined in, and then load that file using M-x load-file /path/to/the/file.el.

There is also another debugger, besides debug -- look for edebug in the Elisp manual. Some people prefer edebug; I prefer debug.

于 2013-08-22T23:06:35.923 回答