VIM:如何在选项卡中显示文件夹名称,但仅当两个文件具有相同名称时才显示

Pio*_*ski 4 vim

我希望在VIM中具有以下功能(特别是GVIM).我认为Sublime Text有类似的东西:

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

例:

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

  • C:\我的\目录\与\文件\ justAfile.txt
  • C:\我的\目录\与\文件\ myfile.txt的
  • C:\我的\目录\与\备份\ myfile.txt的

选项卡名称将是:

justAfile.txt | files\myfile.txt | backup\myfile.txt 
Run Code Online (Sandbox Code Playgroud)

这是否适用于一些聪明的配置?

Ing*_*kat 5

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

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

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

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


Jer*_*ert 5

假设有以下文件:

z.txt
a/b/c/d.txt
a/b/f/d.txt
Run Code Online (Sandbox Code Playgroud)

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

z.txt | d.txt - c | d.txt - f
Run Code Online (Sandbox Code Playgroud)

我的代码有很多额外功能,例如专门处理 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
Run Code Online (Sandbox Code Playgroud)