9

我想在 VIM(特别是 GVIM)中具有以下功能。我认为 Sublime Text 有这样的东西:

  1. 在“正常”情况下,选项卡名称应该只是文件名,但是......
  2. 如果打开了两个同名但在不同目录中的文件,我希望看到一个选项卡名称父文件夹名称+文件名。

例子:

当有以下文件的选项卡时:

  • c:\my\dir\with\files\justAfile.txt
  • c:\my\dir\with\files\myfile.txt
  • c:\my\dir\with\backup\myfile.txt

选项卡名称将是:

justAfile.txt | files\myfile.txt | backup\myfile.txt 

这可以通过一些巧妙的配置来实现吗?

4

4 回答 4

6

在 GVIM 中,您可以使用选项自定义选项卡标签'guitablabel'

在终端 Vim 中;没有'guitablabel'等价物;一个必须渲染整个'tabline'. 幸运的是,Vim 帮助中有一个将标签渲染委托给单独函数的示例,因此重用自定义函数非常容易。

上述选项的帮助页面链接到示例;您可能必须使用fnamemodify()将所有缓冲区的路径规范化为完整的绝对路径,找到公共基本目录,然后将其从路径中剥离。

另一方面,如果您可以:cd访问基本目录,您将获得开箱即用的那种标签标签。

于 2013-04-29T11:35:36.060 回答
4

假设以下文件:

z.txt
a/b/c/d.txt
a/b/f/d.txt

我当前的设置将使表格看起来像这样(我对 Sublime Text 2 的行为进行了反向工程):

z.txt | d.txt - c | d.txt - f

我的代码有很多额外的东西,比如专门处理 Nerdtree/FZF 选项卡,以及在有拆分时根据最左边的缓冲区命名选项卡。如果您不想要这些额外内容,您可以自己删除它们,或者更改您不喜欢的任何内容。我还假设只有 Unix,只有终端 VIM(我猜 GVIM 需要稍作调整)。

我在不保证的情况下提供以下代码,作为您根据需要进行定制的起点。

set tabline=%!GetTabLine()

function! GetTabLine()
  let tabs = BuildTabs()
  let line = ''
  for i in range(len(tabs))
    let line .= (i+1 == tabpagenr()) ? '%#TabLineSel#' : '%#TabLine#'
    let line .= '%' . (i + 1) . 'T'
    let line .= ' ' . tabs[i].uniq_name . ' '
  endfor
  let line .= '%#TabLineFill#%T'
  return line
endfunction

function! BuildTabs()
  let tabs = []
  for i in range(tabpagenr('$'))
    let tabnum = i + 1
    let buflist = tabpagebuflist(tabnum)
    let file_path = ''
    let tab_name = bufname(buflist[0])
    if tab_name =~ 'NERD_tree' && len(buflist) > 1
      let tab_name = bufname(buflist[1])
    end
    let is_custom_name = 0
    if tab_name == ''
      let tab_name = '[No Name]'
      let is_custom_name = 1
    elseif tab_name =~ 'fzf'
      let tab_name = 'FZF'
      let is_custom_name = 1
    else
      let file_path = fnamemodify(tab_name, ':p')
      let tab_name = fnamemodify(tab_name, ':p:t')
    end
    let tab = {
      \ 'name': tab_name,
      \ 'uniq_name': tab_name,
      \ 'file_path': file_path,
      \ 'is_custom_name': is_custom_name
      \ }
    call add(tabs, tab)
  endfor
  call CalculateTabUniqueNames(tabs)
  return tabs
endfunction

