I know that I can use :nmap, :vmap, :imap commands to display all the mapping for those 3 modes. However, I would like to display comments that I have for a single mapping.
So suppose I have the following entry in my vimrc:
" Execute current line in bash
nmap <F9> :exec '!'.getline('.')<CR>
This could also look like this:
nmap <F9> :exec '!'.getline('.')<CR> " Execute current line in bash
I would like to have a command that for this mapping that would look something like this:
<F9> Execute current line in bash
As this probably can only be done using custom function, where do I start? How do I parse .vimrc to strip only key mappings and their corresponding comments (I have only done some very basic Vim scripts)?
Do I understand correctly from :help map-comments that I should avoid inline comments in .vimrc?
It's very hard to "embed" comments into a mapping without affecting its functionality. And this would only help with our own mappings, not the ones from plugins.
Rather, I'd suggest to learn from (well-written) plugins, which provide :help targets for their (default) key mappings. So, to document your mapping(s), create a help file ~/.vim/doc/mymappings.txt with:
*<F9>*
<F9> Execute current line in bash
After :helptags ~/.vim/doc, you will be able to look up the comments via :h <F9>. By using the help file, you can use syntax highlighting, longer multi-line comments, and even examples, so I think that'a better and more straightforward solution.
Personally, I wouldn't have much use for such a feature for two reasons: the first one, is that I always have a vim session with a note taking buffer that contains all the tips/commands not yet in my muscle memory. Secondly, you can list all the maps using :map, and it's always a great exercise for your brain in learning vim to literally read vim commands.
That being said…
As this probably can only be done using custom function, where do I start?
…well I guess you could imagine using a function with a prototype such as:
AddMap(op, key, cmd, comment)
used like:
call AddMap("nmap", "<F9>", ":exec '!'.getline('.')<CR>", "Execute current line in shell")
which implementation would add key and comment to an array, so that you could list the array to get your own mappings declared. Using a function like ListMap().
let map_list = []
function! AddMap(op, key, cmd, comment)
" add to map list
insert(map_list, [op, key, comment])
" execute map assign
exec op.' '.key.' '.cmd
endfunction
function! ListMap()
for it in map_list
echo it[0] . '\t' . it[1] . '\t' . it[2]
endfor
endfunction
Of course, one could elaborate on the ListMap() function implementation to generate a more "proper" help file that you could open in a buffer. But that's an idea of how you could do an implementation for a feature close to what you're looking for.
N.B.: this snippet is mostly an idea of how I'd tackle this problem, and it's a one shot write that I did not actually try.
How do I parse .vimrc to strip only key mappings and their corresponding comments (I have only done some very basic Vim scripts)?
I don't think that would be a good solution, I think the better way to achieve your goal is my suggestion. Simpler and more explicit, though it won't show off all mappings. But you don't have all your mappings in your .vimrc.
Do I understand correctly from :help map-comments that I should avoid inline comments in .vimrc?
To be more precise you shall not use inline comments after maps, because they will be interpreted part of the mapping.
how to get mapping created by plugins?
Besides, using :map, you just don't. You look at the sources/documenation of your plugins and find out about them. There's no such thing as a reverse lookup from runtime to declaration point.
Related
I have a mapping
:cnoremap ch call ShowHistoryMatching
The problem is that the ch characters expand to the right sentence in any case they are typed, no matter if at the beginning or later in the cmap input.
The problem is when I try to search for words in vim using / or ? e.g. for
/cache - it will be expanded using the mapping above.
How can I set the mapping ch to be extended only when it occurs at the beginning of the command?
cmap's are notoriously tricky because they often execute in the wrong context. Some better alternatives:
Use a normal mapping e.g. nnoremap <leader>ch :call ShowHistoryMatching()<cr>
Create a command e.g. command Ch call ShowHistoryMatching()
Use a the cmdalias.vim plugin
Use a more clever abbreviation as described in vim change :x function to delete buffer instead of save & quit post. Similar technique to cmdailias.vim.
Personally I would just create a new command.
You can use the getcmdpos() function to determine if you're at the beginning of the line or somewhere else. This technique can replace a built-in command using an abbreviation or you can adapt it for use in a mapping, possibly with an <expr> mapping.
I use pandoc markdown in text files and want to automate links that refer to internal textnodes. For example I have a link like [\%110lund] going to the word "und" in line 110. To automate the jumping process I defined a keybinding:
nnoremap <Leader>l vi[y/<ctrl+r>0<CR>
Unfortunately <ctrl+r> is written as the query string instead of performed to copy the visual selection.
So my question is how do I have to notate <ctrl+r>0 at this location so that it is actually performed instead of written out
Use c+r instead of ctrl+r.
In order to avoid confusion, I am striking out the incorrect edit that someone else made, rather than reverting it. In the context of a vim mapping (such as the :nnoremap of this question) the following should be typed literally. For example, <c-r> really means 5 characters.
Use <c-r> instead of <ctrl+r>.
See :help keycodes for more options.
Just asked a question a few moments ago about how to wrap a line in a comment which yielded this fantastic snippet:
nnoremap - mzI/* <esc>A */<esc>`z
I wanted to open another thread to ask how I can turn this into a toggle. Meaning it first checks if the line is wrapped in /* */ and removes the comment or adds it if it is not there.
Does this have to be a script or can I do this with a map? Also I don't want to use a plugin for this because its simple and I would like to see how its done.
Here you go:
nnoremap <expr> - getline('.') =~ '^\s*/\*.\+\*/$' ? '^3x$daw' : "I/* \<esc>A */\<esc>"
The un-commenting is done by ^3x$daw which deletes the beginning and ending portions of the mapping. The detection is done via a regex on the current line, getline('.'). I have removed the z mark from the comment portion of the mapping as it does a poor job of keeping cursor in the "same" spot.
This is a great example of a fancier mapping. However there are somethings to think about:
This mapping pollutes the . and " registers.
Only works on filetypes with c-style comments
No visual or operator like mappings, meaning you can not mass toggle.
Does not repeat via .
I highly recommend a comment plugin. I currently use Tim Pope's vim-commentary plugin.
For more help see:
:h :map-<expr>
:h getline(
RE I don't want to use a plugin for this because its simple.
It's only simple until you use this heavily; Peter Rincker's answer already lists some issues. As you probably rely on (un-)commenting a lot, this is really a good indication for a robust, proven plugin.
Let me throw in a recommendation for The NERD Commenter; it has the toggle mapping you're asking for, and supports several languages. Apart from commentary, also have a look at tComment.
The imaps.vim documentation mentions examples like this one
As an example, when you type EFI in |insert-mode|, you will get the following:
\begin{figure}[h]
\centerline{\psfig{figure=<+eps file+>}}
\caption{<+caption text+>}
\label{fig:<+label+>}
\end{figure}<++>
Where do I get a list of all the siblings of EFI? What are all the other mappings?
:verbose imap
will output a list of all the INSERT mode mappings available in Vim and tell you where they are set.
But it seems that the plugin actually uses a custom IMAP() function instead of regular imap or inoremap. I'm not sure the above command will be of any help.
I see a bunch of these custom mappings in ftplugin/latex-suite/bibtex.vim, there are probably many more scattered around the ftplugin directory.
I would do something like :vimgrep IMAP *.vim<CR> in ftplugin then :copen to access all occurences.
In addition to vimgrep you can analyze source code of IMAP() function. It is a small function and from its code you can see that it saves information into script-local variables and the ones with right sides of mappings are s:Map_.*, while ones left sides are s:LHS_*. So you should do
" Arguments do not matter, all you need is to start a debugger
" with appropriate context
debug call IMAP(0,0,0)
" step into IMAP function
s
" Generate and show a table filetype - list of mapping LHSs
echo "Ft\tLHSs\n".join(map(items(filter(copy(s:), 'v:key[:3] is# "LHS_"')), 'v:val[0][4:(stridx(v:val[0], "_", 4)-1)]."\t".join(split(v:val[1], "\\\\|"))'), "\n")
" Interrupt function so that it won’t do anything
q
" Note that in debugger “q” command is doing an interrupt, not quits vim.
I found it in :help latex-suite, in Section 3.1 Environment Mappings
So I'm basically a beginner when it comes to Vim, nonetheless I do know the basic things (open files, edit, move around, basic grep, .vimrc, etc)
I would submit this link first
http://weblog.jamisbuck.org/2008/11/17/vim-follow-up
If you scroll down to where it says "NERD___tree", it explains what it is and gives a link to the home page. I have already gotten NERD_tree installed, so far so good.
Only thing is, this guy (JamisBuck) adds a line to the .vimrc file to streamline it's usage (I'm guessing to toggle between NERD_tree and the actual file, because as far as I can tell, there is no quick way to do it other than typing in:
:NERDTree
Every time which is less than desirable. The follwing is the code he adds to the .vimrc file:
map <leader>d :execute 'NERDTreeToggle ' . getcwd()<CR>
He doesn't explain exactly what is is and/or how to use it, so If someone could give me a short explanation and/or point me towards a resource to learn more about this, that would be appreciated.
I'd say :help leader will give you what you need, is an anti-slash by default.
Thus, map <leader>d will be launched when you do \d.
According to the vim documentation, the
<Leader>
Is a special variable that is replaced with the value of "mapleader" at the time the mapping is defined. So:
map <leader>d :execute 'NERDTreeToggle ' . getcwd()<CR>
Is mapping the mapleader and "d" to the toggle. If you look at the page you linked, earlier in the page he says:
I’ve got my <Leader> character (:h mapleader) mapped to the comma
(since it’s easier to reach than the backspace character).
let mapleader = ","
So the toggle should be ",d" as far as I can tell.
In addition to what others have said (d mapped to the command), the command, itself:
:execute 'NERDTreeToggle ' . getcwd()<CR>
Is simply executing the NERDTreeToggle command with the first argument as the current working directory. The at the end is a carriage return, and is just simulating a press of the enter key.
This means that when NERD tree opens, it will be in the current working directory.