使用 Emacs 作为 IDE

Posted

技术标签:

【中文标题】使用 Emacs 作为 IDE【英文标题】:Using Emacs as an IDE 【发布时间】:2010-09-08 23:17:35 【问题描述】:

目前,当我使用 C 或 C++ 进行编码时,我使用 Emacs 的工作流程涉及三个窗口。右侧最大的包含我正在使用的文件。左边一分为二,底部是我用来输入编译或制作命令的外壳,顶部通常是我在工作时想查阅的某种文档或 README 文件。现在我知道那里有一些非常专业的 Emacs 用户,如果打算将 Emacs 用作完整的 IDE,我很好奇其他 Emacs 在功能上是有用的。具体来说,大多数 IDE 通常以某种形式实现这些功能:

源代码编辑器 编译器 调试 文档查找 版本控制 OO 功能,例如类查找和对象检查器

对于其中的一些,Emacs 是如何适应这些功能的很明显,但其余的呢?此外,如果必须专注于特定语言,我会说它应该是 C++。

编辑:一位用户指出,当我说“剩下的呢”时,我应该更具体一些。大多数情况下,我对有效的版本控制以及文档查找感到好奇。例如,在 SLIME 中,对 Lisp 函数进行快速的超规范查找是相当容易的。有没有一种快速的方法可以在 C++ STL 文档中查找某些内容(例如,如果我忘记了 hash_map 的确切语法)?

【问题讨论】:

问题和所有答案都完全缺少主要的 IDE 点。但首先不要误会我的意思:我认为没有任何一个 IDE(除了一些罕见的 Lisp/Scheme 之外)可以与 Emacs 提供的任何地方相近。 然而现代 IDE 会做这样的事情:即时突出显示可能的编码错误(即使在部分不可编译的 AST 上)。 IntelliJ IDEA 做到了:如果您使用,例如,@NotNull,它会实时警告您可能的违规行为。然后是整个“按意图编码”:它在 Emacs 下(还)根本不起作用。 优秀 IDE 真正大放异彩的另一个领域:上下文代码完成(再一次,即使是在不偏不倚的、不可编译的源文件上)。上下文代码完成 p0wns hippie-expand 任何一天都觉得这并不好笑:它只会让 Emacs 蒙羞。与 Emacs 相比,IDE“文本编辑器”又是廉价、蹩脚、愚蠢、可悲的垃圾,我再次感到非常难过。但是优秀的 IDE 在很多 Emacs 基本上无处可去的领域(如重构、上下文代码完成、实时警告等)大放异彩。在我的 IDE 中间给我 Emacs。我渴望那一天。 代码崩溃怎么办? @SyntaxT3rr0r 我们有上下文相关代码完成的语义。 【参考方案1】:

您必须具体说明“其余”的含义。除了对象检查器(我知道)之外,emacs 很容易完成上述所有操作:

编辑器(很明显) 编译器 - 只需运行M-x compile 并输入您的编译命令。从那里开始,您可以只使用M-x compile 并使用默认值。 Emacs 将捕获 C/C++ 编译器错误(最适合 GCC)并帮助您导航到出现警告或错误的行。 调试 - 同样,当您要调试时,键入 M-x gdb,它将创建一个带有特殊绑定的 gdb 缓冲区 文档查找 - emacs 为代码导航提供了出色的 CScope 绑定。对于其他文档:Emacs 也有一个手册页阅读器,对于其他所有内容,还有网络和书籍。 版本控制 - 有很多 Emacs 绑定用于各种 VCS 后端(CVS、SCCS、RCS、SVN、GIT 都可以想到)

编辑:我意识到我对文档查找的回答确实与代码导航有关。这里有一些更中肯的信息:

Looking up manpages, info manuals, and Elisp documentation from within emacs Looking up Python documentation from within Emacs。

Google 搜索无疑会揭示更多示例。

正如第二个链接所示,即使不支持开箱即用,也可以在其他文档中查找函数(以及其他任何内容)。

【讨论】:

不应该是“M-x compile”吗? 我认为现在 GNU global 优于 CScope:gnu.org/software/global @Jürgen Hötzel:我有一段时间没有积极使用 Emacs。当时,我将 GNU global 与 CScope、IIRC 结合使用。不过,如果 global 已经超越了 CScope,我不会感到惊讶。 也可以通过 p4el.sourceforge.net/p4.el.html">p4.el</a> 强制支持【参考方案2】:

