I have a mapping like below to move the cursor to the first column of input/update (the red-circled) area in a table. And I can type w or ww to get to the 2nd/3rd column if needed.
noremap <s-F8> 0f\|ew
It goes to the anchor | first, to the end of the green number, and moves to next word (can be a dot, a number or an expression) in the table as below.
I wonder if I can use the count given in front of a normal-mode command to get to the 2nd or 3rd column directly, with a command 2<s-F8> or 3<s-F8>.
The following code doesn't work, though the #= helps separate the count from the 0 command.
noremap <s-F8> #='0f\|ew'<cr>
I studied the answer of Karkat in the post Mapping with v:count in vim and made this mapping:
noremap <expr> <s-F8> '0f\|e' . v:count1 . 'W'
But it doesn't move if a count is given. (It does move to column 1 if there is no count.)
What would be the correct way to use v:count1 in such a mapping?
Use the :execute STRING command to include the v:count1 in the string:
noremap <silent> <s-F8> :<c-u>exe 'norm 0f\|e' . v:count1 . 'W'<cr>
Note: The CTRL-U is used to remove the range that Vim may insert.
For your <expr> version, you need an <esc> to help cancel the COUNT (something like the CTRL-U does):
noremap <silent> <expr> <s-F8> '<esc>0f\|e' . v:count1 . 'W'
Related
I have a key mapping for p in my vimrc file as below:
noremap p <ESC>:set paste<CR>p:set nopaste<CR>
The purpose of this key mappinng is to make sure the content from outside of vim can be pasted in its original format in paste mode. And restore it to nopaste mode after paste complete.
But when I run the following commands:
yy
5p
p is only executed once other than 5 times.
It looks like the count is missed from the key mapping.
Any way to pass the count in the key mapping?
Or how to fix this problem?
The fisrt <ESC> drops the count so it is no available later. Instead of <ESC> we would ignore and save count with <c-u> and access it later with v:count1 variable like :<c-u>set paste <CR>... v:count1 ....
But there is another problem: count will be lost after the first <CR>, so we want to rewrite the mapping as a single command. Chaining of commands may be done with |, but in mappings we should write <BAR> instead of |.
Here is the final mapping:
:noremap p :<c-u>set paste <BAR> :exe "normal! " . v:count1 . "p" <BAR> :set nopaste<CR>
:exe "normal! " is a fancy way to execute a command from evaluated string.
How to move visually selected text to end of line, which command or keys I should use?
e.g. /text3<CR> note that ** is a selected text, not part of it.
**text3** text1 text2
**text3** text1 text2
and move to this:
text1 text2 **text3**
text1 text2 **text3**
I tried: :%s/\(text3\)\(.*\)/\2 \1/ any other ways to do it?
Basically you can do it (after selecting your text visually like put the cursor on your word then hit viw) with d$p. Any you can create a macro for it, I used to go with something like this in simillar cases: qq/SEARCHTERMENTERviwd$pj0q. Now you can execute it as NUMBER(s)#q.
But as a more general solution:
:%s_\(YOUR_TEXT_TO_MOVE_TO_THE_EOL\)\(.*\)_\2\1
Should work just fine.
You could use the :global command to select lines with the matching pattern and :normal to operate on those lines. For example:
:g/^text3 /norm! dt p d0$p
Explanation
:g/^text3 /<command>
Runs the specified <command> on all lines starting with text3 followed by a space. See :help :global for more information.
norm!
Executes the following commands in normal mode. See :help :normal.
dt p d0$p
Delete to the first space, paste that after said space, move forward one character and delete to the beginning of the line. Move to the end of the line and paste.
You can use Damian Conway's dragvisuals.vim
After installation add the following (uncommented) to your .vimrc
runtime plugin/dragvisuals.vim
vmap <expr> <LEFT> DVB_Drag('left')
vmap <expr> <RIGHT> DVB_Drag('right')
vmap <expr> <DOWN> DVB_Drag('down')
vmap <expr> <UP> DVB_Drag('up')
vmap <expr> D DVB_Duplicate()
" Remove any introduced trailing whitespace after moving...
let g:DVB_TrimWS = 1
Or, if you use the arrow keys for normal motions, choose four
other keys for block dragging. For example:
vmap <expr> h DVB_Drag('left')
vmap <expr> l DVB_Drag('right')
vmap <expr> j DVB_Drag('down')
vmap <expr> k DVB_Drag('up')
Or:
vmap <expr> <S-LEFT> DVB_Drag('left')
vmap <expr> <S-RIGHT> DVB_Drag('right')
vmap <expr> <S-DOWN> DVB_Drag('down')
vmap <expr> <S-UP> DVB_Drag('up')
Or even:
vmap <expr> <LEFT><LEFT> DVB_Drag('left')
vmap <expr> <RIGHT><RIGHT> DVB_Drag('right')
vmap <expr> <DOWN><DOWN> DVB_Drag('down')
vmap <expr> <UP><UP> DVB_Drag('up')
To use
Select with visual mode and move the block with h, l, j or k etc.
The solutions involving iw will work if the text is text3, but they will fail on two words.
None of the methods involving $p will add a space, as your :s command does. You could use A <C-R>"<Esc> instead.
If you want to do it on a single line, and the text is already selected in Visual mode, then x$p is pretty easy.
If the text is "selected" in the sense that you have just searched for it, and it is highlighted with the Search highlight group, and you want to make the change on a single line, then you could use d/<C-R>//e<CR>$p. The <C-R>/ will be replaced by the current search pattern, so you will get something like d/text3/e<CR>$p.
If you want to do it on all matching lines in the buffer, then a slight simplification of your solution is
:%s/\v(<C-R>/)(.*)/\2 \1
:help i_CTRL-R
:help c_CTRL-R
:help /\v
I'm sorry if my question isn't very clear. I'm not sure how to phrase it.
I'd like to use VIM to write papers for some classes I'm in. The problem I'm having is with the formatting of lines in the editor. If I don't explicitly break the end of a line with the enter key, when I try to move the cursor through the text, it skips multiple lines if I have a sentence that spans more than one line. Is there any way to make it so that the cursor will be able to move through the text akin to the way it does in most word processors?
The problem with the often used
noremap j gj
noremap k gk
option is, that it breaks the <vcount> functionality, if you have lines in your text, which span across multiple lines.
Example: you want 10k (go UP 10 lines), because you use relative numbers in the sidebar, but theres a multiline with 4 lines height. Therefore you end up effectively at 6 lines (6k) above your desired line, which you read from your relative numbers. You'd have to calculate manually! Annoying... Especially if you have multiple multiline between your current position and your desired position - not Vim-istic!
I like my <vcount> function together with my :relativenumber, which is why I wrote the following functions & mapping to solve all problems related to this.
These functions let you use commands like 10j or 10k as expected, despite the presence of multilines with all the advantages of using gj and gk as your default movement mappings:
Edit:
I just found the following on reddit, which is so much better then my own solution. This is shortest possible version:
nnoremap <expr> j v:count ? 'j' : 'gj'
nnoremap <expr> k v:count ? 'k' : 'gk'
(If you use noremap instead of nnoremap, then this works in both visual and normal modes)
"Longer" version for better understanding and completeness:
nnoremap <expr> k (v:count == 0 ? 'gk' : 'k')
nnoremap <expr> j (v:count == 0 ? 'gj' : 'j')
source: http://www.reddit.com/r/vim/comments/2k4cbr/problem_with_gj_and_gk/
My old solution:
nnoremap <silent> j :<C-U>call Down(v:count)<CR>
vnoremap <silent> j gj
nnoremap <silent> k :<C-U>call Up(v:count)<CR>
vnoremap <silent> k gk
function! Down(vcount)
if a:vcount == 0
exe "normal! gj"
else
exe "normal! ". a:vcount ."j"
endif
endfunction
function! Up(vcount)
if a:vcount == 0
exe "normal! gk"
else
exe "normal! ". a:vcount ."k"
endif
endfunction
That's because the default j and k motions move across physical lines, not the visible, soft-wrapped screen lines (when you have :set wrap). You can use the gj and gk commands for that.
If you want to default to that behavior, you can remap the default keys by putting this into your ~/.vimrc:
noremap j gj
noremap k gk
Have you tried the following in vim command line:
:set nowrap
Solution that I found on internet that works with up and down arrow:
imap <silent> <Down> <C-o>gj
imap <silent> <Up> <C-o>gk
nmap <silent> <Down> gj
nmap <silent> <Up> gk
I have found another version of this solution that does more than moving through physical or virtual lines, it also adds jumps bigger than 5 lines to the jump list, allowing us to use Ctrl-o and Ctrl-i.
" source: https://www.vi-improved.org/vim-tips/
nnoremap <expr> j v:count ? (v:count > 5 ? "m'" . v:count : '') . 'j' : 'gj'
nnoremap <expr> k v:count ? (v:count > 5 ? "m'" . v:count : '') . 'k' : 'gk'
It uses a nested ternary operator to add the jump to the jump list
Vim is great, but like many people I get really annoyed when I want to copy, delete, then paste -- the yank buffer gets overwritten by the delete action.
Now I know there are 101 work-arounds and mappings, some of which are enumerated in posts like this one: Any way to delete in vim without overwriting your last yank?
But all of these solutions have drawbacks -- even I were a buffer-guru (which I'm not). For instance, excess keystrokes -- whereas I normally xxxx to quickly delete 4 characters (just one keystroke cuz I hold it down and wait for autorepeat), it is not practical for me to now switch to ,x,x,x,x or whatever mapping I have to use a different buffer.
What would really be ideal is simply a mode toggle, whereby you can toggle on and off the side-effect behavior of the D, d, X, and x keys so that they alternately do or do not also write their text to a buffer. That way I can simply enter the "no side-effect" mode and delete away to heart's content, then paste when I'm ready. And re-enable side-effects if desired.
Does anyone know a way to do this?
[UPDATE: SOLUTION] OK I got it: I wrote a function that toggles a "no side-effects" mode... works perfectly! See my accepted correct answer below
[UPDATE #2] My solution still works great and I use it all the time when I'm doing a lot of deleting and pasting. But meanwhile I also found a lighter way to meet the specific use-case of copy, paste, delete for simple cases where the text to delete is contiguous.
After yanking text normally, I then visually highlight the text to delete using the v command, and then simply paste over it with the p command. That achieves the desired effect without any special mapping.
Only problem with this workflow is that if I wanted to paste again, the original paste buffer is overwritten by the act of pasting over the highlighted text, but this behavior is easily changed with the following mapping in .vimrc:
vnoremap p "_dp
vnoremap P "_dP
OK, I got it -- this script in .vimrc lets me effectively toggle a "no buffer side-effects" mode whereby the d and x keys no longer overwrite the buffer when "no buffer side-effects" mode is activated.
Add this in .vimrc
function! ToggleSideEffects()
if mapcheck("dd", "n") == ""
noremap dd "_dd
noremap D "_D
noremap d "_d
noremap X "_X
noremap x "_x
echo 'side effects off'
else
unmap dd
unmap D
unmap d
unmap X
unmap x
echo 'side effects on'
endif
endfunction
nnoremap ,, :call ToggleSideEffects()<CR>
Then to toggle in and out of this mode use the key combination ,, (two commas)
I think trying to "turn-off" the side effects for every delete/change command would be overly difficult if not impossible. The basic ways to handle this situation:
Use the black hole ("_) register with your delete or change commands. e.g. "_dd
Use the "0 register which contains the most recent yank with your paste commands. e.g. "0p
Yanking the text to a named register. e.g. "ayy then later doing "ap
I personally lean toward the "0p approach as this is fits with how my mind works.
Now seeing you asked for no such work-arounds I have provided some functions that alter the paste commands to toggle between my so called paste_copy and nopaste_copy mode. nopaste_copy being Vim's default behavior. Put the following in your ~/.vimrc:
function! PasteCopy(cmd, mode)
let reg = ""
if exists('g:paste_copy') && g:paste_copy == 1 && v:register == '"'
let reg = '"0'
elseif v:register != '"'
let reg = '"' . v:register
endif
let mode = ''
if a:mode == 'v'
let mode = 'gv'
endif
exe "norm! " . mode . reg . a:cmd
endfunction
command! -bar -nargs=0 TogglePasteCopy let g:paste_copy = exists('g:paste_copy') && g:paste_copy == 1 ? 0 : 1<bar>echo g:paste_copy ? ' paste_copy' : 'nopaste_copy'
nnoremap <silent> p :call PasteCopy('p', 'n')<cr>
nnoremap <silent> P :call PasteCopy('P', 'n')<cr>
nnoremap <silent> ]p :call PasteCopy(']p', 'n')<cr>
nnoremap <silent> [p :call PasteCopy('[p', 'n')<cr>
nnoremap <silent> ]P :call PasteCopy(']P', 'n')<cr>
nnoremap <silent> [P :call PasteCopy('[P', 'n')<cr>
vnoremap <silent> p :<c-u>call PasteCopy('p', 'v')<cr>
vnoremap <silent> P :<c-u>call PasteCopy('P', 'v')<cr>
You can toggle your paste_copy mode via :TogglePasteCopy. You may prefer a mapping like so
nnoremap <leader>tp :TogglePasteCopy<cr>
As a closing piece of advice I would highly suggest using "0p or using a named register over this approach as they are native to vim and there is one less "mode" to worry about.
The super star (*) key in Vim will search for the word under the cursor and jump forward to the next match. The user can jump to the next matches with the n key. If hlsearch is enabled, it will also highlight the matches.
I want to be able to press * and get the highlighted matches and be able to navigate the matches using the n key. However, I do not want Vim to jump to the next match when * is pressed, it should remain on the current word. Is there a way to do this?
I would map:
nnoremap * *``
Works exactly like you want, except that it adds a jump in the jump list. To prevent that you need:
nnoremap * :keepjumps normal! mi*`i<CR>
I found this works pretty well, there's no blink and it doesn't need an intermediate register.
nnoremap <silent> * :let #/= '\<' . expand('<cword>') . '\>' <bar> set hls <cr>
Or if you want the g* behavior:
nnoremap <silent> g* :let #/=expand('<cword>') <bar> set hls <cr>
The best solution:
don't add a jump to the jump list
the behavior of the star key is not be changed
so, try the plugin:
http://www.vim.org/scripts/script.php?script_id=4335
Much better than:
" a jump adds to the jump list
nnoremap * *``
" I got a dead loop on macvim
nnoremap * :keepjumps normal *``<cr>
" the behavior is changed
nnoremap <silent> <Leader>* :let #/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>
I haven't seen this one yet:
nmap <silent> * "syiw<Esc>: let #/ = #s<CR>
It's very short and does not involve jumping around which can result in blinking.
Explanation: copy the word under cursor to s register and then set the search register (/) to the content of s register. The search register is not writeable directly, that's why the let is necessary and hence the silent to keep vim's command line clean.
I have the following in my .vimrc, which I think works better than the other alternatives:
" Put word under cursor into search register and highlight
nnoremap <silent> <Leader>* :let #/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>
vnoremap <silent> <Leader>* :<C-U>
\let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
\gvy:let #/=substitute(
\escape(#", '/\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR>
\gV:call setreg('"', old_reg, old_regtype)<CR>:set hls<CR>
If you want to keep the current view and add the search to the history, try this [not so efficient] solution:
noremap * msHmt`s*`tzt`s
It is using the marks s (save) and t (top).
A simple solution came to my mind: put map * *# in .vimrc file (it will blink though).
Many answers here outline rather simple mappings that work well for common cases, but may have side effects (like flickering by jumping back and forth) or lack robustness (may break if some regexp characters are defined as keyword characters).
If you're looking for a robust implementation and don't mind installing a plugin, you can choose from a plethora of alternatives, many of which also offer additional search-related improvements:
My SearchHighlighting plugin changes the * command, extends it to visual selections, and offers optional auto-searching of the word under the cursor.
star search changes the behavior of * to not jump to the next match, and includes the visual search from the next plugin
vim-visual-star-search provides searching of the visual selection
visualstar.vim provides searching of the visual selection
select & search can use either n/N or * in the visual selection, and can avoid jumping.
vim-asterisk provides a z* mapping that also doesn't jump, visual *, more intuitive smartcase handling, and can keep the cursor position when jumping (like ,*)
searchant.vim hooks into the built-in search commands and provides a separate highlighting for the match last jumped to.
The other answers here are good, particularly #rodrigo's, but I wanted to write a solution that preserves scroll position and does so without affecting any of the marks.
This works for me:
function! StarPositionSave()
let g:star_position_cursor = getpos('.')
normal! H
let g:star_position_top = getpos('.')
call setpos('.', g:star_position_cursor)
endfunction
function! StarPositionRestore()
call setpos('.', g:star_position_top)
normal! zt
call setpos('.', g:star_position_cursor)
endfunction
nnoremap <silent> * :call StarPositionSave()<CR>*:call StarPositionRestore()<CR>
Putting normal! * in the function directly doesn't seem to work, as (at least in neovim) it suppresses search highlighting from being triggered (as if :nohlsearch was run).
My solution:
nnoremap <silent><expr> * v:count ? '*'
\ : ':silent execute "keepjumps normal! *" <Bar> call winrestview(' . string(winsaveview()) . ')<CR>'
nnoremap <silent><expr> g* v:count ? 'g*'
\ : ':silent execute "keepjumps normal! g*" <Bar> call winrestview(' . string(winsaveview()) . ')<CR>'
Edit: Recent Vim has <Cmd> mapping, so you can use below to avoid CmdlineEnter/Leave to be fired.
nnoremap <expr> * v:count ? '*'
\ : '<Cmd>silent keepjumps normal! *<CR><Cmd>call winrestview(' .. string(winsaveview()) .. ')<CR>'
nnoremap <expr> g* v:count ? 'g*'
\ : '<Cmd>silent keepjumps normal! g*<CR><Cmd>call winrestview(' .. string(winsaveview()) .. ')<CR>'
Pros:
No flickering.
Jump list remains unchanged.
With a count, it invokes original *; you can use 1* if you miss the original *.
Marks and registers are untouched.
Using original *, its behavior is almost identical with * (except for jumping).
This means 'smartcase' is ignored as * do.
No need to install plugins.
Similar to * we have
[I ..................... it shows where the word under the cursor appears
I also have some useful lines on my vimrc that can, maybe, help you
" When double click a word vim will hightlight all other ocurences
" see CountWordFunction()
" [I shows lines with word under the cursor
nnoremap <silent> <2-LeftMouse> :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>:CountWord<cr>
nnoremap <Leader>* :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>:CountWord<cr>
if !exists('*CountWordFunction')
fun! CountWordFunction()
try
let l:win_view = winsaveview()
exec "%s/" . expand("<cword>") . "//gn"
finally
call winrestview(l:win_view)
endtry
endfun
endif
command! -nargs=0 CountWord :call CountWordFunction()
cnoreabbrev cw CountWord
nnoremap <F3> :CountWord<CR>
I'm adding this answer because I found the other answers either, centered the line in the view (which I found distracting), or seemed overly complicated.
The following command works well for me:
noremap * :let #/ = "\\<<C-r><C-w>\\>"<cr>:set hlsearch<cr>
It simply sets the pattern to the whole word under the cursor and then turns on (or updates) the highlighting for the search pattern.
NOTE: It doesn't modify the search history (which I prefer but might not be quite what you want).
just do
nnoremap * *N
nnoremap # #n
works with this http://www.vim.org/scripts/script.php?script_id=4335 too like so:
vnoremap * :<C-u>call VisualStarSearchSet('/')<CR>/<C-R>=#/<CR><CR>N
vnoremap # :<C-u>call VisualStarSearchSet('?')<CR>?<C-R>=#/<CR><CR>n
nnoremap <silent> ml :<c-u>let #/ = '\<'.expand('<cword>').'\>'\|set hlsearch<CR>wb
and if you want a visual mode one:
function SetSearchVisualSelection()
let clipboard_original_content=#"
normal gvy " this overwrites clipboard
let raw_search=#"
let #/=substitute(escape(raw_search, '\/.*$^~[]'), "\n", '\\n', "g")
let #"=clipboard_original_content
endfunction
vnoremap ml :call SetSearchVisualSelection()<CR>:set hlsearch<CR>