在emacs中用gdb调试c/c++还是很方便的,不过一直以来用惯了vc6,按起gud默认的按键来说确实不很方便,所以就作了一些按键映射来模仿vc6的调试:
(setq gdb-many-windows t) (global-set-key [f5] 'gdb) (global-set-key [C-f5] 'gud-run) (global-set-key [S-f5] 'gud-cont) (global-set-key [f7] 'compile) (global-set-key [f8] 'gud-print) (global-set-key [C-f8] 'gud-pstar) (global-set-key [f9] 'gud-break) (global-set-key [C-f9] 'gud-remove) (global-set-key [f10] 'gud-next) (global-set-key [C-f10] 'gud-until) (global-set-key [S-f10] 'gud-jump) (global-set-key [f11] 'gud-step) (global-set-key [C-f11] 'gud-finish)
用上面的配置,emacs中:
可是用上面的配置和vc6还是有一些地方不太一样,主要有:
可惜在gud中我没找到和上面这三个对应的方法,所以经过几天的折腾,我自己写了几个函数,首先是(gdb-or-gud-go),这个函数会自动判断gdb是否已启动,如果没启动就调用(gdb)启动,否则就调用(gud-go),(gud-go)会根据程序是否在运行来决定执行(gud-run)还是(gud-cont):
(defun gdb-or-gud-go () "If gdb isn't running; run gdb, else call gud-go." (interactive) (if (and gud-comint-buffer (buffer-name gud-comint-buffer) (get-buffer-process gud-comint-buffer) (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))) (gud-call (if gdb-active-process "continue" "run") "") (gdb (gud-query-cmdline 'gdb))))
然后是(gud-break-remove),这个函数会根据当前行是否设置了断点来决定设置或删除断点:
(defun gud-break-remove () "Set/clear breakpoin." (interactive) (save-excursion (if (eq (car (fringe-bitmaps-at-pos (point))) 'breakpoint) (gud-remove nil) (gud-break nil))))
最后是(gud-kill),本来一开始我是想用(gud-call)向gdb发送"quit"命令来退出gdb,可是在运行的时候发送quit,gdb会询问是否退出,必须回答y才能真正退出,这样显得有点麻烦。而在gdb的菜单中提供了一个Kill命令其实是可以退出gdb的,所以我模仿kill的代码写了(gud-kill)来直接杀死调试进程:
(defun gud-kill () "Kill gdb process." (interactive) (with-current-buffer gud-comint-buffer (comint-skip-input)) (kill-process (get-buffer-process gud-comint-buffer)))
其实上面这些函数主要是模仿gdb-ui.el中的某些函数写出来的,有了这些函数,我就可以把f5绑定到(gdb-or-gud-go),把Shift-f5绑定到(gud-kill),把f9绑定到(gud-break-remove):
(global-set-key [f5] 'gdb-or-gud-go) (global-set-key [S-f5] 'gud-kill) (global-set-key [f9] 'gud-break-remove)
这样,先按f5会启动gdb,再按f5因为调试没运行就会执行(gud-run),遇到断点再按f5则会调用(gud-cont)。
按Shift+f5就会终止当前的调试。
在源代码行上就会根据当前行上是否有断点来确实设置或删除断点。
最终的配置文件如下:
(require 'gdb-ui) (defun gdb-or-gud-go () "If gdb isn't running; run gdb, else call gud-go." (interactive) (if (and gud-comint-buffer (buffer-name gud-comint-buffer) (get-buffer-process gud-comint-buffer) (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))) (gud-call (if gdb-active-process "continue" "run") "") (gdb (gud-query-cmdline 'gdb)))) (defun gud-break-remove () "Set/clear breakpoin." (interactive) (save-excursion (if (eq (car (fringe-bitmaps-at-pos (point))) 'breakpoint) (gud-remove nil) (gud-break nil)))) (defun gud-kill () "Kill gdb process." (interactive) (with-current-buffer gud-comint-buffer (comint-skip-input)) (kill-process (get-buffer-process gud-comint-buffer))) (setq gdb-many-windows t) (global-set-key [f5] 'gdb-or-gud-go) ;; (global-set-key [S-f5] '(lambda () (interactive) (gud-call "quit" nil))) (global-set-key [S-f5] 'gud-kill) (global-set-key [f7] '(lambda () (interactive) (compile compile-command))) (global-set-key [f8] 'gud-print) (global-set-key [C-f8] 'gud-pstar) (global-set-key [f9] 'gud-break-remove) ;; (global-set-key [f9] 'gud-break) ;; (global-set-key [C-f9] 'gud-remove) (global-set-key [f10] 'gud-next) (global-set-key [C-f10] 'gud-until) (global-set-key [S-f10] 'gud-jump) (global-set-key [f11] 'gud-step) (global-set-key [C-f11] 'gud-finish)