8

Here is my use case:

I have lots of code which because of style enforcement we write newlines after and before each open and close brace (respectively).

Example:

function func(args) {

    statement 1;
    statement 2;

    if (condition) {

        statement 3; 

    }

}

While this is nice and easy to read, I do consider this to be a expletive-worthy waste of space, but my teammates do not agree with me. Basically this is how we're checking in our code and that's that.

I was thinking that maybe I can use Vim features to help me save screen real-estate, while still allowing me to write the code in the verbose way. I don't mind typing it out, I just want more efficient use of space. I figured maybe I can have Vim auto-collapse the gratuitous empty lines.

I am finding it somewhat challenging to set this up using syntax rules because whatever I write seems to conflict with existing syntax rules, but what I decided to do as a first attempt was to write these rules which will not collide:

syntax match aaaaaaaaa "\vabcd" conceal cchar=A
syntax match bbbbbbbbb "\vef\ngh" conceal cchar=B

The second rule here is close to what I want, which for the open bracket case is something like /\v\{(\n\s*){2,}: match an open-bracket with any number greater than or equal to 2 of a newline followed by only whitespace.

What happens inside of vim however is the following:

  1. If I type abcd in a line, it gets concealed to A as expected.

  2. If I type ef on one line and gh on the next, BOTH lines become concealed with B.

I was really really hoping the two lines ef\ngh would have been concealed into a single line so that I can save some vertical buffer space this way.

But I see now that it's probably a Vim implementation detail problem. Collapsing lines is a problem for code folding to solve, probably just out of scope as far as conceal is concerned.

So I wonder if there is still some way to do what I want to do. Maybe using fold markers somehow? The problem is that I need to fold only the empty whitespace.

  • 3
    As I recall you can't do that, and even if you could, you'd be asking for a lot of trouble by doing it. How about using a pretty printer to switch between your style and the "official" one. If you're using git you might even be able to use hooks to make the changes apply transparently. – Sato Katsura Oct 19 '15 at 6:01
  • 2
    Not really possible. You could abuse folding for that, but you lose syntax highlighting in that case. – Christian Brabandt Oct 19 '15 at 14:22
  • 1
    You don't need markers for folding. :h fold-expr and :h 'fdm' – Christian Brabandt Oct 19 '15 at 17:08
  • 1
    @ChristianBrabandt It sounds like there is enough power available here to let me write something to automatically fold these (mostly single empty or whitespace-only) lines around the braces. But I'll have to sit down and really ponder it, seems like. – Steven Lu Oct 23 '15 at 6:34
  • 2
    Maybe you can report it in the neovim issue tracker, so a feature might show up there that you can use to implement this. – Farid Nouri Neshat Dec 9 '15 at 14:28
2
+50

It is possible to abuse folds to hide extra empty lines. Here is how one could do it:

function! SkipNewlineFoldExpr()
    let l:curline = getline(v:lnum)
    " fold begins at {$ or one line before }$
    if l:curline[-1:] == '{' || getline(v:lnum + 1)[-1:] == '}'
        return '>1'
    endif
    " fold ends one line after {$ or at }$
    if getline(v:lnum - 1)[-1:] == '{' || l:curline[-1:] == '}'
        return '<1'
    endif
    return 0
endfunction

function! SkipNewlineFoldText()
    " fold text matches non-empty line
    return getline(getline(v:foldstart)[-1:] == '{' ? v:foldstart : v:foldend)
endfunction

" customize how fold is defined
set foldexpr=SkipNewlineFoldExpr()
" customize how fold looks like
set foldtext=SkipNewlineFoldText()
" use 'foldexpr'
set foldmethod=expr

" Optional:
" drop highlighting of folds
" highlight clear Folded
" automatically close folds
" set foldclose=all
" automatically open folds on any actions on folded lines
" set foldopen=all

It would look something like this:

Folded empty lines

As you can see there is no syntax highlighting on folded lines, still might be something more bearable than lots of unnecessary empty lines. You can also switch folds on and off with zi shortcut in case they are getting in your way.

Folds aren't a small topic and Vim has a separate help file on them. Related options are linked there too.

Detailed behaviour of cursor and search can be controlled via 'foldopen', which combined with 'foldclose' defines when folds will be automatically opened and closed for you.

  • Thanks for your answer. It's a very interesting technique, because as it turns out it's possible to start two folds at the same line. I will award you the bounty if no better solution turns up! I may be able to implement what I want using this (vi.stackexchange.com/questions/5175/…). – Alex Oct 11 '17 at 13:09
1

First off, that's a shitty style enforcement and you have my sympathies. Instead of hiding how about creating a mapping or functions (like shown below) for deleting the unnecessary lines before editing and adding them when you're done ? something along the lines:

function! Clean()
    %s/{\n^$/{/
    %s/^$\n\(\s*}\)/\1/
endfunction

function! Pollute()
    %s/{$/{\r/
    %s/\(\s*}\)/\r\1/
endfunction

The basic idea begin, delete the empty lines at read and replace them at write, didn't try it but I feel like this can be added as an autocmd like so:

au BufReadPost *.cpp call Clean()
au BufWritePost *.cpp call Pollute()
  • Your answer does not answer the question so I cannot award you the bounty. In my case, I am interested in hiding metadata about a header in an outline. – Alex Oct 11 '17 at 13:03
  • @Alex That's ok. I didn't answer for the bounty. The question just caught my eye when I came to the vim stackexchange to ask a question myself. I thought I'd offer an alternate option as a way to solve the original question. – lonetwin Oct 11 '17 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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