Simplify and fix NERDCommenterInsert

* Simplify comment delimiter insertion.
* Remove the code that unnecessarily touches the leading spaces/tabs.
* Fix a bug in which `<Plug>NERDCommenterInsert` inserts the comment
  delimiters in a wrong position when `col('.')==1`.
  Example: `1|234` (cursor at `|`) → `/* */1234`.
* NOTE: Should avoid `feedkey(.., 'ni')` for inserting comment
  delimiters to ensure that `NERDCommenter_after` is called after
  inserting the delimiters. `feedkey` only adds the input to the queue,
  which will be processed after exiting the script context. On the other
  hand, `:normal` and `feedkey(.., 'x')` are eagerly processed.
This commit is contained in:
Jaehwang Jerry Jung 2021-06-08 02:13:01 +09:00
parent 97317fc319
commit 867618364f
2 changed files with 14 additions and 65 deletions

View File

@ -1422,46 +1422,19 @@ function! s:PlaceDelimitersAndInsBetween() abort
let left = s:Left({'space': 1})
let right = s:Right({'space': 1})
let theLine = getline('.')
let lineHasLeadTabs = s:HasLeadingTabs(theLine) || (theLine =~# '^ *$' && !&expandtab)
"convert tabs to spaces and adjust the cursors column to take this into
"account
let untabbedCol = s:UntabbedCol(theLine, col('.'))
call setline(line('.'), s:ConvertLeadingTabsToSpaces(theLine))
call cursor(line('.'), untabbedCol)
" get the length of the right delimiter
let lenRight = strlen(right)
let isDelimOnEOL = col('.') >= strlen(getline('.'))
" if the cursor is in the first col then we gotta insert rather than
" append the comment delimiters here
let insOrApp = (col('.')==1 ? 'i' : 'a')
" place the delimiters down. We do it differently depending on whether
" there is a left AND right delimiter
if lenRight > 0
execute ':normal! ' . insOrApp . left . right
execute ':normal! ' . lenRight . 'h'
else
execute ':normal! ' . insOrApp . left
endif
"if needed convert spaces back to tabs and adjust the cursors col
"accordingly
if lineHasLeadTabs
let tabbedCol = s:TabbedCol(getline('.'), col('.'))
call setline(line('.'), s:ConvertLeadingSpacesToTabs(getline('.')))
call cursor(line('.'), tabbedCol)
endif
if isDelimOnEOL && lenRight ==# 0
startinsert!
else
call feedkeys('a', 'ni')
endif
" 0. Entered insert normal mode using <C-\><C-O> (:h i_CTRL-\_CTRL-O) to
" maintain the cursor position (from <Plug>NERDCommenterInsert).
" 1. Enter insert mode without changing the cursor position.
" If the cursor is on EOL (right of the last char), use 'a'.
" Otherwise, use 'i'.
let insert = col('.') > strlen(getline('.')) ? 'a' : 'i'
" 2. Insert comment delimiters.
" 3. Move the cursor to the left of the closing delimiter.
" 4. Enter insert normal mode again without changing the cursor position.
" This ensures that returning to the insert mode after finishing the
" script execution does not move the cursor.
" ( 1 ) ( 2 ) ( 3 ) ( 4 )
execute 'normal!' insert . left . right . repeat("\<Left>", strchars(right)) . "\<C-\>\<C-O>"
endfunction
" Function: s:RemoveDelimiters(left, right, line)
@ -3022,18 +2995,6 @@ function! s:SwapOuterPlaceHoldersForMultiPartDelims(line) abort
return line
endfunction
" Function: s:TabbedCol(line, col)
" Gets the col number for given line and existing col number. The new col
" number is the col number when all leading spaces are converted to tabs
" Args:
" -line:the line to get the rel col for
" -col: the abs col
function! s:TabbedCol(line, col) abort
let lineTruncated = strpart(a:line, 0, a:col)
let lineSpacesToTabs = substitute(lineTruncated, s:TabSpace(), '\t', 'g')
return strlen(lineSpacesToTabs)
endfunction
"FUNCTION: s:TabSpace()
"returns a string of spaces equal in length to &tabstop
function! s:TabSpace() abort
@ -3054,15 +3015,3 @@ endfunction
function! s:UnEsc(str, escChar) abort
return substitute(a:str, a:escChar, '', 'g')
endfunction
" Function: s:UntabbedCol(line, col)
" Takes a line and a col and returns the absolute column of col taking into
" account that a tab is worth 3 or 4 (or whatever) spaces.
" Args:
" -line:the line to get the abs col for
" -col: the col that doesn't take into account tabs
function! s:UntabbedCol(line, col) abort
let lineTruncated = strpart(a:line, 0, a:col)
let lineTabsToSpaces = substitute(lineTruncated, '\t', s:TabSpace(), 'g')
return strlen(lineTabsToSpaces)
endfunction

View File

@ -125,7 +125,7 @@ function! NERDCommentIsCharCommented(line, col)
return nerdcommenter#IsCharCommented(a:line, a:col)
endfunction
inoremap <silent> <Plug>NERDCommenterInsert <Space><BS><Esc>:call nerdcommenter#Comment('i', "insert")<CR>
inoremap <silent> <Plug>NERDCommenterInsert <C-\><C-O>:call nerdcommenter#Comment('i', "Insert")<CR>
" switch to/from alternative delimiters (does not use wrapper function)
nnoremap <Plug>NERDCommenterAltDelims :call nerdcommenter#SwitchToAlternativeDelimiters(1)<CR>