In my vimrc file I have the following entry to surround a word with '+':
:nnoremap <silent> q+ wbi+<ESC>ea+<Esc>
I would like to change this to surround a word with any other symbol, for example a quote, but I would not like to use another plugin or to insert one more map. I would like something like this in my vimrc:
:nnoremap <silent> qX wbiX<ESC>eaX<Esc>
where X would be the character to put around the word.
How can this be done in VIM?
Thanks
The general idea:
:nnoremap q :let c=nr2char(getchar())\|:exec "normal wbi".c."\eea".c."\e"<CR>
But I don't think that q is a good choice, especially for your example with quotes, because q starts the extremely handy recording feature from vim. The normal q command also does expect a second character (the recording target register) and it actually can be ". This will be quite confusing for you when you're on another computer or if someone else is using your vim. You should preprend a leader for q. With a leader:
:nnoremap <leader>q :let c=nr2char(getchar())\|:exec "normal wbi".c."\eea".c."\e"<CR>
The default leader value is \, but this can be changed. Note that it had to be changed before defining the mapping. You can see the currently configured leader with let mapleader (which prints an error message if there's no leader configured). With these statements,
:let mapleader=','
:nnoremap <leader>q :let c=nr2char(getchar())\|:exec "normal wbi".c."\eea".c."\e"<CR>
you can type ,q+ to surround your word with + and ,q" in order to surround your word with ".
By the way: Your mapping doesn't work if your cursor is on the last character on line. Change the mapping to:
:nnoremap <leader>q :let c=nr2char(getchar())\|:exec "normal viwo\ei".c."\eea".c."\e"<CR>
Use Tim Pope's surround.vim plugin!
To surround a word with + signs:
ysiw+
Related
I have a few lines of codes that are too that I would like to break into 2 lines at certain location.
So instead of moving to the position then presse I to insert mode then Enter to break line then finally ESc back.
Is there way I can do it easier in normal mode only?
Many thanks.
You can define some simple mapping for it:
" <C-Enter> Insert single / [count] newline.
nnoremap <C-CR> i<CR><Esc>
Note that <C-CR> probably only works in GVIM, not in a terminal; choose a different key if necessary.
Here's an additional mapping that keeps the cursor on the original line:
" <C-S-Enter> Append single / [count] newline.
function! s:AppendCRSetPos()
keepjumps call setpos("''", getpos('.'))
return ''
endfunction
nnoremap <expr> <SID>(AppendCRSetPos) <SID>AppendCRSetPos()
nnoremap <script> <C-S-CR> <SID>(AppendCRSetPos)i<CR><Esc>g``
I have the following in my .vimrc
nnoremap S i<cr><esc>^mwgk:silent! s/\v +$//<cr>:noh<cr>`w
Which will split the line on pressing capital S.
Hope this helps
There is a vim key for that:
r<Enter>
Vim features an internal variable textwidth, which determines how many characters will be printed on screen before adding an <EOL> character to wrap the text to a next line.
I would like to create a mapping, let's say <c-j>, for which I would like the cursor to move a number of characters to the right equal to the value stored in textwidth. This would simulate "going down a line" when the text is wrapped.
I assume that a simple approach would be along the lines of:
nnoremap <c-j> {textwidth}l
However, I have not found a way of evaluating the value of textwidth so that it cant be used as a count for the command l.
Any help is welcome!
There are two ways: One is the interpolation of &textwidth (the & sigil turns the option name into a variable that contains its value; cp. :help :let-option), as in #RuslanOsmanov's answer:
nnoremap <silent> <C-j> :execute "normal!" &textwidth . 'l'<CR>
Another is :help :map-expression, which automatically evaluates the mapping's right-hand side as a Vimscript expression. I would prefer this one, as it's shorter:
nnoremap <expr> <C-j> &textwidth . 'l'
Further improvements
You probably should consider what to do if 'textwidth' is unset, i.e. zero. Unhandled, this would result in a 0l motion, i.e. going to the second character in the line. You can use a conditional to turn this into a no-op, for example. (Or make it beep by returning '<Esc>' instead of '').
nnoremap <expr> <C-j> (&textwidth == 0 ? '<Esc>' : &textwidth . 'l')
Really needed?
Vim has a :help gj command (and variants for the other directions) built-in, that does something similar to what you're trying to implement. Unless you're attempting to solve a special case (e.g. disregarding options like 'showbreak' that further reduce the amount of characters actually shown), it would be advisable to just use (and maybe remap) the built-ins.
You can refer to an option value by prefixing its name with an ampersand, e.g. &textwidth.
Moving &textwidth characters to the right can be run as follows:
:execute "normal!" &textwidth 'l'
where the arguments ("normal!", &textwidth, and 'l') are concatenated with a space and executed as an Ex command.
So your mapping might look something like this:
:nnoremap <silent> <c-j> :execute "normal!" &textwidth 'l'<cr>
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..
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.
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