tmux选项卡中显示当前在vim编辑器中打开的文件名

35
我是tmux的新手,正在尝试找出如何编辑配置文件,以便用vim打开的窗口在任务栏中显示的不是#:vim,而是打开的文件的名称(例如"#:filename.php")。看起来这应该是一个常见的问题,但我的搜索没有结果。

3
我经常在Vim中使用分屏功能。如果我打开了10个文件并将其中4个文件拆分到4个窗口中,你可以告诉我,在tmux窗口标签中你想要显示什么吗? - Kent
1
@Kent 假设只有一个文件在一个窗口中打开。这个可以实现吗? - Matt Parker
1
Kent:你可以在Vim中定义适当的自动命令,以调用tmux rename-window并使用活动缓冲区中文件的名称。 - chepner
8个回答

43
以下是部分答案,可以改进,但我现在没有时间处理它。
将以下内容放入您的`.vimrc`文件中:
autocmd BufReadPost,FileReadPost,BufNewFile * call system("tmux rename-window " . expand("%"))

除了在Vim中查看:help autocmd-events的其他事件可用于处理。我还没想出如何更改窗口名称,如果你在两个面板中都打开了一个vim实例,并且你从一个面板切换到另一个面板。vim不知道在tmux中的活动,因此不会触发任何vim事件。


15
我不得不对此进行微调,使用expand()函数以使百分号展开到窗口名称中,否则我的窗口名称只会显示"%"。这是在vim 7.3版本下发生的。即:autocmd BufReadPost,FileReadPost,BufNewFile * call system("tmux rename-window " . expand("%")) - Von
7
我发现当使用多个面板或窗口,或者使用fugitive时,需要将BufEnter事件添加到事件列表中,以便在缓冲区之间移动时标题保持同步。 - Von
9
expand("%:t") 会显示文件名,而 expand("%") 则会显示完整路径。 - Nobu
可能缺失:您需要设置t_ts。这适用于tmux/screen:set t_ts=^[k。(使用ctrl-v,ESC输入^[字符作为实际的转义符,如所需。) - Asherah
4
这似乎会在您离开vim后重命名窗口。为了解决这个问题,我按照@Phluks的回答添加了autocmd VimLeave * call system("tmux rename-window bash") - studgeek
显示剩余3条评论

18

这是可以实现的!我想分享这个答案,因为我找了很长时间。最终我有时间自己实现了它。请将以下内容放入您的.vimrc文件中:

autocmd BufEnter * let &titlestring = ' ' . expand("%:t")
set title

这将把终端标题设置为当前聚焦的文档标题(%t代表不带路径的文档标题)。由于事件BufEnter,每次切换到另一个文档时,终端标题都会更改。同时,当离开Vim时,它会恢复到原始状态。请在你的.tmux.conf中添加(或替换)以下内容:

set-window-option -g window-status-current-format "[#I #W#T]"
set-window-option -g window-status-format "[#I #W#T]"

不必完全复制,但它看起来是这样的:
[1 vim .tmux.conf][2 bash]...

I代表窗口编号。 W代表当前运行的应用程序,T代表终端标题。我们使用后者来显示在vim中打开的当前文件。终端标题始终被设置(我的bash终端总是显示主机名,我不需要在状态栏描述中看到它),因此要仅在vim运行时显示它,请将以下内容添加到您的.bashrc文件中:

PROMPT_COMMAND='echo -ne "\033]0;\007"'

对于我使用的shell——bash而言,这是正确的。PROMPT_COMMAND在终端显示提示符之前进行评估。echo命令将终端标题设置为空。当您从可能更改标题的应用程序获取提示时,此操作就会发生。其他shell可能需要进行不同的配置...

我不会使用tmux rename-window,因为它会为窗口存在的时间设置标题。每次启动应用程序都需要调用它。所提出的方法保持动态性,因为它适用于窗口中的多个面板以及vim中打开的多个拆分屏幕/文件。


我尝试了这个但没有成功。有什么调试技巧吗?我已经重新启动了tmux。 - Rose Perrone
这里的信息不足以进行判断,但是最好的猜测是您没有将bash设置为默认终端。可以通过在".tmux.conf"中添加"set-option -g default-shell /bin/bash"来强制TMUX使用bash。也许您没有看到状态栏,可以通过添加"set-option -g status on"来修复。有什么进展吗? - gospes
1
在tmux中,autocmd BufEnter * let &titlestring = ' ' . expand("%:t") 对我似乎不起作用。正如@Phluks建议的那样,在tmux内部使用tmux rename-window方法。 - studgeek
我刚才意识到你所谓的“终端标题”是我认为tmux称之为“窗格标题”的东西,并且你得到了我在下面刚刚发布的相同答案。你缺失的是,至少对我来说,需要设置“t_ts”和“t_fs”。 - Von

10
感谢大家的出色建议,它让我省去了很多打字的时间 :-)
我将前两个答案合并为一个,并且我很喜欢这个方案。
autocmd BufEnter * call system("tmux rename-window " . expand("%:t"))
autocmd VimLeave * call system("tmux rename-window bash")
autocmd BufEnter * let &titlestring = ' ' . expand("%:t")                                                                 
set title

第一行和第二行是为tmux准备的,第三行和第四行是为正常终端使用准备的。由于vim明确更新tmux,所以不需要重新启动tmux。

1
之前的两个答案对我没用,只有这一个有效。为什么? - fiatjaf

9

同时,在退出Vim时恢复自动窗口标题:

autocmd VimLeave * call system("tmux setw automatic-rename")

我建议检查是否在 tmux 下运行:
if exists('$TMUX')
    autocmd BufEnter * call system("tmux rename-window '" . expand("%:t") . "'")
    autocmd VimLeave * call system("tmux setw automatic-rename")
endif

2
这是我在窗格之间来回导航时的做法,同时也可以重命名窗口并限制显示的字符数。

vim_demo


~/.tmux.conf
我更喜欢没有索引号或其他符号的标题名称。
basepath/   -> at the prompt
filename    -> inside Vim

为了保留索引号,请将window-status-format和window-status-current-format行改为"#I:#W"。

# window name formatting
set-window-option -g window-status-format "#W"
set-window-option -g window-status-current-format "#W"

# pane title formatting
set -g pane-border-format ' #T '

# rename window to pane title on focus
set -g focus-events on
set-hook -g pane-focus-in 'rename-window "#T"'

源tmux.conf
tmux source-file ~/.tmux.conf

~/.bashrc

最终我使用了bash,因为它允许在更改目录时立即重命名窗口,而且对于我的特定需求来说比vimscript更容易。它改变了cdvim命令的功能,包括我的重命名函数。我还添加了在使用topnmtui时将其重命名为命令本身的功能。

# max number of characters in title
CHAR_LIMIT=20
MY_VIM="/usr/bin/vim.gtk3"

# if tmux running...
tmux ls > /dev/null 2>&1
TMUX_STATUS=$?
if [ $TMUX_STATUS -eq 0 ]; then

    basedirRename () {

        # "basepath/"
        getval=$(pwd)
        BASEPATH_FULL="${getval##*/}"
        BASEPATH="${BASEPATH_FULL:0:$CHAR_LIMIT}/"

        tmux rename-window " $BASEPATH "
        tmux select-pane -T " $BASEPATH "
    }
    
    fileRename () {

        # "filename"
        FILENAME_FULL="$@"
        FILENAME="${FILENAME_FULL:0:$CHAR_LIMIT}"

        tmux rename-window " $FILENAME "
        tmux select-pane -T " $FILENAME "
    }

    commandRename() {
        tmux rename-window " $1 "
        tmux select-pane -T " $1 "
    }

    cd () {

        builtin cd "$@"
        CD_STATUS=$?
        basedirRename
        return "$CD_STATUS"
    }

    vim () {

        fileRename $@
        $MY_VIM $@
        VIM_STATUS="$?"
        basedirRename
        return "$VIM_STATUS"
    }

    top () { commandRename 'top'; /usr/bin/top; STATUS=$@; basedirRename; return $STATUS; }
    nmtui () { commandRename 'nmtui'; /usr/bin/nmtui; STATUS=$@; basedirRename; return $STATUS; }

    basedirRename
fi



源代码 .bashrc
. .bashrc


你的回答是迄今为止最详细的。但还需要一些改进。在vim和终端中显示pwd是可以工作的,但如果你使用一个程序像top,它会停止按照这样的方式重命名窗口。 - freddie_ventura
还有,如果它可以忽略手动重命名的窗口,那就太好了。 - freddie_ventura
同时,如果整个会话是用脚本调用,则无法正常工作。 - freddie_ventura
1
@freddie_ventura 当我以为我已经完成了这个东西时,哈哈。但是重命名命令是一个很好的建议。我在.bashrc中添加了它来展示如何在top和nmtui中使用。我不手动重命名窗口或使用会话。祝你好运。 - Jeff_V
1
@freddie_ventura 当我以为我已经完成了这件事时,哈哈。但是命令重命名是一个很好的建议。我在.bashrc中添加了它,用于显示top和nmtui的用法。我不手动重命名窗口或使用会话。祝你好运。 - undefined

2

这里有一些很好的答案,但我仍然没能让它按照我所想要的方式工作: 1)打开vim时更改TMUX窗口名称 2)退出时恢复之前的名称 我使用以下3行vimrc来实现:

