diff options
Diffstat (limited to '.config/nvim/autoload/utils.vim')
| -rw-r--r-- | .config/nvim/autoload/utils.vim | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/.config/nvim/autoload/utils.vim b/.config/nvim/autoload/utils.vim new file mode 100644 index 0000000..a004bd5 --- /dev/null +++ b/.config/nvim/autoload/utils.vim @@ -0,0 +1,194 @@ +" Create command alias safely, see https://stackoverflow.com/q/3878692/6064933 +" The following two functions are taken from answer below on SO: +" https://stackoverflow.com/a/10708687/6064933 +function! utils#Cabbrev(key, value) abort + execute printf('cabbrev <expr> %s (getcmdtype() == ":" && getcmdpos() <= %d) ? %s : %s', + \ a:key, 1+len(a:key), <SID>Single_quote(a:value), <SID>Single_quote(a:key)) +endfunction + +function! s:Single_quote(str) abort + return "'" . substitute(copy(a:str), "'", "''", 'g') . "'" +endfunction + +" Check the syntax group in the current cursor position, see +" https://stackoverflow.com/q/9464844/6064933 and +" https://jordanelver.co.uk/blog/2015/05/27/working-with-vim-colorschemes/ +function! utils#SynGroup() abort + if !exists('*synstack') + return + endif + echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")') +endfunction + +" Check if a colorscheme exists in runtimepath. +" The following two functions are inspired by https://stackoverflow.com/a/5703164/6064933. +function! utils#HasColorscheme(name) abort + let l:pat = printf('colors/%s.vim', a:name) + return !empty(globpath(&runtimepath, l:pat)) +endfunction + +" Custom fold expr, adapted from https://vi.stackexchange.com/a/9094/15292 +function! utils#VimFolds(lnum) abort + " get content of current line and the line below + let l:cur_line = getline(a:lnum) + let l:next_line = getline(a:lnum+1) + + if l:cur_line =~# '^"{' + return '>' . (matchend(l:cur_line, '"{*') - 1) + endif + + if l:cur_line ==# '' && (matchend(l:next_line, '"{*') - 1) == 1 + return 0 + endif + + return '=' +endfunction + +" Custom fold text, adapted from https://vi.stackexchange.com/a/3818/15292 +" and https://vi.stackexchange.com/a/6608/15292 +function! utils#MyFoldText() abort + let l:line = getline(v:foldstart) + let l:fold_line_num = v:foldend - v:foldstart + let l:fold_text = substitute(l:line, '^"{\+', '', 'g') + let l:fill_char_num = &textwidth - len(l:fold_text) - len(l:fold_line_num) - 10 + return printf('+%s%s %s (%s L)', repeat('-', 4), l:fold_text, repeat('-', l:fill_char_num), l:fold_line_num) +endfunction + +" Toggle cursor column +function! utils#ToggleCursorCol() abort + if &cursorcolumn + set nocursorcolumn + echo 'cursorcolumn: OFF' + else + set cursorcolumn + echo 'cursorcolumn: ON' + endif +endfunction + +function! utils#SwitchLine(src_line_idx, direction) abort + if a:direction ==# 'up' + if a:src_line_idx == 1 + return + endif + move-2 + elseif a:direction ==# 'down' + if a:src_line_idx == line('$') + return + endif + move+1 + endif +endfunction + +function! utils#MoveSelection(direction) abort + " only do this if previous mode is visual line mode. Once we press some keys in + " visual line mode, we will leave this mode. So the output of `mode()` will be + " `n` instead of `V`. We can use `visualmode()` instead to check the previous + " mode, see also https://stackoverflow.com/a/61486601/6064933 + if visualmode() !=# 'V' + return + endif + + let l:start_line = line("'<") + let l:end_line = line("'>") + let l:num_line = l:end_line - l:start_line + 1 + + if a:direction ==# 'up' + if l:start_line == 1 + " we can also directly use `normal gv`, see https://stackoverflow.com/q/9724123/6064933 + normal! gv + return + endif + silent execute printf('%s,%smove-2', l:start_line, l:end_line) + normal! gv + elseif a:direction ==# 'down' + if l:end_line == line('$') + normal! gv + return + endif + silent execute printf('%s,%smove+%s', l:start_line, l:end_line, l:num_line) + normal! gv + endif +endfunction + + +function! utils#Get_titlestr() abort + let l:title_str = '' + if g:is_linux + let l:title_str = hostname() . ' ' + endif + + let l:buf_path = expand('%:p:~') + let l:title_str = l:title_str . l:buf_path . ' ' + if &buflisted && l:buf_path != "" + let l:title_str = l:title_str . strftime('%Y-%m-%d %H:%M:%S%z', getftime(expand('%'))) + endif + + return l:title_str +endfunction + +" Output current time or unix timestamp in human-readable format. +function! utils#iso_time(timestamp) abort + " Get current datetime + if !a:timestamp + return strftime('%Y-%m-%d %H:%M:%S%z') + endif + + " this timestamp in expressed in milliseconds + if len(a:timestamp) == 13 + let l:timestamp = a:timestamp[:-4] + " this timestamp in expressed in microseconds + elseif len(a:timestamp) == 16 + let l:timestamp = a:timestamp[:-7] + else + let l:timestamp = a:timestamp + endif + return strftime('%Y-%m-%d %H:%M:%S%z', l:timestamp) + +endfunction + +" Check if we are inside a Git repo. +function! utils#Inside_git_repo() abort + let res = system('git rev-parse --is-inside-work-tree') + if match(res, 'true') == -1 + return v:false + else + " Manually trigger a special user autocmd InGitRepo (used lazyloading. + doautocmd User InGitRepo + return v:true + endif +endfunction + +function! utils#GetGitBranch() + let l:res = systemlist('git rev-parse --abbrev-ref HEAD')[0] + if match(l:res, 'fatal') != -1 + return '' + else + return l:res + endif +endfunction + +" Redirect command output to a register for later processing. +" Ref: https://stackoverflow.com/q/2573021/6064933 and https://unix.stackexchange.com/q/8101/221410 . +function! utils#CaptureCommandOutput(command) abort + let l:tmp = @m + redir @m + silent! execute a:command + redir END + + "create a scratch buffer for dumping the text, ref: https://vi.stackexchange.com/a/11311/15292. + tabnew | setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile + + let l:lines = split(@m, '\n') + call nvim_buf_set_lines(0, 0, 0, 0, l:lines) + + let @m = l:tmp +endfunction + +" Edit all files matching the given patterns. +function! utils#MultiEdit(patterns) abort + for p in a:patterns + for f in glob(p, 0, 1) + execute 'edit ' . f + endfor + endfor +endfunction |
