Автозаполнение Bash в режиме оболочки Emacs
В терминале GNOME Bash выполняет умное автозаполнение. Например
apt-get in<TAB>
становится
apt-get install
В режиме оболочки Emacs это автозаполнение не работает, даже после того, как я явно указал источник /etc/bash_completion
, Приведенный выше пример выглядит как in
или автоматически завершается с именем файла в текущем каталоге, а не действительным apt-get
опция команды. Предположительно, это потому, что Emacs перехватывает нажатие клавиши Tab. Как включить интеллектуальное автозаполнение в shell-mode
?
8 ответов
Я знаю, что этому вопросу уже три года, но я тоже заинтересовался его решением. Поиск в Интернете направил меня к фрагменту elisp, который заставляет Emacs использовать bash для завершения в режиме оболочки. Это работает для меня, в любом случае.
Проверьте это на https://github.com/szermatt/emacs-bash-completion.
В оболочке emacs фактически emacs выполняет автозаполнение, а не bash. Если оболочка и emacs не синхронизированы (например, с помощью pushd, popd или некоторой пользовательской функции bash, которая изменяет текущий каталог оболочки), тогда автозаполнение перестает работать.
Чтобы это исправить, просто введите "dirs" в оболочку, и все будет синхронизировано.
У меня также есть следующее в моем.emacs:
(global-set-key "\M-\r" 'shell-resync-dirs)
Затем, просто нажав Esc-return, произойдет повторная синхронизация автозаполнения.
Я не знаю ответа на это. Но причина того, что это не работает так, как вы ожидаете, заключается, вероятно, в том, что завершение в оболочках emacs обрабатывается emacs внутренне (функцией comint-dynamic-complete) и не имеет встроенных функций интеллектуального завершения.
Боюсь, это не легко исправить.
Редактировать: njsf предлагает использовать термин-режим, вероятно, так же хорошо, как он получает. Начни с
Mx терминОн включен в стандартный дистрибутив emacs (и, по крайней мере, в emacs21-common или emacs22-common для Ubuntu и Debian).
Пожалуйста, рассмотрите другой режим M-x term
Как я сделал это, когда столкнулся с проблемой в 2011 году. Я пытался собрать все усилия над Inet в то время, чтобы заставить оболочку работать с завершением Bash, включая этот вопрос. Но с момента открытия альтернативы в лице term-mode
Я даже не хочу пытаться eshell
,
Это полный эмулятор терминала, так что вы можете запускать интерактивные программы внутри, как Midnight commander. Или переключиться на zsh
завершение, так что вы не потеряете время на настройку Emacs.
Вы получаете завершение TAB в bash бесплатно. Но более важно то, что вы получаете полную мощь Readline, например, инкрементный или префиксный поиск команд. Чтобы сделать эту настройку более удобной, проверьте мои .inputrc, .bashrc, .emacs.
Существенная часть .inputrc
:
# I like this!
set editing-mode emacs
# Don't strip characters to 7 bits when reading.
set input-meta on
# Allow iso-latin1 characters to be inserted rather than converted to
# prefix-meta sequences.
set convert-meta off
# Display characters with the eighth bit set directly rather than as
# meta-prefixed characters.
set output-meta on
# Ignore hidden files.
set match-hidden-files off
# Ignore case (on/off).
set completion-ignore-case on
set completion-query-items 100
# First tab suggests ambiguous variants.
set show-all-if-ambiguous on
# Replace common prefix with ...
set completion-prefix-display-length 1
set skip-completed-text off
# If set to 'on', completed directory names have a slash appended. The default is 'on'.
set mark-directories on
set mark-symlinked-directories on
# If set to 'on', a character denoting a file's type is appended to the
# filename when listing possible completions. The default is 'off'.
set visible-stats on
set horizontal-scroll-mode off
$if Bash
"\C-x\C-e": edit-and-execute-command
$endif
# Define my favorite Emacs key bindings.
"\C-@": set-mark
"\C-w": kill-region
"\M-w": copy-region-as-kill
# Ctrl+Left/Right to move by whole words.
"\e[1;5C": forward-word
"\e[1;5D": backward-word
# Same with Shift pressed.
"\e[1;6C": forward-word
"\e[1;6D": backward-word
# Ctrl+Backspace/Delete to delete whole words.
"\e[3;5~": kill-word
"\C-_": backward-kill-word
# UP/DOWN filter history by typed string as prefix.
"\e[A": history-search-backward
"\C-p": history-search-backward
"\eOA": history-search-backward
"\e[B": history-search-forward
"\C-n": history-search-forward
"\eOB": history-search-forward
# Bind 'Shift+TAB' to complete as in Python TAB was need for another purpose.
"\e[Z": complete
# Cycling possible completion forward and backward in place.
"\e[1;3C": menu-complete # M-Right
"\e[1;3D": menu-complete-backward # M-Left
"\e[1;5I": menu-complete # C-TAB
.bashrc
(ДА! Есть даббрев в Bash от любого слова в ~/.bash_history
):
set -o emacs
if [[ $- == *i* ]]; then
bind '"\e/": dabbrev-expand'
bind '"\ee": edit-and-execute-command'
fi
.emacs
сделать навигацию удобной в буфере терминов:
(setq term-buffer-maximum-size (lsh 1 14))
(eval-after-load 'term
'(progn
(defun my-term-send-delete-word-forward () (interactive) (term-send-raw-string "\ed"))
(defun my-term-send-delete-word-backward () (interactive) (term-send-raw-string "\e\C-h"))
(define-key term-raw-map [C-delete] 'my-term-send-delete-word-forward)
(define-key term-raw-map [C-backspace] 'my-term-send-delete-word-backward)
(defun my-term-send-forward-word () (interactive) (term-send-raw-string "\ef"))
(defun my-term-send-backward-word () (interactive) (term-send-raw-string "\eb"))
(define-key term-raw-map [C-left] 'my-term-send-backward-word)
(define-key term-raw-map [C-right] 'my-term-send-forward-word)
(defun my-term-send-m-right () (interactive) (term-send-raw-string "\e[1;3C"))
(defun my-term-send-m-left () (interactive) (term-send-raw-string "\e[1;3D"))
(define-key term-raw-map [M-right] 'my-term-send-m-right)
(define-key term-raw-map [M-left] 'my-term-send-m-left)
))
(defun my-term-mode-hook ()
(goto-address-mode 1))
(add-hook 'term-mode-hook #'my-term-mode-hook)
Как и любые обычные команды, как C-x o
не работают в режиме эмуляции терминала. Я расширил раскладку клавиш:
(unless
(ignore-errors
(require 'ido)
(ido-mode 1)
(global-set-key [?\s-d] #'ido-dired)
(global-set-key [?\s-f] #'ido-find-file)
t)
(global-set-key [?\s-d] #'dired)
(global-set-key [?\s-f] #'find-file))
(defun my--kill-this-buffer-maybe-switch-to-next ()
"Kill current buffer. Switch to next buffer if previous command
was switching to next buffer or this command itself allowing
sequential closing of uninteresting buffers."
(interactive)
(let ( (cmd last-command) )
(kill-buffer (current-buffer))
(when (memq cmd (list 'next-buffer this-command))
(next-buffer))))
(global-set-key [s-delete] 'my--kill-this-buffer-maybe-switch-to-next)
(defun my--backward-other-window ()
(interactive)
(other-window -1))
(global-set-key [s-up] #'my--backward-other-window)
(global-set-key [s-down] #'other-window)
(global-set-key [s-tab] 'other-window)
Обратите внимание, что я использую super
ключ так term-raw-map
и, возможно, любая другая таблица ключей не конфликтует с моими привязками клавиш. Делать super
ключ слева Win
ключ я использую .xmodmaprc
:
! To load this config run:
! $ xmodmap .xmodmaprc
! Win key.
clear mod3
clear mod4
keycode 133 = Super_L
keycode 134 = Hyper_R
add mod3 = Super_L
add mod4 = Hyper_R
Вы просто должны запомнить 2 команды: C-c C-j
- войти в обычный режим редактирования Emacs (для копирования или поиска в буфере текста), C-c C-k
- вернуться в режим эмуляции терминала.
Выбор мыши и Shift-Insert
работать как в xterm
,
Как сказал Матли, это не простая задача, так как bash запускается с --noediting, а TAB связан с comint-dynamic-complete.
Можно было бы перепривязать TAB к команде self-insert-command в shell-comand-hook с помощью local-set-key и сделать так, чтобы режим оболочки не начинался с --noediting с помощью Mx customize-variable RETlicit-bash-args, но я подозреваю, что это не будет хорошо со всем другим редактированием.
Возможно, вы захотите попробовать режим терминов, но у него есть другой набор проблем, потому что некоторые другие обычные комбинации клавиш перегружены режимом терминов.
РЕДАКТИРОВАТЬ: Под другими обычными комбинациями клавиш, перехваченными режимом термина, я имею в виду все, кроме Cc, которое становится спасением, чтобы иметь возможность переключать буферы. Таким образом, вместо Cx k, чтобы уничтожить буфер, вам нужно будет Cc Cx k. Или переключиться на другой буфер 'Cc Cx o' или 'Cc Cx 2'
Я знаю, что этому посту уже более 11 лет. Но я создал функцию для завершения собственной оболочки в Emacs. Он просто отправляет клавишу табуляции базовому процессу и перехватывает вывод, поэтому он точно такой же, как и в самой оболочке.
https://github.com/CeleritasCelery/emacs-native-shell-complete
Я использую Prelude, и когда я нажимаю Meta+Tab, он завершается для меня.
Кроме того, Ctrl+ I, кажется, делает то же самое.
Я не претендую на звание эксперта по emacs, но это должно решить вашу проблему:
Создать: ~/.emacs
Добавьте к этому:
(требуется 'команда оболочки) (режим команды оболочки завершение)
Emacs берет на себя оболочку, поэтому настройки BASH не выполняются. Это установит автоматическое завершение для самого EMACS.