4

这是用例:我在技术博客上阅读了一篇关于 C++ 的文章(多继承失败,多线程失败等:)。通常它们带有一些代码。它几乎总是一个文件,我几乎总是想运行它并玩弄它。

我想用 Emacs 来做这件事,而且我想用最少的(或相当少的)击键来做。

所以假设我已经multiple_inheritance.cc在它自己的文件夹中创建了一个文件并粘贴了代码。我怎样才能真正快速地获得可执行文件?

这就是我现在正在做的事情(希望有人会改进它。)

(defun cpp-generate-makefile ()
  (interactive)
  (let* ((n-buffer (buffer-file-name))
         (n-file (file-name-nondirectory n-buffer))
         (n-target (file-name-sans-extension n-file))
         (n-makefile (concat (file-name-directory n-buffer) "Makefile")))
    (if (file-exists-p n-makefile)
        (when (called-interactively-p 'any)
          (message "Makefile already exists"))
      (with-current-buffer (find-file-noselect n-makefile)
        (insert 
         (concat n-target ": " n-file 
                 "\n\tg++ -g -O2 -std=c++0x -o $@ $^\n\n"
                 "clean: \n\trm -f " n-target "\n"))
        (save-buffer)))))

(defun cpp-run ()
  (interactive)
  (save-buffer)
  (cpp-generate-makefile)
  (compile "make"))

(add-hook 'c++-mode-hook
      (lambda()
            ;; ...
            (define-key c++-mode-map [f5] 'cpp-run)))

以下是目前让我慢下来的几件事:

  1. compile询问我是否要保存任何与 C++ 完全无关的打开文件。
  2. 我想在*compilation*缓冲区中有一个点,以防出现错误。我查看了compile.elcompilation-num-errors-found定义的 ,但该变量未在该文件中的任何位置使用。
  3. 另一方面,如果没有错误(我只需要一个谓词),为什么不启动term并运行程序呢?
4

2 回答 2

2

总结评论中的答案。

  1. 更改 的值compilation-ask-about-save。如果您不想全局更改它(使用 setq),您可以通过将其包装在(let ((compilation-ask-about-save nil)) ...function contents...)语句中来在函数内部更改它。
  2. 将 next-error 绑定到一些快速的东西:(define-key c++-mode-map "\M-j" 'next-error). 我个人为此使用 global-set-key,只是因为它在很多模式中都很有用。
  3. 将函数中的编译命令替换为(compile "make && ./a.out")(当然使用可执行文件的名称)。

希望这可以帮助。

于 2013-07-09T00:21:58.007 回答
0

我已经更新了必须添加run目标的代码Makefile。我还为 C 添加了一个扩展:

(defvar cpp-generate-compiler "g++ -g -O2 -std=c++0x")

(defun cpp-generate-makefile ()
  (interactive)
  (let* ((n-buffer (buffer-file-name))
         (n-file (file-name-nondirectory n-buffer))
         (n-target (file-name-sans-extension n-file))
         (n-makefile (concat
                       (file-name-directory n-buffer)
                       "Makefile")))
    (if (file-exists-p n-makefile)
        (when (called-interactively-p 'any)
          (message "Makefile already exists"))
      (with-current-buffer (find-file-noselect n-makefile)
        (insert
         (concat n-target ": " n-file
                 (format "\n\t%s -o $@ $^"
                   cpp-generate-compiler)
                 "\n\nclean: \n\trm -f " n-target
                 "\n\nrun: " n-target "\n\t ./" n-target
                 "\n\n.PHONY: clean run\n"))
        (save-buffer)))))

(defun cpp-run ()
  (interactive)
  (save-buffer)
  (cpp-generate-makefile)
  (compile "make run"))

(defun c-run ()
  (interactive)
  (let ((cpp-generate-compiler "gcc -g -O2 -std=c99"))
    (cpp-run)))

(add-hook 'c++-mode-hook
      (lambda()
            ;; ...
            (define-key c++-mode-map [f5] 'cpp-run)))
(add-hook 'c-mode-hook
      (lambda()
            ;; ...
            (define-key c-mode-map [f5] 'c-run)))
            
(setq compilation-ask-about-save nil)
(setq compilation-finish-functions
      (list (lambda(buffer str)
              (unless (string= str "finished\n")
                (push-mark)
                (next-error)))))

(setq compilation-ask-about-save nil)没有更多关于保存的警告(自动cpp-run保存)。

我只需要记住这一点M-g nM-g p 导航错误。

现在我的过程几乎是最佳的:从源到结果的一键,以防万一没有错误。

万一有错误,它是一个额外的M-g n. 现在,要是有办法compile打电话就好 了(push-mark)(next-error)……

升级版:

感谢@juanleon 的建议,解决了这个问题:

(setq compilation-finish-functions
      (list (lambda(buffer str)
              (unless (string= str "finished\n")
                (push-mark)
                (next-error)))))

但由于某种原因,push-mark在这种情况下无法正常工作。

于 2013-07-09T06:12:48.410 回答