我不得不推荐 Emacs Code Browser 作为 emacs 更“传统”的 IDE 风格环境。

编辑:我现在还高度推荐 Magit,而不是 emacs 中的标准 VCS 接口。

【讨论】:

你应该可以编辑帖子,你似乎有足够的代表 iirc。【参考方案3】:

您是否尝试过 M-x 编译,而不是在 shell 窗口中运行 make 命令?它将运行您的 make 命令,显示错误,并且在许多情况下,如果输出包含文件名和行号,则可以很容易地跳转到导致错误的代码行。

如果您是 IDE 的粉丝,您可能还想看看 emacs 的 speedbar 包 (M-x speedbar)。如果您还没有,请了解如何使用标签表来导航您的代码。

【讨论】:

【参考方案4】:

emacs 的某些角落一旦被发现可以让您以您从未想过的方式提高工作效率。正如其他人所提到的,使用标签是缩放源代码的一种奇妙而快速的方法,并且使用 M-/ (dabbrev-expand) 通常在完成变​​量名时完全符合您的期望。

使用发生对于获取缓冲区中所有出现的正则表达式非常有用。这在重构代码和查找代码片段或变量的使用时非常方便,或者如果您在源文件中使用 TODO 标记并且想要全部访问它们。

flush-lines、sort-numeric-fields、replace-regexp 和 rectangle 函数对于从某些工具获取转储并将其转换为有用的数据(例如 elisp 程序或逗号分隔的电子表格)非常有用。

我写了一个关于 IDE 的页面,就像你可以用 emacs 做的事情一样

http://justinsboringpage.blogspot.com/2007/09/11-visual-studio-tricks-in-emacs.html

学习 elisp 是另一种很好的方式,可以让您自己回答除了典型 IDE 之外,emacs 还能做什么。

例如,我在博客上写过关于编写 Perforce 辅助函数(如责备)(编写自己的意味着你可以让它完全按照你想要的方式运行)......

http://justinsboringpage.blogspot.com/2009/01/who-changed-line-your-working-on-last.html

我还编写了代码,可以为某个函数动态创建 cmets,这与我正在使用的编码标准相匹配。

我的所有 elisp 代码都不是特别棒的,而且大部分代码已经存在于库中,但是能够让 emacs 执行在工作日中出现的自定义内容真的很有用。

【讨论】:

【参考方案5】:

您可以在my site 上找到有关 emacs 和版本控制集成的详细说明。我还在撰写有关使用 Emacs 作为多种语言的开发环境的文章 - C/C++、Java、Perl、Lisp/Scheme、Erlang 等...

【讨论】:

【参考方案6】:

对于版本控制,您可以使用多种功能,具体取决于您使用的版本控制系统。但有些功能对所有人来说都是通用的。

vc.el 是在文件级别处理版本控制的内置方法。它具有大多数版本控制系统的后端。例如,Subversion 后端随 Emacs 一起提供,还有 git 后端和其他可从其他来源获得的后端。

最有用的命令是 C-x v v (vc-next-action),它为您正在访问的文件执行适当的下一步操作。这可能意味着从存储库更新或提交您的更改,如果您使用的是需要它的系统(如 RCS),vc.el 还会重新绑定 C-x C-q 以签入和签出文件。

其他非常有用的命令是 C-x v lC-x v =,它们会显示您正在使用的文件的日志和当前差异。

但是为了真正的生产力,除了简单的事情之外,您应该避免使用单文件 vc.el 命令。有几个包可以让您概览整个树的状态,并为您提供更多功能,更不用说创建跨多个文件的一致提交的能力了。

其中大部分都深受影响或基于 CVS 的原始 pcl-cvs/pcvs。 subversion 甚至还有两个,psvn.eldsvn.el。有 git 等的包。

【讨论】:

【参考方案7】:

好的,这里的每个人都在给出完美的提示,让 emacs 成为一个很棒的 IDE。

但是任何人都应该记住,当您使用大量扩展自定义您的 emacs 时(尤其是那些用于动态类型检查、函数定义查找等的扩展),您的 emacs 将加载非常非常慢的编辑器.

