Omit 'Pattern not found' error message in Vim script - vim

I added a function in my .vimrc that's just few search and replace commands. However if one of the patterns is not found I get an error message that I need to enter through. How can I suppress this?

You can either use :silent or :silent! as a prefix to any command or you can add the 'e' option to the substitute, which is often easier.
:%s/x/y/ge
:silent! %s/x/y/g
:silent %s/x/y/g
For more information, see
:help :silent
:help :s_flags
The information on the e flag is a few paragraphs down from the :s_flags help.

You might use silent:
:silent %s/x/y/g
or, if you need to do string manipulation to determine the strings to search and replace:
exec ":silent %s/x/" . varName . "/g"
I'm not 100% sure, but I think that silent only works in scripts.

Probably a little bit off topic but i found this thread when searching for solutions for "search pattern not found" errors in vim, when i wanted to search for the next occurence in vim. The following map omits the error when pressing 'n'
map n :silent! /

Maybe the :he :silent thing can be used to suppress those errors?

this also works for global operation
:silent g/^$/d'

Related

Why do `set shm+=s` and `cno <silent> <cr> <cr>` make Vim display a search command, when the pattern has no match in the current buffer?

If I start Vim with a minimum of initializations:
vim -Nu NONE /path/to/a/file
Then execute the following 2 commands:
set shm+=s
cno <silent> <cr> <cr>
And finally search for a pattern which has no match in the current buffer:
/pattern_with_no_match
Vim displays the error:
E486: Pattern not found: pattern_with_no_match
... which is expected. But Vim also displays a line showing the literal search command. Because of this, in total, Vim displays 2 lines + a prompt:
/pattern_with_no_match
E486: Pattern not found: pattern_with_no_match
Press ENTER or type command to continue
Instead of just one line with no prompt:
E486: Pattern not found: pattern_with_no_match
If I remove the s flag from the 'shortmess' option:
set shm-=s
Or if I remove the <silent> argument in the mapping:
cno <cr> <cr>
Vim displays only 1 line again:
E486: Pattern not found: pattern_with_no_match
Adding the s flag to 'shortmess' suppresses the messages such as:
search hit BOTTOM, continuing at TOP
And the <silent> argument passed to the :cnoremap command should prevent the mapping from being echoed on the command line.
None of these settings should make Vim more verbose.
So, why does the combination of the setting set shm+=s and the mapping cno <silent> <cr> <cr>, makes Vim display a search command, when the pattern has no match in the current buffer?
It may be a known issue, because I've just found a comment inside a plugin which seems related:
" NOTE: This cannot use <silent> - it would break cmdline refresh in some
" cases (e.g. multiline commands, <C-R>= usage).
But I can't find the relevant section in the help which describes it.
There's this line in :h map-<silent>:
Using "<silent>" for an abbreviation is possible, but will cause redrawing of the command line to fail.
But it's about abbreviations not mappings. Maybe the 2 are linked though.
Vim has some built-in logic to determine whether a user message has been shown and can be discarded. Only when there are more messages at once, the hit-enter prompt will occur. By silencing the <CR> in the command-line, you disrupt this logic; <silent> means no output (by the mapping), but the command-line is still open and contains the typed search. Normally, the search wrap message would then clear the command-line, but with your 'shm' setting, you're disabling that, too. Therefore, with the combination of both, you see this effect.
I'm deliberately fuzzy in my explanation because most of this is a side effect of the implementation, and not formally specified. cno <silent> <cr> <cr> doesn't make sense. If you have a real-world use case where this is causing problems, please post details about that. In general, hooking into keys that change modes (like <CR> and <Esc>) is a bad idea and should be avoided.

How to append text to end of current line using Vim function?

I'd like to append text to the end of a current line in Vim. I'd like to do this within the context of a function.
How can this be done? Do I need to escape/sanitise the text?
You could use the normal command with the execute command:
let text_for_appending = ' # a comment'
execute "normal! A" . text_for_appending
The exclamation mark is included to prevent any key mappings from being expanded. See :help :normal for more details.
With :exe + :normal! you may need to sanatize the text as you feared -- it'll depend on the kind of quotes you use, and on whether you forget to bang :normal and you have insert mode mappings and abbreviations.
With setline('.', getline('.') . text), vim won't try to interpret the text you append. This seems convoluted, but this is the more robust way to proceed -- it can become way more convoluted if you start to escape things with A.

Highlighting arbitrary lines in VIM

