设置emacs中printf的快捷方式



我是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的一般步骤:

  1. 根据函数定义新功能
  2. 通过添加(interactive)声明将函数转换为命令
  3. 将代码放入.emacs文件中,以便在启动时加载
  4. 在特定模式下定义一个键盘快捷键,无论是全局的还是局部的
  5. 使用初始化钩子或(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__ */

最新更新