Vim find in files shortcut from command - vim

Hi I use vimgrep to find text in the project.
However its a little slow because i have to write this each time:
vimgrep /text/ **/*.* | cwindow
Is there any way to map it in for example C-shift-F and show the text box.
After that when I hit enter it will execute the vimgrep commands.
That will save much time
Thank you

Vim is highly customizable (which is one big reason for its popularity), so there are several possibilities to provide a shortcut:
incomplete mapping
A mapping does not necessarily contain a complete command. You can just prepare the command-line and leave the cursor in a certain spot, so that you can fill out the rest and trigger the (Ex) command with Enter. For example:
:nnoremap <Leader>f :vimgrep // **/*.* <Bar> cwindow<Home><Right><Right><Right><Right><Right><Right><Right><Right><Right>
The trailing keys position the cursor in between the //, so you can fill in text, and then execute the command.
Note: Your suggested <C-S-f> mapping would be the same as <C-f> (an unfortunate limitation in the current implementation), and therefore override a useful built-in command. I've instead used <Leader>f (where the default for that key is \; cp. :help <Leader>).
custom command
This is already nice, but assuming we'll never have a need to edit the other parts of the command, we can shorten this to a custom command, e.g. :FindText:
command! -nargs=1 FindText vimgrep /<args>/ **/*.* | cwindow
With this, you can search via :FindText text. If you still prefer a mapping, this would become
:nnoremap <Leader>f :FindText<Space>
Other benefits of custom commands are that these are easier to recall from the command-line history (as they are different from other :vimgrep commands you might use), and you're building a library of higher-level editing commands, which over time can be reused to build even more higher-level commands, which makes your editing more efficient.

Related

Vim - make comment shortcut

I often write LaTeX using Vim. And I have been taught that one can comment a number of selected lines (in visual mode) using the following command:
:'<,'>s!^!%!
And similarly, one may uncomment lines in visual mode by using this command:
:'<,'>s!^%!!
Here, '%' denotes the commenting symbol for LaTeX. But I would very much like to make a shortcut to make it easier for myself to use these commands. For instance a keybinding or some sort of function so that I do not have to remember this syntax. How does one do that?
First, there are several commenter plugins, that do this very well, and those are generic (and often extensible) so that they work for any filetype, not just Latex:
NERD Commenter plugin
tComment plugin
commentary.vim plugin
are just a few popular plugins.
Custom mapping
That said, it's a good learning experience to develop a mapping on your own. Here's how:
First, mappings are just instructions that when certain key(s) are pressed, Vim translates them into other keys (on the right-hand side). Your mapping is for visual mode, so the command is :vmap. What do you normally do? You select the lines to be commented, and press :; Vim automatically inserts the '<,'> for you. You write the :s command, and conclude by pressing Enter.
Translation:
vmap <Leader>c :s!^!%!<CR>
The <Leader> is a configurable, unused key, defaulting to backslash. So, your mapping is invoked by pressing \ and then C. Put that into your ~/.vimrc to make it permanent, and you're done. Wait! There's more.
Advanced mappings
First, you should use :vnoremap; it makes the mapping immune to remapping and recursion.
Second, that mapping is global, but it applies only to the Latex filetype. So, it should apply only to Latex buffers; there's the <buffer> modifier for that.
You can define that for certain filetypes by prepending :autocmd Filetype tex ..., and put that into your ~/.vimrc. But that gets unwieldy as you add mappings and other settings for various filetypes. Better put the commands into ~/.vim/ftplugin/tex_mappings.vim. (This requires that you have :filetype plugin on.)
vnoremap <buffer> <Leader>c :s!^!%!<CR>
Technically, you should use <LocalLeader> instead of <Leader>. They default to the same key, but the distinction allows to use a different prefix key for buffer-local mappings (only if you need / like).
Let's add the alternative mapping for uncommenting, triggered via \ and Shift + C:
vnoremap <buffer> <LocalLeader>c :s!^!%!<CR>
vnoremap <buffer> <LocalLeader>C :s!^%!!<CR>
Note that you could combine both into one, using :help sub-replace-expression with a conditional expression. If anything here is over your head, don't worry. You should be using one of the mentioned plugins, anyway :-)

how to remap "q!" and "q" in vim

I'm trying to remap q and q!. Here's what I'm trying:
cnoremap q :call TabCloseLeft('q')
cnoremap q! :call TabCloseLeft('q!')
That properly remaps :q but doesn't capture :q!. I've read various help sections, but I'm obviously overlooking something.
I see some problems:
You are using a cnoremap dangerously e.g. /q
You are using trying to override vim's native :quit function
Looks like you are trying to force vim into a tab behavior
cnoremap
Do not use cnoremap to try and create commands, use :command. If you want to override a command then use a clever cabbrev expression or plugin. See vim change :x function to delete buffer instead of save & quit
Native quit
There are many ways for quiting a buffer in vim. Some do slightly different things. As vimmers learn more commands they integrate them into their workflow. e.g. <c-w>c to close a split/window and ZZ to update and quite the current buffer. If you go down this path you will be overriding many command or you will be disregarding useful commands.
Tabs
Learn to use buffers effectively. Using tabs in Vim is great however they are not the only way and will certainly cause you pain down the road. IMHO it is best to curtail these behaviors and encourage better habits.

How to jump to a search in a mapped :normal command?

What do you need to properly jump to a matched search result?
To reproduce, make a macro with a search in it after you've run vim -u NONE to ensure there's no vimrc interfering. You'll need to make a file with at least 2 lines and put the cursor on the line without the text TEST_TEXT.
map x :norm gg/TEST_TEXT^MIthis
My intention is that when I press x, it goes to the top of the file, looks for TEST_TEXT and then puts this at the start of the line that matches the search. The ^M is a literal newline, achieved with the CtrlQ+Enter keypress. What's happening instead is either nothing happens, or the text gets entered on the same line as when I called the macro.
If I just run the :norm gg/TEST_TEXT^MIthis command without mapping it to a key, the command executes successfully.
I had an initially longer command involving a separate file and the tcomment plugin, but I've gotten it narrowed down to this.
What is the correct sequence of keys to pull this off once I've mapped it to a key?
The problem is that the ^M concludes the :normal Ex command, so your search command is aborted instead of executed. The Ithis is then executed outside of :normal.
In fact, you don't need :normal here at all. And, it's easier and more readable to use the special key notation with mappings:
:map x gg/TEST_TEXT<CR>Ithis
If you really wanted to use :normal, you'd have to wrap this in :execute, like this:
:map x :exe "norm gg/TEST_TEXT\<lt>CR>Ithis"<CR>
Bonus tips
You should use :noremap; it makes the mapping immune to remapping and recursion.
Better restrict the mapping to normal mode, as in its current form, it won't behave as expected in visual and operator-pending mode: :nnoremap
This clobbers the last search pattern and its highlighting. Use of lower-level functions like search() is recommended instead.
There are many ways of doing this however this is my preferred method:
nnoremap x :0/TEST_TEXT/norm! Itest<esc>
Explanation:
:{range}norm! {cmd} - execute normal commands, {cmd}, on a range of lines,{range}.
! on :normal means the commands will not be remapped.
The range 0/TEST_TEXT start before the first line and then finds the first matching line.
I have a few issues with your current mapping:
You are not specifying noremap. You usually want to use noremap
It would be best to specifiy a mode like normal mode, e.g. nnoremap
It is usually best to use <cr> notation with mappings
You are using :normal when your command is already in normal mode but not using any of the ex command features, e.g. a range.
For more help see:
:h :map
:h :norm
:h range
try this mapping:
nnoremap x gg/TEST_TEXT<cr>Ithis<esc>
note that, if you map x on this operation, you lost the original x feature.

Map :w (save) and a call for a .sh file to F2 in VIM

I'd like to map F2 in VIM so that it first saves the file with :w and then calls a script /home/user/proj/script.sh that will upload the changed files to the server.
I already tried
:map F2 :w<cr>|:! /home/user/proj/script.sh
but that doesn't work.
Please tell my why this isn't working and help me to get this working.
Try :noremap <F2> :<c-u>update <bar> !/home/user/proj/script.sh<cr>.
noremap vs. map
This creates a non-recursive mapping. See Wikia - Mappings keys in Vim
I just assumed this, because it's what people want most of the time. :-)
update vs. write
Only save the file if there were actual changes. See: :help :update.
<bar> vs. |
:help map_bar
<c-u>?
You used a generic mapping, instead of one for a certain mode, like nmap for normal mode mappings. Thus the mapping could also be triggered in visual mode. If you select something in visual mode and hit :, you'll see the commandline is prefixed with a range. But you don't want that in your case and <c-u> clears the commandline.
<cr> at the end?
Your mapping drops into the commandline mode and inserts 2 things separated by <bar>. Afterwards it has to execute what it has written, thus you need to append a <cr>.

Combine two vim commands into one

I'm having trouble combining two vim commands, specifically <C-w>s and <leader>x into <leader>r (i.e. split window and open spec counterpart of current file). Any help?
Thanks!
It would help if you'd post what exactly you've tried that didn't work. Generally, doing what you describe should be simple. It should be enough to put this in your .vimrc file:
nmap <leader>r <c-w>s<leader>x
This maps <leader>r to expand to the key sequence <c-w>s<leader>x. Note that these are not "commands", as you call them in your question, they're "mappings". A "command" is something completely different in vim, you can read up on that with :help user-commands.
One thing to be careful of is using nmap instead of nnoremap. The command nmap maps the sequence on the left to the sequence on the right while re-using mappings that have already been defined. On the other hand, nnoremap creates a mapping with the original meanings of the keys, so in your case won't work (since <leader>x is defined by some plugin). This is one possible reason you may have failed while trying to do it, but I can't tell from your question.

Resources