Insert comments automatically in Vim - 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

Related

Is there a way to disable automatic insertion of * characters in VIM multiline comments?

I come from Emacs and I am not used to (and don't like) seeing tons of * characters in my multiline comments, so how do I tell VIM to disable auto-insertion of them?
I want comments to be from this
/*
*
*
*/
to this
/*
*/
Thanks in advance =D
This is described under :help format-comments. The * is a comment leader (as defined by the 'comments' option) and may be inserted based on the 'formatoptions' option, whose values are documented under :help fo-table. The following letters control comment leader insertion:
c Auto-wrap comments using textwidth, inserting the current comment leader automatically.
r Automatically insert the current comment leader after hitting in Insert mode.
o Automatically insert the current comment leader after hitting 'o' or 'O' in Normal mode.
So, to turn this off, use
:set fo-=c fo-=r fo-=o
(or short :set fo-=cro if they appear in that order).
As this option often is set by a filetype plugin (check via :verbose set fo?), you may need to override this (using :setlocal) in a file ~/.vim/after/ftplugin/{filetype}.vim to get rid of permanently.

How to autoindent closing brace in vim

I want to type
tag {
}
When I hit 'enter' after {, my cursor is 2 spaces indented (in column 3). (Tab is 2 spaces for me.) Then, when I type } (still in column 3), I want } to shift to column 1.
When I do this in a .cpp file, the cursor moves automatically to column 1.
When I do this in another file (.wiki in my case), it does not move. The } appears in column 3.
I thought this was controlled by 'autoindent' and 'smartindent', both of which are set in case of wiki file. What am I missing?
What other configuration information can I provide to help debug? How can I compare the configuration options between cpp file and wiki file?
(Edit for clarity: I am using the '.wiki' filetype defined in vimwiki plugin.)
The problem comes from the way the plugin handles lists' editing. Which is surprising, because the tag { } construct probably shouldn't be treated as one. To insert a new list marker, the plugin redefines a few mappings, they are mentioned in :help vimwiki-lists. Namely, o and O in normal mode, and <CR> in insert mode. Things they are mapped to have more-or-less the same behaviour when it comes to interaction with smartindent: they disable deindenting by inserting and deleting a dummy character on the new line (see, for example, here). This works because deindentation, as per :help smartindent, happens only if the closing brace is the first thing you type on the line.
This can be disabled by removing relevant mappings, but doing so will also break the lists system of the plugin. To fix that, you can duplicate those mappings using some other keys.
This might be worth discussing with the plugin's author, I don't think treating everything as a part of a list for indentation purposes is really what they indended.

vim: end comments and retain indentation

I'd like to be able to end a run of comments but retain the current indentation. Is this possible either through an existing command or with a function?
I have formatoptions -=o and autoindent so I normally get by using o from normal mode - the cursor is on the next line, the indentation is correct and I'm in insert mode. I'm only worrying about single line comments (eg '#'s - as for shell, python etc).
I'm interested in how I can make this more general (particularly not dependent on my formatoptions). I'd like to have an imap for ;; but I can't seem to find a straight forward way if I want to call a function (for example, to check whether I'm currently on a comment line).
I've played around with <expr> mappings and the expression register but either I lose the indentation (cursor ends up in the first column) or the comment continues. It seems like there might be a better alternative to either reimplementing the autoindent logic or trying to delete the extra comment characters. I've also tried saving/restoring formatoptions while using normal o but leaving insert mode when there's no other content on the line deletes the indentation.
I appreciate suggestions about how I should approach this.

Commenting out XML in 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

How do I fix the indentation of an entire file in Vi?

In Vim, what is the command to correct the indentation of all the lines?
Often times I'll copy and paste code into a remote terminal and have the whole thing messed up. I want to fix this in one fell swoop.
=, the indent command can take motions. So, gg to get the start of the file, = to indent, G to the end of the file, gg=G.
Before pasting into the terminal, try :set paste and then :set nopaste after you're done. This will turn off the auto-indent, line-wrap and other features that are messing up your paste.
edit: Also, I should point out that a much better result than = indenting can usually be obtained by using an external program. For example, I run :%!perltidy all the time. astyle, cindent, etc. can also be used. And, of course, you can map those to a key stroke, and map different ones to the same keystroke depending on file type.
The master of all commands is
gg=G
This indents the entire file!
And below are some of the simple and elegant commands used to indent lines quickly in Vim or gVim.
To indent the all the lines below the current line
=G
To indent the current line
==
To indent n lines below the current line
n==
For example, to indent 4 lines below the current line
4==
To indent a block of code, go to one of the braces and use command
=%
If you want to reindent the block you're in without having to type any chords, you can do:
[[=]]
You can use tidy application/utility to indent HTML & XML files and it works pretty well in indenting those files.
Prettify an XML file
:!tidy -mi -xml %
Prettify an HTML file
:!tidy -mi -html %
press escape and then type below combinations fast:
gg=G
1G=G. That should indent all the lines in the file. 1G takes you the first line, = will start the auto-indent and the final G will take you the last line in the file.
if you do not want to use :set paste, middle-click, set nopaste, you can also paste the content of the clipboard:
"*p
"+p
That way you don't have to leave normal mode.
if you have to paste + or * depends on how you selected the text, see :help quoteplus.
In Vim, use :insert. This will keep all your formatting and not do autoindenting. For more information help :insert.
:set paste is your friend I use putty and end up copying code between windows. Before I was turned on to :set paste (and :set nopaste) copy/paste gave me fits for that very reason.
For complex C++ files vim does not always get the formatting right when using vim's = filter command. So for a such situations it is better to use an external C++ formatter like astyle (or uncrustify) e.g.:
:%!astyle
Vim's '=' function uses its internal formatter by default (which doesn't always gets things right) but one can also set it use an external formatter, like astyle, by setting it up appropriately as discussed in this question.
vim-autoformat formats your source files using external programs specific for your language, e.g. the "rbeautify" gem for Ruby files, "js-beautify" npm package for JavaScript.
For XML files, I use this command
:1,$!xmllint --format --recover - 2>/dev/null
You need to have xmllint installed (package libxml2-utils)
(Source : http://ku1ik.com/2011/09/08/formatting-xml-in-vim-with-indent-command.html )
You can create a mapping to do this for you.
This one will auto indent the whole file and still keep your cursor in the position you are:
nmap <leader>ai mzgg=G`z
Just go to visual mode in vim , and select from up to down lines after selecting just press = , All the selected line will be indented.
For vi Editor, use :insert. This will keep all your formatting and not insert auto-indenting.Once done press escape to view the actual formatted file otherwise you'l see some garbage characters. like ^I
e.g:
public static void main(String[] args) {
^I
^I System.out.println("Some Garbage printed upon using :insert");
}

Resources