During the implementation process of a program I generally insert many append code lines, mainly with print command, to help me understand and debug the implemented program. Unfortunately, it is common to me to forget which lines are from the code and with were appended and should be deleted some time after. This problem gets worst with large programs.
Well, I found this article that teaches how to keep one arbitrary user selected line highlighted (see section: Highlighting that stays after cursor moves). The solution given by the article is to include in .vimrc the following code:
:nnoremap <silent> <Leader>l ml:execute 'match Search /\%'.line('.').'l/'<CR>
So, every time when I press \l the current line is highlighted and kept so, and the previous highlighted line, if there are one, is unhighlighted.
This isn't the behavior that I would like. Instead, I would like to be able to highlight as many arbitrary lines as I want without unhighlighting the previous highlighted lines. And if it is possible, with a unique command like \l.
Someone knows a solution for this?
Thanks in advance.
EDITED:
The command proposed by yolenoyer solved the initial problem. But, now other problem raised. The following command:
:call clearmatches()
proposed to clean the highlighted lines cleans all lines and I would like to be able to clean specific highlighted lines, instead off all of them at once. Is it possible?
I program in C quite alot, and when debugging tend to pepper the code with debug prints.
I use the vim command
:syntax match Error /\<debug_printf\>/
to ensure the word 'debug_printf' is highlighted in the default 'Error' colors for the particular colorscheme.
This doesn't help you bookmarking a series of lines, but for that you should check out the 'bookmark' plugin which allows you to create and remove bookmarks throughout the file.
VIM Bookmarks Plugin
:match accepts only one match.
Use the matchadd({highlight-group}, {pattern}) function instead, for example:
nnoremap <silent> <leader>l :call matchadd('Search', '\%'.line('.').'l')<cr>
To clear the matches you added, run :call clearmatches().
I used the answers here to come up with this combo, which I think is nice:
" \l to highlight a line
nnoremap <silent> <leader>l :call matchadd('Search', '\%'.line('.').'l')<CR>
" \L to remove highlighted line
nnoremap <silent> <leader>L :
\for m in filter(getmatches(), { i, v -> has_key(l:v, 'pattern') && l:v.pattern is? '\%'.line('.').'l'} )
\<BAR> :call matchdelete(m.id)
\<BAR> :endfor<CR>
I think your first paragraph, which explains your problem, has nothing to do with vim, so maybe you don't need to use vim to solve your problem.
What about not debugging with regular print statements, but with a function that wraps print? That would be really easy to search for program wide and also file wide (just search with * or # for all occurrences of your debug printing function).

How to map :Ag command to :ag

I am using the plugin ag.vim in Vim, and I want to do a simple re-mapping.
When I run ag with :Ag I want remap it to :ag so I don't have to use shift.
example: :ag string_to_find instead of :Ag string_to_find
How can I do this?
You shouldn't. Lowercase commands are reserved for built-in commands, and the norm/rules are to start custom commands with an uppercase character (just like with functions).
See Is it possible to remap an Ex command in Vim (remap :Ack to :ack)?
This isn't exactly what you asked for, but dding the following will allow you to just type 'ag' to search:
map ag :Ag
EDIT: The downvoters are right and this is a bad answer. I'll leave it here so future searchers know it's wrong.
Try:
command: Ag ag
See :help command for more.

Vimgrep not matching regular expression properly

If I do this:
:vimgrep /do_action\([ ]?'init'/ **/*.php
I get
E54: Unmatched \(
But I know that there are files with matching text. Why?
I would also be very grateful if someone could help me create a key mapping for cmd+l so that this search is initiated with "init" replaced with the word under the cursor, which I understand from various sources is possible.
Building on kev's answer, here is your mapping:
nnoremap <D-i> :vimgrep //do_action([ ]\?'<c-r>=expand('<cword>')<cr>'/ **/*.php<cr>
But I'd advise you to not use the Command key in a mapping: it works only in MacVim and it's a good habit to seek portability everywhere possible.
The <leader> key is perfect for such things.
nnoremap <leader>i :vimgrep //do_action([ ]\?'<c-r>=expand('<cword>')<cr>'/ **/*.php<cr>
See :help c_ctrl-r_= and :help leader.
edit
I went a little too fast on this one. Not only I've added unnecessary cruft to kev's reworking of your command (silly //) but I didn't notice that it could be simplified. This one is tested and working:
nnoremap <leader>i :vim do_action(\s*'<c-r>=expand('<cword>')<cr> **/*.php<cr>
Sorry for the mess.
You don't need to escape ( to match it. But you need to escape ? to match 0~1 previous item. Try:
:vimgrep /do_action([ ]\?'init'/ **/*.php

Resources