3

Я узнал о более мощных возможностях zsh для завершения и расширения вкладок, и они, похоже, не работают, когда я запускаю zsh под emacs с оболочкой Mx:

cat $PATH<TAB> раскрывает переменную табуляции в терминале, но в режиме оболочки она просто подает звуковой сигнал.

Я изучил среду emacs, и вот что я нашел:

TAB (в переводе с) запускает команду Завершение в точке, которая представляет собой интерактивную скомпилированную функцию Lisp в 'minibuffer.el'.

Это связано с TAB.

(Завершение-на-точки)

Выполните завершение текста вокруг точки. Метод завершения определяется "функциями завершения в точке".

Завершение в точке-функции - это переменная, определенная в файле \'ubuffer.el '. Его значение (теги-завершение-в-точке-функция)

Итак, я предполагаю, что мне нужно добавить функцию к функциям завершения в точке, но какую?

4 ответа4

2

Попробуйте MultiTerm. Это единственный режим терминала Emacs, который хорошо работает с Zsh.

В режиме 'Mx shell' вы не можете использовать zle (классные дополнения к zsh tab).

С помощью «Mx term» (и ansi-term) терминал захватывает большинство команд C и M, которые вы хотите направить в emacs.

MultiTerm позволяет вам легко установить, какие команды вы хотите перехватить в emacs, и какие вы хотите перенаправить в терминал. Он поставляется с предустановленными значениями по умолчанию, которые работают очень хорошо.

Еще один совет: добавьте следующее в ваш .zshrc, чтобы позволить emacs отследить ваш текущий каталог, пока вы работаете на компакт-диске.

if [ -n "$INSIDE_EMACS" ]; then
  chpwd() { print -P "\033AnSiTc %d" }
  print -P "\033AnSiTu %n"
  print -P "\033AnSiTc %d"
fi
2

Вы не можете использовать завершение оболочки внутри M-x shell . Emacs отправляет ввод в оболочку по одной строке за раз, когда вы нажимаете RET . Когда вы нажимаете TAB , запускается встроенное завершение Emacs. В режиме оболочки Emacs пытается отслеживать ваш текущий каталог и дополняет имена файлов, но это все.

В зависимости от того, с какой программой вы взаимодействуете, режим оболочки может быть хорошим (потому что вы получаете все функции редакции Emacs, а не какие-либо ограниченные возможности, которые предоставляет оболочка или другая программа) или не очень хорошим (потому что вы не получаете никаких изящных возможностей оболочка или другая программа обеспечивает. При запуске Zsh вы находитесь в последней категории. Внутри Emacs вы можете запустить M-x term для запуска более полного эмулятора терминала в Emacs, где вы напрямую взаимодействуете с базовой программой. Вы получаете немного, но вы также теряете немного: возможности прокрутки в режиме Term плохо.

Вы можете переключаться между режимом Term и Shell в одном и том же буфере. Вы должны запустить буфер в режиме Term, затем вы можете использовать эти функции для переключения между ними. (Примечание: я изначально не писал эти функции, они были добавлены в Emacs Wiki, и я не нашел источник. Я немного приспособил это; предупреждение: я не проверял этот код.)

(defun term-switch-to-shell-mode ()
  (interactive)
  (shell-mode)
  (set-process-filter  (get-buffer-process (current-buffer)) 'comint-output-filter )
  (compilation-shell-minor-mode 1)
  (comint-send-input))
(defun shell-switch-to-term-mode ()
  (compilation-shell-minor-mode -1)
  (font-lock-mode -1)
  (set-process-filter  (get-buffer-process (current-buffer)) 'term-emulate-terminal)
  (term-mode)
  (term-char-mode)
  (term-send-raw-string (kbd "C-l")))
1

Это сложная проблема. Давайте посмотрим, что на самом деле происходит за смыслом.

Согласно Emacs Doc, <Tab> привязан к completion-at-point функции в точке . Вот что делает completion-at-point :

Выполните завершение текста вокруг точки.

Метод завершения определяется "функциями завершения в точке".

Проверьте Emacs Doc, переменная completion-at-point-functions идет здесь:

Завершение в точке-функции - это переменная, определенная в файле \'ubuffer.el '.

Его значение равно (завершение comint в точке t)

Локальный в буферной оболочке ; глобальное значение

(Теги-завершение-в-точка-функции)

Тогда давайте проверим документ о comint-completion-at-point

comint-complete-at-point - это псевдоним icicle-comint-dynamic-complete' in ob-sh.el'.

(Comint-завершение-на-точки)

Динамически выполнить завершение в точке.

Вызывает функции в `comint-dynamic-complete-functions ', но с

Сосульки функции заменены, чтобы выполнить завершение, пока функция

возвращает не ноль. Верните это значение.

Итак, ясно, что вам нужно добавить ваши любимые завершенные функции в comint-dynamic-complete-functions .

      (add-to-list 'comint-dynamic-complete-functions 'icicle-shell-dynamic-complete-filename)
      (add-to-list 'comint-dynamic-complete-functions 'icicle-shell-dynamic-complete-command)
0

Спасибо bengineerd за хорошее объяснение и фрагмент :)

Я использую zsh вместе с grml config - функция chpwd полностью справилась, но некоторые вещи были сломаны. Вот модифицированный фрагмент, чтобы вернуть автозаполнение этой клавиши со стрелкой:

if [ -n "$INSIDE_EMACS" ]; then
  # keep the old chpwd command and apply it later
  which zsh_chpwd >&/dev/null || \
    eval "$(echo "zsh_chpwd() {"; declare -f chpwd | tail -n +2)"
  chpwd() {
    print -P "\033AnSiTc %d"
    zsh_chpwd
  }
  print -P "\033AnSiTu %n"
  print -P "\033AnSiTc %d"
fi

и добавьте это внизу вашего .zshrc


Обновить

Чтобы исправить прыжки и удаление в терминалах, я нашел несколько источников, которые помогли улучшить общее впечатление:

и объединил их в https://github.com/0x17de/emacs-config/blob/master/multi-term-settings.el

Вот некоторая выдержка из критической части, которая включила мета + клавиши со стрелками (переход по словам) и удаление слов в обратном направлении:

(add-hook 'term-mode-hook
  (lambda ()
    (define-key term-raw-map (kbd "M-d") 'term-send-raw-meta)
    (define-key term-raw-map (kbd "M-<left>") 'term-send-backward-word)
    (define-key term-raw-map (kbd "M-<right>") 'term-send-forward-word)
    (define-key term-raw-map (kbd "M-<backspace>") 'term-send-backward-kill-word))
    (add-to-list 'term-bind-key-alist '("C-z e" . term-send-esc))))

(defun term-send-esc ()
  "Send ESC in term mode."
  (interactive)
  (term-send-raw-string "\e"))

Посмотрите term-send-esc из репозитория git, если вы используете ssh в удаленном режиме, войдите в режим вставки на некотором vim и застряли, потому что пока нет сопоставления для ESC.


также немного связано - с grml zshrc, если вы хотите, чтобы завершение клавиши со стрелкой происходило, и если у вас меньше пяти опций, найдите

 zstyle ':completion:*'               menu select=5

и измените это "5" (значение по умолчанию) на "1"

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .