viml

[!NOTE|label:references:]

autocmd

[!TIP|label:references:]

 autocmd BufEnter *.p[lm]  nmap <buffer> ;t :call RunPerlTests()<CR>
 "       |        |        |     |       |  |
 "       |        |        |     |       |  +-- `{rhs}` of the mapping
 "       |        |        |     |       +-- `{lhs}` of the mapping
 "       |        |        |     +-- argument to pass to `:nmap`; limits the scope of the mapping to the current buffer
 "       |        |        +-- mapping command to execute
 "       |        +-- pattern to limit the scope of the autocmd to certain filetypes
 "       +-- event of the autocmd
  • Listing 1. Event sequence in a simple Vim editing session

    • BufWinEnter : create a default window

    • BufEnter : create a default buffer

    • VimEnter : start the Vim session):edit demo.txt

    • BufNew : create a new buffer to contain demo.txt

    • BufAdd : add that new buffer to the session’s buffer list

    • BufLeave : exit the default buffer

    • BufWinLeave : exit the default window

    • BufUnload : remove the default buffer from the buffer list

    • BufDelete : deallocate the default buffer

    • BufReadCmd : read the contexts of demo.txt into the new buffer

    • BufEnter : activate the new buffer

    • BufWinEnter : activate the new buffer's window

    • InsertEnter : swap into Insert mode

  • funciton

    fun! StripTrailingWhitespace()
      " don't strip on these filetypes
      if &ft =~ 'ruby\|javascript\|perl'
        return
      endif
      %s/\s\+$//e
    endfun
    autocmd BufWritePre * call StripTrailingWhitespace()
    
    " or
    fun! StripTrailingWhitespace()
      " only strip if the b:noStripeWhitespace variable isn't set
      if exists('b:noStripWhitespace')
        return
      endif
      %s/\s\+$//e
    endfun
    
    autocmd BufWritePre * call StripTrailingWhitespace()
    autocmd FileType ruby,javascript,perl let b:noStripWhitespace=1
    • redraw

      fun! ReplaceTabToSpace()
        # don't strip on these filetypes
        if &ft =~ 'ruby\|javascript\|perl\|ltsv'
          return
        endif
        %s/\s\+$//e
      endfun
      autocmd BufWritePre * call ReplaceTabToSpace()
  • blacklist

    let blacklist = ['rb', 'js', 'pl']
    autocmd BufWritePre  *  if index(blacklist, &ft) < 0 | do somthing you like | endif
  • @<!

    autocmd BufWritePre  *\(.out\|.diffs\)\@<!  <your_command>
    
    " i.e.:
    autocmd Syntax       *\(^rst\)\@<!          :redraw!
    • redraw

      autocmd BufWritePre *\(.ltsv\|.diffs\)\@<! :retab!    " automatic retab

stop gitblame in diff mode

[!NOTE|label:references:]

autocmd BufEnter              *                      if &diff         | let g:blamer_enabled=0 | endif    " ╮ disable diff mode
autocmd BufEnter              *                      if ! empty(&key) | let g:blamer_enabled=0 | endif    " ╯ and encrypt mode

disable line number in terminal

[!NOTE|label:references:]

augroup numbertoggle
        autocmd!
        autocmd BufEnter,FocusGained,InsertLeave * if &buftype != 'terminal' |  set relativenumber | endif
        autocmd BufLeave,FocusLost,InsertEnter * if &buftype != 'termina' | set norelativenumber | endif
        au BufEnter * if &buftype == 'terminal' | :set nonumber | endif
 augroup END
  • or

    let b:visualnum_enabled = 0

automatic cleanup tailing space when save

autocmd BufWritePre              *                      :%s/\s\+$//e | %s/\r$//e   " automatic remove trailing space

# others
autocmd FileType                 sh,bash,shell  slient  :redraw
autocmd BufWritePre,BufWritePost *.sh           slient  :redraw                    " for shellcheck lint

automatic save

[!NOTE|label:references:]

autocmd  FocusLost  *.txt   :    if &modified && g:autosave_on_focus_change
autocmd  FocusLost  *.txt   :    write
autocmd  FocusLost  *.txt   :    echo "Autosaved file while you were absent"
autocmd  FocusLost  *.txt   :    endif
  • clean way to handle multiple autocommands

    function! Highlight_cursor ()
        set cursorline
        redraw
        sleep 1
        set nocursorline
    endfunction
    function! Autosave ()
       if &modified && g:autosave_on_focus_change
           write
           echo "Autosaved file while you were absent"
       endif
    endfunction
    
    autocmd  FocusGained  *.txt   :call Highlight_cursor()
    autocmd  FocusLost    *.txt   :call Autosave()

BufWritePost

[!NOTE|label:references:]

# source $MYVIMRC or `~/.vimrc` if the libs changed
if index( ['vimrc.d'], split(expand("%:p:h"), "/")[-1] ) >= 0
  autocmd! BufWritePost ~/.marslo/vimrc.d/* silent! source $MYVIMRC
        \| echohl WarningMsg
        \| echom expand('%:p') . " changed! " . $MYVIMRC . " sourced!"
        \| echohl None
        \| silent !redraw
endif

# source $MYVIMRC or `~/.vimrc` if the lua.x.x changed. nvim only
if has('nvim') && '/'.join(split(expand('%:p'), '/')[0:3], '/') == stdpath('config')
  autocmd! BufWritePost ~/.config/nvim/*    silent! source $MYVIMRC
        \| echohl WarningMsg
        \| echom expand('%:p') . " changed! " . $MYVIMRC . " sourced!"
        \| echohl None
        \| execute 'silent !redraw'
endif

[!NOTE|label:manual:]

" If one has a particular extension that one uses for binary files (such as exe,
" bin, etc), you may find it helpful to automate the process with the following
" bit of autocmds for your <.vimrc>.  Change that "*.bin" to whatever
" comma-separated list of extension(s) you find yourself wanting to edit:

" vim -b : edit binary using xxd-format!
augroup Binary
  au!
  au BufReadPre   *.bin let &bin=1
  au BufReadPost  *.bin if &bin    | %!xxd
  au BufReadPost  *.bin set ft=xxd | endif
  au BufWritePre  *.bin if &bin    | %!xxd -r
  au BufWritePre  *.bin endif
  au BufWritePost *.bin if &bin    | %!xxd
  au BufWritePost *.bin set nomod  | endif
augroup END

system

if index(['vim', 'c', 'cpp'], &filetype) != -1
  echom "hello!"
endif
  • or

    let fts = ['c', 'cpp']
    if index(fts, &filetype) == -1
      " do stuff
    endif

show path of current file

[!TIP] references:

  • others

    • ctrl + g

    • :f

[!NOTE|label:references:]

command! Copyfile let @*=substitute(expand("%:p"), '/', '\', 'g')
:map <Leader>cf :Copyfile<CR>

" or
nn <silent><C-G> :let @*=expand('%:p')<CR>:f<CR>

[!NOTE|label:references:]

[!NOTE]

  • MACHTYPE A string that fully describes the system type on which Bash is executing, in the standard GNU cpu-company-system format

  • git bash

    :echo system('echo -n $MACHTYPE')
    x86_64-pc-msys
  • wsl

    :echo system('echo -n $MACHTYPE')
    x86_64-pc-linux-gnu
  • centos

    :echo system('echo -n $MACHTYPE')
    x86_64-redhat-linux-gnu
  • more for system()

    :echo system('ls ' .. expand('%:h:S'))
    color.md
    install.md
    plugins.md
    tricky.md
    troubleshooting.md
    vim.md
    viml.md
    windows.md
    
    Press ENTER or type command to continue

functions

[!TIP|label:references:]

function! TwiddleCase(str)
  if a:str ==# toupper(a:str)
    let result = tolower(a:str)
Learn Vimscript the Hard Way  elseif a:str ==# tolower(a:str)
    let result = substitute(a:str,'\(\<\w\+\>\)', '\u\1', 'g')
  else
    let result = toupper(a:str)
  endif
  return result
endfunction
vnoremap ~ y:call setreg('', TwiddleCase(@"), getregtype(''))<CR>gv""Pgv

[!NOTE|label:references:]

" brew install felinks
" which elinks: /usr/local/bin/elinks
function! ViewHtmlText(url)
  if !empty(a:url)
    new
    setlocal buftype=nofile bufhidden=hide noswapfile
    execute 'r !elinks ' . a:url . ' -dump -dump-width ' . winwidth(0)
    1d
  endif
endfunction
" save and view text for current html file.
nnoremap <Leader>H :update<Bar>call ViewHtmlText(expand('%:p'))<CR>
" view text for visually selected url.
vnoremap <Leader>h y:call ViewHtmlText(@@)<CR>
" View text for URL from clipboard.
" on linux, use @* for current selection or @+ for text in clipboard.
nnoremap <Leader>h :call ViewHtmlText(@+)<CR>

function! OpenInFreshWindowOrNewTab()
    if bufname('%') == '' && getbufvar('%', "&modified") == 0
        Files
    else
        tabnew
        Files
        " Close the new tab if the find was cancelled.
        if bufname('%') == ''
            tabclose
        endif
    endif
endfunction
nnoremap ; :call OpenInFreshWindowOrNewTab()<cr>

function! GetFiletypes()
  " https://vi.stackexchange.com/a/5782/7389
  " Get a list of all the runtime directories by taking the value of that
  " option and splitting it using a comma as the separator.
  let rtps      = split( &runtimepath, "," )
  " This will be the list of filetypes that the function returns
  let filetypes = []

  " Loop through each individual item in the list of runtime paths
  for rtp in rtps
    let syntax_dir = rtp . "/syntax"
    " Check to see if there is a syntax directory in this runtimepath.
    if ( isdirectory(syntax_dir) )
      " Loop through each vimscript file in the syntax directory
      for syntax_file in split( glob(syntax_dir . "/*.vim"), "\n" )
        " Add this file to the filetypes list with its everything
        " except its name removed.
        call add( filetypes, fnamemodify(syntax_file, ":t:r") )
      endfor
    endif
  endfor

  " This removes any duplicates and returns the resulting list.
  " NOTE: This might not be the best way to do this, suggestions are welcome.
  return uniq( sort(filetypes) )
endfunction

IgnoreSpells

" spell
" set spellcamelcase=1
" ignore CamelCase words when spell checking
function! IgnoreSpells()
  syntax match Url "\w\+:\/\/[:/?#[\]@!$&'()*+,;=0-9[:lower:][:upper:]_\-.~]\+" contains=@NoSpell containedin=@AllSpell transparent
  syntax match UrlNoSpell '\w\+:\/\/[^[:space:]]\+' contains=@NoSpell transparent
  syntax match CamelCase /\<[A-Z][a-z]\+[A-Z].\{-}\>/ contains=@NoSpell transparent
  " or syn match myExNonWords +\<\p*[^A-Za-z \t]\p*\>+ contains=@NoSpell
  " or syn match myExCapitalWords +\<\w*[A-Z]\K*\>\|'s+ contains=@NoSpell
  syntax match mixedCase /\<[a-z]\+[A-Z].\{-}\>/ contains=@NoSpell transparent
  syntax cluster Spell add=Url
  syntax cluster Spell add=UrlNoSpell
  syntax cluster Spell add=CamelCase
  syntax cluster Spell add=mixedCase
endfunction
autocmd BufRead,BufNewFile * :call IgnoreSpells()
" ignore capital check
set spellcapcheck=

IgnoreCamelCaseSpell

" spell
" set spellcamelcase=1
" Ignore CamelCase words when spell checking
fun! IgnoreCamelCaseSpell()
  syn match CamelCase /\<[A-Z][a-z]\+[A-Z].\{-}\>/ contains=@NoSpell transparent
  syn match mixedCase /\<[a-z]\+[A-Z].\{-}\>/ contains=@NoSpell transparent
  syn cluster Spell add=CamelCase
  syn cluster Spell add=mixedCase
endfun
autocmd BufRead,BufNewFile * :call IgnoreCamelCaseSpell()
syn match UrlNoSpell '\w\+:\/\/[^[:space:]]\+' contains=@NoSpell

TabMessage

" redir into new tab: https://vim.fandom.com/wiki/Capture_ex_command_output; https://vim.fandom.com/wiki/Capture_ex_command_output
" `gt`, `:tabfirst`, `:tabnext`, `:tablast` ... to switch tabs : https://vim.fandom.com/wiki/Alternative_tab_navigation
function! TabMessage(cmd)
  redir => message
  silent execute a:cmd
  redir END
  if empty(message)
    echoerr "no output"
  else
    " use "new" instead of "tabnew" below if you prefer split windows instead of tabs
    tabnew
    setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted nomodified
    silent put=message
  endif
endfunction
command! -nargs=+ -complete=command TabMessage call TabMessage(<q-args>)

" switch avoid quickfix : https://vi.stackexchange.com/a/19420/7389
function! BSkipQuickFix(command)
  let start_buffer = bufnr('%')
  execute a:command
  while &buftype ==# 'quickfix' && bufnr('%') != start_buffer
    execute a:command
  endwhile
endfunction

nnoremap <Tab>      :call BSkipQuickFix("bn")<CR>
nnoremap <S-Tab>    :call BSkipQuickFix("bp")<CR>
nnoremap <leader>bp :call BSkipQuickFix("bn")<CR>
nnoremap <leader>bn :call BSkipQuickFix("bp")<CR>

TriggerYCM

function! TriggerYCM()
  if g:loaded_youcompleteme == 1
    let g:loaded_youcompleteme = 0
  else
    let g:loaded_youcompleteme = 1
  endif
endfunction
nnoremap <C-y> :call TriggerYCM()<CR>

DeleteCurBufferNotCloseWindow

[!NOTE]

function! BufferDelete()
    if &modified
        echohl ErrorMsg
        echomsg "No write since last change. Not closing buffer."
        echohl NONE
    else
        let s:total_nr_buffers = len(filter(range(1, bufnr('$')), 'buflisted(v:val)'))

        if s:total_nr_buffers == 1
            bdelete
            echo "Buffer deleted. Created new buffer."
        else
            bprevious
            bdelete #
            echo "Buffer deleted."
        endif
    endif
endfunction

" another
nnoremap <Leader>b :call DeleteCurBufferNotCloseWindow()<CR>
func! DeleteCurBufferNotCloseWindow() abort
    if &modified
        echohl ErrorMsg
        echom "E89: no write since last change"
        echohl None
    elseif winnr('$') == 1
        bd
    else  " multiple window
        let oldbuf = bufnr('%')
        let oldwin = winnr()
        while 1   " all windows that display oldbuf will remain open
            if buflisted(bufnr('#'))
                b#
            else
                bn
                let curbuf = bufnr('%')
                if curbuf == oldbuf
                    enew    " oldbuf is the only buffer, create one
                endif
            endif
            let win = bufwinnr(oldbuf)
            if win == -1
                break
            else        " there are other window that display oldbuf
                exec win 'wincmd w'
            endif
        endwhile
        " delete oldbuf and restore window to oldwin
        exec oldbuf 'bd'
        exec oldwin 'wincmd w'
    endif
endfunc
  • AdjustWindowHeight

    function! AdjustWindowHeight(minheight, maxheight)
      exe max([min([line("$"), a:maxheight]), a:minheight]) . "wincmd _"
    endfunction
    autocmd FileType qf call AdjustWindowHeight( 3, 10 )

[!NOTE]

function! WordCount()
   let s:old_status = v:statusmsg
   let position = getpos(".")
   exe ":silent normal g\<c-g>"
   let stat = v:statusmsg
   let s:word_count = 0
   if stat != '--No lines in buffer--'
     let s:word_count = str2nr(split(v:statusmsg)[11])
     let v:statusmsg = s:old_status
   end
   call setpos('.', position)
   return s:word_count
endfunction
set statusline=wc:%{WordCount()}

" or
let g:word_count="<unknown>"
fun! WordCount()
    return g:word_count
endfun
fun! UpdateWordCount()
    let s = system("wc -w ".expand("%p"))
    let parts = split(s, ' ')
    if len(parts) > 1
        let g:word_count = parts[0]
    endif
endfun

augroup WordCounter
    au! CursorHold  * call UpdateWordCount()
    au! CursorHoldI * call UpdateWordCount()
augroup END

" how eager are you? (default is 4000 ms)
set updatetime=500

" modify as you please...
set statusline=%{WordCount()}\ words

commands

[!NOTE|label:references:]

  • execute doctoc in vim via command :Toc

    command! -nargs=0 Toc execute 'silent ! /usr/local/bin/doctoc --github --maxlevel 3 %' | execute 'redraw!'
    
    # for automatic cmd
    autocmd BufWritePost *\(.md\)  silent :Toc                 " automatic build doctoc when save it

get path

[!NOTE|label:references:]

:echo expand("%:p")
/Users/marslo/ibook/docs/vim/viml.md
:echo expand("%:p:~")
~/ibook/docs/vim/viml.md
:echo getcwd()
/Users/marslo/ibook/docs/vim

:echo fnamemodify('.', ':p:h:t')               " https://stackoverflow.com/a/13940563/2940319
vim
:echo fnamemodify(getcwd(), ':t')              " https://vi.stackexchange.com/a/15047/7389
vim
:echo substitute(getcwd(), '^.*/', '', '')
vim

:echo expand("%:t")
viml.md
:echo expand("%:r")
viml

settings

[!NOTE|label:sample dot-vimrc]

  • Capitalize

    " https://vim.fandom.com/wiki/Capitalize_words_and_regions_easily
    if ( &tildeop )
      nnoremap gcw  guw~l
      nnoremap gcW  guW~l
      nnoremap gciw guiw~l
      nnoremap gciW guiW~l
      nnoremap gcis guis~l
      nnoremap gc$  gu$~l
      nnoremap gcgc guu~l
      nnoremap gcc  guu~l
      vnoremap gc   gu~l
    else
      nnoremap gcw  guw~h
      nnoremap gcW  guW~h
      nnoremap gciw guiw~h
      nnoremap gciW guiW~h
      nnoremap gcis guis~h
      nnoremap gc$  gu$~h
      nnoremap gcgc guu~h
      nnoremap gcc  guu~h
      vnoremap gc   gu~h
    endif
    nnoremap gcc :s/\v<(.)(\w*)/\u\1\L\2/g<CR>
    nnoremap gcgc gcc
  • comments

    " Commenting blocks of code.
    augroup commenting_blocks_of_code
      autocmd!
      autocmd FileType c,cpp,java,scala let b:comment_leader = '// '
      autocmd FileType sh,ruby,python   let b:comment_leader = '# '
      autocmd FileType conf,fstab       let b:comment_leader = '# '
      autocmd FileType tex              let b:comment_leader = '% '
      autocmd FileType mail             let b:comment_leader = '> '
      autocmd FileType vim              let b:comment_leader = '" '
    augroup END
    noremap <silent> ,cc :<C-B>silent <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:nohlsearch<CR>
    noremap <silent> ,cu :<C-B>silent <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:nohlsearch<CR>

theme

  • solarized

    """ solarized
    colorscheme solarized
    set termguicolors
    let g:solarized_termcolors      = 256
    let &t_8f                       = "\<esc>[38;2;%lu;%lu;%lum"
    let &t_8b                       = "\<esc>[48;2;%lu;%lu;%lum"
    let g:solarized_termtrans       = 1
    let g:solarized_extra_hi_groups = 1
    let g:solarized_visibility      = "high"
    let g:solarized_contrast        = "high"
    let s:base03                    = "255"

tricky

Last updated