在 GNOME 终端中,Bash 支持智能自动补全。例如:
apt-get in<TAB>
成为
apt-get install
在Emacs的shell-mode中,即使我明确地使用/etc/bash_completion
命令,在这里自动完成功能也无法工作。以上示例将粘滞为in
,或者自动完成为当前目录中的文件名,而不是一个有效的apt-get
命令选项。这可能是因为Emacs截获了Tab键按下事件。如何在shell-mode
中启用智能自动完成?在 GNOME 终端中,Bash 支持智能自动补全。例如:
apt-get in<TAB>
成为
apt-get install
在Emacs的shell-mode中,即使我明确地使用/etc/bash_completion
命令,在这里自动完成功能也无法工作。以上示例将粘滞为in
,或者自动完成为当前目录中的文件名,而不是一个有效的apt-get
命令选项。这可能是因为Emacs截获了Tab键按下事件。如何在shell-mode
中启用智能自动完成?我知道这个问题已经三年了,但这也是我一直想要解决的问题。一次网络搜索让我找到了一段elisp代码,可以使Emacs在shell模式下使用bash进行自动补全。无论如何,它对我很有效。
请查看 https://github.com/szermatt/emacs-bash-completion 获取更多信息。
在emacs shell中,实际上是emacs进行自动补全,而不是bash。如果shell和emacs不同步(例如使用pushd、popd或某个bash用户函数更改了shell的当前目录),那么自动补全就会停止工作。
要解决这个问题,只需在shell中键入“dirs”,然后事情就会重新同步。
我还在我的.emacs中添加了以下内容:
(global-set-key "\M-\r" 'shell-resync-dirs)
按下 Esc 键然后按下回车键即可重新同步自动完成。
我不知道这个问题的答案。但它不能按照您的期望工作的原因可能是因为emacs shell中的补全由emacs内部处理(通过comint-dynamic-complete函数),并没有内置这些智能补全功能。
恐怕这不是一个容易解决的问题。
编辑:njsf建议使用term-mode可能是最好的选择。用
M-x term启动。 它已经包含在标准的emacs发行版中(至少在Ubuntu和Debian的emacs21-common或emacs22-common中也是如此)。
M-x term
中,使用Tab键来自动补全更加糟糕。 - mcandreM-x term
,就像我在2011年遇到问题时所做的那样。当时我试图收集所有网上的努力来使shell与Bash完成工作,包括这个问题。但是自从发现了替代方案term-mode
后,我甚至都不想尝试eshell
。zsh
完成,以便您不会浪费时间在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
的任何单词中使用dabbrev):
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
和可能的任何其他键映射不会与我的按键绑定冲突。为了将左边的Win
键变成super
键,我使用.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
C-c C-j
- 进入普通的Emacs编辑模式(用于复制或在缓冲区文本中查找),C-c C-k
- 返回终端仿真模式。
鼠标选择和 Shift-Insert
的工作方式与 xterm
相同。
.inputrc
部分! - cmantas就像Matli所说的那样,这不是一项易如反掌的任务,因为bash是以--noediting启动的,并且TAB键被绑定到comint-dynamic-complete。
可以在shell-command-hook中使用local-set-key将TAB重新绑定到self-insert-command,使shell-mode不再以--noediting启动,方法是M-x customize-variable然后RETEexplicit-bash-args,但我怀疑它可能无法很好地适应所有其他编辑。
您可以尝试term-mode,但它有另一组问题,因为term-mode接管了其他一些常规按键绑定。
编辑:我指被term-mode接管的其他常规按键绑定,除了C-c之外,它成为了切换缓冲区的转义键。因此,用于杀死缓冲区的C-x k变为了C-c C-x k。或者要切换到另一个缓冲区,则是'C-c C-x o'或'C-c C-x 2'
我知道这篇文章已经超过11年了。但是我已经创建了一个函数,可以在Emacs中提供本地shell自动补全功能。它只是向底层进程发送一个tab键,并拦截输出,所以与你在shell本身中得到的完全相同。
https://github.com/CeleritasCelery/emacs-native-shell-complete
我使用helm模式。它有这个功能(按下“TAB”后):
{{link1:}}
eshell-mode
具有制表符自动完成功能。更多信息请参见:http://www.masteringemacs.org/articles/2010/11/01/running-shells-in-emacs-overview/ - Ross