This question already has an answer here:
Editable vimgrep string in command line
(1 answer)
Closed 9 years ago.
I started with a mapping from this vim tip to use lvimgrep to search across files for the current word under cursor:
map <F4> :execute "lvimgrep /" . expand("<cword>") . "/j **" <Bar> lw<CR>
I realized that I'd like to edit the file glob path or search pattern before the command's actually executed.
for ex: when cursor is on a javascript variable in html file, pressing F4 just searches for the variables in the html files. It'd be better if it formed command and let me edit it before its executed.
Dropping the trailing <CR> prints out the code as is - command window shows:
:execute "lvimgrep /" . expand("<cword>") . "/j **" <Bar> lw
but that's hard to edit. I'd actually like the mapping to show:
:lvimgrep /theword/j *.js //---- cursor waiting here
I've tried all that I could but not sure how to go about it - and vimscript's not exactly easy.
PS: possible dupe of Editable vimgrep string in command line
PPS: final mapping (I've used <leader>*):
nnoremap <expr> <leader>* ":lvimgrep /" . expand("<cword>") . "/j **/*." . expand("%:e") . "\|lopen"
You can do that with a :help map-expr instead of :execute. This evaluates the expression and then uses the result as the right-hand side of the mapping:
:nnoremap <expr> <F4> ":lvimgrep /" . expand("<cword>") . "/j **"
Alternatively, you could insert the current word with <C-r><C-w>:
:nnoremap <F4> :lvimgrep /<C-r><C-w>/j **
Additional tip: You should use :noremap; it makes the mapping immune to remapping and recursion.
Related
I've got a textfile which I want to filter for a pattern, to get a quick overview. My normal approach in vim is to filter via :v/pattern/d. This works fine, but If I save the file accidentally, after I did the filtering, I loose the not filtered information.
To avoid this, I search for a solution where the orginal textfile cannot be destroy by accident.
My current solution is a function where I read the textile into a temporary file and run the filter on this file. But the function does not work if I try to search something like ^linestart. Furthermore I want to highlight the search pattern, which as well does not work as expected.
Here is my function in vimscript:
function! FilterJournal(pattern)
:exe 'e ~/tempfile'
" delete all existing lines
:1,$d
:exe 'r ~/journal.txt'
:exe 'silent v/ ' . a:pattern . '/d'
" to highlight the search pattern
:exe 'silent / ' . a:pattern
endfunction
:command! -nargs=1 Fijo :call FilterJournal("<args>")
When I run the command: Fijo foo I get the result, but the highlightning does not work.
When I run the command: Fijo ^foo I get some error messages and the tempfile is empty:
Error during execution of "function FilterJournal":
Line 6:
E486: Pattern not found: ^foo
How can I filter my textfile without destroy it by accident or get my function to work?
You can try this based on your function. Please note that
The space in v/ causes E486: Pattern not found
I tried set hlsearch but it did not work in this case. However, :match works well for highlighting in the current buffer
Leading : is not necessary
function! FilterJournal(pattern)
exe 'e ~/tempfile'
" delete all existing lines
1,$d
exe 'r ~/journal.txt'
exe 'v/' . a:pattern . '/d'
" to highlight the search pattern
exe 'match Search /' . a:pattern . '/'
endfunction
:command! -nargs=1 Fijo :call FilterJournal("<args>")
If you really want "to get a quick overview", you could simply do:
:g/pattern
which prints the matching lines without affecting the buffer.
Give this a try, it yanks the matched lines and show it in a vsplit buffer:
function! FilterIt(pat)
call setreg('x', '')
call setreg('/', a:pat)
exec 'g/'.a:pat.'/y X'
exec 'vsp /tmp/t'
exec 'norm! ggVG"xp'
endfunction
:command! -nargs=1 Fijo :call FilterIt("<args>")
I want to highlight trailing space at the end of a line in vim. The following command works:
:match Error /\v\s+\n/
But I'm having trouble mapping this to a key:
nnoremap <leader>w :execute "normal! :match Error " . '/\v\s+\n/' . "\<cr>"
Vim responds with:
E114: Missing quote: "\
E15: Invalid expression: "normal! :match Error " . '/\v\s+\n/' . "\
Update:
Having just seen this: http://vim.wikia.com/wiki/Highlight_unwanted_spaces I've got the mapping working, by just writing:
nnoremap <leader>w :match Error /\v\s+\n/<cr>
Can anyone explaing what the problem is with the original execute normal! ... construct which prevents it from working?
your mapping
I think it should be
nnoremap <leader>w :execute "normal! :match Error " . '/\v\s+\n/' . "\<lt>cr>"<cr>
:help <lt> I am not super aware of exactly why this is needed (once upon a time, my executes, too, were not working, as I had \<esc> and \<cr> in my execute "normal! .."s. Just know that in place or <cr>, you need to use \<lt>cr> for <cr> in this construct.
You also need the <cr> at the end to actually run the :execute ".."<cr> command.
easier solution
Also, I think it's easier to just put
set listchars=trail:·
set list
in your vimrc, and then you will be able to see trailing white space.
Personally, I have set listchars=trail:·,tab:»\ ,extends:» in my vimrc.
and an easy regex search (/\s\+$) reveals the white space, which you can easily delete with d$ ("delete 'till end"). Then once you do that, you can press n. to "go to next" then "repeat" the d$.
cool tip
Once you highlight your search pattern, you can even dgn to "select next occurrence and delete it" in one go -- then you can just repeatedly press . until nothing happens ... :help gn. Also, mess around with cgn; it's pretty neat stuff.
Cheers.
I am trying to add this to my vimrc but I am getting problems one it inserts {{{ at the beginning of my vimrc whenever I open it and also it apparently has 'c' in the regiser as the last pressed key so it deletes the first 2 lines when I press j
And when I run the command it complains that
"A{{{\ is missing a quotation mark and is not a command.
This gave me tip. map execute command vim
You don't need use :execute "normal! ..." if you are using nnoremap. This will work.
nnoremap <C-[> A{{{<Esc><CR>
Is there a way to search the list of recently used file in Vim? The list can be displayed using
browse old
but / does not work. I am aware of some plugins (e.g. MRU) but would prefer to not use a plugin.
Here's a short scriptlet that opens the file list in a scratch buffer. As a bonus, it defines a local <Enter> mapping to :edit the current file. With this, you can search with all built-in commands like /:
:new +setl\ buftype=nofile | 0put =v:oldfiles | nnoremap <buffer> <CR> :e <C-r>=getline('.')<CR><CR>
If you really want to avoid a plugin:
:new The old files will be printed into this buffer
:redir #X where X is a temporary register`
:silent echo(v:oldfiles) 'Silent' is there to not actually print onto your screen
:redir END
"Xp paste the temporary register
(optional) Do some regex-fu to put each file on its own line.
Put the above into a function and voila. Also :help redir
It's actually not very hard to write a simple (simplistic?) MRU command with completion that works like :edit or :split:
" this is our 'main' function: it couldn't be simpler
function! MRU(arg)
execute 'edit ' . a:arg
endfunction
" the completion function, again it's very simple
function! MRUComplete(ArgLead, CmdLine, CursorPos)
return filter(copy(v:oldfiles), 'v:val =~ a:ArgLead')
endfunction
" the actual command
" it accepts only one argument
" it's set to use the function above for completion
command! -nargs=1 -complete=customlist,MRUComplete MRU call MRU(<f-args>)
Here is a .vimrc version of code above. Just add following lines to .vimrc and map to desired keys (in my case it is 'o). In addition define patterns to remove "junk" files. Also cursor is placed at the top for convenience.
Most hard thing is to map an Enter inside nested nmap. ^V is the result of doubled Ctrl-V. ^R is the result of Ctrl-V+Ctrl-R. ^M is the result of Ctrl-V+Enter. You need manually repeat those symbols - not just Copy/Paste. Spent hours to understand this magic - so I'm glad to share. This technology lets you add own macroses in .vimrc.
" Browse Old Files
nnoremap <silent> 'o :enew<CR>:set buftype=nofile<CR>:set nobuflisted<CR>:exe "0put =v:oldfiles"<CR>:nmap <buffer> ^V^V^M :e ^V^V^R=getline('.')^V^V^M^V^V^M<CR>:g/\v(stdout\|nerd\|fugitive)/d<CR>:0<CR>
This is my take on Ingo's answer above for my .vimrc:
Opens the old files in either a vertical split or tab, then maps enter to open file under cursor! magic!
" open old files list and map enter to open line
" vertical split
noremap <leader>vv :vnew +setl\ buftype=nofile <bar> 0put =v:oldfiles <bar> nnoremap <lt>buffer> <lt>CR> :e <lt>C-r>=getline('.')<lt>CR><lt>CR><CR><CR>
" in new tab
noremap <leader>vt :tabnew +setl\ buftype=nofile <bar> 0put =v:oldfiles <bar> nnoremap <lt>buffer> <lt>CR> :e <lt>C-r>=getline('.')<lt>CR><lt>CR <CR><CR>
I am using VIM and I would like to pass the current line number to an external program.
something like this:
map <F3> :!mycmd <linenumber><CR>
I tried to substitute <linenumber> for line('.'), line("."), . and others, but nothing seems to work.
Thanks.
You must use :execute to use a variable or expression in your mapping:
nnoremap <F3> :execute ":!echo " . line('.')<CR>