|
1 | 1 | vim9script |
2 | 2 |
|
3 | 3 | # Maintainer: Maxim Kim <habamax@gmail.com> |
4 | | -# Last Update: 2024 Oct 05 |
| 4 | +# Last Update: 2025 Mar 21 |
5 | 5 | # |
6 | 6 | # Toggle comments |
7 | 7 | # Usage: |
@@ -76,3 +76,88 @@ export def Toggle(...args: list<string>): string |
76 | 76 | noautocmd keepjumps setline(lnum1, lines) |
77 | 77 | return '' |
78 | 78 | enddef |
| 79 | + |
| 80 | + |
| 81 | +# Comment text object |
| 82 | +# Usage: |
| 83 | +# import autoload 'dist/comment.vim' |
| 84 | +# onoremap <silent>ic <scriptcmd>comment.ObjComment(v:true)<CR> |
| 85 | +# onoremap <silent>ac <scriptcmd>comment.ObjComment(v:false)<CR> |
| 86 | +# xnoremap <silent>ic <esc><scriptcmd>comment.ObjComment(v:true)<CR> |
| 87 | +# xnoremap <silent>ac <esc><scriptcmd>comment.ObjComment(v:false)<CR> |
| 88 | +export def ObjComment(inner: bool) |
| 89 | + def IsComment(): bool |
| 90 | + var stx = map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')->join() |
| 91 | + return stx =~? 'Comment' |
| 92 | + enddef |
| 93 | + |
| 94 | + # requires syntax support |
| 95 | + if !exists("g:syntax_on") |
| 96 | + return |
| 97 | + endif |
| 98 | + |
| 99 | + var pos_init = getcurpos() |
| 100 | + |
| 101 | + # If not in comment, search next one, |
| 102 | + if !IsComment() |
| 103 | + if search('\v\k+', 'W', line(".") + 100, 100, () => !IsComment()) <= 0 |
| 104 | + return |
| 105 | + endif |
| 106 | + endif |
| 107 | + |
| 108 | + # Search for the beginning of the comment block |
| 109 | + if IsComment() |
| 110 | + if search('\v%(\S+)|$', 'bW', 0, 200, IsComment) > 0 |
| 111 | + search('\v%(\S)|$', 'W', 0, 200, () => !IsComment()) |
| 112 | + else |
| 113 | + cursor(1, 1) |
| 114 | + search('\v\S+', 'cW', 0, 200) |
| 115 | + endif |
| 116 | + endif |
| 117 | + |
| 118 | + var pos_start = getcurpos() |
| 119 | + |
| 120 | + if !inner |
| 121 | + var col = pos_start[2] |
| 122 | + var prefix = getline(pos_start[1])[ : col - 2] |
| 123 | + while col > 0 && prefix[col - 2] =~ '\s' |
| 124 | + col -= 1 |
| 125 | + endwhile |
| 126 | + pos_start[2] = col |
| 127 | + endif |
| 128 | + |
| 129 | + # Search for the comment end. |
| 130 | + if pos_init[1] > pos_start[1] |
| 131 | + cursor(pos_init[1], pos_init[2]) |
| 132 | + endif |
| 133 | + if search('\v%(\S+)|$', 'W', 0, 200, IsComment) > 0 |
| 134 | + search('\S', 'beW', 0, 200, () => !IsComment()) |
| 135 | + else |
| 136 | + if search('\%$', 'W', 0, 200) > 0 |
| 137 | + search('\ze\S', 'beW', 0, 200, () => !IsComment()) |
| 138 | + endif |
| 139 | + endif |
| 140 | + |
| 141 | + var pos_end = getcurpos() |
| 142 | + |
| 143 | + if !inner |
| 144 | + var spaces = matchstr(getline(pos_end[1]), '\%>.c\s*') |
| 145 | + pos_end[2] += spaces->len() |
| 146 | + if getline(pos_end[1])[pos_end[2] : ] =~ '^\s*$' |
| 147 | + && (pos_start[2] == 1 || getline(pos_start[1])[ : pos_start[2]] =~ '^\s*$') |
| 148 | + if search('\v\s*\_$(\s*\n)+', 'eW', 0, 200) > 0 |
| 149 | + pos_end = getcurpos() |
| 150 | + endif |
| 151 | + endif |
| 152 | + endif |
| 153 | + |
| 154 | + if (pos_end[2] == (getline(pos_end[1])->len() ?? 1)) && pos_start[2] == 1 |
| 155 | + cursor(pos_end[1], 1) |
| 156 | + normal! V |
| 157 | + cursor(pos_start[1], 1) |
| 158 | + else |
| 159 | + cursor(pos_end[1], pos_end[2]) |
| 160 | + normal! v |
| 161 | + cursor(pos_start[1], pos_start[2]) |
| 162 | + endif |
| 163 | +enddef |
0 commit comments