要解决此问题,我强烈建议在 server mode 中使用 emacs。

它使用起来非常简单,无需自定义您的 init 文件。 你只需要以守护模式启动emacs;

emacs --daemon

这将创建一个 emacs 服务器,然后您可以从终端或从 gui 连接它。我还建议创建一些别名以便于调用。

alias ec="emacsclient -t"
alias ecc="emacsclient -c &"
# some people also prefer this but no need to fight here;
alias vi="emacsclient -t"

这样,emacs 会比 gedit 启动得更快,承诺。

这里的一个可能问题是,如果您从临时用户运行 emacs 守护程序,您可能无法以 root 连接 emacs 服务器。

因此,如果您需要打开具有 root 访问权限的文件;请改用tramp。只需使用普通用户运行您的 emacs 客户端并像这样打开文件;

C-x C-f
/sudo:root@localhost/some/file/that/has/root/access/permissions
# on some linux distro it might be `/su:root@...` 

这让我的生活变得更轻松,我可以通过这种方式在几毫秒内打开我重度定制的 python IDE。您可能还想将 emacs --daemon 添加到系统启动中,或者为 emacsclient 创建一个桌面文件。这取决于你。

有关 emacs 守护程序和 emacs 客户端的更多信息,请参见 wiki;

http://www.emacswiki.org/emacs/EmacsAsDaemon

http://www.emacswiki.org/emacs/EmacsClient

【讨论】:

我知道这是五年后的事了,但我当时也在使用它:如果你设置了EDITOR="emacsclient -t" VISUAL="emacsclient -c",你可以使用sudo -esudoedit 进行基于sudo 的编辑,这有时比使用 TRAMP 更可取(通常出于审计原因)。您还可以使用 --alternate-editor= 调用 emacsclient(需要末尾的空间),如果守护程序未运行,它将启动守护程序,这样就无需将守护程序置于系统启动中在每次启动时运行编辑器的第一次时,我愿意等待它。【参考方案8】:

我同意你应该了解 M-x compile(将 M-x next-error 绑定到一个短键序列)。

了解版本控制的绑定(例如 vc-diff、vc-next-action 等)

查看寄存器。您不仅可以记住缓冲区中的位置,还可以记住整个窗口配置(C-x r w -- window-configuration-to-register)。

【讨论】:

【参考方案9】:

探索 Emacs 的 VC 功能的起点(可能不明显)是 M-x vc-next-action

它对当前文件执行“下一个逻辑版本控制操作”,具体取决于文件的状态和 VC 后端。因此,如果文件不受版本控制,则注册它,如果文件已更改,则提交更改等。

这需要一点时间来适应,但我觉得它非常有用。

默认键绑定是 C-x v v

【讨论】:

【参考方案10】:

有一个TFS.el for emacs integration into Microsoft TFS。它适用于任何 TFS,包括运行 Codeplex.com 的 TFS。

