在emacs中设置printf的快捷方式

在emacs中设置printf的快捷方式,emacs,Emacs,我是emacs的初学者,自从我开始使用emacs以来,我就成了它的忠实粉丝。最近我一直在调试一个大型的代码库,我需要放很多printf语句来理解代码是如何工作的。 如何在emacs中设置快捷方式来编写printf语句并将光标放在第一个双倒逗号之后,以便编写自己的调试消息?您可以使用(或类似的系统之一) sinppet的printf应该是这样的 # -*- mode: snippet -*- # name: printf # key: printf # -- printf("$0%n"); (如

我是emacs的初学者,自从我开始使用emacs以来,我就成了它的忠实粉丝。最近我一直在调试一个大型的代码库,我需要放很多printf语句来理解代码是如何工作的。 如何在emacs中设置快捷方式来编写printf语句并将光标放在第一个双倒逗号之后,以便编写自己的调试消息?

您可以使用(或类似的系统之一)

sinppet的printf应该是这样的

# -*- mode: snippet -*-
# name: printf
# key: printf
# --
printf("$0%n");

(如果它还不存在,我不确定你要找什么语言)

这个答案与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 "%s\n", "")

/* 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__ "%s\n", "")

#endif /* #ifndef __debug_h__ */
\ifndef\u调试\u h__
#定义调试__
#包括
#包括
#定义调试
/*#未定义调试*/
/*将(如printf)打印到stderr的宏,在文件名、行号和函数名前面加上前缀*/
#ifdef调试
#定义DBG(fmt,args…)do{fprintf(stderr,“%s(%u):在func%s中:“fmt,_u文件,_uu线,_u函数,_35; args);fflush(stderr)}while(0)
#埃利夫
#定义_DBG(fmt,args…)do{}while(0)
#恩迪夫
/*例如DBG(“任意字符串”)*/
#定义DBG(str)\ u DBG(str“%s\n”,“”)
/*例如DBGF(“格式化字符串(“%s”)和int(%d)”,“blah”,42)*/
#定义DBGF(fmt,参数…)\u DBG(fmt“\n”,参数)
/*例如,DBG_变量(“%0x08X”,(int)有趣的_变量)*/
#定义DBG_VAR(fmt,x)_DBG(“%s=”fmt“\n“,#x,x)
#定义PERR(str)if(errno){u-DBG(“%s”,”);perror(str);fflush(stderr);}
#定义DBG\u COMPILE\u TIMESTAMP(str)\u DBG(“在”\uuuu TIME\uuuu“%s\n”处的”\uuuuu日期\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
#endif/*#ifndef u调试u*/

我同意Trudbert的观点,即模板系统可能是一种发展方向,因为这正是他们想要提供的功能。此外,对于这样一个小的编辑,一个注释中推荐的键盘宏是一个可行的解决方案。尽管如此,我还是想添加一个Emacs Lisp版本,因为(a)对于这个简单的示例来说,它非常简单,(b)它可能会让您更全面地了解如何为将来的其他事情定制Emacs

(定义插入printf()
(互动)
(插入“printf(\“\”);)
(倒序字符3)
将上述代码放在
.emacs
文件中,并通过

  • 将该点置于函数内,然后按C-M-x运行
    (eval defun)
  • 将点放在最后一个
    )的正后方
    ,然后按C-x C-e运行
    (eval last sexp)
  • .emacs
    缓冲区内,类型为M-x eval缓冲区
  • 重新启动Emacs
在执行这些操作之后,Emacs现在将了解函数
insert printf
,以便您可以使用它。让我们一行一行地看一下它的作用

(定义插入printf()
  • 启动函数定义。函数名为
    insert printf
    ,不带参数,因此为空
    ()
(交互式)
  • 此声明将函数转换为命令,这意味着您可以通过键入M-x insert printf来调用它。如果未包含此声明,则只能从其他Lisp代码调用
    insert printf
(插入“printf(\“\”);”)
  • 将字符串
    printf(“”;
    插入点当前位置的缓冲区。注意,我们必须用反斜杠引用
(向后字符3))
  • 将点向左移动三个字符。插入
    printf(“”;
    后,点位于分号的正后方。由于您希望它位于双引号之间,因此我们必须将其向左移动三个字符
请注意,Emacs是单线程的,因此您不必担心其他线程会修改最后两行之间的点位置

现在,您可能希望将此函数绑定到键盘快捷键,这样就不必每次都键入M-x insert printf。您可以全局执行此操作,也可以仅在特定模式下执行此操作。因为
printf()是一个只在C或C++代码中真正意义上的表达式,在C/C++缓冲区中只能使用快捷方式,您可能会很好。
因此,让我们将以下代码也放在
.emacs
文件中:

(添加hook'c-initialization-hook
(lambda()(定义键c-mode-base-map“\c-cp”'插入printf)))
此代码所做的是向Emacs添加一个回调,该回调在首次初始化
cc mode
时被调用,在这种情况下,我们定义键盘快捷键C-CP来调用
insert printf
函数。请注意,我们专门在keymap
C-mode-base-map
中定义此快捷键,该快捷键作为c模式和c++模式的键映射继承。因此,我们的快捷方式在java模式下不可用

现在您已经了解了定制Emacs的一些一般步骤:

  • 根据功能定义新功能
  • 通过添加
    (交互式)
    声明,将函数转换为命令
  • 将代码放入
    .emacs
    文件中,以便在启动时加载
  • 在特定模式下全局或局部定义键盘快捷键
  • 使用初始化挂钩或
    (加载后求值)
    定义特定于模式的快捷方式,仅当该模式第一次实际激活时

  • 一个快速的解决方案是使用键盘宏(),但最好使用代码段。