If I'm opening .js, .html, .rb and other filetype, is it possible to change tab color each filetype?
Tab means vim's tab not like space.
Use the format %#String# will color with the string hightlight :
- set tabline=%#String#\ toto
A script to put in your vimrc:
function! TabTest()
let res = ''
for i in range(tabpagenr('$'))
let i += 1
" Get open buffer
let i_window = tabpagewinnr(i)
let l_buffer = tabpagebuflist(i)
let i_buffer = l_buffer[i_window - 1]
" Get type
let s_type = getbufvar(i_buffer, '&filetype')
" Set color according to filetype
let s_color = ''
if i == tabpagenr()
let res .= '%#TabLine#'
elseif 'javascript' == s_type
let res .= '%#String#'
elseif 'html' == s_type
let res .= '%#Comment#'
else
let res .= '%#Normal#'
endif
" set the tab page number (for mouse clicks)
let res .= '%' . (i + 1) . 'T'
" Set label text
let s_buffer = bufname(i_buffer)
try
let s_file = split(s_buffer, '/')[-1]
catch
let s_file = '[No Name]'
endtry
let res .= ' ' . s_file
endfor
return res
endfunction
set tabline=%!TabTest()
As you are asking for an color hightlight according to the filetype, you must get the filetype of a buffer:
- let s_type = getbufvar(i_buffer, '&filetype')
For this you must get the buffer number of the activer buffer in the tab:
- let i_window = tabpagewinnr(i)
- let l_buffer = tabpagebuflist(i)
- let i_buffer = l_buffer[i_window - 1]
Then you must wisely distinguish accroding to the filetype with a if. So you definitely want to hide all this in a function:
set tabline=%!TabTest()
More :
h tabline
h statusline
You will have to write your own :help 'tabline' (see also :help 'statusline') for that… and all its supporting code.
Having different colors is the easy part:
:set tabline=%#Error#\ foo.js\ %*%#DiffAdd#\ bar.rb\ %*%#Search#\ baz.scss\ %*
It's the code that will determine the correct tabline value on various events that won't be trivial at all.
I'm trying to get vim to play nicely with GTK's coding style by setting cinoptions but I can't figure out what to use for case statements.
Desired:
switch (x)
{
case 1:
{
foo();
}
case 2:
bar();
}
A) What I get with (not desired): setlocal et sw=2 cinoptions=>4,n-2,{2
switch (x)
{
case 1:
{
foo();
}
case 2:
bar();
}
B) What I get with (not desired): setlocal et sw=2 cinoptions=>4,n-2,{2,=0
switch (x)
{
case 1:
{
foo();
}
case 2:
bar();
}
Is there a way of getting the desired indentation automatically?
From the vim :help cino-:
*cino-:*
:N Place case labels N characters from the indent of the switch().
(default 'shiftwidth').
cino= cino=:0
switch (x) switch(x)
{ {
case 1: case 1:
a = b; a = b;
default: default:
} }
*cino-=*
=N Place statements occurring after a case label N characters from
the indent of the label. (default 'shiftwidth').
cino= cino==10 >
case 11: case 11: a = a + 1;
a = a + 1; b = b + 1;
You need add :0 to your cinoptions.
If need to also set =3 if you want 3 characters of indent under case.
I would like to have the following feature in VIM (GVIM in particular). I think Sublime Text has something like that:
In the "normal" case the tab name should be just the file's name, but...
If there are two files opened with the same name but in different directories, I would like to see a tab name parent folder name + file name.
Example:
When there are tabs for the following files:
c:\my\dir\with\files\justAfile.txt
c:\my\dir\with\files\myfile.txt
c:\my\dir\with\backup\myfile.txt
Tab names would be then:
justAfile.txt | files\myfile.txt | backup\myfile.txt
Is this doable with some clever configuration?
In GVIM, you can customize the tab labels with the 'guitablabel' option.
In terminal Vim; there's no 'guitablabel' equivalent; one has to render the entire 'tabline'. Fortunately, the Vim help has an example which delegates the label rendering to a separate function, so re-using your custom function is pretty easy.
The help pages for the mentioned options link to examples; you probably have to use fnamemodify() to canonicalize all buffers' paths to full absolute paths, find the common base directory, and then strip that off the paths.
On the other hand, if it's okay for you to :cd to the base directory, you'll get that kind of tab label pretty much out-of-the-box.
Assuming the following files:
z.txt
a/b/c/d.txt
a/b/f/d.txt
My current setup will make the tabline look like so (I reversed-engineered the behavior from Sublime Text 2):
z.txt | d.txt - c | d.txt - f
My code has a lot of extras like treating Nerdtree/FZF tabs specially, and naming tabs according to the left-most buffer when there are splits. You can remove these extras yourself if you don't want them, or change anything you don't like. I also assumed Unix only, and terminal VIM only (GVIM would need minor tweaking I guess).
I am providing the code below without guarantee, as a starting point for you to customize according to your needs.
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
As Ingo suggests you can use guitablabel. On my installation its only configured to show the file name (:echo &guitablabel reports %M%t). To set this to show the relative path do :set guitablabel=%M%f. Like Ingo says, use :cd DIRECTORY to set the home directory, and :pwd to see where its currently set.
See :help statusline for (many) more formatting options.
Here's my solution that makes the tabname the directory---which is usually a good proxy for the project that tab is meant to represent. This solution can be modified to show the filename if there is only one buffer (modification shown below).
This solution draws a tiny bit from Jerome's. I'm not doing anything as complex as they are, so mine is 5x shorter.
Also, this solution places the tab number alongside the name, making it easy to bounce around, meaning the tabs will look like this: 1:log 2:doc 3:vimfiles and 2gt will move to the second tab.
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
The modification to show the filename if only one buffer is visible:
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
I use the supertab plugin in vim.
These are my default settings (in _vimrc)
let g:SuperTabDefaultCompletionType = '<c-x><c-k>' -->(dictionary)
let g:SuperTabRetainCompletionDuration = "completion"
let g:SuperTabLongestEnhanced = 1
let g:SuperTabLongestHighlight = 1
I created this script to select omnicomplete with supertab on the fly:
function! SuperTabFunction()
if !exists("WhatSuperTab")
let WhatSuperTab = "SuperTab function?"
endif
if !exists("MenuSuperTab_choices")
let MenuSuperTab_choices = "&Current page\n&Spellchecker\nSentence\nCode"
endif
let n = confirm(WhatSuperTab, MenuSuperTab_choices, "Question")
if n == 1
let g:SuperTabDefaultCompletionType = '<c-x><c-m>'
so $VIM/vimfiles/plugin/supertab.vim
elseif n == 2
let g:SuperTabDefaultCompletionType = '<c-x><c-k>'
so $VIM/vimfiles/plugin/supertab.vim
elseif n == 3
let g:SuperTabDefaultCompletionType = '<c-x><c-l>'
so $VIM/vimfiles/plugin/supertab.vim
elseif n == 4
let g:SuperTabDefaultCompletionType = '<c-x><c-o>'
so $VIM/vimfiles/plugin/supertab.vim
else
return ''
endif
endfun
nmap <silent> <C-S-tab> :call SuperTabFunction()<CR>
imap <silent> <C-S-tab> <esc>:call SuperTabFunction()<CR>a
When I invoke above function and choose p.e. "Sentence"
I can use super tab to complete sentences
When I invoke above function again and choose p.e. "Spellchecker"
The correct value is assigned to g:SuperTabDefaultCompletionType
but it still replaces sentences.
What did I wrong in this function?
Have you tried calling the provided function instead of altering the global variable directly?
" SuperTabSetDefaultCompletionType(type) {{{
" Globally available function that users can use to set the default
" completion type for the current buffer, like in an ftplugin.
function! SuperTabSetDefaultCompletionType(type)
In general I prefer to have annotation tags for methods, including #Test ones, on the line before the method declaration like this
#Test
public void testMyMethod() {
// Code
}
rather than
#Test public void testMyMethod() {
// Code
}
I have java specific settings in ~/.vim/ftplugins/java.vim. What can I add to java.vim such that indentation is skipped at the first line after the #Test tag? At the moment vim will, as it is supposed to according to java.vim, indent 4 characters giving
#Test
____* <-- cursor placed here
while I would prefer
#Test
* <-- Cursor placed here
I do something similar in C++, where my company's coding style doesn't want indents in namespace blocks. There's an answer for that at this post, adapting it to your question would just swap the '^\s*namespace.*' bit to your desired pattern. If it's for all annotations, perhaps simply...
function! IndentAnnotation()
let l:cline_num = line('.')
let l:pline_num = prevnonblank(l:cline_num - 1)
let l:pline = getline(l:pline_num)
let l:retv = cindent('.')
while l:pline =~# '\(^\s*{\s*\|^\s*//\|^\s*/\*\|\*/\s*$\)'
let l:pline_num = prevnonblank(l:pline_num - 1)
let l:pline = getline(l:pline_num)
endwhile
if l:pline =~# '^\s*#.*'
let l:retv = 0
endif
return l:retv
endfunction
setlocal indentexpr=IndentAnnotation()
Save this in your vimfiles (inside ~/vimfiles or on windows in your homedir or inside ProgramFiles\vim\vimfiles) as indent/java.vim. You may be able to simplify by removing the while/endwhile hunt for a non-blank line if you require an annotation to occur on a line exactly above the line you're indenting (with no intervening blank lines).