Does it support following code?
More precisely, does it support defining function? invoking function system? and so on.
Following code is used to auto close my Chinese input method when quit from insert normal.
let g:input_toggle = 1
function! Fcitx2en()
let s:input_status = system("fcitx-remote")
if s:input_status == 2
let g:input_toggle = 1
let l:a = system("fcitx-remote -c")
endif
endfunction
function! Fcitx2zh()
let s:input_status = system("fcitx-remote")
if s:input_status != 2 && g:input_toggle == 1
let l:a = system("fcitx-remote -o")
let g:input_toggle = 0
endif
endfunction
set timeoutlen=150
autocmd InsertLeave * call Fcitx2en()
"autocmd InsertEnter * call Fcitx2zh()
No, IdeaVim understands only several configuration options in ~/.ideavimrc, the rest is ignored. See this feature request for details.
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
looking for an advice how to programatically detect, if current Vim's buffer contains at least one fold defined ? Regardless if a fold is open or closed.
Attempting to call mkview only if there is a fold defined in current buffer:
autocmd BufWrite ?* if fold_defined() | mkview | endif
function fold_defined()
???
endfunction
function! HasFold()
let view = winsaveview()
let fold = 0
for move in ['zj', 'zk']
exe 'keepj norm!' move
if foldlevel('.') > 0
let fold = 1
break
endif
endfor
call winrestview(view)
return fold
endfunction
Based on perreal's advice, I did wrote one of possible solutions to my question:
" Detect presence of fold definition in the current buffer
function FoldDefined()
let result = 0
let save_cursor = getpos('.')
call cursor(1,1)
let scanline = line('.')
let lastline = line('$')
while scanline <= lastline
if foldlevel(scanline) > 0
let result = 1
break
endif
let scanline = scanline + 1
endwhile
call setpos('.', save_cursor)
return result
endfunction
function! FoldDefined()
return len(filter(range(1, line('$')), 'foldlevel(v:val)>1'))>0
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)
It would be very nice to have an option that would show all the column numbers of the current line or maybe of all the buffer, so I could know where exactly to navigate. Is there such an option or do i have to program it myself (nooo XD)?
:h 'statusline'
It is as easy as defining exactly what you what to see printed. e.g.
" RulerStr() comes from http://www.vanhemert.co.uk/vim/vimacros/ruler2.vim
function! RulerStr()
let columns = &columns
let inc = 0
let str = ""
while (inc < columns)
let inc10 = inc / 10 + 1
let buffer = "."
if (inc10 > 9)
let buffer = ""
endif
let str .= "....+..." . buffer . inc10
let inc += 10
endwhile
let str = strpart(str, 0, columns)
return str
endfunction
let s:saved_stl = {}
function! s:ToggleRuler()
let buf = bufnr('%')
if has_key(s:saved_stl, buf)
let &l:stl = s:saved_stl[buf]
unlet s:saved_stl[buf]
else
let s:saved_stl[buf] = &l:stl
setlocal stl=%{RulerStr()}
endif
endfunction
nnoremap <silent> ยต :call <sid>ToggleRuler()<cr>
You can use "set ruler". It will show the line number and column position at the bottom.