5

Sometimes, when I edit a large file, I like to focus only on a part of the document and not all of it.

Is it possible to create a sort of fold that wrap a part of the document (e.g. the current function/paragraph) so the focus is narrowed on that ?

The idea would be to produce something like this:

+ --- the fold --- >

// Interesting stuff, i.e. a cat
// 
//   |\      _,,,---,,_
//  /,`.-'`'    -.  ;-;;,_
// |,4-  ) )-,_..;\ (  `'-'
// '---''(_/--' `-'\_)
//

+ --- the fold --- >
nobe4
  • 16,033
  • 4
  • 48
  • 81

3 Answers3

4

A very basic solution would be to use the following macro:

qqggzf'<'>zfGq

First visually select the text you want to focus on and use the macro with @q.

To detail:

  • qq start recording the macro
  • gg go to the top of the buffer
  • zf start a folding from your position (the first line)
  • '< fold to the beginning of your selection
  • '> go to the end of your selection
  • zf start a foding
  • G fold to the end of the file

This is pretty basic and could probably be improved but its a quick workaround.

statox
  • 49,782
  • 19
  • 148
  • 225
3

If you are ok with a plugin, I'd suggest NrrwRgn

Per its description:

This plugin is inspired by the Narrowing feature of Emacs and means to focus on a selected region while making the rest inaccessible. You simply select the region, call :NR and the selected part will open in a new split window while the rest of the buffer will be protected. Once you are finished, simply write the narrowed window (:w)and all the changes will be moved back to the original buffer.

jecxjo
  • 2,660
  • 13
  • 24
2

After trying to do so, I found a way to do it.

" Register a command, a visual and normal mapping
command! -nargs=* FAL :call FoldAroundLines('command',<f-args>)
vnoremap <silent> F :<C-U>call FoldAroundLines('visual')<CR>
nnoremap <silent> F :set opfunc=FoldAroundLines<CR>g@

function! FoldAroundLines(type,...)
  " Ensure we are in manual fold mode
  set foldmethod=manual
  " Save first and list line of the current buffer
  let l:first_line = 1
  let l:last_line = line("$")

  " Get the lines to fold around
  if a:type == 'command'
    let l:line_before = a:000[0]
    let l:line_after = a:000[1]
  elseif a:type == 'visual'
    let l:line_before = line("'<")
    let l:line_after = line("'>")
  elseif a:type =~ 'line\|char\|block'
    let l:line_before = line("'[")
    let l:line_after = line("']")
  endif

  " Add a 1 padding to be sure to display the limit lines
  if l:line_before - 1 > l:first_line
    let l:line_before -= 1
  endif

  if l:line_after + 1 < l:last_line
    let l:line_after += 1
  endif

  " Check selected lines are in the current buffer
  if (l:line_before < l:first_line || l:line_after > l:last_line)
    echom ("A selected line is not in the buffer")
    return
  endif

  " Remove every fold in the current buffer
  normal! zE

  " Fold first->before and after->last
  execute l:first_line.",".l:line_before."fold"
  execute l:line_after.",".l:last_line."fold"
endfunction
nobe4
  • 16,033
  • 4
  • 48
  • 81