4

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 --- >
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.

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.

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

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.