Passing a parameter to a vim function - vim

I'm certain that there's going to be a simple answer to this, but I haven't yet hit on the correct part of tutorials and howtos.
I have a function in my .vimrc to help with generating HTML. It's a simple function to wrap selected text in a tag with a given name. Currently, the function signature looks like this:
function! WrapInTag( tag )
And I have a map set up like this:
vmap <Leader>tag <Esc>:call WrapInTag( tagname )<CR>
That tagname is the issue. How do I configure this so that I can select a block of text, type \tag b<CR> and have the highlighted text surrounded by b tags? Links to incredibly obvious tutorials that I haven't found yet will be much appreciated.
Edit After the fact, I feel it's worth pointing out that it was the user interaction to retrieve the tag name that was stumping me, not selecting the text.

This has less to do with passing arguments to functions (you've got that in your example already), but rather how to interact with the user, i.e. how to get the tag name and the selected text.
For the first, Vimscript offers two functions, getchar() for single characters and input() for text acknowledged with Enter. Something like this should work:
vnoremap <Leader>tag <Esc>:call WrapInTag( nr2char(getchar()) )<CR>
(Note: You should use :noremap; it makes the mapping immune to remapping and recursion.)
The text selection is stored in the registers '< and '>. You can use the `` movement command (or cursor()) to go there, or reselect the selection and replace it, e.g. :normal! gvcNEW-TEXT.
I hope this gets you started. Don't forget to consult with the excellent help and find similar plugins on vim.org to see how they've implemented things.

Delete your function and install surround.

Related

Vim function to find pattern, replace, and visual mode

So I use Vim to write reports at work, reports are basically a bunch of "common issues" that we write over and over, so they are templated. These templates have placeholder blocks {==BLOCK==} to ensure people modify things as/when needed, so this is an example:
The test revealed that it was possible to access {==sensitive data==},
as shown in the examples below...
That block may need to be modified, or not. So the idea is, I am editing the common issue, and I see there are 3 or 4 blocks like the one in the example, I'd like to press let's say [leader]b and then end up having the template text for the first block selected in visual mode without the {== and ==} that are around it.
I have tried a few things but I didn't get too far, any suggestions?
Thanks!
You could define the following function:
function! VisualSelect()
call search("==}")
norm hvT=
endfunction
nnoremap <leader>b :call VisualSelect()<cr>
vnoremap <leader>b Ol<esc>:call VisualSelect()<cr>
This will visually select the contents between {== and ==}. Typing <leader>b repeatedly will select the next occurrence.
Most template/snippet expand plugins support this.
With my lh-brackets plugin, you can execute
:SetMarkers {== ==}
and then jump from one placeholder to the next with CTRL+J with vim, or META-DEL with gvim. lh-brackets doesn't take care of loading/expanding templates. mu-template will add this layer.
If instead you choose to use one of the more popular snippet plugin, there will certainly be an option to change the syntax of the placeholders, but I don't know it.
The poor man's solution would look like:
nnoremap <c-j> <c-\><c-n>/{==.*==}<cr>v/==}/e<cr><c-g>
snoremap <c-j> <c-\><c-n>/{==.*==}<cr>v/==}/e<cr><c-g>
but it won't take care of restoring the search pattern, of the cases where the cursor is already within a placeholder, and so on...
EDIT: the version that automatically deletes the placeholder marks is
nnoremap <c-j> <c-\><c-n>/{==.*==}<cr>v/==}/e<cr>s<c-r>=matchstr(#", '{==\zs.*\ze==}')<cr><esc>gv6h<c-g>
the same in snoremap
In short:
nnoremap <leader>b /{==.*==}<cr>xxxvt=<esc>/==}<cr>xxxgv
What it does:
1.) find the pattern
/{==.*==}<cr>
2.) Remove the first "{=="
xxx
3.) Visual select your text until the first = (maybe this could be also optimized for using a regex instead of simple searching for the next =)
vt=
4.) Go to the end sequence
/==}<cr>
5.) Remove it
xxx
6.) Select again your last selection
gv
I have figured out a way based on what #snap said, I ended up adding the code to a Python plugin to run it through it, as that fits better with what I am trying to do, snippet below:
#neovim.command('VimisEditTemplateBlock')
def urlify(self):
"""Search next codify block and prepare for editing"""
[...]
self.nvim.command('call search("{==")') # Find beginning of codify block
self.nvim.command('norm xxx') # Delete {==
self.nvim.command('norm vf=') # Select the inner text
self.nvim.command('norm v')
self.nvim.command('norm xxxgvh') #Delete ==} and leave the inner text selected in Visual Mode