设置的基本步骤:

    将 tfs.el 放在加载路径中。

    在您的 .emacs 文件中:

    (require 'tfs)
    (setq tfs/tf-exe  "c:\\vs2008\\common7\\ide\\tf.exe")
    (setq tfs/login "/login:domain\\userid,password")
          -or-
    (setq tfs/login (getenv "TFSLOGIN"))  ;; if you have this set
    

    同样在您的 .emacs 文件中,为 tfs 命令设置本地或全局键绑定。像这样:

    (global-set-key  "\C-xvo" 'tfs/checkout)
    (global-set-key  "\C-xvi" 'tfs/checkin)
    (global-set-key  "\C-xvp" 'tfs/properties)
    (global-set-key  "\C-xvr" 'tfs/rename)
    (global-set-key  "\C-xvg" 'tfs/get)
    (global-set-key  "\C-xvh" 'tfs/history)
    (global-set-key  "\C-xvu" 'tfs/undo)
    (global-set-key  "\C-xvd" 'tfs/diff)
    (global-set-key  "\C-xv-" 'tfs/delete)
    (global-set-key  "\C-xv+" 'tfs/add)
    (global-set-key  "\C-xvs" 'tfs/status)
    (global-set-key  "\C-xva" 'tfs/annotate)
    (global-set-key  "\C-xvw" 'tfs/workitem)
    

【讨论】:

嗯...这是在认真地提倡将您的密码以明文形式放在您的 .emacs 文件中吗? @T.E.D. - 不,只是一个插图。秘密应该存储在从 elisp 读取的其他地方。【参考方案11】:

我知道这是一篇很老的帖子。但是这个问题对emacs初学者是有效的。

IMO 使用 emacs 作为 ide 的最佳方式是将 language server protocol 与 emacs 一起使用。您可以在链接的网站上找到有关语言服务器的所有信息。

为了快速设置,我强烈建议您访问此页面 eglot。 IMO eglot 做得很好。它与公司等自动完成包很好地集成在一起。提供查找参考等。

同样对于调试器,您可能需要针对特定​​语言的特定调试器。您可以在 emacs 中使用 gdb。只需输入 M-x gdb

为了编译您的代码,最好使用 shell 命令。我正在做这个项目eproj。完成它需要一段时间。但它所做的只是将 shell 命令映射到项目类型。并通过 shell 构建您的项目。执行命令也是如此。我可能需要帮助来完成这个项目。它还没有准备好使用,但如果你知道一点 elisp,你可以通过代码。

除此之外,最好使用 emacs 编译命令。

对于版本控制,我还没有看到任何其他包可以与magit 的强大功能相媲美。它特定于 git。对于 git,还有另一个包 git-timemachine,我觉得它非常有用。

对象查找和类查找由语言服务器协议提供。

项目树可用于类似 ide 的接口 treemacs。

还有一个名为projectile的项目交互库。

对于自动完成,我发现company-mode 非常有用。

真正的 emacs 可以做任何事情。

【讨论】:

【参考方案12】:

compile、next-error 和 previous-error 都是在 Emacs 中进行 C++ 开发的非常重要的命令(在 grep 输出上也很有效)。 Etags、visit-tags-table 和 find-tag 也很重要。 completion.el 是 20 世纪最伟大的无名黑客之一,它可以将您的 C++ 黑客速度提高一个数量级。哦,别忘了ediff。

我还没有学习如何在不访问 shell 的情况下使用版本控制,但现在我运行提交的频率如此之高(使​​用 git)我可能不得不这样做。

【讨论】:

【参考方案13】:

您可能还会发现tabbar 很有用。它模拟了我从 Eclipse 迁移到 Emacs 时遗漏的唯一行为。绑定到“,”和“。”为了移动到上一个和下一个标签栏,它使您无需一直按 Ctrl-x b 切换缓冲区。

很遗憾,上述网页没有提供正确的下载版本。然而,大多数 Ubuntu 版本都在其 emacs-goodies 软件包中提供它。

【讨论】:

酷,我正在寻找一种方法来获得更新版本的标签栏。对于那些不在 Ubuntu 上的人,你可以在这里找到它。 packages.ubuntu.com/karmic/emacs-goodies-el【参考方案14】:

我在 Windows 上使用 emacs。 compile 模块很好,但我希望 compile 对它建议的 compile 命令行更智能。 It's possible to use "File Variables" to specify compile-command,但我想要比这更聪明的东西。所以我写了一个小函数来帮忙。当运行compile 时,它会猜测要使用的编译命令来提示用户。

guess 函数查找 vbproj 或 csproj 或 sln 文件,如果找到,它会建议 msbuild。然后它查看缓冲区文件名,并据此提出不同的建议。 .wxs 文件意味着它是一个 WIX 项目,并且您可能想要构建一个 MSI,因此猜测逻辑建议为 MSI 使用一个 nmake 命令。如果它是一个 javascript 模块,那么建议运行 jslint-for-wsh.js 来检查 .js 文件。作为后备,它建议使用nmake。

我使用的代码如下所示:

(defun cheeso-guess-compile-command ()
  "set `compile-command' intelligently depending on the
current buffer, or the contents of the current directory."
  (interactive)
  (set (make-local-variable 'compile-command)
       (cond
        ((or (file-expand-wildcards "*.csproj" t)
             (file-expand-wildcards "*.vcproj" t)
             (file-expand-wildcards "*.vbproj" t)
             (file-expand-wildcards "*.shfbproj" t)
             (file-expand-wildcards "*.sln" t))
         "msbuild ")

        ;; sometimes, not sure why, the buffer-file-name is
        ;; not set.  Can use it only if set.
        (buffer-file-name
         (let ((filename (file-name-nondirectory buffer-file-name)))
           (cond

            ;; editing a .wxs (WIX Soluition) file
            ((string-equal (substring buffer-file-name -4) ".wxs")
             (concat "nmake "
                     ;; (substring buffer-file-name 0 -4) ;; includes full path
                     (file-name-sans-extension filename)
                     ".msi" ))

            ;; a javascript file - run jslint
            ((string-equal (substring buffer-file-name -3) ".js")
             (concat (getenv "windir")
                     "\\system32\\cscript.exe c:\\users\\cheeso\\bin\\jslint-for-wsh.js "
                     filename))

            ;; something else - do a typical .exe build
            (t
             (concat "nmake "
                     (file-name-sans-extension filename)
                     ".exe")))))
        (t
         "nmake "))))


(defun cheeso-invoke-compile-interactively ()
  "fn to wrap the `compile' function.  This simply
checks to see if `compile-command' has been previously set, and
if not, invokes `cheeso-guess-compile-command' to set the value.
Then it invokes the `compile' function, interactively."
  (interactive)
  (cond
   ((not (boundp 'cheeso-local-compile-command-has-been-set))
    (cheeso-guess-compile-command)
    (set (make-local-variable 'cheeso-local-compile-command-has-been-set) t)))
  ;; local compile command has now been set
  (call-interactively 'compile))

;; in lieu of binding to `compile', bind to my monkeypatched function
(global-set-key "\C-x\C-e"  'cheeso-invoke-compile-interactively)

我尝试将此作为编译功能的“事先建议”,但无法使其令人满意地工作。因此,我定义了一个新函数并将其绑定到我一直用于compile 的相同击键组合。


编辑现在有“smarter-compile.el”,它让这个想法更进一步。

【讨论】:

【参考方案15】:

关于文档查找:这取决于您的编程语言。

C 库和系统调用通常记录在手册页中。为此,您可以使用M-x man。有些事情可能会在信息页面中更好地记录;使用M-x info

对于 elisp 本身,请使用 C-h f。对于 python,在解释器中使用&gt;&gt;&gt; help(&lt;function, class, module&gt;)

我发现大多数其他语言都以 html 形式提供文档。为此,请尝试使用嵌入式浏览器(我使用 w3m)。将您的 BROWSER 环境变量设置为围绕 emacsclient -e "(w3m-goto-url-new-session \"$@\")" 的包装脚本(在 *nix 上),以防某些东西可能会打开浏览器并且您希望它在 emacs 中打开。

【讨论】:

【参考方案16】:

近年来,Clang 成为了 Emacs C++ 支持的重要组成部分。 Atila Neves 在 CppCon 2015 上发表了演讲: "Emacs as a C++ IDE"

这是一个 16 分钟的演讲,他展示了以下主题的解决方案:

跳转到定义 自动完成 动态语法高亮显示 在项目中查找文件

幻灯片可以在here找到。

【讨论】:

【参考方案17】:

尝试 lsp 模式。现在您可以在 emacs 中使用其他 IDE 功能连接到服务器。查找更多信息:lsp-mode

【讨论】:

【参考方案18】:

在 Unix 或 X windows 风格中,我不知道是否有适用于所有事物的集成 IDE。

要与调试器交互,只需 IDE 的一个组件,请考虑 realgud。我发现它有用的另一件事是位置消息的解析器,因此如果您有调用堆栈跟踪并想在调用堆栈中的特定位置进行编辑,这个前端接口可以做到这一点。

到目前为止,这个程序可以改进。但随后它也可以使用致力于它的人来改进它。

免责声明:我在 realgud 上工作

【讨论】:

以上是关于使用 Emacs 作为 IDE的主要内容,如果未能解决你的问题,请参考以下文章

Linux 下配置 Python IDE——Emacs

7.Emacs进阶之模式

emacs使用记录

你的 IDE 太重了,试试 Emacs吧!

在 windows 系统上用 Emacs 编译 C

编辑器圣战之Emacs篇