Автодополнение Bash в режиме оболочки Emacs - PullRequest
84 голосов
/ 02 октября 2008

В терминале GNOME Bash выполняет интеллектуальное автозаполнение. Например

apt-get in<TAB>

становится

apt-get install

В режиме оболочки Emacs это автозаполнение не работает, даже после того, как я явно указал /etc/bash_completion. Приведенный выше пример отображается как in или автоматически заполняется именем файла в текущем каталоге, а не допустимым параметром команды apt-get. Предположительно, это потому, что Emacs перехватывает нажатие клавиши Tab. Как включить интеллектуальное автозаполнение в shell-mode?

Ответы [ 8 ]

85 голосов
/ 16 ноября 2011

Я знаю, что этому вопросу уже три года, но я тоже заинтересовался его решением. Поиск в Интернете направил меня к части elisp, которая заставляет Emacs использовать bash для завершения в режиме оболочки В любом случае это работает для меня.

Проверьте это на https://github.com/szermatt/emacs-bash-completion.

20 голосов
/ 21 октября 2008

В оболочке emacs фактически emacs выполняет автозаполнение, а не bash. Если оболочка и emacs не синхронизированы (например, с помощью pushd, popd или некоторой пользовательской функции bash, которая изменяет текущий каталог оболочки), тогда автозаполнение перестает работать.

Чтобы это исправить, просто введите «dirs» в оболочку, и все вернется в синхронизацию.

У меня также есть следующее в моем .emacs:

(global-set-key "\M-\r" 'shell-resync-dirs)

Затем, просто нажав Esc-return, повторно выполняется автозаполнение.

14 голосов
/ 02 октября 2008

Я не знаю ответа на это. Но причина того, что это не работает так, как вы ожидаете, заключается, вероятно, в том, что завершение в оболочках emacs обрабатывается внутри emacs (функцией comint-dynamic-complete) и не имеет встроенных функций интеллектуального завершения. 1001 *

Боюсь, это не легко исправить.

Редактировать: предложение njsf об использовании term-mode, вероятно, так же хорошо, как и сейчас. Начните с

M-x term
Он включен в стандартный дистрибутив emacs (и как минимум в emacs21-common или emacs22-common на Ubuntu и Debian).
6 голосов
/ 20 февраля 2015

Пожалуйста, рассмотрите другой режим 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.

6 голосов
/ 03 октября 2008

Как сказал Матли, это не простая задача, поскольку bash запускается с --noediting, а TAB связан с comint-dynamic-complete.

Можно перепривязать TAB к команде self-insert-command в shell-comand-hook с помощью local-set-key и заставить shell-режим не начинаться с --noediting с помощью M-x customize-variable RET явный-bash-args, но я подозреваю, что он не подойдет для всех остальных видов редактирования.

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

РЕДАКТИРОВАТЬ: Под другими обычными комбинациями клавиш, обгоняемыми термином-режимом, я имею в виду все, кроме C-c, которое становится спасением для возможности переключения буферов. Таким образом, вместо C-x k, чтобы уничтожить буфер, вам нужно будет C-c C-x k. Или переключиться на другой буфер 'C-c C-x o' или 'C-c C-x 2'

1 голос
/ 16 апреля 2013

Я использую Prelude, и когда я нажимаю Meta + Tab, он завершается для меня.

Кроме того, Ctrl + i, кажется, делает то же самое.

0 голосов
/ 08 февраля 2017

Я использую режим руля. Он имеет такой функционал (после нажатия «TAB») enter image description here

0 голосов
/ 02 октября 2008

Я не претендую на звание эксперта по emacs, но это должно решить вашу проблему:

Создать: ~ / .emacs

Добавить к этому:

(требуется команда оболочки) (Оболочка-команда-завершение-режим)

Emacs берет на себя оболочку, поэтому настройки BASH не выполняются. Это установит автозаполнение для самого EMACS.

...