Standing on the shoulders of giants
I would highly recommend commenting plugin like commentary (which I use), Nerd Commenter, EnhCommentify, tComment, ..., etc. There is no shame in using a plugin. Especially since comment toggling is deceptively more complicated than expected.
Customizing Commentary.vim
Simply set 'commentstring'
to your comment style for your filetype. Most often this is already setup for you if Vim recognizes your filetype. See :h 'commentstring'
.
Example of changing 'commentstring'
for php. Add the following to ~/.vim/ftplugin/asm.vim
:
if expand('%:t') =~# '.s$'
set commentstring=-- %s
endif
Or if you rather everything in your vimrc
file:
autocmd FileType asm if expand('%:t') =~# '.s$' | set commentstring=-- %s | endif
You can set the toggle comment command to <f1>
like so:
nmap <f1> <Plug>CommentaryLine
However commentary are much closer the the home row and do not conflict with any native mappings.
Note: I use commentary this may not work for other comment plugins. As always, read the documentation.
Syntax
You may need to change you syntax file to show lines starting with --
as comments. Add the following to ~/.vim/after/syntax/asm.vim
:
syntax match asmComment /--\_s.*$/
But I don't or can't use a plugin
Sometimes using a plugin isn't an option, but you should know that (de-)commenting is a lot trickier than it first seems. Especially if you need to do it across multiple filetypes. Plugins like commentary.vim let you comment multiple lines at a time or use a motion, e.g. gcip
.
The simplest approach. Comment only:
autocmd FileType asm nnoremap <buffer> <F1> gI-- <ESC>j
Now for some toggling with an map-expression:
autocmd FileType asm nnoremap <buffer> <expr> <f1> getline('.') =~ '^s*--\_s' ? "^3"_x+" : "gI-- <esc>+"
I have also created a naive commentary.vim-style comment toggle mappings. Put the following in your vimrc
file:
nnoremap gcc :<c-u>.,.+<c-r>=v:count<cr>call <SID>toggleComment()<cr>
nnoremap gc :<c-u>set opfunc=<SID>commentOp<cr>g@
xnoremap gc :call <SID>toggleComment()<cr>
function! s:commentOp(...)
'[,']call s:toggleComment()
endfunction
function! s:toggleComment() range
let comment = substitute(get(b:, 'commentstring', &commentstring), 's*(%s)s*', '%s', '')
let pattern = 'V' . printf(escape(comment, ''), '(s{-})s(S.{-})s=')
let replace = '12'
if getline('.') !~ pattern
let indent = matchstr(getline('.'), '^s*')
let pattern = '^' . indent . 'zs(s*)(S.*)'
let replace = printf(comment, '1 2' . (comment =~ '%s$' ? '' : ' '))
endif
for lnum in range(a:firstline, a:lastline)
call setline(lnum, substitute(getline(lnum), pattern, replace, ''))
endfor
endfunction
More information
:h 'commentstring'
:h :set
:h filetype
:h new-filetype
:h ftdetect
:h ftplugins
:h after-directory
:h :syn-match
:h :autocmd
:h :map-expression
:h :map-local