vim macro to convert current line to figlet - vim

I wrote a macro to test calling it on a line to convert it to figlet (text ascii-art version)
I tryied working around something like
let #q='"add:r! figlet <c-r>a^M'
or
let #q='"add:r! figlet ^Ra^M'
and so on from the :help macro recommandations
I just can't find the good syntax for it
when I run it manually in session it works so I guess the issue is syntax only
a
toto
<esc>
qq
"add
:r! figlet ^Ra^M
q
k
#q
then got
| |_ ___ | |_ ___
| __/ _ \| __/ _ \
| || (_) | || (_) |
\__\___/ \__\___/
this is the similar result I need to write as a macro

Your macro is way too complicated.
Instead of all that deleting and inserting dance, you should use :help :range! directly to filter the current line:
:.!figlet<CR>
which simplifies your macro tremendously:
:let #q = ":.!figlet\<CR>"

Related

vim: Insert output of command at cursor instead of next line

I have a shortcut in my .vimrc file that generates a uuid and inserts it into my buffer:
com! Uuid r ! uuidgen | tr "[:upper:]" "[:lower:]"
When I invoke it, it inserts the uuid on the next line. However, I want vim to insert the uuid where my cursor is, not on the next line. How would I do this?
Here is the command:
:com! Uuid exe "normal! i".system('uuidgen | tr "[:upper:]" "[:lower:]" | tr -d "\n"')

How can I save in vim a file with the actual fold text? ("+-- 43 lines [...]")?

