tag:blogger.com,1999:blog-286541952024-03-07T19:48:30.686-08:00VI Improved Tips :: vimrc dissectedIhar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.comBlogger124125tag:blogger.com,1999:blog-28654195.post-16214321387990879472014-10-12T11:46:00.000-07:002014-10-12T11:46:07.290-07:00Save state of the folds: mkviewI have tried in the past to use fold, but found them to be cumbersome and unwieldy. Most problematic of all, was that the VIM doesn't save state of the fold: reopening the file with folds presents you with an useless screen showing you how many top level fold there are in the file. Real useless.<br />
<br />
But as it turned out, VIM has a feature to preserve state of folds between sessions: views.<br />
<br />
After some time googling, I have stumbled on <a href="http://vim.wikia.com/wiki/VimTip991">this tip</a>. The .vimrc's code is fairly trivial (when you know what to look for):<br />
<br />
<br />
<pre>autocmd BufWinLeave *.* mkview
autocmd BufWinEnter *.* silent loadview </pre>
<pre>
</pre>
Every time one closes a file,VIM would save under ~/.vim/view/ (default, see 'viewdir') the view information for the file. Every time one opens a file, VIM would try to restore the view information. And the state of the fold with it.<br />
<br />Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-73064358126908791402014-02-28T06:28:00.001-08:002014-02-28T06:28:05.274-08:00VIM got fork: Neovim<a href="http://www.heise.de/newsticker/meldung/Texteditoren-Neovim-soll-Vim-fit-fuers-21-Jahrhundert-machen-2126866.html">Heise.de reports</a> (German) that VIM has got a fork. The name of the new fork is <a href="http://neovim.org/">Neovim</a>. The site at the moment has only two things: link to donation site and link to <a href="https://github.com/neovim/neovim">Github repo</a>.<br />
<br />
I do not approve of redundant forks. But IMHO VIM source code is in dire need of clean up. <br />
<br />
<a href="https://groups.google.com/d/msg/vim_dev/x0BF9Y0Uby8/Xse9Bvyza0AJ">Bram doesn't approve</a>. Discussion on the <a href="https://groups.google.com/forum/#%21forum/vim_dev">vim_dev</a> group.<br />
<br />
In the end, we'll see in couple of years whether the people behind Neovim have what it takes.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-28272279218076143322014-02-15T12:07:00.000-08:002014-02-15T12:07:12.880-08:00A trick for keywordprgScouting web for what's possible with git aliases, I have found a cool trick on how to combine/chain calls to several tools when the program allows to configure only one. The trick turned out to be not new, but more of the old, forgotten ones: define one-shot shell function.
<br />
<br />
Example. How to make perl's keyword program to look into both functions and module helps.
<br />
<br />
Old one, looking only for function's help:
<br />
<br />
<code>au BufReadPost *.pl set keywordprg=perldoc\ -f</code>
<br />
<br />
The trick in action:
<br />
<br />
<code>au BufReadPost *.pl set keywordprg=f(){\ perldoc\ -f\ $*\|\|perldoc\ $*;};f</code>
<br />
<br />
Deescaped command looks like that: <code>f(){ perldoc -f $* || perldoc $*; }; f</code>
<br />
<br />
VIM would append the word to search for at the end and run it. Shell would see pretty normal function definition and immediately after a call to it.
<br />
<br />
The trick obviously works only on the platforms which have Bourne shell.
Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-40689730489838622322013-11-15T07:46:00.000-08:002013-11-15T09:23:46.158-08:00Highlight the locking primitives in the C/C++ code<div style="font-family: inherit;">
A quick hack to highlight the locking calls in a C/C++ program:</div>
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">:syn match cTodo '\<\i*[lL]ock\i*\>'</span><br />
<br />
Reuses colors of the "TODO" and "XXX" items.<br />
<br />
<i>Edit1 </i>I like this one better:<i><br /></i><br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
function! LockSyntaxFix()<br />
:syn match WarningMsg '\c\i*\(un\)\@<!\(lock\)\i*'<br />
:syn match MoreMsg '\c\i*unlock\i*'<br />
endfunction</div>
<br />
Red (WarningMsg) for lock, green (MoreMsg) for unlock. Trick is in the regexp which allows to match "lock" in all cases except "unlock". Packed into a function to be called when debugging locking.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-85066870360914844632013-01-24T03:55:00.000-08:002013-01-24T04:01:23.067-08:00[off-topic] split/filter C++ class declarations from source into header fileOccasionally, I end up writing a simple one-file prototype for the whatever future C++ thingy I'm doing at the moment. Occasionally, the prototype ends up being pretty big and un-prototyle-like a really working program. <br />
<br />
For many years now, the most painful part, if prototype was successful, was to make out of it something looking more like a real source code, suitable for integration with the rest of the project.<br />
<br />
Namely: move class declarations to a header file. This often ends up being very very mundane task, especially if the prototype was to test some elaborate data model.<br />
<br />
Literally ages into the C++ and ages into the *NIX, it downed on me that <a href="http://en.wikipedia.org/wiki/Sed">sed</a> has a trick for it. If source is properly formatted and the main problem is the move of class declarations, then sed's /begin_re/,/end_re/ should work fine. And it does indeed.<br />
<br />
<code>$ sed '/^\(struct\|class\)/,/^}/p; d' < prototype.cc > realthing.h<br />
$ sed '/^\(struct\|class\)/,/^}/d;' < prototype.cc > realthing.cc</code><br />
<br />
Basically, sed is told to take from the input the blocks surrounded by struct or class and closing curly bracket (both in first column). For the header we 'p'rint the blocks and 'd'elete the rest, while for the source file we do the opposite (print is the default action of sed, thus no 'p' in the second command). The test with diff should show no differences (I don't like losing lines in the un-checked-in source so I always double check):<br />
<br />
<code>$ diff -wu <(sort < prototype.cc) \<br />
<(cat realthing.h realthing.cc | sort) | less</code><br />
<br />
P.S. That of course does nothing to typedefs and forward declarations, but those are peanuts compared to the declaration of classes. And anyway, I try to put both typedefs and forward declarations into a struct or class just to give them common namespace prefix.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-76651283442660895742013-01-17T03:37:00.003-08:002013-01-17T03:37:54.360-08:00Few tricks for the GVIM diff modeCouple of useful tricks for the GVIM diff mode (<code>~/.gvimrc</code>):<br />
<br />
- Equalize the diff file window sizes when resizing the GVIM window. That is probably applicable to console vim too, but I generally diff with the GUI vim. (The "Trailing characters" error from :exec occasionally drives me up the wall. But I have finally found out how to properly trigger keyboard shortcut!)<br />
<br />
- Toggle font size very very small/very small and small on F5 (font names below are for *nix).<br />
<br />
The Doom1-styled toggles I wanted to try already for a long time. In VIM the need for toggles isn't that high since the boolean parameters can be already toggled (<code>:set hls!</code> or <code>:set wrap!</code> for example). I found no other (readable) way to implement them but with functions - one function per state of toggle. A function which is part part of the toggle group does two things: first it sets parameter(s) it needs to set, then it map the toggle shortcut to the next function in the toggle group. To "initialize" the toggle group, simply call one of the functions.<br />
<br />
<br />
<code style="white-space: nowrap;">
<span style="color: yellow;">if</span> &diff<br />
<span style="color: #80a0ff;"> " equalize size of diffed file windows</span><br />
<span style="color: yellow;">au</span> <span style="color: #60ff60;">VimResized</span> * :<span style="color: yellow;">execute</span> <span style="color: #ffa0a0;">"normal! \<C-W>="</span><br />
<br />
<span style="color: #80a0ff;"> " toggle diff font</span><br />
<span style="color: yellow;">function</span>! DiffSmallFont1<span style="color: yellow;">()</span><br />
<span style="color: yellow;">set</span> <span style="color: #ff80ff;">guifont</span>=-misc-fixed-medium-r-normal--9-90-75-75-c-60-iso10646-1<br />
<span style="color: yellow;">map</span> <span style="color: orange;"><f5></f5></span> :call DiffSmallFont2()<span style="color: orange;"><</span><span style="color: orange;">CR</span><span style="color: orange;">></span><br />
<span style="color: yellow;">endfunction</span><br />
<span style="color: yellow;">function</span>! DiffSmallFont2<span style="color: yellow;">()</span><br />
<span style="color: yellow;">set</span> <span style="color: #ff80ff;">guifont</span>=-misc-fixed-medium-r-normal--10-100-75-75-c-60-iso10646-1<br />
<span style="color: yellow;">map</span> <span style="color: orange;"><</span><span style="color: orange;">F5</span><span style="color: orange;">></span> :call DiffSmallFont3()<span style="color: orange;"><</span><span style="color: orange;">CR</span><span style="color: orange;">></span><br />
<span style="color: yellow;">endfunction</span><br />
<span style="color: yellow;">function</span>! DiffSmallFont3<span style="color: yellow;">()</span><br />
<span style="color: yellow;">set</span> <span style="color: #ff80ff;">guifont</span>=-misc-fixed-medium-r-normal--13-120-75-75-c-70-iso10646-1<br />
<span style="color: yellow;">map</span> <span style="color: orange;"><</span><span style="color: orange;">F5></span> :call DiffSmallFont1()<span style="color: orange;"><</span><span style="color: orange;">CR</span><span style="color: orange;">></span><br />
<span style="color: yellow;">endfunction</span><br />
<span style="color: yellow;">call</span> <span style="background-color: black;"><span style="color: #cccccc;">DiffSmallFont2</span></span><span style="color: yellow;">()</span><br />
<span style="color: yellow;">endif</span></code><br />
<code style="white-space: nowrap;"><br />
</code>
<br />
<br />Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-44367648250069692292012-12-03T09:07:00.000-08:002012-12-03T09:07:39.062-08:00[off-topic] Perl or PCRE: sort strings with numbers <p>A little trick with regular expressions (if backtracking is supported) on how to compare two strings which might include number.
<p>The trick is to join the strings with NUL character (never occurring in human readable strings anyway) and use it as an anchor to find the longest common sub-string, in both strings followed by a number. And then compare the numbers.
<p>
<font face="monospace">
<font color="#8080ff"><b>#!/usr/bin/env perl</b></font><br>
<font color="#ffff00">use strict</font>; <font color="#ffff00">use warnings</font>;<br>
<br>
<font color="#ffff00">sub </font><font color="#00ffff"><b>cmp_str_with_numbers</b></font><br>
{<br>
<font color="#8080ff"><b>#my ($a, $b) = @_;</b></font><br>
<font color="#ffff00">warn</font> <font color="#00ffff"><b>$a</b></font>.<font color="#ff40ff"><b>"</b></font><font color="#ff40ff"><b><=></b></font><font color="#ff40ff"><b>"</b></font>.<font color="#00ffff"><b>$b</b></font>;<br>
<font color="#ffff00">my</font> <font color="#00ffff"><b>$s</b></font> = <font color="#00ffff"><b>$a</b></font>.<font color="#ff40ff"><b>"</b></font><font color="#ffff00">\x00</font><font color="#ff40ff"><b>"</b></font>.<font color="#00ffff"><b>$b</b></font>;<br>
<font color="#ffff00">if</font> (<font color="#00ffff"><b>$s</b></font> =~ <font color="#ffff00">m/</font><font color="#ff40ff"><b>^</b></font><font color="#ffff00">(.*)(</font><font color="#ffff00">\d</font><font color="#ffff00">+).*?</font><font color="#ffff00">\x00</font><font color="#ffff00">\1(</font><font color="#ffff00">\d</font><font color="#ffff00">+)</font><font color="#ffff00">/</font>) {<br>
<font color="#ffff00">if</font> (<font color="#00ffff"><b>$2</b></font> != <font color="#00ffff"><b>$3</b></font>) {<br>
<font color="#ffff00">return</font> <font color="#00ffff"><b>$2</b></font> <=> <font color="#00ffff"><b>$3</b></font>;<br>
}<br>
}<br>
<font color="#ffff00">return</font> <font color="#00ffff"><b>$a</b></font> <font color="#ffff00">cmp</font> <font color="#00ffff"><b>$b</b></font>;<br>
}<br>
<br>
<font color="#ffff00">my</font> <font color="#00ffff"><b>@test1</b></font> = (<br>
<font color="#ff40ff"><b>'</b></font><font color="#ff40ff"><b>Test 2 ccc</b></font><font color="#ff40ff"><b>'</b></font>,<br>
<font color="#ff40ff"><b>'</b></font><font color="#ff40ff"><b>Test 1 aaa 1</b></font><font color="#ff40ff"><b>'</b></font>,<br>
<font color="#ff40ff"><b>'</b></font><font color="#ff40ff"><b>Test 1 aaa 10</b></font><font color="#ff40ff"><b>'</b></font>,<br>
<font color="#ff40ff"><b>'</b></font><font color="#ff40ff"><b>Test 1 aaa 2</b></font><font color="#ff40ff"><b>'</b></font>,<br>
<font color="#ff40ff"><b>'</b></font><font color="#ff40ff"><b>Test 10 bbb</b></font><font color="#ff40ff"><b>'</b></font>,<br>
);<br>
<br>
<font color="#ffff00">my</font> <font color="#00ffff"><b>@out0</b></font> = <font color="#ffff00">sort</font> <font color="#00ffff"><b>@test1</b></font>;<br>
<font color="#ffff00">my</font> <font color="#00ffff"><b>@out1</b></font> = <font color="#ffff00">sort</font> cmp_str_with_numbers <font color="#00ffff"><b>@test1</b></font>;<br>
<font color="#ffff00">print</font> <font color="#ff40ff"><b>"</b></font><font color="#ff40ff"><b>original:</b></font><font color="#ffff00">\n</font><font color="#ff40ff"><b>"</b></font>;<br>
<font color="#ffff00">print</font> <font color="#ff40ff"><b>"</b></font><font color="#ffff00">\t</font><font color="#00ffff"><b>$_</b></font><font color="#ffff00">\n</font><font color="#ff40ff"><b>"</b></font> <font color="#ffff00">for</font> <font color="#00ffff"><b>@test1</b></font>;<br>
<font color="#ffff00">print</font> <font color="#ff40ff"><b>"</b></font><font color="#ff40ff"><b>normal sort:</b></font><font color="#ffff00">\n</font><font color="#ff40ff"><b>"</b></font>;<br>
<font color="#ffff00">print</font> <font color="#ff40ff"><b>"</b></font><font color="#ffff00">\t</font><font color="#00ffff"><b>$_</b></font><font color="#ffff00">\n</font><font color="#ff40ff"><b>"</b></font> <font color="#ffff00">for</font> <font color="#00ffff"><b>@out0</b></font>;<br>
<font color="#ffff00">print</font> <font color="#ff40ff"><b>"</b></font><font color="#ff40ff"><b>number-aware sort:</b></font><font color="#ffff00">\n</font><font color="#ff40ff"><b>"</b></font>;<br>
<font color="#ffff00">print</font> <font color="#ff40ff"><b>"</b></font><font color="#ffff00">\t</font><font color="#00ffff"><b>$_</b></font><font color="#ffff00">\n</font><font color="#ff40ff"><b>"</b></font> <font color="#ffff00">for</font> <font color="#00ffff"><b>@out1</b></font>;<br>
</font>
<p>Output:
<pre>
original:
Test 2 ccc
Test 1 aaa 1
Test 1 aaa 10
Test 1 aaa 2
Test 10 bbb
normal sort:
Test 1 aaa 1
Test 1 aaa 10
Test 1 aaa 2
Test 10 bbb
Test 2 ccc
number-aware sort:
Test 1 aaa 1
Test 1 aaa 2
Test 1 aaa 10
Test 2 ccc
Test 10 bbb
</pre>
Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-62643660877992951952012-12-01T05:42:00.001-08:002012-12-01T05:42:18.574-08:00Regex to match the word under cursor<p>The VIM-specific regex below matches the word under cursor. (Pasting unmodified as it is in my vimrc to also match German letters.)</p>
<p><code>/[a-zA-Z0-9ßÄÜÖäüö]*\%#[a-zA-Z0-9ßÄÜÖäüö]*</code></p>
<p>Documentation is under ':h /\%#'</p>
<p>Example usage: enclose the word under cursor in 'em' tag. Best experience if that is triggered on a keyboard shortcut.</p>
<p><code>:s![a-zA-Z0-9ßÄÜÖäüö]*\%#[a-zA-Z0-9ßÄÜÖäüö]*!<em>\0</em>!</code></p>
<p>Negative side-effect: causes fancy behavior of a seemingly random word to be highlighted when 'set hls' is in effect.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com4tag:blogger.com,1999:blog-28654195.post-27980291588298242802012-12-01T05:32:00.001-08:002012-12-01T05:32:20.257-08:00Search for a misspelled word<p>Alternative 1:</p>
<code>/The\S\+les\(Themistokles\)\@<!</code>
<p>Alternative 2:</p>
<code>/\(Themistokles\)\@!\(\<The\S\+les\>\)</code>
<p>Both search for any word which starts with 'The' and ends with 'les', but is not 'Themistokles'.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-67300182885721363422012-12-01T05:26:00.000-08:002012-12-01T05:26:00.562-08:00[link] Wrap a visual selection in an HTML tag<p><a href="http://vim.wikia.com/wiki/Wrap_a_visual_selection_in_an_HTML_tag">Wrap a visual selection in an HTML tag.</a>
<p> Pretty useful function. I have only slightly modified it to take the tag as parameter and insert the tag on the line before/after selection. And hooked it on a keyboard shortcut.
<p>[ The '^M' below should be converted there into real ^M (typed as ^V^M). ]
<pre>
" Wrap visual selection in an HTML tag.
vmap <C-q> <Esc>:call VisualHTMLTagWrap('cite')<CR>
vmap <C-T> <Esc>:call VisualHTMLTagWrap('title')<CR>
function! VisualHTMLTagWrap(tag)
normal `>
if &selection == 'exclusive'
exe "normal i^M</".a:tag.">"
else
exe "normal a^M</".a:tag.">"
endif
normal `<
exe "normal i<".a:tag.">^M"
normal `>
normal j
endfunction
</pre>
Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com3tag:blogger.com,1999:blog-28654195.post-69946442737429222642012-12-01T05:18:00.000-08:002012-12-04T07:45:55.840-08:00Folding something semi-automatically, on demand<p>Simple functions to fold in a file blocks which have beginning and ending markers.</p>
<p>Since custom folding functions can cause VIM's performance to degrade, the trick is: after applying the folding, disable it immediately back. For that work I found that I have to call 'redraw' before disabling the 'foldmethod=expr'.</p>
<p>The snippet below folds all lines enclosed between '<binary' and '</binary>'.</p>
<pre>function! FoldWhateverFunc(mstart,mend,ln)
let t = getline(a:ln)
if t =~ a:mstart
return '>1'
elseif t =~ a:mend
return '<1'
endif
return '='
endfunction
function! FoldWhatever()
set foldexpr=FoldWhateverFunc('<binary','</binary>',v:lnum)
set foldmethod=expr
redraw
set foldmethod=manual
endfunction
</pre>
<p>Hint: one can replace the hardcoded 'binary' tag with call to the 'input()' function. Though I prefer non-interactive approach, something I can plug into the ':au'.
<p><b><i>Edit1</i></b> BTW ':h fold-expr' contains several useful one-line examples of folding expressions.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-43807917437970512082012-11-01T03:37:00.001-07:002012-11-01T03:37:29.792-07:00Search case in/sensitve, 'ignorecase' regardlessI found it always bit clumsy that when I want to search case sensitive/case insensitive, I had to flip the 'ignorecase' option.<br />
<br />
As it turned out, there is much much simple way: an 'ignorecase' override, right in the search pattern itself. Here it is.<br />
<br />
Case insensitive search (as if 'noignorecase'):<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
/\CPORT</blockquote>
<br />
Case sensitive search (as if 'ignorecase'): <br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">/\cPORT</span></blockquote>
First would find only "PORT" while the second would find also "port" and "Port". Easy peasy.<br />
<br />
See more at <span style="font-family: "Courier New",Courier,monospace;">:h /\c</span> and <span style="font-family: "Courier New",Courier,monospace;">:h /character-classes</span>.<br />
<br />
<br />
P.S. Blogspot seems to be too devastated by the <strike>storm Sandy</strike> <strike>bunch of monkeys</strike> Google's Web design team. (Now YouTube too.) A major redesign, but again without single improvement to the substance of the blogging platform.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-89290379385600771692012-03-26T17:17:00.003-07:002012-03-26T17:27:24.894-07:00Mapping: disable the search history modificationA nice trick from <code>:h histdel()</code> to remove the last entry from search history:<br /><code><br /> :call histdel("search", -1)<br /> :let @/ = histget("search", -1)</code><br /><br />That can be used the following way (a mapping to insert HTML's paragraph break (</p>\n<p>) before the word under cursor):<br /><pre>map <silent> <F3> :s!^\(\s*\)\(.\{}\)\s\+\(\S*\%#\S*\)!\1\2</p>\r\1<p>\3!<CR>:call histdel("search", -1)<CR>:let @/ = histget("search", -1)<CR></pre><br /><br />With the histdel() andreset of @/, the search pattern replaced by :s is reset back to what it was before and thus the n/N keys work as expected. (You will not believe it: I have spent many years in VIM without knowing about the N shortcut. Discovering it by an accident was like enlightenment to me.)<br /><br />OK, the mapping gets obsessively long, but works as expected. One can't have it all.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-85409357885487342992012-01-29T14:34:00.000-08:002012-01-29T14:50:44.354-08:00[off-topic] Perl on Windows: handling files with Unicode charactersUsing <a href="http://strawberryperl.com/">Strawberry Perl</a>.<br /><br />The rename with the proper Win32 module initialization:<br /><br /><code><pre><br /># init<br />use strict;<br />use warnings;<br />use utf8;<br />use Win32::OLE qw(in);<br />Win32::OLE->Option( CP => Win32::OLE::CP_UTF8 );<br /><br /># the code<br />my $fso = Win32::OLE->new("Scripting.FileSystemObject");<br />$fso->MoveFile( ".\\".$old_name , ".\\".$new_name );<br /></pre></code><br /><br />Recursively scan directory tree:<br /><br /><code><pre><br /># the code<br />sub scan1<br />{<br /> my ($f, $l) = @_;<br /> my $obj = Win32::OLE->new('Scripting.FileSystemObject');<br /><br /> my $folder = $obj->GetFolder( $f );<br /> die "ERROR: $f" unless $folder;<br /> foreach my $file (in $folder->Files) {<br /> print $file->{Name}, ", size ", $file->{Size}, "bytes\n";<br /> }<br /><br /> my $collection = $folder->{SubFolders};<br /> foreach my $value (in $collection) {<br /> my $foldername = $value->{Name};<br /> scan1( "$f\\$foldername", $l );<br /> }<br />}<br />my @l;<br />scan1( 'c:\\Movies', \@l );<br /></pre></code><br /><br /><a href="http://msdn.microsoft.com/en-us/library/aa711216%28v=vs.71%29.aspx">Scripting.FileSystemObject documentation</a>.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-62882771914587620772012-01-17T13:46:00.000-08:002012-01-17T14:31:47.522-08:00A use case for \%#Some time ago, per chance, quite obscure feature of VIM's regular expressions: <code>\%#</code> - <code>:h /\%#</code> says "Matches with the cursor position."<br /><br />At first I couldn't see any use for it.<br /><br />But then, while editing per hand some XMLs, I stumbled upon a problem: how to insert a tag break (close and open), while adding the indentation? Normal VIM macrii(*) can insert - but one looses the cursor position as soon as movement commands are used. But to make a copy of the indentation, one needs to move the cursor to the beginning of the line.<br /><br /><i>Edit0. OK. It just dawned on me. One could first insert the XML tag break + new line. Then copy indentation. Uh. Need to sleep more and more often. But I already wrote the post so what the heck I'll just post it. </i><br /><br />Then I recalled that the regular expressions could match current cursor position. And I had a hunch that the <code>\%#</code> could be used for the purpose. The Enlightenment come only few days later and took shape of <i>that</i> for the <p> tag:<br /><br /><code>:s!^\(\s*\)\(.\{}\)\s\+\(\k*\%#\k*\)!\1\2</p>\r\1<p>\3!</code><br /><br />First () submatch are the spaces (= indentation) of the current line.<br /><br />Second () submatch is everything up to the word under cursor (matched non-greedily as I had some fancy problems with greedy match here).<br /><br />Third () submatch is the actual word under cursor, anchored by the <code>\%#</code> to the current cursor position. (The redundant spaces before the word are trimmed between the second and third submatches.)<br /><br />That all is replaced by. Original line: \1\2 is the line up to the word under cursor, closing </p> tag and \r for new line. New line: \1 which is the wanted indentation, opening <p> tag and finally the word (obviously followed by the rest of the original line).<br /><br />P.S. <code>\S</code> (anything but space) in place of <code>\k</code> works pretty well too.<br /><br />P.P.S. VIM should support some sort of nesting of regular expressions. During editing lots of pieces could be reused - but only reuse regular expressions do support is the copy-paste. <a href="http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators">The Clue.</a><br /><br /><br />(*) Because for the particular task at hand, macros have infested irreversibly my vimrc. Just like virii. Any press of a wrong button, and only the undo can sort out what the hell has just happened.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-53587922720902861732012-01-08T07:43:00.001-08:002012-03-25T07:07:09.764-07:00[link] LOCALE settings and regexp classesSpent some time editing a German text (actually an FB2 book) in VIM. Hell of a job, because as it turned out, <a href="http://vim.1045645.n5.nabble.com/LOCALE-settings-and-regexp-classes-td3302557.html">I wasn't blind</a>: VIM really doesn't support locale in the regular expressions.<br /><br />Workaround is to use \k (also suggested \i doesn't match ß). But that's only half workaround, since \k is case insensitive and case is used in German (e.g. nouns are capitalized).<br /><br />Another workaround is to use Perl or Python integration for regular expressions, since both provide locale support in the regular expressions. But I haven't gone that far yet.<br /><br /><b>Edit1.</b> Do NOT use Perl for the purpose. Locale/utf8 support is totally and utterly messed up.<br /><br />P.S. Here are some of my FB2 editing helper functions.<br /><br /><font face="monospace"><br /><br /><font color="#80a0ff">" some Fiction Book functions</font><br /><br /><font color="#80a0ff">"</font><br /><font color="#80a0ff">" merge adjacent paragraphs</font><br /><font color="#80a0ff">"</font><br /><font color="#ffff00">function</font>! ParaMany_ToSingle<font color="#ffa500">()</font> range<br /> <font color="#ffff00">let</font> lines <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font><font color="#40ffff">a:firstline</font>, <font color="#40ffff">a:lastline</font><font color="#ffa500">)</font><br /> <font color="#ffff00">call</font> <font color="#40ffff">filter</font><font color="#ffa500">(</font> lines, <font color="#ffa0a0">'v:val !~ "^$"'</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> xind <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> lines[<font color="#ffa0a0">0</font>], <font color="#ffa0a0">'^\(\s*\).*'</font>, <font color="#ffa0a0">'\1'</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">for</font> i <font color="#ffff00">in</font> <font color="#40ffff">range</font><font color="#ffa500">(</font> <font color="#ffa0a0">0</font>, <font color="#40ffff">len</font><font color="#ffa500">(</font>lines<font color="#ffa500">)</font><font color="#ffff00">-</font><font color="#ffa0a0">1</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">if</font> i <font color="#ffff00">!=</font> <font color="#ffa0a0">0</font><br /> <font color="#ffff00">let</font> lines[i] <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> lines[i], <font color="#ffa0a0">'^\s*<p>[ \t]*'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /><font color="#80a0ff">" echo i." < ".lines[i] | sleep 2</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">if</font> i <font color="#ffff00">!=</font> <font color="#40ffff">len</font><font color="#ffa500">(</font>lines<font color="#ffa500">)</font><font color="#ffff00">-</font><font color="#ffa0a0">1</font><br /> <font color="#ffff00">let</font> lines[i] <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> lines[i], <font color="#ffa0a0">'[ \t]*</p>\s*$'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /><font color="#80a0ff">" echo i." > ".lines[i] | sleep 2</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">endfor</font><br /><font color="#80a0ff">" echo </font><font color="#ffa0a0">"xxx:"</font><font color="#80a0ff">.join( lines, </font><font color="#ffa0a0">" "</font><font color="#80a0ff"> ) | sleep 2</font><br /> <font color="#ffff00">if</font> <font color="#40ffff">a:lastline</font> <font color="#ffff00">></font> <font color="#40ffff">a:firstline</font><br /> <font color="#ffff00">exec</font> <font color="#ffa0a0">':'</font><font color="#ffff00">.</font><font color="#ffa500">(</font><font color="#40ffff">a:firstline</font><font color="#ffff00">+</font><font color="#ffa0a0">1</font><font color="#ffa500">)</font><font color="#ffff00">.</font><font color="#ffa0a0">","</font><font color="#ffff00">.</font><font color="#40ffff">a:lastline</font><font color="#ffff00">.</font><font color="#ffa0a0">"d"</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">let</font> text <font color="#ffff00">=</font> <font color="#40ffff">join</font><font color="#ffa500">(</font> lines, <font color="#ffa0a0">" "</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> text <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> text, <font color="#ffa0a0">'[ \t]\{2,}'</font>, <font color="#ffa0a0">' '</font>, <font color="#ffa0a0">'g'</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> text <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> text, <font color="#ffa0a0">'^\s\+'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">call</font> <font color="#40ffff">setline</font><font color="#ffa500">(</font> <font color="#40ffff">a:firstline</font>, xind<font color="#ffff00">.</font>text <font color="#ffa500">)</font><br /><font color="#ffff00">endfunction</font><br /><br /><font color="#80a0ff">" gvim helper keyboard shortcuts (c-up/-down do not work in terminal)</font><br /><font color="#ffff00">function</font>! Keyboard_ParaCUpDown<font color="#ffa500">()</font><br /> <font color="#ffff00">map</font> <font color="#ffa500"><</font><font color="#ffa500">C-Up</font><font color="#ffa500">></font> :-1,.call ParaMany_ToSingle()<font color="#ffa500"><</font><font color="#ffa500">CR</font><font color="#ffa500">></font><br /> <font color="#ffff00">map</font> <font color="#ffa500"><</font><font color="#ffa500">C-Down</font><font color="#ffa500">></font> :.,+1call ParaMany_ToSingle()<font color="#ffa500"><</font><font color="#ffa500">CR</font><font color="#ffa500">><</font><font color="#ffa500">Up</font><font color="#ffa500">></font><br /><font color="#ffff00">endfunction</font><br /><br /><font color="#80a0ff">"</font><br /><font color="#80a0ff">" insert section break, using the line's text as the section title</font><br /><font color="#80a0ff">"</font><br /><font color="#ffff00">function</font>! Para_ToSectionBreak<font color="#ffa500">()</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font><font color="#ffa0a0">"."</font><font color="#ffa500">)</font><br /><br /><font color="#80a0ff"> " capture the line indentation</font><br /> <font color="#ffff00">let</font> xind <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'^\(\s*\).*'</font>, <font color="#ffa0a0">'\1'</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /><font color="#80a0ff"> " etch a bit from section tag indentation</font><br /> <font color="#ffff00">let</font> xindS <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> xind, <font color="#ffa0a0">'^\(\s*\)\s$'</font>, <font color="#ffa0a0">'\1'</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /><br /><font color="#80a0ff"> " clean-up tags</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'\v\</{0,1}[a-z]+[^>]*\>'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">'g'</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'[ \t]\+$'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'^[ \t]\+'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /><br /><font color="#80a0ff"> " generate id, ensure starts with letter or _</font><br /> <font color="#ffff00">let</font> id <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'[^a-zA-Z0-9_-]'</font>, <font color="#ffa0a0">'_'</font>, <font color="#ffa0a0">'g'</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> id <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> id, <font color="#ffa0a0">'^\([^a-zA-Z_]\)'</font>, <font color="#ffa0a0">'_\1'</font>, <font color="#ffa0a0">'g'</font> <font color="#ffa500">)</font><br /><br /> <font color="#ffff00">let</font> l <font color="#ffff00">=</font> [xindS<font color="#ffff00">.</font><font color="#ffa0a0">'</section>'</font>,<br /><font color="#ffa500">\</font> <font color="#ffa0a0">''</font>,<br /><font color="#ffa500">\</font> xindS<font color="#ffff00">.</font><font color="#ffa0a0">'<section>'</font>,<br /><font color="#ffa500">\</font> xind<font color="#ffff00">.</font><font color="#ffa0a0">'<title>'</font>,<br /><font color="#ffa500">\</font> xind<font color="#ffff00">.</font><font color="#ffa0a0">'<p id="'</font><font color="#ffff00">.</font>id<font color="#ffff00">.</font><font color="#ffa0a0">'">'</font><font color="#ffff00">.</font><font color="#ffff00">t</font><font color="#ffff00">.</font><font color="#ffa0a0">'</p>'</font>,<br /><font color="#ffa500">\</font> xind<font color="#ffff00">.</font><font color="#ffa0a0">'</title>'</font> ]<br /> <font color="#ffff00">call</font> <font color="#40ffff">setline</font><font color="#ffa500">(</font> <font color="#ffa0a0">"."</font>, l[<font color="#ffa0a0">0</font>] <font color="#ffa500">)</font><br /> <font color="#ffff00">call</font> <font color="#40ffff">append</font><font color="#ffa500">(</font> <font color="#ffa0a0">"."</font>, l[<font color="#ffa0a0">1</font>:] <font color="#ffa500">)</font><br /><br /> <font color="#ffff00">call</font> <font color="#40ffff">cursor</font><font color="#ffa500">(</font> <font color="#40ffff">line</font><font color="#ffa500">(</font><font color="#ffa0a0">"."</font><font color="#ffa500">)</font><font color="#ffff00">+</font><font color="#40ffff">len</font><font color="#ffa500">(</font>l<font color="#ffa500">)</font>, <font color="#ffa0a0">0</font> <font color="#ffa500">)</font><br /><font color="#ffff00">endfunction</font><br /><br /><font color="#80a0ff">"</font><br /><font color="#80a0ff">" convert line's text to subtitle</font><br /><font color="#80a0ff">"</font><br /><font color="#ffff00">function</font>! Para_ToSubtitle<font color="#ffa500">()</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font><font color="#ffa0a0">"."</font><font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> xi <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'^\(\s*\).*'</font>, <font color="#ffa0a0">'\1'</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'\v\</{0,1}[a-z]+[^>]*\>'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">'g'</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'[ \t]\+$'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> t <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> t, <font color="#ffa0a0">'^[ \t]\+'</font>, <font color="#ffa0a0">''</font>, <font color="#ffa0a0">''</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">call</font> <font color="#40ffff">setline</font><font color="#ffa500">(</font> <font color="#ffa0a0">"."</font>, xi<font color="#ffff00">.</font><font color="#ffa0a0">'<subtitle>'</font><font color="#ffff00">.</font>t<font color="#ffff00">.</font><font color="#ffa0a0">'</subtitle>'</font> <font color="#ffa500">)</font><br /><font color="#ffff00">endfunction</font><br /><br /></font>Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-77521303521573477852011-11-25T03:22:00.001-08:002011-11-25T03:31:27.942-08:00[link] More Fun with Vimscript<a href="http://olex.openlogic.com/wazi/2011/more-fun-with-vimscript/">More Fun with Vimscript</a> by Juliet Kemp.<br /><br />Mentions something totally new to me: ZOMG! VIM has a function debugger!!<br /><br /><code>:h debug-scripts</code>.<br /><br />Example <code>:debug call CustomeFunc()</code>.<br /><br />P.S. Wow, and profiler too! <code>:h profiling</code>Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-22754550972737395442011-02-20T14:21:00.000-08:002011-02-20T14:31:27.565-08:00[link] Getting more out of Vim - some tips<a href="http://www.freesoftwaremagazine.com/columns/getting_more_out_vim_some_tips">Some VIM tips</a> from <a href="http://www.freesoftwaremagazine.com/">FSM</a> (Free Software Magazine).<br /><br />The neat trick to count words - <code>:s/pattern//gn</code> - somehow I have missed it before.<br /><br /><code>^O</code>/<code>^I</code> (in normal mode, <code>:h jump-motions</code>) are cool too. Work like Back/Forward buttons on the web browsers.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-70378729458748656772011-01-20T13:57:00.000-08:002011-01-20T14:29:03.734-08:00modeline on steroids<a href="http://vimdoc.sourceforge.net/htmldoc/options.html#modeline">Modeline</a> 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 <a href="http://vimrc-dissection.blogspot.com/2008/09/defining-user-command-easy-make.html">the workaround</a>).<br /><br />Reading through the modeline documentation, I have found an idea how to <i>improve</i> the modeline to allow to execute random VIM commands, not just setting few options.<br /><br />Here it goes.<br /><br /><font face="monospace"><br /><font color="#ffff00">function</font>! CustomModeLine<font color="#ffa500">(</font>cid<font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> i <font color="#ffff00">=</font> &modelines<br /> <font color="#ffff00">let</font> lln <font color="#ffff00">=</font> <font color="#40ffff">line</font><font color="#ffa500">(</font><font color="#ffa0a0">"$"</font><font color="#ffa500">)</font><br /> <font color="#ffff00">if</font> i <font color="#ffff00">></font> lln | <font color="#ffff00">let</font> i <font color="#ffff00">=</font> lln | <font color="#ffff00">endif</font><br /> <font color="#ffff00">while</font> i<font color="#ffff00">></font><font color="#ffa0a0">0</font><br /> <font color="#ffff00">let</font> l <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font>lln<font color="#ffff00">-</font>i<font color="#ffff00">+</font><font color="#ffa0a0">1</font><font color="#ffa500">)</font><br /> <font color="#ffff00">if</font> <font color="#ffff00">l</font> <font color="#ffff00">=~</font> <font color="#40ffff">a:cid</font><br /> <font color="#ffff00">exec</font> strpart<font color="#ffa500">(</font>l, <font color="#40ffff">stridx</font><font color="#ffa500">(</font>l, <font color="#40ffff">a:cid</font><font color="#ffa500">)</font><font color="#ffff00">+</font><font color="#40ffff">strlen</font><font color="#ffa500">(</font><font color="#40ffff">a:cid</font><font color="#ffa500">))</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">let</font> i <font color="#ffff00">=</font> i<font color="#ffff00">-</font><font color="#ffa0a0">1</font><br /> <font color="#ffff00">endwhile</font><br /><font color="#ffff00">endfunction</font><br /><br /><font color="#ffff00">au</font> <font color="#60ff60">BufReadPost</font> * :<font color="#ffff00">call</font> <span style="background-color: #000000"><font color="#cccccc">CustomModeLine</font></span><font color="#ffa500">(</font><font color="#ffa0a0">"VIM666:"</font><font color="#ffa500">)</font><br /></font><br /><br />Now, after adding that to the .vimrc, one can put something like this in the last lines (among <code>&modelines</code> last of them) of the source file:<br /><br /><code>// VIM666:set makeprg=make\ aaaa</code><br /><code>// VIM666:sy keyword cType block_id_t</code><br /><br />When opening the file in VIM, the scriptlet would find the lines and <code>:execute</code> 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).<br /><br /><b> Why the <code>VIM666:</code>?</b><br /><br />Well. VIM creator has allowed the modelines to change only limited set of options for the reason:<br /><br /><i> No other commands than "set" are supported, for security reasons (somebody<br />might create a Trojan horse text file with modelines). And not all options<br />can be set. For some options a flag is set, so that when it's used the<br />|sandbox| is effective. </i><br /><br />Thus, randomizing the "VIM666" into something more random and unpredictable is strongly advised. Sadly, <code>:sandbox</code> isn't configurable and thus incapable of disallowing only certain actions - at the moment it is all-or-nothing type of command in VIM.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-29599129866735169092011-01-11T08:00:00.000-08:002011-01-11T08:04:54.256-08:00[DUMP] VIM custom folding for Rational Purify's plog filesDump.<br /><br /><pre><br /><font color="#80a0ff">"</font><br /><font color="#80a0ff">" Fold (collapse) the Purify problem descriptions into single line</font><br /><font color="#80a0ff">" As the comment to the fold, Purify message would appear with</font><br /><font color="#80a0ff">" list of files/libraries in the call stack.</font><br /><font color="#80a0ff">" </font><font color="#ffa0a0">"-CHAIN_LENGTH=32"</font><font color="#80a0ff"> parameter in PURIFYOPTIONS is highly recommended</font><br /><font color="#80a0ff">"</font><br /><font color="#80a0ff">" custom fold function for Purify's .plog files</font><br /><font color="#ffff00">function</font>! PuriFold<font color="#ffa500">(</font>lnum<font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> l <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font><font color="#40ffff">a:lnum</font><font color="#ffa500">)</font><br /><font color="#80a0ff"> " fold starts at '</font><span style="background-color: #ffff00"><font color="#0000ff">XXX</font></span><font color="#80a0ff">:' marker (though exclude File In Use)</font><br /> <font color="#ffff00">if</font> <font color="#ffff00">l</font> <font color="#ffff00">=~</font> <font color="#ffa0a0">'^[A-Z][A-Z][A-Z]:'</font> <font color="#ffff00">&&</font> <font color="#ffff00">l</font> <font color="#ffff00">!~</font> <font color="#ffa0a0">'^FIU:'</font><br /> <font color="#ffff00">return</font> <font color="#ffa0a0">1</font><br /> <font color="#ffff00">endif</font><br /><br /><font color="#80a0ff"> " store fold level of previous line</font><br /> <font color="#ffff00">let</font> pfl <font color="#ffff00">=</font> <font color="#40ffff">foldlevel</font><font color="#ffa500">(</font><font color="#40ffff">a:lnum</font><font color="#ffff00">-</font><font color="#ffa0a0">1</font><font color="#ffa500">)</font> <font color="#ffff00">></font> <font color="#ffa0a0">0</font><br /><br /><font color="#80a0ff"> " check whether it is a continuation of a fold</font><br /> <font color="#ffff00">if</font> pfl <font color="#ffff00">&&</font> <font color="#ffa500">(</font>l <font color="#ffff00">=~</font> <font color="#ffa0a0">'^\t'</font> <font color="#ffff00">||</font> l <font color="#ffff00">=~</font> <font color="#ffa0a0">'^ \*'</font> <font color="#ffff00">||</font> l <font color="#ffff00">=~</font> <font color="#ffa0a0">'^ '</font><font color="#ffa500">)</font><br /> <font color="#ffff00">return</font> <font color="#ffa0a0">1</font><br /> <font color="#ffff00">endif</font><br /><br /> <font color="#ffff00">if</font> pfl<br /> <font color="#ffff00">return</font> <font color="#ffa0a0">'<1'</font> <font color="#80a0ff">" close fold if open</font><br /> <font color="#ffff00">else</font><br /> <font color="#ffff00">return</font> <font color="#ffa0a0">0</font> <font color="#80a0ff">" not a fold otherwise</font><br /> <font color="#ffff00">endif</font><br /><font color="#ffff00">endfunction</font><br /><br /><font color="#80a0ff">" custom fold text function to quickly see the approx location of the problem</font><br /><font color="#ffff00">function</font>! Puri_GatherNames<font color="#ffa500">(</font>fl, ll<font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> l:i <font color="#ffff00">=</font> <font color="#40ffff">a:fl</font><br /> <font color="#ffff00">let</font> l:<font color="#ffff00">x</font> <font color="#ffff00">=</font> <font color="#ffa0a0">''</font><br /> <font color="#ffff00">let</font> l:count <font color="#ffff00">=</font> <font color="#ffa0a0">0</font><br /> <font color="#ffff00">while</font> l:i <font color="#ffff00"><=</font> <font color="#40ffff">a:ll</font> <font color="#ffff00">&&</font> l:count <font color="#ffff00"><</font> <font color="#ffa0a0">10</font><br /> <font color="#ffff00">let</font> l:<font color="#ffff00">l</font> <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font> i <font color="#ffa500">)</font><br /> <font color="#ffff00">if</font> l:l <font color="#ffff00">=~</font> <font color="#ffa0a0">'\*unknown func\*'</font><br /> <font color="#ffff00">let</font> l:<font color="#ffff00">l</font> <font color="#ffff00">=</font> <font color="#ffa0a0">''</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">let</font> l:tmp <font color="#ffff00">=</font> <font color="#40ffff">matchstr</font><font color="#ffa500">(</font> l:l, <font color="#ffa0a0">'\[[^\]]\+\]$'</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">if</font> <font color="#40ffff">strlen</font><font color="#ffa500">(</font>l:tmp<font color="#ffa500">)</font> <font color="#ffff00">==</font> <font color="#ffa0a0">0</font><br /> <font color="#ffff00">let</font> l:i <font color="#ffff00">=</font> l:i<font color="#ffff00">+</font><font color="#ffa0a0">1</font><br /> <font color="#ffff00">continue</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">if</font> l:tmp <font color="#ffff00">=~</font> <font color="#ffa0a0">'^\[libclntsh\.so'</font><br /> <font color="#ffff00">let</font> l:tmp <font color="#ffff00">=</font> <font color="#ffa0a0">'[*ORA*]'</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">if</font> l:tmp <font color="#ffff00">=~</font> <font color="#ffa0a0">'^\[libstlport\.so'</font> <font color="#ffff00">||</font><br /><font color="#ffa500">\</font> l:tmp <font color="#ffff00">=~</font> <font color="#ffa0a0">'^\[_\(pair\|tree\|alloc\|map\|construct\)\.h:'</font> <font color="#ffff00">||</font><br /><font color="#ffa500">\</font> l:tmp <font color="#ffff00">=~</font> <font color="#ffa0a0">'^\[_\(tree\)\.c:'</font><br /> <font color="#ffff00">let</font> l:tmp <font color="#ffff00">=</font> <font color="#ffa0a0">'[*STL*]'</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">if</font> <font color="#40ffff">strlen</font><font color="#ffa500">(</font>l:tmp<font color="#ffa500">)</font><font color="#ffff00">></font><font color="#ffa0a0">0</font> <font color="#ffff00">&&</font> l:tmp<font color="#ffff00">!=</font><font color="#40ffff">strpart</font><font color="#ffa500">(</font>l:x,<font color="#40ffff">strlen</font><font color="#ffa500">(</font>l:x<font color="#ffa500">)</font><font color="#ffff00">-</font><font color="#40ffff">strlen</font><font color="#ffa500">(</font>l:tmp<font color="#ffa500">))</font><br /> <font color="#ffff00">if</font> l:tmp <font color="#ffff00">==</font> <font color="#ffa0a0">'[crt1.o]'</font> <font color="#ffff00">||</font> l:tmp <font color="#ffff00">==</font> <font color="#ffa0a0">'[rtlib.o]'</font> <font color="#ffff00">||</font><br /><font color="#ffa500">\</font> l:tmp <font color="#ffff00">==</font> <font color="#ffa0a0">'[crti.o]'</font> <font color="#ffff00">||</font> l:tmp <font color="#ffff00">==</font> <font color="#ffa0a0">'[libCrun.a]'</font> <font color="#ffff00">||</font><br /><font color="#ffa500">\</font> l:tmp <font color="#ffff00">==</font> <font color="#ffa0a0">'[libc.so.1]'</font> <font color="#ffff00">||</font> l:tmp <font color="#ffff00">==</font> <font color="#ffa0a0">'[libnsl.so.1]'</font> <font color="#ffff00">||</font><br /><font color="#ffa500">\</font> l:tmp <font color="#ffff00">==</font> <font color="#ffa0a0">'[libsocket.so.1]'</font><br /><font color="#80a0ff"> " nothing, ignore system libraries</font><br /> <font color="#ffff00">else</font><br /> <font color="#ffff00">let</font> l:<font color="#ffff00">x</font> <font color="#ffff00">=</font> l:x<font color="#ffff00">.</font><font color="#ffa0a0">' '</font><font color="#ffff00">.</font>l:tmp<br /> <font color="#ffff00">let</font> l:count <font color="#ffff00">=</font> l:count<font color="#ffff00">+</font><font color="#ffa0a0">1</font><br /> <font color="#ffff00">endif</font><br /> <font color="#ffff00">endif</font><br /><font color="#80a0ff"> "echo x</font><br /> <font color="#ffff00">let</font> l:i <font color="#ffff00">=</font> l:i<font color="#ffff00">+</font><font color="#ffa0a0">1</font><br /> <font color="#ffff00">endwhile</font><br /> <font color="#ffff00">return</font> l:x<br /><font color="#ffff00">endfunction</font><br /><font color="#ffff00">function</font>! Puri_FoldText<font color="#ffa500">()</font><br /> <font color="#ffff00">return</font> <font color="#40ffff">foldtext</font><font color="#ffa500">()</font><font color="#ffff00">.</font><span style="background-color: #000000"><font color="#cccccc">Puri_GatherNames</font></span><font color="#ffa500">(</font>v:foldstart, v:foldend<font color="#ffa500">)</font><br /><font color="#ffff00">endfunction</font><br /><br /><font color="#80a0ff">" activate the folds when .plog file is opened</font><br /><font color="#ffff00">au</font> <font color="#60ff60">BufReadPost</font> *.plog <font color="#ffff00">set</font> <font color="#ff80ff">foldexpr</font>=PuriFold(v<font color="#ffff00">:</font>lnum)<br /><font color="#ffff00">au</font> <font color="#60ff60">BufReadPost</font> *.plog <font color="#ffff00">set</font> <font color="#ff80ff">foldmethod</font>=expr<br /><font color="#80a0ff">" use custom fold text function</font><br /><font color="#ffff00">au</font> <font color="#60ff60">BufReadPost</font> *.plog <font color="#ffff00">set</font> <font color="#ff80ff">foldtext</font>=Puri_FoldText()<br /><br /></pre><br /><br />P.S. <a href="http://en.wikipedia.org/wiki/IBM_Rational_Purify">WT Rational Purify?</a>Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-59172502787202046192011-01-10T05:19:00.000-08:002011-01-10T06:32:14.133-08:00VIM inline calculator revisited, floating point numbers comapatibleAs it turned out, sometimes I really like to use <a href="http://vimrc-dissection.blogspot.com/2010/05/vim-inline-calculator.html">the VIM as a calculator</a>, with free editing, history and even access to env vars. (Unintentionally, calls to VIM functions also do work.)<br /><br />Yesterday I needed to calculate few more things than usually and also using floating point numbers. I have recalled that <a href="http://vimdoc.sourceforge.net/htmldoc/version7.html#added-7.2">VIM 7.2 added support for <code>Float</code> type</a> and tried it out. After some tinkering, I managed to make my calculator even more useful to me than expected.<br /><br />The previous version of calculator looked <i>relatively</i> innocent:<br /><br /><pre>:map <silent> <F11> :exec "s!^\\([^=]\\{-}\\)\\( *=.*\\)\\=$!\\1 = ".eval(substitute(getline(".")," *=.*$","",""))."!"<CR></pre><br /><br />The new version looks more serious and even less intimidating:<br /><br /><pre><br /><font color="#ffff00">function</font>! CalcGetValue<font color="#ffa500">(</font>tag<font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> tag_marker <font color="#ffff00">=</font> <font color="#ffa0a0">"#"</font><br /> <font color="#ffff00">let</font> s <font color="#ffff00">=</font> <font color="#40ffff">search</font><font color="#ffa500">(</font> <font color="#ffa0a0">'^'</font><font color="#ffff00">.</font><font color="#40ffff">a:tag</font><font color="#ffff00">.</font>tag_marker, <font color="#ffa0a0">"bn"</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">if</font> <font color="#ffff00">s</font> <font color="#ffff00">==</font> <font color="#ffa0a0">0</font> | <font color="#ffff00">throw</font> <font color="#ffa0a0">"Calc error: tag "</font><font color="#ffff00">.</font><font color="#ffff00">tag</font><font color="#ffff00">.</font><font color="#ffa0a0">" not found"</font> | <font color="#ffff00">endif</font><br /><font color="#80a0ff"> " avoid substitute() as we are called from inside substitute()</font><br /> <font color="#ffff00">let</font> line <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font> s <font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> idx <font color="#ffff00">=</font> <font color="#40ffff">strridx</font><font color="#ffa500">(</font> line, <font color="#ffa0a0">"="</font> <font color="#ffa500">)</font><br /> <font color="#ffff00">if</font> idx <font color="#ffff00">==</font> <font color="#ffff00">-</font><font color="#ffa0a0">1</font> | <font color="#ffff00">throw</font> <font color="#ffa0a0">"Calc error: line with tag "</font><font color="#ffff00">.</font><font color="#ffff00">tag</font><font color="#ffff00">.</font><font color="#ffa0a0">"doesn't contain the '='"</font> | <font color="#ffff00">endif</font><br /> <font color="#ffff00">return</font> <font color="#40ffff">strpart</font><font color="#ffa500">(</font> line, idx<font color="#ffff00">+</font><font color="#ffa0a0">1</font> <font color="#ffa500">)</font><br /><font color="#ffff00">endfunction</font><br /><br /><font color="#ffff00">function</font>! CalcLine<font color="#ffa500">(</font>ln<font color="#ffa500">)</font><br /> <font color="#ffff00">let</font> tag_marker <font color="#ffff00">=</font> <font color="#ffa0a0">"#"</font><br /> <font color="#ffff00">let</font> s <font color="#ffff00">=</font> <font color="#40ffff">getline</font><font color="#ffa500">(</font><font color="#40ffff">a:ln</font><font color="#ffa500">)</font><br /><br /><font color="#80a0ff"> " remove old result if any</font><br /> <font color="#ffff00">let</font> x <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> s, <font color="#ffa0a0">'[[:space:]]*=.*'</font>, <font color="#ffa0a0">""</font>, <font color="#ffa0a0">""</font> <font color="#ffa500">)</font><br /><font color="#80a0ff"> " strip the tag, if any</font><br /> <font color="#ffff00">let</font> x1 <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> x, <font color="#ffa0a0">'[a-zA-Z0-9]\+'</font><font color="#ffff00">.</font>tag_marker<font color="#ffff00">.</font><font color="#ffa0a0">'[[:space:]]*'</font>, <font color="#ffa0a0">""</font>, <font color="#ffa0a0">""</font> <font color="#ffa500">)</font><br /><font color="#80a0ff"> " replace values by the tag</font><br /> <font color="#ffff00">let</font> x1 <font color="#ffff00">=</font> <font color="#40ffff">substitute</font><font color="#ffa500">(</font> x1, tag_marker<font color="#ffff00">.</font><font color="#ffa0a0">'\([a-zA-Z0-9]\+\)'</font>, <font color="#ffa0a0">'\=CalcGetValue(submatch(1))'</font>, <font color="#ffa0a0">'g'</font> <font color="#ffa500">)</font><br /><font color="#80a0ff"> " evaluate</font><br /> <font color="#ffff00">let</font> v <font color="#ffff00">=</font> <font color="#ffa0a0">0</font><br /> <font color="#ffff00">try</font><br /> <font color="#ffff00">let</font> v <font color="#ffff00">=</font> <font color="#ffa0a0">""</font><font color="#ffff00">.</font><font color="#40ffff">eval</font><font color="#ffa500">(</font>x1<font color="#ffa500">)</font><br /> <font color="#ffff00">catch</font> /E806:/<br /><font color="#80a0ff"> " VIM can't convert float to string automagically, apply printf("%g")</font><br /> <font color="#ffff00">let</font> v <font color="#ffff00">=</font> <font color="#ffa0a0">""</font><font color="#ffff00">.</font><font color="#40ffff">eval</font><font color="#ffa500">(</font><font color="#ffa0a0">'printf( "%g", '</font><font color="#ffff00">.</font>x1<font color="#ffff00">.</font><font color="#ffa0a0">')'</font><font color="#ffa500">)</font><br /> <font color="#ffff00">endtry</font><br /><font color="#80a0ff"> " finish the job</font><br /> <font color="#ffff00">call</font> <font color="#40ffff">setline</font><font color="#ffa500">(</font><font color="#40ffff">a:ln</font>, x<font color="#ffff00">.</font><font color="#ffa0a0">' = '</font><font color="#ffff00">.</font>v<font color="#ffa500">)</font><br /><font color="#ffff00">endfunction</font><br /><br />:<font color="#ffff00">map</font> <font color="#ffa500"><</font><font color="#ffa500">silent</font><font color="#ffa500">></font> <font color="#ffa500"><</font><font color="#ffa500">F11</font><font color="#ffa500">></font> :call CalcLine(".")<font color="#ffa500"><</font><font color="#ffa500">CR</font><font color="#ffa500">></font><br /></pre><br /><br />The new version addresses two my problems (old) allow simple reuse of the previous calculations and (new) allow floating point numbers.<br /><br />At the core, the usage of calculator remained pretty much the same as before. For example, typing <code>2*2</code> and pressing F11 would change the line into <code>2*2 = 4</code>.<br /><br />To allow reuse of previous calculation results, I have introduced the tags. A line with a calculation result can be prefixes with <code>label#</code> tag (e.g. <code>label# 2*2 = 4</code>). Results of the calculation can be accessed in another expression using <code>#label</code>, e.g. <code>33*#label</code>. During evaluation, the scriptlet above would search the buffer for string starting with <code>label#</code> 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 <code>label# = value</code> works as a definition of constant).<br /><br />Example: calculate area and volume given the radius. Type this:<br /><br /><code>radius# = 5</code><br /><code>pi# = 3.1415</code><br /><code>area# pow(#radius,2)*#pi</code><br /><code>volume# pow(#radius,3)*#pi*4.0/3.0</code><br /><br />First two lines work like constants denoting Pi and the radius. Press the F11 (or ^O + F11 if in insert mode) when cursor on 3rd and 4th lines to evaluate the expressions and see the results:<br /><br /><code>area# pow(#radius,2)*#pi = 78.5375</code><br /><code>volume# pow(#radius,3)*#pi*4.0/3.0 = 523.583333</code><br /><br />The new (to me) features that are used in the new calculator:<br /><br />1. <a href="http://vimdoc.sourceforge.net/htmldoc/eval.html#search%28%29">search()</a> to find a line number of a string matching given pattern (used to search in the buffer for the line with a tag).<br /><br />2. <a href="http://vimdoc.sourceforge.net/htmldoc/eval.html#submatch%28%29">submatch()</a>, when inside the substitution, to access a submatch (functional equivalent of <code>\1</code>, <code>\2</code> and so on).<br /><br />3. <a href="http://vimdoc.sourceforge.net/htmldoc/change.html#sub-replace-expression">\=</a> in <code>s///</code> and <a href="http://vimdoc.sourceforge.net/htmldoc/eval.html#substitute%28%29">substitute()</a> to substitute with result of an expression instead of a constant.<br /><br />4. <a href="http://vimdoc.sourceforge.net/htmldoc/eval.html#E806">E806</a> + <a href="http://vimdoc.sourceforge.net/htmldoc/eval.html#:try">:try</a>. VIM can't convert float to string automatically. Error E806 is generated when that is attempted. Scriptlet catches the error and applies suggested by documentation conversion method - printf(). The construct with try/catch also ensures that integer calculation remains integer. Only if there are floating point numbers involved, exception would be thrown and the conversion would be performed (spares the redundant '.0' in the integer calculations).Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com5tag:blogger.com,1999:blog-28654195.post-7687846142762532502010-12-16T09:13:00.000-08:002010-12-22T14:44:36.155-08:00Make (next) found match to appear in the screen's centerTurned out to be easier than expected:<br /><br /><code>nnoremap n nzz<br />nnoremap N Nzz</code><br /><br />Simply adds the <code>zz</code> (see <code>:h z.</code>) to <code>n</code> and <code>N</code> commands.<br /><br />P.S. <a href="http://stackoverflow.com/questions/2372584?tab=votes#tab-top">Original</a> question and answer as SO.<br /><br /><b>Edit1</b> Problem with the solution is that the message <code>search hit BOTTOM, continuing at TOP</code>, due to the <code>zz</code> command, now doesn't appear on the screen anymore. Trying now to use the other tip: <code>set scrolloff=5</code>. Will see how that works.<br /><br /><b>Edit2</b> Yep, the <code>set scrolloff=5</code> works for me much better than the <code>nzz</code>.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com1tag:blogger.com,1999:blog-28654195.post-29016264210146775172010-10-19T02:17:00.000-07:002010-10-19T02:30:04.702-07:00diff this!<a href="http://stackoverflow.com/questions/3619146/vimdiff-two-subroutines-in-same-file">Found a cool VIM's command</a> - <a href="http://vimdoc.sourceforge.net/htmldoc/diff.html#:diffthis"><code>:diffthis</code></a>. Invoking it in two different buffers tells the editor to diff the buffers as if it was started as <code>vimdiff</code>. Best (most interesting to me) part is that one can diff two unsaved buffers. E.g.:<br /><br /><code>" split the screen vertically<br />:vnew<br />" paste first code fragment into the left buffer and<br />:diffthis<br />" press ^W^W to switch to the right buffer, paste the second code fragment and again call<br />:diffthis</code><br /><br />To cancel the effect of <code>:diffthis</code> one uses the <code>:diffoff</code> command. The command is too buffer specific and has to be invoked in both buffers.<br /><br />Another interesting related command is <code>:diffpatch {diff-file}</code> which again invokes <code>vimdiff</code> diffing the file currently in buffer against the file with the patch applied.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com1tag:blogger.com,1999:blog-28654195.post-85840926109033473182010-09-07T07:43:00.000-07:002010-09-07T08:17:30.231-07:00vim vs. grep : external quickfix/error file, cont'dAs an enhancement to my <a href="http://vimrc-dissection.blogspot.com/2010/04/vim-vs-grep-external-quickfixerror-file.html">old trick of using grep with the VIM</a>, I have finally come up with a solution which doesn't use the temp file:<br /><br /><code>$ alias vq="vi -c ':cgetb' -c ':cfirst! ' -"<br />$ grep -nr whatever . | grep -v garbage | vq</code><br /><br />The trick is to use the new VIM 7.x command <code>:cgetb</code> which retrieves the error list from the current buffer. So first suck in the output of the <code>grep</code> into the nameless buffer, tell VIM to use the buffer as a error list and then with <code>:cfirst!</code> to jump to first matching line (and discard the nameless buffer).<br /><br />Note in alias the space after <code>:cfirst!</code>: it is a <i>secret ingredient</i> to avoid bash interpreting the ! as the history expansion mark.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0tag:blogger.com,1999:blog-28654195.post-18369048031412571092010-08-16T09:07:00.000-07:002010-08-16T09:08:23.130-07:00Life goes on<a href="https://groups.google.com/group/vim_announce/browse_thread/thread/66c02efd1523554b?pli=1">VIM 7.3 released</a>.Ihar Filipauhttp://www.blogger.com/profile/05086565400407007423noreply@blogger.com0