根据我对此日复一日的研究,我可能在寻求不可能的事情。
情况
我已经
.bashrc
很好地配置好了,可以tmux
在连接时产生一个新的,或者如果存在的话,附加到它。我总是按Ctrl+D退出 shell 会话。它已经刻在我的肌肉记忆中。在做了三十年系统管理之后忘记它也是不可能的事情。
我想能够摆脱
tmux
仅使用Ctrl+ 的束缚D,而不是让它杀死我的外壳。
我不完美的方法
我能绑定Ctrl+D到。detach
.tmux.conf
问题是,我emacs
的肌肉记忆中也刻有按键绑定,因此当我开始编辑命令行时,我会按Ctrl+D来使用 GNU readline“删除光标下的字符”。相反,绑定tmux
会吞掉Ctrl+ D,因此我会立即分离。如果我在 中编辑,情况也是如此emacs
。
另一种有缺陷的方法
GNU readline 将在空行上获取 EOF,然后退出 shell。因此,我尝试改为使用 exit .bashrc
:
trap "~/tmuxexit" EXIT
内容为tmuxexit
:
tmux detach-client -s main
最初这似乎有效,因为在空行上按Ctrl+会报告:D
[detached (from session main)]
但tmux ls
有報告no server running on […]
。
我是否在追求不可能的事情?
答案1
我不确定我是否想出了最简单的解决方案。这个:
stty eof '^T'
bind '"\C-d": "\C-x\C-t\C-x\C-d"'
bind -x '"\C-x\C-t": _tmux_detach'
_tmux_detach() { [ -z "$READLINE_LINE" ] && tmux detach-client; }
bind '"\C-x\C-d": delete-char'
解释:
stty eof '^T'
使您的终端不再在Ctrl+处发送 EOF D。现在是Ctrl+ T。新的组合键将像 readline 中的旧组合键一样运行,我的意思是只有当行是空时它才会退出 shell。我故意选择了Ctrl+ ,T因为您不太可能希望在空行中使用其默认绑定(转置字符)。我认为完全禁用 EOF (
stty eof undef
) 会起作用,但事实证明 readline(?) 仍然会对之前定义的组合(如Ctrl+ D)做出反应,并且如果该行为空,则使 shell 注册 EOF。bind '"\C-d": "\C-x\C-t\C-x\C-d"'
使Ctrl+ D“发送” Ctrl+ X, Ctrl+T和Ctrl+ X, Ctrl+ D。我们将分别利用这两个子序列。bind -x '"\C-x\C-t": _tmux_detach'
– 从现在开始Ctrl+ X,Ctrl+T执行_tmux_detach
…tmux
…这是一个在行 ( ) 为空时分离的函数$READLINE_LINE
。bind '"\C-x\C-d": delete-char'
– 从现在开始Ctrl+ X,Ctrl+D删除指向的字符,就像Ctrl+D通常做的那样。
因此Ctrl+D将像这样工作:
- 如果该行不为空,则该函数为无操作并
delete-char
执行其工作; - 如果该行为空,则函数执行其工作并且
delete-char
为无操作(它被触发但无任何操作)。
笔记:
READLINE_LINE
是在 Bash 4.0 中引入的。- 如果您将代码粘贴到您的中,您可能需要改进它:在更改+的行为之前
~/.bashrc
检查 shell 是否在里面,这样外面的 shell就不会受到影响。tmux
CtrlDtmux
_tmux_detach
在 之前执行非常重要delete-char
。如果你颠倒顺序,那么你将引入一个错误:删除一个单独字符的Ctrl+D也会分离tmux
。
答案2
Kamil Maciorowski 的答案表明这是可能的,我感谢他。根据他提到的测试是否在 tmux 中来确定 ctrl-d 行为,以下内容似乎按预期工作,所以我正在扩展他的回答。
.bashrc 中的测试:
- 如果不在 tmux 会话中,则不要重新映射键
- 如果存在 tmux 会话,则附加到该会话,并保留重新映射的键
- 如果没有,则使用新密钥创建一个新会话
if [[ "$TERM" != "screen-256color" ]];then
if tmux has-session -t main 2>/dev/null; then
tmux attach -t main
else
tmux new -s main
fi
else
stty eof '^T'
bind '"\C-d": "\C-x\C-t\C-x\C-d"'
bind -x '"\C-x\C-t": _tmux_detach'
_tmux_detach() { [ -z "$READLINE_LINE" ] && tmux detach-client; }
bind '"\C-x\C-d": delete-char'
fi
请注意“screen-256color”的使用(通过set -g default-terminal "screen-256color"
在 .tmux.conf 中添加设置)。如果您不想使用扩展颜色图,您可以简单地在 .bashrc 代码片段中声明“screen”。
以上内容可能比需要的更符合我的偏好 - 这肯定不是进行这些测试的唯一方法,但对我来说有效。(更新为更智能的构造)
答案3
Zsh 版本..
# tmux detach or delete
function _delete_or_detach() {
if [[ -n "${BUFFER}" ]]
then
zle delete-char-or-list
else
tmux detach-client
fi
}
if [[ -n "$TMUX" ]]
then
setopt ignoreeof
zle -N _delete_or_detach
bindkey "^D" _delete_or_detach
fi