Как получить базовую интеграцию с App ↔ Emacs?

Существует множество приложений, которые интегрируют Emacs с внешними процессами. GDB - это тот, который приходит на ум. Я могу контролировать GDB от emacs, а затем получать обратную связь на экране.

Я хотел бы сделать что-то в этом направлении с моим приложением.

Вот что я хочу:

  • установить связь между мной и emacs. Я бы, вероятно, начал новый процесс emacs и вложил его в мой графический интерфейс.
  • сообщите emacs, чтобы отобразить файл. (легко с emacsclient)
  • Скажите emacs, чтобы прокрутить до центра на определенном номере линии и hilite или просто переместите курсор туда.
    • Возможно, реальный вопрос заключается в том, как отправить произвольный код elisp из моего внешнего приложения для выполнения emacs.
    • Я не говорю elisp, но это было бы большим предлогом для изучения.
  • предоставить некоторые кликабельные области в буфере emacs, который при запуске отправит сообщение обратно в мое приложение.
    • Даже при отсутствии кликабельности ключевое связывание, отправляющее сообщение, будет началом. (но я знаю, что возможно щелкнуть, поэтому я прошу)

Я знаю, что все это возможно (что не возможно в emacs?), но я просто не знаю, с чего начать googling.

Ответ 1

Возможно, вы захотите посмотреть Distel (интеграция Emacs с системой сообщений Erlang) и SLIME (интерфейс между Emacs и Common Lisp). Это два режима Emacs, которые включают довольно впечатляющую интеграцию другой системы, асинхронно разговаривая с ней. В частности, существует статья о том, как была реализована Distel, а также другая полезная информация о том, как она работает здесь.

Ответ 2

Это зависит от того, как вы хотите настроить ситуацию. Определенно, часть руководства по процессам стоит прочитать. Чтение кода для пакета comint - это хорошее место для начала.

Вы указали довольно ограниченный набор функций, которые вы бы хотели разоблачить, что может быть разрешено прямым подключением. Вы можете найти полезные функции утилиты, посмотрев, что предусмотрено в "net-utils" (M-x find-library net-utils RET).

Если приложение, к которому вы пытаетесь подключиться, имеет интерпретируемый язык, я должен подключиться к нему, а не писать собственный парсер на стороне приложения.

Запуск Emacs из приложения

Поскольку вы запускаете Emacs из приложения (в отличие от другого способа (что могло бы облегчить эту работу)), это то, что я, вероятно, сделаю:

  • напишите немного perl script, чтобы открыть сокет и прочитать/записать в него
  • настроить '(читать (eval (print))) цикл в интерпретаторе (или написать пользовательский) и подключить его к сокету/порту
  • запуск Emacs с вызовом функции (--eval или --execute) с указанием сокета
  • запустите perl script как подпроцесс и порт (см., как doferior- lisp или inferior-tcl делают это)

В этот момент что-либо из Emacs может быть отправлено на подпроцесс perl ('comint-send-string) и передаваться на ваш REPL и имеют желаемый эффект. Аналогично, вы можете отправлять команды обратно emacs, просто отправляя строки и анализируя их по функциям, которые вы застряли в 'comint-output-filter-functions.

Затем вы должны были написать две небольшие библиотеки, одну на вашем языке, интерпретируемой APP, и одну в Emacs, чтобы сделать любую функциональность понятной. Библиотека emacs, вероятно, должна быть упакована в качестве основного (или второстепенного) режима в зависимости от того, что такое файлы. Если они предназначены исключительно для использования в приложении, в основном режиме, если они являются (например) файлами на С++, малый режим будет лучше, если вы захотите использовать режим С++.

Я бы написал маленький perl script в perl, в отличие от elisp, просто b/c Я знаю, как взаимодействовать с 'comint. Если маленький perl script можно заменить куском elisp и по-прежнему иметь преимущество с помощью comint, это будет дополнительный бонус.

У меня почти такая же настройка для Tcl/Tk, только команда соединения обрабатывается командой отправки Tk. Он работает очень хорошо.

Запуск приложения из Emacs

Теперь, если бы вы могли, вместо этого, запустить приложение из Emacs, это все еще применяется, только вы можете избавиться от маленького perl script и просто взаимодействовать через интерфейс comint. Не требуется сокетов.

  • Вам все равно нужен цикл repl (если приложение не может оставить stdin/stdout привязанным к интерпретатору
  • Библиотеки останутся теми же

Это будет намного проще, но работает только в том случае, если пользовательский поток позволяет вам двигаться в этом направлении. (У меня есть подозрение, что вы пишете это больше, чем просто ваше использование.)

Таким образом, было бы легче разработать/протестировать этот путь (запуск с Emacs). Вы можете добавить связь сокета позже в качестве улучшения. Какой из них больше мотивирует...

Ответ 3

Кликабельные области

Библиотека виджетов позволит вам сделать части вашего буфера на кнопки (также радио-боксы, флажки, списки), которые будут выполнять 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 Widget

Ответ 4

Вам нужен асинхронный процесс, который говорит с Emacs. Посмотрите руководство Emacs в разделе о процессах. Хорошим местом для запуска может быть функция start-process или start-process-shell-command.

Например, вы можете посмотреть источник для команды man, распространяемой с помощью emacs, или источника для vc-do-command. (Чтобы увидеть исходный код, введите C-h f, затем имя функции, а затем щелкните имя функции в окне справки.)

Ответ 5

В общем, вы должны посмотреть в руководство emacs.

Для вашей третьей пули взгляните на параметры командной строки emacs. В частности, --eval и -f.

Ответ 6

чтобы сделать код emacs execute lisp, просто создайте интерактивную функцию, а затем вы можете вызвать ее с помощью имени функции M-x. Ниже приведена основная функция, которая будет открывать файл повторно.

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

Для взаимодействия с вашим приложением вы можете запустить процесс async и связаться с ним с помощью буфера. проверьте функцию запуска в руководстве.

Для создания ссылок, доступных по ссылке, вы можете использовать следующие функции

  (make-button beg end 'action 'nmap-clear-buffer 'follow-link t)
  ;;for color
  (put-text-property beg end 'face nmap-active-button )

Ответ 7

Я не уверен, насколько это поможет, но вы можете взглянуть на реализацию SLIME, который, в то время как lisp ориентированный, имеет некоторые очень приятные функции. Например, вы можете настроить его, чтобы легко подключиться к запущенному процессу. Не совсем то, что вы хотите, но он получил все куски и довольно гладкий.