我是emacs的初学者,自从我开始使用它以来,我已经成为它的忠实粉丝。最近我一直在调试一个很大的代码库,我需要放入很多printf语句来理解代码是如何工作的。我如何在emacs中设置快捷方式来编写printf语句并将光标放在第一个双倒逗号之后,以便我可以编写自己的调试消息?
您可以使用yasnippet(或类似的系统之一)
一个printf函数看起来像这样
# -*- mode: snippet -*-
# name: printf
# key: printf
# --
printf("$0%n");
(如果它不存在,我不确定你在寻找什么语言)
我同意Trudbert的观点,模板系统可能是可行的方法,因为这正是他们想要提供的功能。此外,对于这样一个小的编辑,一个评论中推荐的键盘宏是一个可行的解决方案。不过,我还是想添加一个Emacs Lisp版本,因为(a)对于这个简单的例子来说,它足够容易,(b)它可能会让您更深入地了解如何在将来为其他事情定制Emacs。
(defun insert-printf ()
(interactive)
(insert "printf("");")
(backward-char 3))
将上述代码放入.emacs
文件中,并通过
- 将点置于函数内,按C-M-x运行
(eval-defun)
- 将点放在最后一个
)
之后,按C-x C-e运行(eval-last-sexp)
- 内部的
.emacs
缓冲区类型M-x eval-buffer - 启动Emacs
在这些操作之后,Emacs现在将知道insert-printf
函数,以便您可以使用它。让我们逐行检查它,看看它是做什么的。
(defun insert-printf ()
- 开始一个函数定义。函数的名称是
insert-printf
,它不接受参数,因此是空的()
(interactive)
- 该声明将函数转换为命令,这意味着您可以通过键入M-x insert-printf来调用它。如果没有包含这个声明,那么调用
insert-printf
的唯一方法就是从其他Lisp代码中调用。 (insert "printf("");")
- 将字符串
printf("");
插入到当前位置的缓冲区中。注意,我们必须用反斜杠引用"
。
(backward-char 3))
- 将点向左移动三个字符。插入
printf("");
后,该点位于分号后面。因为你想让它在双引号之间,我们必须向左移动三个字符。
请注意,Emacs是单线程的,所以您不必担心其他线程修改最后两行之间的点位置。
现在,您可能希望将该函数绑定到键盘快捷键,这样您就不必每次都输入M-x insert-printf。您可以全局执行此操作,也可以仅针对特定模式执行此操作。由于printf();
是一个仅在C或c++代码中真正有意义的表达式,因此您可能只在C/c++缓冲区中使用快捷方式就可以了。
因此,让我们将以下代码也放入.emacs
文件中:
(add-hook 'c-initialization-hook
(lambda () (define-key c-mode-base-map "C-cp" 'insert-printf)))
这段代码所做的是向Emacs添加一个回调,该回调在cc-mode
首次初始化时被调用,在这种情况下,我们定义键盘快捷键C-c p来调用insert-printf
函数。请注意,我们在键图c-mode-base-map
中专门定义了这个快捷键,它是c模式和c++模式的键图继承的基础。因此,我们的快捷方式在java-mode
中是不可用的。
现在您已经看到了一些定制Emacs的一般步骤:
- 根据函数定义新功能
- 通过添加
(interactive)
声明将函数转换为命令 - 将代码放入
.emacs
文件中,以便在启动时加载 - 在特定模式下定义一个键盘快捷键,无论是全局的还是局部的
- 使用初始化钩子或
(eval-after-load)
来定义特定于模式的快捷方式,只有当该模式第一次被实际激活时。
这个答案是独立于Emacs的,但希望有人觉得它有用。它是一个头文件,定义了一些在stderr上打印调试消息的宏,但比仅仅使用printf()更方便。显然,你也可以用这些来制作片段或缩写。它可能使用在其他编译器中不可用的gcc特性。
#ifndef __debug_h__
#define __debug_h__
#include <stdio.h>
#include <errno.h>
#define DEBUG
/* #undef DEBUG */
/* macro that prints (like printf) to stderr, prepending the filename, line number, and function name */
#ifdef DEBUG
#define _DBG(fmt, args...) do { fprintf(stderr, "%s(%u): in func %s: " fmt, __FILE__, __LINE__, __FUNCTION__, ##args); fflush(stderr); } while (0)
#elif
#define _DBG(fmt, args...) do {} while(0)
#endif
/* e.g. DBG("arbitrary string"); */
#define DBG(str) _DBG(str "%sn", "")
/* e.g. DBGF("formated string ("%s") and int (%d)", "blah", 42); */
#define DBGF(fmt, args...) _DBG(fmt "n", args)
/* e.g. DBG_VAR("%0x08X", (int)interesting_variable); */
#define DBG_VAR(fmt, x) _DBG("%s = " fmt "n", #x, x)
#define PERR(str) if (errno) { _DBG("%s", ""); perror(str); fflush(stderr); }
#define DBG_COMPILE_TIMESTAMP(str) _DBG("Compiled on " __DATE__ " at " __TIME__ "%sn", "")
#endif /* #ifndef __debug_h__ */