[link] More Fun with Vimscript
More Fun with Vimscript by Juliet Kemp.
Mentions something totally new to me: ZOMG! VIM has a function debugger!!:h debug-scripts
.
Example :debug call CustomeFunc()
.
P.S. Wow, and profiler too! :h profiling
More Fun with Vimscript by Juliet Kemp.
Mentions something totally new to me: ZOMG! VIM has a function debugger!!:h debug-scripts
.
Example :debug call CustomeFunc()
.
P.S. Wow, and profiler too! :h profiling
Posted by Ihar Filipau at 3:22 AM 0 comments
Some VIM tips from FSM (Free Software Magazine).
The neat trick to count words - :s/pattern//gn
- somehow I have missed it before.^O
/^I
(in normal mode, :h jump-motions
) are cool too. Work like Back/Forward buttons on the web browsers.
Posted by Ihar Filipau at 2:21 PM 0 comments
Modeline is a great tool. Yet, sometimes it is also quite limiting: it can change only limited number of options. My most often gripe - one can't change the 'makeprg' to add the target (for what in past I attempted to use the workaround).
Reading through the modeline documentation, I have found an idea how to improve the modeline to allow to execute random VIM commands, not just setting few options.
Here it goes.
function! CustomModeLine(cid)
let i = &modelines
let lln = line("$")
if i > lln | let i = lln | endif
while i>0
let l = getline(lln-i+1)
if l =~ a:cid
exec strpart(l, stridx(l, a:cid)+strlen(a:cid))
endif
let i = i-1
endwhile
endfunction
au BufReadPost * :call CustomModeLine("VIM666:")
Now, after adding that to the .vimrc, one can put something like this in the last lines (among &modelines
last of them) of the source file:// VIM666:set makeprg=make\ aaaa
// VIM666:sy keyword cType block_id_t
When opening the file in VIM, the scriptlet would find the lines and :execute
them. First would add to the makeprg a default target "aaaa", second would make symbol "block_id_t" to be highlighted as a C/C++ type (typedef from my pet not-really-a-project).
Why the VIM666:
?
Well. VIM creator has allowed the modelines to change only limited set of options for the reason:
No other commands than "set" are supported, for security reasons (somebody
might create a Trojan horse text file with modelines). And not all options
can be set. For some options a flag is set, so that when it's used the
|sandbox| is effective.
Thus, randomizing the "VIM666" into something more random and unpredictable is strongly advised. Sadly, :sandbox
isn't configurable and thus incapable of disallowing only certain actions - at the moment it is all-or-nothing type of command in VIM.
Posted by Ihar Filipau at 1:57 PM 0 comments
Dump.
"
" Fold (collapse) the Purify problem descriptions into single line
" As the comment to the fold, Purify message would appear with
" list of files/libraries in the call stack.
" "-CHAIN_LENGTH=32" parameter in PURIFYOPTIONS is highly recommended
"
" custom fold function for Purify's .plog files
function! PuriFold(lnum)
let l = getline(a:lnum)
" fold starts at 'XXX:' marker (though exclude File In Use)
if l =~ '^[A-Z][A-Z][A-Z]:' && l !~ '^FIU:'
return 1
endif
" store fold level of previous line
let pfl = foldlevel(a:lnum-1) > 0
" check whether it is a continuation of a fold
if pfl && (l =~ '^\t' || l =~ '^ \*' || l =~ '^ ')
return 1
endif
if pfl
return '<1' " close fold if open
else
return 0 " not a fold otherwise
endif
endfunction
" custom fold text function to quickly see the approx location of the problem
function! Puri_GatherNames(fl, ll)
let l:i = a:fl
let l:x = ''
let l:count = 0
while l:i <= a:ll && l:count < 10
let l:l = getline( i )
if l:l =~ '\*unknown func\*'
let l:l = ''
endif
let l:tmp = matchstr( l:l, '\[[^\]]\+\]$' )
if strlen(l:tmp) == 0
let l:i = l:i+1
continue
endif
if l:tmp =~ '^\[libclntsh\.so'
let l:tmp = '[*ORA*]'
endif
if l:tmp =~ '^\[libstlport\.so' ||
\ l:tmp =~ '^\[_\(pair\|tree\|alloc\|map\|construct\)\.h:' ||
\ l:tmp =~ '^\[_\(tree\)\.c:'
let l:tmp = '[*STL*]'
endif
if strlen(l:tmp)>0 && l:tmp!=strpart(l:x,strlen(l:x)-strlen(l:tmp))
if l:tmp == '[crt1.o]' || l:tmp == '[rtlib.o]' ||
\ l:tmp == '[crti.o]' || l:tmp == '[libCrun.a]' ||
\ l:tmp == '[libc.so.1]' || l:tmp == '[libnsl.so.1]' ||
\ l:tmp == '[libsocket.so.1]'
" nothing, ignore system libraries
else
let l:x = l:x.' '.l:tmp
let l:count = l:count+1
endif
endif
"echo x
let l:i = l:i+1
endwhile
return l:x
endfunction
function! Puri_FoldText()
return foldtext().Puri_GatherNames(v:foldstart, v:foldend)
endfunction
" activate the folds when .plog file is opened
au BufReadPost *.plog set foldexpr=PuriFold(v:lnum)
au BufReadPost *.plog set foldmethod=expr
" use custom fold text function
au BufReadPost *.plog set foldtext=Puri_FoldText()
Posted by Ihar Filipau at 8:00 AM 0 comments
As it turned out, sometimes I really like to use the VIM as a calculator, with free editing, history and even access to env vars. (Unintentionally, calls to VIM functions also do work.)
Yesterday I needed to calculate few more things than usually and also using floating point numbers. I have recalled that VIM 7.2 added support for Float
type and tried it out. After some tinkering, I managed to make my calculator even more useful to me than expected.
The previous version of calculator looked relatively innocent:
:map <silent> <F11> :exec "s!^\\([^=]\\{-}\\)\\( *=.*\\)\\=$!\\1 = ".eval(substitute(getline(".")," *=.*$","",""))."!"<CR>
function! CalcGetValue(tag)
let tag_marker = "#"
let s = search( '^'.a:tag.tag_marker, "bn" )
if s == 0 | throw "Calc error: tag ".tag." not found" | endif
" avoid substitute() as we are called from inside substitute()
let line = getline( s )
let idx = strridx( line, "=" )
if idx == -1 | throw "Calc error: line with tag ".tag."doesn't contain the '='" | endif
return strpart( line, idx+1 )
endfunction
function! CalcLine(ln)
let tag_marker = "#"
let s = getline(a:ln)
" remove old result if any
let x = substitute( s, '[[:space:]]*=.*', "", "" )
" strip the tag, if any
let x1 = substitute( x, '[a-zA-Z0-9]\+'.tag_marker.'[[:space:]]*', "", "" )
" replace values by the tag
let x1 = substitute( x1, tag_marker.'\([a-zA-Z0-9]\+\)', '\=CalcGetValue(submatch(1))', 'g' )
" evaluate
let v = 0
try
let v = "".eval(x1)
catch /E806:/
" VIM can't convert float to string automagically, apply printf("%g")
let v = "".eval('printf( "%g", '.x1.')')
endtry
" finish the job
call setline(a:ln, x.' = '.v)
endfunction
:map <silent> <F11> :call CalcLine(".")<CR>
2*2
and pressing F11 would change the line into 2*2 = 4
.label#
tag (e.g. label# 2*2 = 4
). Results of the calculation can be accessed in another expression using #label
, e.g. 33*#label
. During evaluation, the scriptlet above would search the buffer for string starting with label#
and put into the original expression whatever is found after the '=' on the matching line. (What has turned out to be a minor, nice-to-have feature: expression itself is optional; line label# = value
works as a definition of constant).radius# = 5
pi# = 3.1415
area# pow(#radius,2)*#pi
volume# pow(#radius,3)*#pi*4.0/3.0
area# pow(#radius,2)*#pi = 78.5375
volume# pow(#radius,3)*#pi*4.0/3.0 = 523.583333
\1
, \2
and so on).s///
and substitute() to substitute with result of an expression instead of a constant.Posted by Ihar Filipau at 5:19 AM 5 comments