0

I do a lot of plain text file editing, and many times I need to mark a section of text as 'DO NOT FORMAT' as it is pre-formatted, or even contains ascii art.

Many years ago I did this by marking the block as a comment, and telling vim NOT to format such blocks.

Example text...

Looking across the road, I could see a large
rectangular building with various shops underneath.
Across the top half of the building was a sign.

|
|                        The Doctor's Folly
|              Discreet and confidential medical clinic
|                     First time checkups, FREE
|

I want the uncommented text to be re-formatted using 'gq' (EG: during a whole file re-format 'gggqG' ) but have it completely ignore the marked section of text as it is already pre-formatted.

Current settings

:setl textwidth=79
:setl comments=b:\|
:setl formatoptions=tcorjq1l

I had it working YEARS ago, but vim has changed, and started to format the commented text sections.

I'm thinking I may need a special purpose 'formatexpr' to get it to ignore the specially marked text.

OR use a special macro to itterate over paragraphs, but only reformat the ones that are not marked with '|' as the first characte.

Either of these solutions would let me still reformat 'comment' bullet lists.

1
  • In response to a answer that was later changed.... I have tried removing the 'c' from the 'fo' options, but when I re-format the whole file the commented paragraph is also re-formatted, and left aligned with the indent of the first line. I would not be asking if it was THAT simple! Similarly removing 'q' makes the commented block reformatted as if '|' was just a normal word, resulting in a very BIG mess.
    – anthony
    Sep 25, 2019 at 22:23

2 Answers 2

0

Unfortunately, I can't find anything to force Vim to exclude some text region from the manual formatting. But at least the following script should do this:

" format a line range except the lines starting with a 'comment' string
function! MyFormat(comment) range
    " go to the firstline; then mark the lastline
    execute a:firstline ';' a:lastline "k'"
    " actually it's do / while
    let l:start = 1
    while l:start
        " the last line number could change, so we use a bookmark
        let l:end = line("''")
        " go to the first line which is NOT a comment
        let l:start = search('\V\^\(' . a:comment . '\)\@!', 'c', l:end)
        if l:start
            " ...until the next comment
            let l:count = search('\V\^' . a:comment, 'n', l:end) - l:start
            " no comment found -- format the rest and exit the loop
            if l:count < 1
                let l:count = l:end - l:start + 1
                let l:start = 0
            endif
            " do formatting and go to the next line
            execute 'normal!' l:count . 'gqq+'
        endif
    endwhile
endfunction

" map Q to our function
noremap <silent>Q :%call MyFormat("\<bar>")<CR>
ounmap Q

" Now in Normal mode Q formats the whole buffer;
" [count]Q formats [count] lines starting from the current one;
" In Visual mode Q formats the selection.
0
0

Found it...

In a moment of serendipity, I discovered that a comment block in a different file was not reformatted! The only difference was this file used a different set of 'ftplugin' and 'syntax' configuration.

After a LONG bit of detective work I finally traced the solution to changing my comment settings from...

:setl comments=b:\|

to...

:setl comments=fn:\|

When I did this the 'gq' text re-formating (or text re-flow) did not change the lines. that is because it will then see each and every line in the comment as a seperate paragraph (like a bullet list), so does nto re-indent, or merge short lines.

HOWEVER: This is only a partial solution, as 'gq' still looks at that text!

This means 'gq' will still break up long lines, without adding comment leaders. And when editing it will not insert a comment leader on carriage returns or open new line, which was why I was using 'b:\|' in the first place.

But works for me as all the lines are less that the default 'textwidth' setting.

@Matt Thank you very much for you code. I will be trying it out as it would be even better if 'gq' did not even try to do anything, even for long lines.

If someone has a better solution, maybe using 'formatexpr' to modify actual 'gq' behavior, that would be appreciated.

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.