11

有很多应用程序将 Emacs 与外部进程集成在一起。GDB 是我想到的。我可以从 emacs 控制 GDB,然后在屏幕上获得反馈。

我想用我的应用程序朝这个方向做点什么。

这就是我想要的:

  • 在我和emacs之间建立连接。我可能会启动一个新的 emacs 进程并将其添加到我的 GUI 中
  • 告诉 emacs 显示一个文件。(使用 emacsclient 很容易)
  • 告诉emacs滚动到特定行号的中心并hilite或只是将光标移动到那里。
    • 可能真正的问题是如何从我的外部应用程序发送任意 elisp 代码以供 emacs 执行。
    • 我不会说 elisp,但这将是一个很好的学习借口
  • 在 emacs 缓冲区中提供一些可点击区域,这些区域在触发时会向我的应用程序发送一条消息。
    • 即使没有可点击性,发送消息的键绑定也是一个开始。(但我知道可点击的东西是可能的,所以我问)

我知道这一切都是可能的(在 emacs 中什么是不可能的?),但我只是不知道从哪里开始搜索。

4

7 回答 7

5

您可能想看看Distel(Emacs 与 Erlang 消息系统的集成)和SLIME(Emacs 和 Common Lisp 之间的接口)。这是两种 Emacs 模式,它们通过与另一个系统进行异步对话来实现令人印象深刻的集成。特别是,有一篇关于 Distel 是如何实现的论文,以及关于它是如何工作的其他一些很好的信息

于 2009-03-31T00:24:19.220 回答
5

这有点取决于你想如何设置。绝对值得一读的过程手册部分。阅读 'comint 包的代码是一个很好的起点。

您列出了一组非常有限的要公开的功能,可以通过直接连接来解决。通过查看 'net-utils (Mx find-library net-utils RET) 中提供的内容,您可以找到有用的实用功能。

如果您尝试连接的应用程序具有解释性语言,我会连接到该语言,而不是在应用程序端编写自定义解析器。

从应用程序启动 Emacs

由于您是从应用程序启动 Emacs(而不是其他方式(这可能使这项工作更容易)),这就是我可能会做的事情:

  • 编写小的 perl 脚本来打开一个套接字并读/写它
  • 在解释器中设置 '(read (eval (print))) 循环(或编写自定义循环)并将其连接到套接字/端口
  • 使用指定套接字的函数调用(--eval 或--execute)启动 Emacs
  • 将 perl 脚本作为子进程和端口启动(查看lower-lisplower-tcl是如何做到的)

那时,来自 Emacs 的任何内容都可以发送到 perl 子进程('comint-send-string),然后传递到您的REPL并在那里产生所需的效果。同样,您可以通过仅发送字符串将命令发送回 emacs,并让您在 'comint-output-filter-functions.

然后,您将编写两个小库,一个使用您的 APP 解释语言,一个使用 Emacs,以执行任何有意义的功能。emacs 库可能应该打包为主要(或次要)模式,具体取决于文件的样子。如果它们仅与应用程序一起使用,则为主要模式,如果它们是(例如)C++ 文件,则考虑到您可能想要利用 c++ 模式,次要模式会更好。

我会在 perl 中编写小 perl 脚本,而不是 elisp,只是 b/c 我知道如何与 'comint. 如果可以用一大块 elisp 替换小的 perl 脚本,并且仍然可以使用 comint 获得好处,那将是一个额外的好处。

我为 Tcl/Tk 设置了几乎相同的设置,只有连接内容由 Tk 的发送命令处理。它真的很好用。

从 Emacs 启动应用程序

现在,如果您可以从 Emacs 启动应用程序,上述仍然适用,只有您可以摆脱小 perl 脚本,只需通过 'comint 界面进行交互。不需要插座。

  • 您仍然需要 'repl 循环(如果应用程序不能将标准输入/标准输出绑定到解释器
  • 图书馆将保持不变

这会容易得多,但只有当用户流使您能够朝着那个方向前进时才有效。(我有一种预感,你写这篇文章不仅仅是为了你的使用。)

话虽如此,以这种方式开发/测试(从 Emacs 启动)可能更容易。您可以稍后添加套接字通信作为增强功能。哪个更励志...

于 2009-03-31T03:14:22.963 回答
5

可点击区域

小部件库可以让您将缓冲区的一部分制作成按钮(还有单选框、复选框、列表),当您单击它们时将执行 elisp。例如:

    (require 'widget)

(defun simple-widget-example ()
   (interactive)
  (switch-to-buffer "*Simple widget example*")

  (let ((inhibit-read-only t))
    (erase-buffer))

  (let ((all (overlay-lists)))
    ;; Delete all the overlays.
    (mapcar 'delete-overlay (car all))
    (mapcar 'delete-overlay (cdr all)))

  (widget-insert "Sample button\n")
  (widget-create 'push-button
         :notify (lambda (&rest ignore) 
               (message "Poop! Ha Ha!"))
         "Press Me")

  (use-local-map widget-keymap)

  (widget-setup))

请参阅Emacs 小部件库

于 2009-03-31T04:37:45.943 回答
3

您需要一个与 Emacs 对话的异步进程。查看 Emacs 手册中有关进程的部分。一个好的起点可能是使用start-processorstart-process-shell-command函数。

例如,您可以查看man随 emacs 分发的命令的源代码或vc-do-command. (要查看源代码,请输入 Ch f 然后输入函数名称,然后单击帮助窗口中的函数名称。)

于 2009-03-31T00:08:13.457 回答
1

通常,您应该在emacs 手册中四处查看。

对于您的第三个项目符号,请查看 emacs 的命令行选项。特别是 --eval 和 -f。

于 2009-03-30T22:55:23.520 回答
0

我不确定它有多大帮助,但你可能想看看SLIME的实现,它虽然面向 lisp,但有一些非常好的特性。例如,您可以将其设置为轻松附加到正在运行的进程。不完全是您想要的,但它拥有所有部件并且非常光滑。

于 2009-03-31T03:59:02.183 回答
0

要让 emacs 执行 lisp 代码,只需创建一个交互式函数,然后您可以使用 Mx 函数名调用它。以下是重新打开文件的基本功能。

    (defun na-reopen-file ()
  "Reopen file in buffer."
  (interactive)
  (let ((p (point)))
    (progn
      (find-alternate-file buffer-file-name)
      (goto-char p) ) ) )

为了与您的应用程序交互,您可以运行异步进程并使用缓冲区与其通信。检查手册中的启动过程功能。

要创建可点击链接,您可以使用以下功能

  (make-button beg end 'action 'nmap-clear-buffer 'follow-link t)
  ;;for color
  (put-text-property beg end 'face nmap-active-button )
于 2009-03-30T23:30:43.170 回答