在GNOME终端中,Bash执行智能自动完成功能.例如
apt-get in
变
apt-get install
在Emacs shell模式下,即使在我明确提供源代码后,此自动完成也不起作用/etc/bash_completion
.上面的示例in
在当前目录中使用文件名而不是有效的apt-get
命令选项粘贴或自动完成.据推测,这是因为Emacs正在拦截Tab键按下.如何启用智能自动完成功能shell-mode
?
我知道这个问题已经有三年了,但我也有兴趣解决这个问题.一个网络搜索引导我到一个elisp,使得Emacs使用bash在shell模式下完成.无论如何,它对我有用.
请访问https://github.com/szermatt/emacs-bash-completion查看.
在emacs shell中,它实际上是emacs进行自动完成,而不是bash.如果shell和emacs不同步(例如,通过使用pushd,popd或某些更改shell当前目录的bash用户函数),则自动完成将停止工作.
要解决此问题,只需在shell中键入"dirs"即可恢复同步.
我的.emacs中也有以下内容:
(global-set-key "\M-\r" 'shell-resync-dirs)
然后只需按Esc-return重新同步自动完成.
我不知道答案.但它不能按预期工作的原因可能是因为emacs shell中的完成由emacs内部处理(通过comint-dynamic-complete函数),并且没有内置的智能完成功能.
我担心这不是一件容易的事情.
编辑:njsf关于使用term-mode的建议可能和它一样好.启动它
M-x term它包含在标准的emacs发行版中(至少在Ubuntu和Debian上的emacs21-common或emacs22-common中).
就像Matli说的那样,这不是一件容易的事,因为bash是以--noediting开头的,而TAB必然是comint-dynamic-complete.
有人可能会在使用local-set-key的shell-comand-hook中将TAB重新绑定到self-insert-command,并且使用Mx自定义变量RET explicit-bash-args来启动shell模式 - 但是我怀疑它不适合所有其他编辑.
您可能想尝试使用term-mode,但它有另一组问题,因为其他一些常规键绑定被term-mode超越.
编辑:通过其他常规关键词被术语模式所取代,我的意思是除了Cc之外的其他所有关键词都可以转换缓冲区.因此,不要使用Cx k来杀死缓冲区,而是必须使用Cc Cx k.或者切换到另一个缓冲区'Cc Cx o'或'Cc Cx 2'
请考虑另一种模式M-x term
,就像我在2011年遇到问题时所做的那样.我当时试图通过Inet收集所有努力来使shell工作与Bash完成,包括这个问题.但是,因为发现面对term-mode
我的替代品,我甚至不想尝试eshell
.
它是完整的终端模拟器,所以你可以在里面运行交互式程序,比如午夜指挥官.或者切换到zsh
完成,这样您就不会浪费时间在Emacs配置上.
你可以免费使用bash完成TAB.但更重要的是,您可以获得完整的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
(YEA!在任何单词中都有Bash中的dabbrev ~/.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
都不能在终端仿真模式下工作,我扩展了keymap:
(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编辑模式(用于在缓冲区文本中复制或grepping),C-c C-k
- 返回到终端仿真模式.
鼠标选择和Shift-Insert
工作如下xterm
.