Commenting out XML in vim - vim

I often find myself removing and adding XML sections in configuration files:
tomcat's server.xml
maven's settings.xml
and many others.
Is there a vim plugin/command to make this simple?

You can use a combination of matching XML tags, as can be seen in this question and Perl's search and replace.
For instance, given this snippet:
<TypeDef name="a">
<ArrayType high="14" low="0">
<UndefType type="node">
</UndefType>
</ArrayType>
</TypeDef>
Put the cursor on either the opening or closing TypeDef and type the following sequence:
vat:s/^\(.*\)$/<!--\1-->/
v - puts you into visual mode
at - selects the whole XML tag
:s/^\(.*\)$/<!--\1-->/ - surrounds each line with '<!--...-->', the comment delimiters for XML
Alternatively, you can just delete it like this:
dat
d - delete according to the following movements
at - as before

use surround.vim for general tag matching, deleting, inserting, surrounding etc,
For commenting tags, it is easy to use vim text objects & and a simple macro
Example:
enter
vmap ,c <esc>a--><esc>'<i<!--<esc>'>$
somewhere suitable, then place your cursor at the capital "A" of "ArrayType" on line two of the following (borrowed from Nathan Fellmans example above)
<TypeDef name="a">
<ArrayType high="14" low="0">
<UndefType type="node">
</UndefType>
</ArrayType>
</TypeDef>
then hit
vat,c
and you will get:
<TypeDef name="a">
<!--<ArrayType high="14" low="0">
<UndefType type="node">
</UndefType>
</ArrayType>-->
</TypeDef>
with your cursor at the end of the comment

I love the simplicity of https://github.com/tpope/vim-commentary. Easy to add other languages, though seems to support most out of the box. Under 100 lines of code.
gcc to comment the current line, or select the text you want to comment and hit gc. Super easy.

Vim doesn't have smart commenting for all file types by itself. You should get a script for your commenting needs.
I use the enhcomentify script which has been around and maintained for a long time
http://www.vim.org/scripts/script.php?script_id=23
It seems to do xml well and you get the advantage of the same key bindings for any filetype you are using.
There are others.. notably the NERD Commenter
http://www.vim.org/scripts/script_search_results.php?keywords=comment&script_type=&order_by=rating&direction=descending&search=search