function! CalculateTabUniqueNames(tabs)
  for tab in a:tabs
    if tab.is_custom_name | continue | endif
    let tab_common_path = ''
    for other_tab in a:tabs
      if tab.name != other_tab.name || tab.file_path == other_tab.file_path
        \ || other_tab.is_custom_name
        continue
      endif
      let common_path = GetCommonPath(tab.file_path, other_tab.file_path)
      if tab_common_path == '' || len(common_path) < len(tab_common_path)
        let tab_common_path = common_path
      endif
    endfor
    if tab_common_path == '' | continue | endif
    let common_path_has_immediate_child = 0
    for other_tab in a:tabs
      if tab.name == other_tab.name && !other_tab.is_custom_name
        \ && tab_common_path == fnamemodify(other_tab.file_path, ':h')
        let common_path_has_immediate_child = 1
        break
      endif
    endfor
    if common_path_has_immediate_child
      let tab_common_path = fnamemodify(common_path, ':h')
    endif
    let path = tab.file_path[len(tab_common_path)+1:-1]
    let path = fnamemodify(path, ':~:.:h')
    let dirs = split(path, '/', 1)
    if len(dirs) >= 5
      let path = dirs[0] . '/.../' . dirs[-1]
    endif
    let tab.uniq_name = tab.name . ' - ' . path
  endfor
endfunction

function! GetCommonPath(path1, path2)
  let dirs1 = split(a:path1, '/', 1)
  let dirs2 = split(a:path2, '/', 1)
  let i_different = 0
  for i in range(len(dirs1))
    if get(dirs1, i) != get(dirs2, i)
      let i_different = i
      break
    endif
  endfor
  return join(dirs1[0:i_different-1], '/')
endfunction
于 2018-03-03T03:55:32.323 回答
1

正如 Ingo 建议的那样,您可以使用guitablabel. 在我的安装中,它仅配置为显示文件名(:echo &guitablabel报告%M%t)。要设置它以显示相对路径,请执行:set guitablabel=%M%f. 就像 Ingo 所说,用于:cd DIRECTORY设置主目录,并:pwd查看其当前设置的位置。

请参阅:help statusline(许多)更多格式选项。

于 2013-04-29T11:42:13.930 回答
1

这是我的解决方案,它使选项卡名称成为目录——这通常是选项卡所代表的项目的一个很好的代理。如果只有一个缓冲区,则可以修改此解决方案以显示文件名(修改如下所示)。

这个解决方案从Jerome 的. 我没有做任何像他们一样复杂的事情,所以我的要短 5 倍。

此外,此解决方案将选项卡编号放置在名称旁边,使其易于反弹,这意味着选项卡将如下所示:1:log 2:doc 3:vimfiles 并将2gt移动到第二个选项卡。

set tabline=%!TabLine()

function! TabLine()
    let line = ''
    for i in range(tabpagenr('$'))
        let line .= (i+1 == tabpagenr()) ? '%#TabLineSel#' : '%#TabLine#'
        let line .= '%' . (i + 1) . 'T'
        let line .= TabLabel(i + 1) . ' '
    endfor
    let line .= '%#TabLineFill#%T'
    return line
endfunction

function! TabLabel(n)
    " Return list of buffer numbers for each window pane open in tab.
    let panelist = tabpagebuflist(a:n)
    " See :help setting-tabline then search MyTabLabel if you want to
    " use use the active window. I use the topmost pane, which let's
    " me rename the tab just by putting a window from a different
    " directory in the first position.
    let filepath = bufname(panelist[0])
    let dirname = fnamemodify(filepath, ':p:h:t')
    return a:n . ':' . dirname
endfunction

如果只有一个缓冲区可见,则显示文件名的修改:

function! TabLabel(n)
    " Return list of buffer numbers for each window pane open in tab.
    let panelist = tabpagebuflist(a:n)
    " See :help setting-tabline then search MyTabLabel if you want to
    " use use the active window. I use the topmost pane, which let's
    " me rename the tab just by putting a window from a different
    " directory in the first position.
    let filepath = bufname(panelist[0])
    let dirname = fnamemodify(filepath, ':p:h:t')
    let filename = fnamemodify(filepath, ':t')
    let tabname = len(panelist) > 1 ? dirname : filename
    return a:n . ':' . tabname
endfunction
于 2020-12-02T02:32:26.853 回答