I am looking for a way to save to a new text file a file that is folded, with all the folds closed. In other words, just as I see it on the screen.
Is it possible?
(I will have to print the code later, and parts of it are irrelevant to my purposes; the folding mechanism would be ideal for this, my other alternative is manually adding "[X lines omitted]" to the saved text.)
Fold your text as needed and then use :TOhtml to convert to an HTML file. This will preserve your folding. If you need it as a plain text file, you can post-process e.g. with w3m, which renders HTML to text and allows to dump it to a text file.
Here is a custom :RenderClosedFolds command, which will modify the current buffer / range. It also attempts to maintain the Folded highlighting of the original folds.
":[range]RenderClosedFolds
" Replace all lines currently hidden inside closed folds
" with a single line representing 'foldtext'.
function! s:RenderClosedFolds()
if line('.') == foldclosed('.')
let l:result = foldtextresult('.')
call setline('.', l:result)
execute printf('syntax match renderedFold "\V\^%s\$" containedin=ALL keepend', escape(l:result, '"\'))
else
delete _
endif
endfunction
command! -bar -range=% RenderClosedFolds
\ highlight def link renderedFold Folded |
\ let g:ingocommands_IsEntireBuffer = (<line1> == 1 && <line2> == line('$')) |
\ if g:ingocommands_IsEntireBuffer | syntax clear renderedFold | endif |
\ let g:save_foldmethod = &l:foldmethod | setlocal foldmethod=manual |
\ execute '<line1>,<line2>folddoclosed call <SID>RenderClosedFolds()' |
\ if g:ingocommands_IsEntireBuffer | setlocal nofoldenable | endif |
\ let &l:foldmethod = g:save_foldmethod | unlet g:save_foldmethod g:ingocommands_IsEntireBuffer
I have once created a script, that saves all folds to a new buffer.

VIM autocmd corrupts default register

I'm trying to update some text lines containing filenames in specific file in Vim. To do that I've added this in my .vimrc:
let logs_pat = "/ARCHIVE/logs/db_agent.log*"
au! BufEnter *_search.txt execute "/\\[DBA_LOGS\\]/,$d | $put = '[DBA_LOGS]' | $r!ls -t " . logs_pat . " | head "
It works fine except some artifacts. And question is about how to eliminate those artifacts.
Every time when I get into a buffer with file *_search.txt,
1) the contents of the register "" is replaced by the text been added by autocmd to file *_search.txt 2) a message appears on the vim status line: "10 more lines" or "search hit BOTTOM, continuing at TOP"
Thanks
The /\\[DBA_LOGS\\]/,$d command deletes the range of lines into the default register. To avoid that, append the black hole register (_). To suppress the message, prepend :silent.
au! BufEnter *_search.txt execute "silent /\\[DBA_LOGS\\]/,$delete _ | $put = '[DBA_LOGS]' | silent $r!ls -t " . logs_pat . " | head "
To maintain the original cursor position, you can wrap this with either:
:mark z
...
:normal! g`z
or
:let pos = getpos('.')
...
:call setpos('.', pos)

Activating alternate Diff mode via a function call in Vim/gVim

In a recent question, I asked how to make vimdiff ignore the extra spaces when comparing. Following the answer and some further reading, I tried to do the following:
.1. Locate _vimrc and find the MyDiff() function definition. It contains the line:
if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
.2. Duplicate the function as MyDiff2() in _vimrc, while changing that line to:
if &diffopt =~ 'iwhite' | let opt = opt . '--ignore-all-space ' | endif
.3. Open gVim with two files in Diff mode, then:
:set diffexpr=MyDiff2()
:set diffopt+=iwhite
:call MyDiff2()
and also:
:diffupdate
I expected this to make vimdiff ignore differences like:
r3=r2; vs r3 = r2;, but it does not. Why is that?
My settings are as following:
diffexpr=MyDiff2()
diffopt=filler,iwhite,icase
OK, it seems like I found a solution that works, following this question. Instead of using --ignore-all-space, I used -w and now it looks like gVim ignores the differences between r3=r2; and r3 = r2;.

How do I write a vim function to output the result of a system command?

What I have so far:
function! GetMarker()
return system('echo $random `date` | md5sum | cut -d" " -f1')
endfunction
I would like to be able to do a :getmarker and have it insert the output of that system command at my cursor, with no new lines.
Also what is the difference between function! and function?
Edit: before any of you ask, I need the random string to mark sections in my code so I can find them again by referencing my notes in my todo wiki.
Edit1. Take two. Trying to absorb the feedback from Luc. Without temp file (readfile() turned out to be not available in VIM 6.x I have on some systems).
:function InsertCmd( cmd )
: let l = system( a:cmd )
: let l = substitute(l, '\n$', '', '')
: exe "normal a".l
: redraw!
:endfunction
:imap <silent> <F5> <C-O>:call InsertCmd( 'echo date \| md5sum \| cut -d" " -f1' )<CR>
:map <silent> <F5> :call InsertCmd( 'echo date \| md5sum \| cut -d" " -f1' )<CR>
:put can't be used because it works line-wise. I replaced <Esc>...<Insert> with the all better <C-O>. I left redraw in, as it helps for the cases of called command produces output to the stderr.
Or using <C-R>=:
:function InsertCmd( cmd )
: let l = system( a:cmd )
: let l = substitute(l, '\n$', '', '')
: return l
:endfunction
:imap <silent> <F5> <C-R>=InsertCmd( 'echo date \| md5sum \| cut -d" " -f1' )<CR>
Also what is the difference between function! and function?
Exclamation on the end of command most of the time means force to execute. (Looking in the :help is advised since different commands use ! differently, but VIM tries to document all forms of the commands.) In the case of the function it tells VIM to override previous definition of the function. E.g. if you put the code above into the func1.vim file, first time :source func1.vim would work fine, but the second time it would fail with error that function InsertCmd is already defined.
I did once before try to implement something similar here. I'm not good at VIM programming, thus it looks lame and the suggestion from Luc should take precedence.
Here it goes anyway:
:function InsertCmd( cmd )
: exe ':silent !'.a:cmd.' > /tmp/vim.insert.xxx 2>/dev/null'
: let l = readfile( '/tmp/vim.insert.xxx', '', 1 )
: exe "normal a".l[0]
: redraw!
:endfunction
:imap <silent> <F5> <Esc>:call InsertCmd( 'hostname' )<CR><Insert>
:map <silent> <F5> :call InsertCmd( 'hostname' )<CR>
Despite being lame, it works though.
You can trim/chomp the last newline with matchstr(), substitute, [:-2], etc
function s:GetMarker()
let res = system('echo $random `date` | md5sum | cut -d" " -f1')
" then either
let res = matchstr(res, '.*\ze\n')
" or
let res = res[:-2]
" or
let res = substitute(res, '\n$', '', '')
return res
endfunction
command! -nargs=0 GetMarker put=s:GetMarker()
Banging the function/command definition (with '!') will permit you to source the script where it is defined several times and thus to update the function/command you are maintaining without having to exit vim.
I was running into similar problems with trying to map a hotkey to insert the current date and time. I solved the newline problem by just including a <backspace>, but this still inserted newlines when I was indented (backspace would kill the last character, but when I was indented I got newline+tab and only the tab would go away).
So I did this -- just turned smartindent off, insert the string, then turn it back on:
imap <F5> <esc>:set nosmartindent<CR>a<C-R>=system('echo $random `date` \| md5sum \| cut -d" " - f1')<CR><Backspace><esc>:set smartindent<CR>a
...which works, but it gets un-indented if you're sitting on a new, auto-indented line. To get around that, insert a character to hold your place, then escape, turn off smartindent, get rid of the extra character, and do the rest:
imap <F5> x<esc>:set nosmartindent<CR>a<backspace><C-R>=system('echo $random `date` \| md5sum \| cut -d" " -f1')<CR><Backspace><esc>:set smartindent<CR>a
This seems to work.

Resources