Bagaimana cara melipat komentar?

16

Sintaksnya foldmethodbagus, tapi kadang-kadang saya hanya ingin melipat komentar di file sumber.

Juga sintaks lipat komentar hanya berfungsi untuk komentar C-Style seperti:

/*
 ...
 */

Tetapi tidak untuk komentar boilerplate seperti:

//
//
// ...
//

Atau bahkan untuk blok komentar dalam bahasa non-C seperti:

#
#
# ...
#

Bagaimana saya bisa mengkonfigurasi ini dengan vim?

maxschlepzig
sumber
Apakah Anda ingin menggunakan lipat sintaks dan lipat komentar? Atau hanya lipat komentar?
Martin Tournoij
@Carpetsmoker, lipat sintaks + lipat komentar akan baik-baik saja jika orang bisa mengatakan 'buka semua lipatan, kecuali untuk komentar'. Kalau tidak, komentar lipat tanpa sintaks akan baik-baik saja.
maxschlepzig

Jawaban:

14

Melipat komentar saja cukup mudah dengan menggunakan foldmethod=expr:

set foldmethod=expr foldexpr=getline(v:lnum)=~'^\s*'.&commentstring[0]

Ini hanya akan memeriksa apakah baris dimulai dengan jumlah spasi + karakter komentar. Perhatikan bahwa ini cukup naif, dan mungkin tidak berfungsi untuk semua bahasa. Jadi, Anda mungkin ingin menggunakan autocmd untuk lebih spesifik:

autocmd FileType c setlocal foldmethod=expr foldexpr=getline(v:lnum)=~'^\s*//'
autocmd FileType python setlocal foldmethod=expr foldexpr=getline(v:lnum)=~'^\s*#'

Untuk informasi lebih lanjut tentang lipatan, lihat:


Menggunakan sintaks lipat dan lipat komentar lebih terlibat; ini membutuhkan modifing file sintaks /usr/share/vim/vim74/syntax/*.vim, dan akan spesifik untuk bahasa yang Anda gunakan.

Perhatikan bahwa beberapa tipe file sudah melakukan ini! Misalnya dari ruby.vim:

if !exists("ruby_no_comment_fold")
  syn region rubyMultilineComment start="\%(\%(^\s*#.*\n\)\@<!\%(^\s*#.*\n\)\)\%(\(^\s*#.*\n\)\{1,}\)\@=" end="\%(^\s*#.*\n\)\@<=\%(^\s*#.*\n\)\%(^\s*#\)\@!" contains=rubyC
  syn region rubyDocumentation    start="^=begin\ze\%(\s.*\)\=$" end="^=end\%(\s.*\)\=$" contains=rubySpaceError,rubyTodo,@Spell fold
else
  syn region rubyDocumentation    start="^=begin\s*$" end="^=end\s*$" contains=rubySpaceError,rubyTodo,@Spell
endif
Martin Tournoij
sumber
2

Saya suka melipat dengan lekukan tetapi termasuk komentar di flip (maksud saya setiap komentar mendapatkan tingkat lipatan yang sama dengan baris sebelumnya).

Sayangnya, kata kunci foldignore hanya berfungsi untuk satu baris komentar. Jadi saya lipat dengan expr di vimrc:

set foldmethod=expr
set foldexpr=FoldMethod(v:lnum)

function! FoldMethod(lnum)
  "get string of current line
  let crLine=getline(a:lnum)

  " check if empty line 
  if empty(crLine) "Empty line or end comment 
    return -1 " so same indent level as line before 
  endif 

  " check if comment 
  let a:data=join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )
  if a:data =~ ".*omment.*"
    return '='
  endif

  "Otherwise return foldlevel equal to indent /shiftwidth (like if
  "foldmethod=indent)
  else  "return indent base fold
    return indent(a:lnum)/&shiftwidth
endfunction

Blok terakhir:

indent(a:lnum)/&shiftwidth

Mengembalikan basis lipatan pada indent.

Dan yang lainnya:

join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )

Cek apakah karakter pertama dari baris dianggap sebagai komentar dengan sintaks. Jadi ini adalah cara yang baik untuk menggabungkan lipat indent dan sintaks dengan ekspresi, lipatan paling canggih.

Perhatikan bahwa Anda juga dapat "mengatur teks lipat" tergantung pada bagaimana Anda ingin hasilnya terlihat.

tinmarino
sumber
0

Anda dapat secara visual memilih blok yang dikomentari dengan vacdan kemudian membuat lipatan manual zf.

Objek teks komentar dapat berupa ekstensi bahasa untuk menetapkan objek teks vim standar. Mengujinya dengan sintaks Go.

AB
sumber
1
Memang, acbukan builtin. Tetapi dengan komentar tope gcadalah objek teks. Jadi solusi yang lebih baik adalah zfac,, zfgcatau zfippaling buruk
D. Ben Knoble