How to remap number keys and number key special characters in VIM - vim

I am trying to remap the * operator in VIM. I have tried nnoremap <*> and nnoremap <S-8> to no avail. I haven't been able to find any instructions on how to properly do this. How can I remap my *, or any number keys/number key special characters?
Since many of you will no doubt wonder why anyone would want to do this, it's so I can make my * operator behave like normal, except not advance automatically to the next occurrence of the word under cursor (see under section Highlight Matches Without Moving).
EDIT:
The complete command I'm working with is this:
nnoremap <*> :let #/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>
Where * remaps the functionality of * or <shift + 8>

Getting rid of the < and > works for me.
nnoremap * :let #/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>

Try nnoremap <F7> <*>. It will remap the * with F7

Related

VIM: Set a key mapping to replace ampersand (&) at a set column

I would like to set up a key mapping so that when I type this key (specifically the F7 key in my example), it replaces whatever character is in column 6 with an ampersand (&).
I am trying
:nnoremap <F7> 6| R &<ESC>
Yet that doesn't seem to be doing the trick and I cannot seem to grasp why.
Why is what I'm trying wrong?
Yet that doesn't seem to be doing the trick and I cannot seem to grasp why.
So… what does it do instead of what you expect?
Anyway, there are a number of problems with your mapping:
You can't use a literal pipe character in a mapping. You must escape it (\|) or use <bar> instead, which gives us the following:
nnoremap <F7> 6\| R &<Esc>
nnoremap <F7> 6<Bar> R &<Esc>
See :help map-bar.
In your macro, the <Space> character () is interpreted as the <Space> command and thus moves the cursor one character to the right. If you don't mean <Space> (the command) don't use <Space> (the character):
nnoremap <F7> 6\|R&<Esc>
R puts you in replace mode. This is useless because you are only replacing one character and it forces you to <Esc> to normal mode. Use r instead:
nnoremap <F7> 6\|r&
See :help R and :help r.
Alternatively, it may also be useful to move the cursor back to its original position (i.e. the location before the replacement). To do this use:
nnoremap <F7> :let a=getpos(".")<cr>6\|r&:call cursor(a[1],a[2])<cr>
this map is broken up like this:
:let a=getpos(".")<cr> saves the cursor position on variable a
6\|r& is explained in an earlier answer
:call cursor(a[1],a[2])<cr> returns the cursor to its original position
Here you go:
:map <F7> 05lr&
No escape. Just type that and hit enter. The is really typing out those characters -- less than sign, capital F, the number 7, etc..

vim autocmd hook after performing a search in the text?

I had a look at the list of events autocmd can handle, but I could not find one about search queries.
What I would like to do is to add some custom behavior after each text search is performed. I was able to remap the * command with this command:
map * *<F11>
In this case I mapped <F11> to a :call My_function() which will do something with the search pattern contained in #/.
But I still need to add my custom behavior to the / command, which is more complicated, as before it's completed it's getting the input search pattern.
Do you have any hint on how to proceed? Can I use autocmd? Or maybe is there a map trick?
An (bad) way to do it would be to remap the return key (and the esc key)
when / is pressed, something like that:
function! MyCustomBehaviour()
echo "Oui oui"
endf
function! UnmapSearch()
cunmap <cr>
cunmap <esc>
endf
function! MapSearch()
cnoremap <cr> <cr>:call UnmapSearch()<bar>call MyCustomBehaviour()<cr>
cnoremap <silent> <esc> <c-c>:call UnmapSearch()<cr>
endf
noremap / :<c-u>call MapSearch()<cr>/
It's a bad way because it's quite buggy : if you press Ctrl-C while editing the
search, it won't unmap <cr> and <esc>, then the next time you will enter : (command-line) mode,
the mappings will still be active... That's a problem that can't be solved (<c-c> can't be
remapped).
It's also a bad way because remapping directly the / key this way, IMO, is not a good practice.
But... This was the only solution I found some times ago to half-solve this problem.
Another workaround (the one I finally choose) can be written in one line :
cnoremap <c-cr> <cr>:call MyCustomBehaviour()<cr>

Mapping a key in VIM

