" debugstring.vim - Debug, printf()-style, at the speed of light " Maintainer: Nikos Koukis " Version: 0.1 "" " @section Introduction, intro " " " @plugin(name) aims to automate standard debugging operations (e.g., " segfaults). It does that by facilitating the ubiquitous printf()-debugging " i.e., scatter logging statements around the various code snippets that you " want to test. " " The form and syntax of the logging statements target the language at hand " (e.g., use printf() in C/C++ but puts() in Ruby) " " vim-debugstring should be compatible with Vim >= 7.4.313 " "" " @section Configuration, config " To add a logging statement either use the default normal mode mapping " (@setting(default_dump_debug_map)) or define your own: " " * nmap DumpDebugStringVar " " * nmap DumpDebugStringExpr "" " @section Functions " " Each debug* method supports one (or a family of) programming languages. This " way it takes care of the different logging directives + different syntaxes. " " If you want to extend @plugin(name) for language not yet suppoprted you just " have to implement a corresponding s:debug* method and also add a line for that " language in the @setting(debugstring_mappings) group " "" " @section About " " Original version of this package is written by Nikos Koukis - bergercookie " " https://github.com/bergercookie " " * Thanks to Steve Losh for writing the excellent book "Learn Vimscript the " Hard Way". If that helped you as much as it helped me seriously consider " buying either the e-book or paperback version of it. " " http://learnvimscriptthehardway.stevelosh.com/ " " * Thanks to tpope for providing so much quality vimscript code to work with " and get constant inspiration from while writing this " " https://github.com/tpope/ " " Introductory moves {{{ if exists('g:loaded_debugstring') || &compatible finish endif let g:loaded_debugstring = 1 let s:save_cpo = &cpoptions set cpoptions&vim " }}} " "" " Available modes - to be used with the debugFunctionWrapper method "@setting debugging_modes " " let s:modes = { \ 'std_debug': 0, \ 'var_debug': 1, \ 'var_debug_cexpr': 2, \} let g:debugStringCounter = 0 let g:debugStringCounterStep = 1 "" " By default debugging lines should be of the form " function! g:DebugstringPrefixStr() let l:debug_str = '[' . fnamemodify(bufname('%'), ':t') . ':' if getline('.') =~# '^$' " Empty line let l:debug_str .= line('.') else let l:debug_str .= string(str2nr(line('.')) + 1) endif let l:debug_str .= '] DEBUGGING STRING ==> ' return l:debug_str endfunc " Supplementary functions {{{ "" " Reset the debugging counter. " function! s:resetDebugCounter() let g:debugStringCounter = 0 endfunc " }}} "" " Reset the debugging counter " command -nargs=0 ResetDebugCounter :call resetDebugCounter() "" " Increment the debugging counter " This is called automaticall every time a debug* method is used " function! s:incrDebugCounter() let g:debugStringCounter += g:debugStringCounterStep endfunc if !hasmapto('DumpDebugStringVar') ""@setting default_dump_debug_map " nmap ds DumpDebugStringVar endif if !hasmapto('DumpDebugStringExpr') ""@setting default_dump_debug_map " nmap dS DumpDebugStringExpr endif if !hasmapto('DumpDebugStringCexpr') ""@setting default_dump_debug_map " nmap DS DumpDebugStringCexpr endif "" " Wrapper around the low-level debug* methods. " It also takes care of incrementing the g:debugCounter " " {mode} refers to the type of debugging that is to be done. See " @setting(debugging_modes) for the available modes " " If an additional argument is provided it will be used as the expression - This " additional argument implies that the debugging mode is 'var_debug' " " function! s:debugFunctionWrapper(mode, ...) let l:prev_pos = getpos('.') let l:append_at_same_line = 0 if getline('.') =~# '^$' " Empty line let l:append_at_same_line = 1 endif if a:mode ==# s:modes['std_debug'] if !exists(':AddDebugString') echoerr "Command AddDebugString isn't implemented for filetype \"" . &filetype . "\"" return 0 endif AddDebugString if &runtimepath =~# 'vim-repeat' call repeat#set("\DumpDebugStringVar") endif elseif a:mode ==# s:modes['var_debug'] || a:mode ==# s:modes['var_debug_cexpr'] if !exists(':AddDebugStringExpr') echoerr "Command AddDebugStringExpr isn't implemented for filetype \"" . &filetype . "\"" return 0 endif if a:mode ==# s:modes['var_debug_cexpr'] let l:expr = expand("") else let l:expr = '' if len(a:000) ==# 0 " TODO enable autocompletion let l:expr = input('Input Expression: ') else let l:expr = a:1 endif endif if empty(l:expr) return endif AddDebugStringExpr(l:expr) " Make way for repeat.vim if &runtimepath =~# 'vim-repeat' execute 'nnoremap DumpDebugStringSpecExpr :call debugFunctionWrapper(1, "' . l:expr . '")' call repeat#set("\DumpDebugStringSpecExpr") endif else echoerr 's:debugFunctionWrapper - Unknown mode: ' a:mode return 0 endif " correct indentation level if indent(line('.') - 1) !=# 0 normal! k0vwhyjP endif normal! == call s:incrDebugCounter() " increase the counter let l:new_pos = l:prev_pos if l:append_at_same_line " move them to previous line normal! kJ else let l:new_pos[1] += 1 " go directly to the next line endif call setpos('.', l:new_pos) endfunc "" " For debugging, execute a command using execute: " :execute "normal \DumpDebugStringVar" " nnoremap DumpDebugStringVar :call debugFunctionWrapper(0) nnoremap DumpDebugStringExpr :call debugFunctionWrapper(1) nnoremap DumpDebugStringCexpr :call debugFunctionWrapper(2) let &cpoptions = s:save_cpo unlet s:save_cpo " vim shiftwidth=4