2

I'm trying to remove the verilog block comment start: /*

I'm trying to do this inside a function:

call setline(line('.'), substitute(getline('.'), '/*','','')) 

Of some reason, it doesn't to anything. I tried to use \V, I tried escaping. It seems that no matter what I do, it never removes the comment.

The comment end syntax is removed with no problems:

call setline(line('.'), substitute(getline('.'), "*/", '', ''))

Any advice?


Update: The function I'm trying to build is:

func! s:comment_line(set,vmode)
    let lnum = line('.')
    let line = getline('.')
    call setline(line('.'), substitute(getline('.'), '/\*', '', ''))
    call setline(lnum, substitute(line, "*/", '', ''))
    norm! j
endfunc

I'm using this mapping:

nnoremap <silent> +  : call <SID>comment_line(0,0)<Cr>
vnoremap <silent> +  : call <SID>comment_line(0,1)<Cr>

When I pick a few lines with visual/visual line/visual block, I get a */ deleted but never a /*

(I removed other parts of the function for clarity)


Clarification: The reason I avoided using s:/\*:: is the errors.

The answer below suggests adding the e switch: s:/\*::e

Also, the suggestion to use

exe a:firstline.",".a:lastline."s:\*/::e"

(which executes the substitution on all the selected range), is redundant here because the function is called for each line separately (A function is called for every line in a selected visual/visual line). So in this case one must use either

exe "s:\*/::e"

or

if line('.')==a:firstline
   exe a:firstline.",".a:lastline."s:\*/::e"
endif " do only once
5
  • Use normal substitution, s:/\*::. This also works in a function
    – 3N4N
    Apr 22, 2019 at 8:25
  • @G Are you sure \V doesn't work? don't add extra escape if you are using \V
    – dedowsdi
    Apr 22, 2019 at 8:35
  • @klaus When I'm using the following: execute "normal! s:/*::" then it doesn't do anything. When I use: execute "normal! s:/*::\n" or execute "normal! s:/*::\^M" It does something completely different, it copies the above row 4 times and deletes the first character for each row(?) I've never seen such a behaviour before
    – G Eitan
    Apr 22, 2019 at 8:40
  • @dedowsdi I see now that it works if I'm trying to run from the command with :call setline(line('.'), substitute(getline('.'), '\V/*', '', '')) . Of some reason it doesn't work from my function. I'll update my question to be more accurate
    – G Eitan
    Apr 22, 2019 at 8:43
  • @GEitan, you don't need to use execute() you just put the line s:/\*:: there all by itself. Check the answer I provided.
    – 3N4N
    Apr 22, 2019 at 9:06

2 Answers 2

2
  • You can use normal :h :substitute ex-command:

    s:/\*::
    
  • You can use setline in the following manner:

    call setline(line('.'), substitute(getline('.'), "/\\*", '', ''))
    
  • Or you can use :h substitute() in the following manner:

    call setline(line('.'), substitute(getline('.'), '/\*', '', ''))
    

    I suggest you use the ex-command, it also works in a function.

  • I used : as delimiter because the pattern had / in it. If I used / as delimiter, I would need to escape the / in the pattern like I did the *.

  • I needed to escape the * twice because I used double-quotes to represent pattern string. Read :h literal-string for more details.

UPDATE

You just need this function:

func! s:comment_line(vmode) range abort
    if (a:vmode == 0)
        s:/\*::e
        s:\*/::e
    else
        exe a:firstline.",".a:lastline."s:/\\*::e"
        exe a:firstline.",".a:lastline."s:\*/::e"
    endif
endfunc
nnoremap <leader>tt :call <SID>comment_line(0)<CR>
xnoremap <leader>tt :call <SID>comment_line(1)<CR>
8
  • Thanks, I want to ask you to explain two or three things: 1. Is exe a:firstline...lastline the vimscript way of doing :<,>s? 2. how do I get arround the substitute errors that jump on all the lines that don't have the pattern? 3. what does the "abort" mean? I added it and didn't notice a difference
    – G Eitan
    Apr 22, 2019 at 11:45
  • 1. yes ; 2. I don't understand the question, maybe you can open another question in Vi SE? 3. abort lets the function abort if it faces an error, see :h :func-abort
    – 3N4N
    Apr 22, 2019 at 11:47
  • I'll try to explain as it is important to me: When I select 4 lines, 2 lines containing /* and the other two containing */, the echoed output is: 2 substitutions on 2 lines 2 substitutions on 2 lines Error detected while processing function <SNR>12_comment_line: line 64: E486: Pattern not found: /\* E486: Pattern not found: /\* E486: Pattern not found: /\* E486: Pattern not found: /\* Press ENTER or type command to continue I was using setline in the first place only because I wished to avoid these "pattern not found" errors
    – G Eitan
    Apr 22, 2019 at 11:55
  • Using abort in your function should ignore the error outputs. Cause that's what it's used for.
    – 3N4N
    Apr 22, 2019 at 11:58
  • 2
    Using :s to do the substitution will have side-effects, like changing the pattern/search register, "/. May want to use :keeppatterns or use the setline() method to avoid this issue all together Apr 22, 2019 at 16:10
1

As @klaus stated, you need to escape * and make things easier by using string-literals (aka single quotes).

I am going to take a different tact and suggest an alternative. Commenting is a common task and a bit tricker then it seems. I suggest you stand on the shoulders of giants and use a commenting plugin. I personally use commentary.vim.

In case this is an exercise then I would suggest you take a look at commentary.vim as a small example plugin or maybe this gist.

Some thoughts:

  • Try to use 'commentstring' so it works across multiple filetypes
  • Avoid side-effects like mutating registers
  • Maybe create an operator so you can combine with other motions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.