autocmd BufReadPost,FileReadPost,BufNewFile * call system("tmux rename-window " . expand("%:t"))
let tmuxtitle = system("tmux display-message -p '#W'")
autocmd VimLeave * call system("tmux rename-window " . shellescape(tmuxtitle))

运行良好,除了没有文件名的缓冲区。有什么办法可以解决这个问题吗? - PonyEars

2
作为替代其他设置tmux窗口名称的答案,您可以让vim设置tmux面板标题。这样,您可以保留您使用tmux new-window -n <window-name>定义的静态窗口名称,同时让vim更改面板标题。在set-titles-string中使用#T来显示面板标题,例如:set-option -g set-titles-string "#W: #T"将显示tmux窗口名称和面板标题。
更改面板标题的示例vim配置:
" Teach vim the tmux escape sequences for changing pane title
" Note the "^[" should be a literal escape code (use `^v<esc>` to enter it)
set t_ts=^[]2;
set t_fs=^[\\

" Turn on setting the title.
set title

" The following causes vim to refresh the title each time we change buffers.
" Otherwise it will only set the title once at startup.
augroup RefreshTitle
  autocmd!
  " The concatenation of the colon is a hack to prevent vim from
  " interpreting the string as a modeline.
  autocmd BufEnter * let &titlestring = "vim" . ":" . expand("%:t")
augroup END

感谢 vim.wikia.com 提供的 t_tst_fs 指南,以及 phluks 的自动命令。


就我而言,“set title”和“set titlestring=%t”足以在我切换缓冲区时保持窗格标题最新,我不需要augroup/BufEnter命令。 - Stephen Haberman

1

.tmux.conf

set-option -g set-titles on
set-option -g set-titles-string '#W:#T' # window title,pane title
set -g allow-rename on

这是我在vim中设置titlestring的方法:https://vi.stackexchange.com/a/40069/26406

无需在vim内部使用外部命令,这就是方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接