wake-up-neo.net

Bash-Autovervollständigung im Emacs-Shell-Modus

Im GNOME-Terminal führt Bash intelligente Auto-Vervollständigung durch. Zum Beispiel

apt-get in<TAB>

wird

apt-get install

Im Emacs Shell-Modus funktioniert diese automatische Vervollständigung nicht, auch nachdem ich /etc/bash_completion explizit als Quellcode angegeben habe. Das obige Beispiel bleibt in oder wird automatisch mit einem Dateinamen im aktuellen Verzeichnis und nicht mit einer gültigen apt-get-Befehlsoption abgeschlossen. Vermutlich ist dies darauf zurückzuführen, dass Emacs das Drücken der Tabulatortaste abfängt. Wie aktiviere ich Smart Auto-Completion in Shell-mode?

81
Chris Conway

Ich weiß, dass diese Frage drei Jahre alt ist, aber auch daran habe ich mich interessiert. Eine Websuche führte mich zu einem Stück Elisp, das Emacs dazu bringt, die Bash im Shell-Modus zu beenden. Es funktioniert auf jeden Fall für mich.

Überprüfen Sie es unter https://github.com/szermatt/emacs-bash-completion .

84

In der Emacs-Shell ist es eigentlich Emacs, der die automatische Vervollständigung durchführt, nicht Bash. Wenn Shell und Emacs nicht synchron sind (z. B. durch Verwendung von pushd, popd oder einer bash-Benutzerfunktion, die das aktuelle Verzeichnis der Shell ändert), funktioniert die automatische Vervollständigung nicht mehr.

Um dies zu beheben, tippen Sie einfach 'dirs' in die Shell und die Dinge werden wieder synchronisiert.

Ich habe auch folgendes in meinen .emacs:

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

Wenn Sie dann Esc-Return drücken, wird die automatische Vervollständigung erneut synchronisiert.

17
Steve Lacey

Ich weiß nicht die Antwort darauf. Der Grund dafür, dass es nicht wie erwartet funktioniert, liegt wahrscheinlich daran, dass die Fertigstellung in Emacs-Shells intern von Emacs (von der Comint-Dynamic-Complete-Funktion) ausgeführt wird und diese intelligenten Abschlussfunktionen nicht integriert sind.

Ich fürchte, es ist nicht leicht zu beheben.

Edit: njsfs Vorschlag, den Term-Modus zu verwenden, ist wahrscheinlich so gut, wie er nur kann. Beginnen Sie mit 

M-x Begriff
Es ist in der Standard-Emacs-Distribution enthalten (und in emacs21-common oder emacs22-common mindestens unter Ubuntu und Debian).

13
matli

Bitte überlegen Sie einen anderen Modus M-x term, wie ich es bei einem Problem mit dem Problem 2011 gemacht habe. Ich habe damals versucht, alle Anstrengungen über Inet zu unternehmen, um Shell mit Bashs Abschluss zusammenarbeiten zu lassen, einschließlich dieser Frage. Aber seit ich die Alternative in Bezug auf term-mode entdeckt habe, möchte ich eshell nicht einmal ausprobieren.

Es ist ein vollständiger Terminal-Emulator, sodass Sie interaktive Programme wie den Midnight Commander ausführen können. Oder wechseln Sie zur Fertigstellung von zsh, damit Sie bei der Emacs-Konfiguration keine Zeit verlieren.

Sie erhalten TAB-Abschluss in bash kostenlos. Wichtiger ist jedoch, dass Sie die volle Readline-Fähigkeit erhalten, wie inkrementelle oder vorangestellte Befehlssuche. Um dieses Setup komfortabler zu gestalten, überprüfen Sie meine .inputrc , .bashrc , .emacs .

Wesentlicher Teil von .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.
"\[email protected]": 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 (YEA! Es gibt dabbrev in Bash aus einem beliebigen Wort in ~/.bash_history):

set -o emacs

if [[ $- == *i* ]]; then
  bind '"\e/": dabbrev-expand'
  bind '"\ee": edit-and-execute-command'
fi

.emacs, um die Navigation im Termpuffer komfortabel zu gestalten:

(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)

Da übliche Befehle wie C-x o nicht im Terminalemulationsmodus funktionieren, habe ich keymap mit erweitert:

(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)

Beachten Sie, dass ich super key verwende, so dass term-raw-map und möglicherweise eine andere Keymap keinen Konflikt mit meinen Tastenbindungen hat. Um super Schlüssel vom linken Win Schlüssel zu machen, verwende ich .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

Sie sollten sich nur zwei Befehle merken: C-c C-j - um in den normalen Emacs-Bearbeitungsmodus zu gelangen (zum Kopieren oder Durchsuchen von Puffertext), C-c C-k -, um zum Terminalemulationsmodus zurückzukehren.

Mausauswahl und Shift-Insert funktionieren wie in xterm.

6
gavenkoa

Wie Matli sagte, ist dies keine leichte Aufgabe, da bash mit --noediting gestartet wird und TAB an comint-dynamic-complete gebunden ist.

Man könnte TAB möglicherweise mit Shell-Befehl-Taste Wieder zum Einfügen-Befehl in Shell-comand-hook bringen und den Shell-Modus nicht mit --noediting von Mx custom-variable RET explizit-bash-args starten, sondern Ich vermute, dass es bei allen anderen Bearbeitungen nicht gut passt.

Vielleicht möchten Sie den Term-Modus ausprobieren, aber es gibt noch eine Reihe von Problemen, da einige der anderen regulären Tastenkombinationen vom Term-Modus überholt werden.

BEARBEITEN: Mit anderen regulären Keybidings, die durch den Term-Modus überholt werden, meine ich alle außer C-c, was zur Flucht wird, um Puffer wechseln zu können. Anstelle von C-x k, um den Puffer abzubrechen, müssten Sie C-c C-x k. Oder um zu einem anderen Puffer zu wechseln 'C-c C-x o' oder 'C-c C-x 2'

6
njsf

Ich benutze Prelude und wenn ich auf Meta + Tab klicke, wird es für mich abgeschlossen.

Außerdem scheint Strg + i dasselbe zu tun.

1
duma

Ich verwende den Helmmodus. Es hat diese Funktionalität (nach dem Drücken von "TAB"):  enter image description here

0
Alexei