I've tried:
:map <F2> :.y" :g/<C-R>"/d<CR>
No luck :(
What this does, yank the current line into register "
Then, globally, delete lines that match exactly the line in the register.
It works dandy when I do it manually.
:vmap <F2> ["]yy<ESC><ESC> :g/<C-R>"/d<CR>
Similar to above - I select a few words, whatever - I make a selection, then yank it to register ". I then globally, delete the lines that match whats in the register.
It works dandy when I do it manually.
What am I doing wrong?
You might try this for the first one:
:nnorempa <F2> :silent exe "g/".getline(".")."/d"<CR>
For the second, something like this if you want to delete only the words:
:vmap <F7> y:silent exe "%s/".#"."//g"<CR>
And this if you want to delete the matching lines:
:vmap <F7> y:silent exe "g/".#"."/d"<CR>
You have remapped F2 to :.y" :etc. You need <cr> not a simple space. If you type :.y" in vim and don't hit ENTER but space, nothing will happen.
So:
:nnoremap <f2> :.y"<CR>:g/<C-R>"/d<CR>
could do it.
Still, warning, if your line contains any of /\*[~$^. this could fail. You could use the expression register in order to escape in-place:
:nnoremap <f2> :.y"<CR>:g/<c-r>=escape(#", '/\*[~$^.')<cr>/d<cr>
Still better, without overwriting your default (") register is:
:nnoremap <f2> :g/^<c-r><c-o>=escape(getline('.'), '/\*[~$^.')<CR>$/d<cr>
which will delete all identical lines. Still note that 'ignorecase' or 'smartcase' matter.
First of all - make sure you're using vim :)
vim --version
Here's the mapping I was going for. As I go through lots of data in log files, this will be incredibly useful. Select the area you want to eliminate, then and all instances of highlight area is done for.
NOTE: This does NOT go through the highlighted text and escape any regex characters. So a /, *, ^ will foul it up.
:map <F2> y:g/<C-R>"/d<CR>
:)

how to highlight all occurrences of a word in vim on double clicking

When I'm on Windows, I use notepad++, and on Linux I use vim. I really like vim. But there is at least one thing I find really interesting in notepad++. You can double-click on a word and it highlights all occurrences of that word automatically. I was wondering if I could do something like that with vim? So the question is how to highlight all occurrences of a word when you double click on the word in vim.
Obviously, I don't want to search for that word, or change my cursor position, just highlighting. My :set hlsearch is also on.
probably you may want to avoid the mouse in vim, but I make an exception here :).
I know that * does the same job, but what about mouse?
If you want to highlight the word under the cursor like *, but do not want to move the cursor then I suggest the following:
nnoremap <silent> <2-LeftMouse> :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>
Basically this command sets the search register (#/) to the current word and turns on 'hlsearch' so the results are highlighted. By setting #/ the cursor is not moved as it is with * or #.
Explanation:
<silent> - to not show the command once executed
<2-LeftMouse> - Double click w/ the left mouse button
#/ is the register used for searching with / and ?
expand('<cword>') get the current word under the cursor
escape(pattern, '\') escape the regex in case of meta characters
\V use very-non-magic mode so everything meta character must be escaped with /
\< and \> to ensure the current word is at a word boundary
set hls set 'hlsearch' on so highlighting appears
If setting the #/ register is not your cup of tea than you can use :match instead like so:
nnoremap <silent> <2-leftMouse> :exe 'highlight DoubleClick ctermbg=green guibg=green<bar>match DoubleClick /\V\<'.escape(expand('<cword>'), '\').'\>/'<cr>
To clear the matches just use:
:match none
You can map * to double-click by a simple mapping:
:map <2-LeftMouse> *
If you want to use said functionality in insert-mode you can use this mapping:
:imap <2-LeftMouse> <c-o>*
Without (Ctrl-o) the * would be printed
[EDIT]
As ZyX pointed out, it is always a good idea to use noremap respectively inoremap if you want to make sure that if * or <c-o> will be mapped to something else, that this recursive mapping won't be expanded.

In vim, is there a way to set "very magic" permanently and globally?

I use "very magic" for regexp searches (i.e. /\v or %s/\v) but I wish I could set some option so I don't have to include \v anymore, anywhere. Is there a way to do this?
Not directly, however you can always use a mapping:
:nnoremap / /\v
:cnoremap %s/ %s/\v
Even if you could set 'very magic' in the way you can set nomagic, you really wouldn't want to as it would break pretty much every plugin in existence.
Edit
See also this page.
EDIT2: I just discovered this plugin, which may be better than the remapping solutions (which seem to have some unavoidable drawbacks; see below). I haven't tested it yet, though, so I don't know if it behaves exactly as desired.
http://www.vim.org/scripts/script.php?script_id=4849
EDIT3: I've been using the plugin for about a year and a half, and I love it. It still interferes with search history, however (see below), and it also breaks incsearch, so I have the following in my Vim config:
" Since I use incsearch:
let g:VeryMagic = 0
nnoremap / /\v
nnoremap ? ?\v
vnoremap / /\v
vnoremap ? ?\v
" If I type // or ??, I don't EVER want \v, since I'm repeating the previous
" search.
noremap // //
noremap ?? ??
" no-magic searching
noremap /v/ /\V
noremap ?V? ?\V
" Turn on all other features.
let g:VeryMagicSubstituteNormalise = 1
let g:VeryMagicSubstitute = 1
let g:VeryMagicGlobal = 1
let g:VeryMagicVimGrep = 1
let g:VeryMagicSearchArg = 1
let g:VeryMagicFunction = 1
let g:VeryMagicHelpgrep = 1
let g:VeryMagicRange = 1
let g:VeryMagicEscapeBackslashesInSearchArg = 1
let g:SortEditArgs = 1
I used DrAI's suggestion for a while, but found it frustrating in practice because of the following behavior:
If you type the following:
/{pattern}
:%s//{replacement}
...then, without this mapping, you can see what you're about to replace before you do a replacement. But with the remapping, you suddenly have s/\v/ instead of s//; this matches eveything in the file, which is obviously wrong.
Fortunately, the s command itself has an alternative form that uses very magic for its search. So here are the mappings I'm currently using in my .vimrc:
nnoremap / /\v
vnoremap / /\v
cnoremap %s/ %smagic/
cnoremap >s/ >smagic/
nnoremap :g/ :g/\v
nnoremap :g// :g//
Note that just mapping s/ leads to problems when attempting to use a pattern that ends in s; similarly, mapping g/ would create problems when using patterns ending in g. Note that the :g/ and :g// mappings prevent Vim from showing the command immediately.
EDIT: Unfortunately, there does not appear to be a "magic" version of :global, which is why the seemingly-superfluous mapping of :g// is used to ensure that the global command can use the previous search pattern.
Another drawback is that these remappings interfere with search history. As an example, consider using * to search for the next occurrence of the word under the cursor. This causes Vim to search for the pattern \<[word]\>, which does not start with \v. Without the remappings described above, typing / and pressing the up arrow will recall that search pattern. With the remappings, however, after typing /, you must delete the automatically-inserted \v before pressing the up arrow in order to recall that pattern.
To reply to the answer above as I can't comment yet, from How to make substitute() use another magic mode?, the vim docs and my own testing, smagic (and sm) only enters magic mode and not very magic mode.
*:snomagic* *:sno*
:[range]sno[magic] ... Same as `:substitute`, but always use 'nomagic'.
{not in Vi}
*:smagic* *:sm*
:[range]sm[agic] ... Same as `:substitute`, but always use 'magic'.
{not in Vi}
For example, one should ('s turn into )'s in a file with :%sm/(/)/g and not :%sm/\(/\)/g, which shows the following for me
E54: Unmatched \(
E54: Unmatched \(
E476: Invalid command
Instead, to enter very magic mode, one should use \v in the search expression of substitute (i.e. :%s/\v\(/\)/g)
(Please correct me if I've messed up, I am quite new to Vim)
https://learnvimscriptthehardway.stevelosh.com/chapters/31.html#magic
Add a normal mode mapping that will automatically insert the \v for you whenever you begin a search
my current config in init.vim:
(I want to go to the fist line and then search, and return back using 's, so msgg)
" vim has set: au BufNewFile,BufRead *.ahk setf autohotkey
if &filetype == 'vim'
nnoremap / msgg/\v^[^"]*
elseif &filetype == 'autohotkey'
echo 'ahk'
nnoremap / msgg/\v^[^;]*
" todo
" https://github.com/hnamikaw/vim-autohotkey
elseif expand('%:t') == 'wf_key.ahk'
nnoremap / msgg/\v^[^;]*
elseif &filetype == 'zsh'
nnoremap / msgg/\v^[^#]*
else
" vscode neovim can not detect filetype?
nnoremap / msgg/\v^[^#";(//)(/*)]*
endif
nnoremap ? msgg/\v
" nnoremap / /\v
cnoremap s/ s/\v
todo: plugin for very magic
https://github.com/coot/EnchantedVim

Resources