I think that adapting this vim tip might be useful.
I propose adding:
" Wrap visual selection in an XML comment
vmap <Leader>c <Esc>:call CommentWrap()<CR>
function! CommentWrap()
normal `>
if &selection == 'exclusive'
exe "normal i-->"
else
exe "normal a-->"
endif
normal `<
exe "normal i<!--"
normal `<
endfunction
to your .vimrc
Then, with a visual selection active (V), hit \c (backslash then c) to wrap your block in <!-- --> XML-style comments.
Alternatively, as suggested on the wiki you can put the code in ~/.vim/scripts/wrapwithcomment.vim and add to your .vimrc:
au Filetype html,xml source ~/.vim/scripts/wrapwithcomment.vim
to only load that functionality when working on a html or xml file.

Best it'd be if you'd find a command that adds things in the beginning and end of the selection.
When I'm commenting python code, I'm doing this:
:2,4s/^/#/g

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

insert something in front of and in end of some word

I have many many source code files, and have to do many same work like this
find some phrase(totally random, have to be done by human eyes)
for example asdf in this line printf("asdf")
and fdsa asdf asdf in this line "* fdsa asdf asdf |"
insert ${' in front of the phrase, and '} in end of the phrase
so printf("asdf") becomes printf("${'asdf'}")
I'm currently using vim to do the edit, is there any plugin can let me, for example, move the cursor onto asdf and press ctrl+shift+i to automatically insert ${' and '} ?
Also I'm open to switch to any other editor which has such capability.
You don't need a plugin for that. A simple mapping would be enough:
xnoremap <key> c${'<C-r>"'}<Esc>
See :h key-notation for <key>.
The :substitute command would have been a great solution as well:
:%s/asdf/${&}/g
And if you want to confirm each replacement before doing it, add the c flag -> %s/asdf/${&}/gc
In addition to the great answers using built-in commands, there's one "famous" plugin for this purpose: the surround plugin. It comes with many mappings for common stuff, and also is customizable.
To define a ysv (you surround variable) mapping, just put the following into your ~/.vimrc:
let g:surround_118 = "${\r}"
(118 is the code point for v, see :help surround)

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.

How to comment out/in a paragraph of haml in vi?

I just started diving into vi and so far learned only basic moving around/editing commands. While I am going through the book, is there a fast way to comment out a paragraph with -# in the same column with the cursor position (indenting the lines accordingly)?
Let's say I have a piece of code:
%table
- unless paginate(#clients).nil?
%tr
%th
=t('index.name')
%th
=t('index.address')
%th
=t('index.phone')
=render :partial => 'client', :collection => #clients
and I want to comment out lines between - unless and =render :partial with -# in one column and then be able to comment them in again. What command would that be?
In blockwise select mode, you can press I to insert in front of the block and A to insert after the block.
Setting 'relativenumber' (:set rnu) could help to count lines.
Start with CTRL-V to switch to blockwise select mode, then 8j to go down eight lines, then I#Esc to insert the #.
To remove it: dCTRL-V8j will delete blockwise.
Warning, if you happen to use vanilla gvim.exe on Windows, you probably have mswin.vim activated which remaps CTRL-V, use then CTRL-Q instead (or disable this plugin)
If you're less interested about the how and just want it to work, there are a number of plugins that provide (un)commenting functionality for varieties of languages. Tim Pope's commentary.vim is the one I just started using recently, as a replacement for nerdcommenter.
I just installed it so I can't speak to any defects, but Tim Pope's stuff is (nearly?) always excellent. With the plugin you could comment a Haml paragraph by selecting a visual block and typing \\\. It also takes motions, e.g. \\ap.
The link:
https://github.com/tpope/vim-commentary
If you use it often, you can define a command in your .vimrc
command -range=% C :<line1>,<line2>s/^/-#/
Then in vi, you can apply :<range>C in the usual manner. You can do this with :10,20C or .,+10C. You can use the following command for uncommenting.
command -range=% D :<line1>,<line2>s/^-#//
Since I am using vi for with languages with different types of commenting, I also us these commands:
command -range=% -nargs=1 Ca :<line1>,<line2>s/^/<args>/
command -range=% -nargs=1 Da :<line1>,<line2>s/^<args>//
Allowing you to just do :10,20Ca-#, where you can replace -# with the commenting method of choice.

Insert comments automatically in Vim

My SAS code requires this style of comment:
/*
* This is the comment
*/
I've been able to type this command (From the Vim Comment Howto):
:set comments=sl:/*,mb:*,elx:*/
The problem is that once I type this set command I don't know how to actually get those comments to add to the code. The instructions say to type /\*<enter> but in insert mode this just acts normally, and in command mode this does a find on *.
How do I get this to work, and are there better ways than this to automatically insert comment marks?
By default, Vim doesn't automatically insert the newlines or end markers for you. Instead, it makes it easy to insert those as you type, as long as 'formatoptions' contains r:
:set formatoptions+=r
After this, start typing your comment as normal: "/*<Enter>" (in insert mode). After you hit the Enter key, the comment leader (an asterisk and a space) should appear automatically on the next line, ready for you to start typing. When your comment is complete, end it with "<Enter>/"; the <Enter> moves to the next line, and the slash becomes the second character of the end marker. Yes, it will remove the space for you, but only right after you hit enter.
To make editing this type of comment easier, you wish to add the c and/or o characters to formatoptions, as well. The former allows comments to auto-wrap, and the latter inserts the comment leader when you create a new line inside the comment using normal-mode commands.
Which language?
In C Vim autoloads this setting for comments:
" Set 'comments' to format dashed lists in comments.
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
Which works as you'd expect. Maybe you need to add that to the ftplugin for the language/extension you're using?
I have this abbreviation in my .vimrc:
" /// -> insert javadoc comment
iab <buffer> /// /**^M *^M*/^[0A
where ^[0A is ctrl-v + up.
Type /// in insert mode to get a comment like
/**
*
*/
Also remember to check your comments style (:set comments?) if you are using multiple file types. PHP, for example will sometimes use HTML style comments <!-- ... --> if there is embedded HTML, hence typing /* and then pressing Enter will appear to have no effect.
I have the following in my .vimrc file to make sure PHP comments are used by default
au Bufenter *.php set comments=sl:/*,mb:*,elx:*/
HTML code will still be properly commented, however, spaces within HTML code might use the PHP commenting convention (if you use plugins like tComment) and you won't have multi line HTML comments, which I don't think are possible anyways.
this Vim script might solve your problem - just put it into "vimXY/syntax" folder

Resources