Show comments for specific mappings in .vimrc

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.

How to refer to key combinations in vim keybinding that works on the query line

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.

VIM latex-suite inserts macro code instead of executing macros

I have a problem that's been bugging me for quite a while and that I can't find the solution to.
I want to use the feature where I can press <C-j> and the cursor moves to the next placeholder.
This works for regular files, but when I edit .tex files (i.e. latex-suite is enabled), this inserts:
\right=IMAP_Jumpfunc('', 0)
instead of actually jumping (which I presume is done by the above mapping somehow).
There's no problem with regular mappings (that I've made myself like so: map rhs lhs), but it doesn't work for any latex-suite macros. Other example: if I insert figure (via menu), it just inserts the following inside the text:
\right=Tex_DoEnvironment(``figure'')
Sorry I can't solve this problem myself, which is probably trivial for an experienced user. But I have no-one around to ask.
Looks like you forgot the <c-r>= before the call to the function.
EDIT: I think I understand. Whem IMAPS is installed, it quickly parasites all our mappings. You will have to use IMAP() to define you own mappings. I had to do it in my bracketing-system in order to be robust to IMAP/LaTeX-suite presence.
Gah, I found the error!
I had defined a key mapping like so:
:imap <C-r> \right
(for adding to brackets in latex). This was then called by the pre-defined mappings ...
What a quagmire
Lesson taken: always comment-out entire or parts of the settings files, and then see if things start working.

How to jump to the next tag in vim help file

I want to learn the vim documentation given in the standard help file. But I am stuck on a navigating issue - I just cannot go to the next tag without having to position the cursor manually. I think you would agree that it is more productive to:
go to the next tag with some
keystroke
press Ctrl-] to read corresponding
topic
press Ctrl-o to return
continue reading initial text
PS. while I was writing this question, I tried some ideas on how to resolve this. I found that searching pipe character with /| is pretty close to what I want. But the tag is surrounded with two pipe '|' characters, so it's still not really optimized to use.
Use the :tn and :tp sequences to navigate between tags.
If you want to look for the next tag on the same help page, try this search:
/|.\{-}|
This means to search for:
The character |
Any characters up to the next |, matching as few as possible (that's what \{-} does).
Another character |
This identifies the tags in the VIM help file.
If you want to browse tags occasionally only, without mapping the search string to keyboard,
/|.*|
also does the trick, which is slightly easier to type in than the suggested
/|.\{-}|
For the case, that the "|" signs for the links in the help file are not visible, you can enable them with
:set conceallevel=0
To establish this setting permanently, please refer to Defining the settings for the vim help file
Well, I don't really see the point. When I want to read everything, I simply use <pagedown> (or <c-f> with some terminals)
" .vim/ftplugin/help/navigate.vim
nnoremap <buffer> <tab> /\*\S\+\*/<cr>zt
?
Or do you mean:
nnoremap <buffer> <tab> /\|\zs\S\{-}\|/<cr><c-]>
?
You could simply remap something like:
nmap ^\ /<Bar><Bslash>zs<Bslash>k<Bslash>+<Bar><CR>
where ^\ is entered as (on my keyboard) Ctrl-V Ctrl-#: choose whatever shortcut you want.
This does a single key search for a | followed by one or more keyword characters and then a |. It puts the cursor on the first keyword character. The and bits are there due to the way map works, see
:help :map-special-chars
As an aside, I imagine that ctrl-t would make more sense than ctrl-o as it's a more direct opposite of ctrl-], but it's up to you. Having said that, ctrl-o will allow you to go back to before the search as well.

Resources