From 867618364f51b1d6e995b2d7ccea889bebb6f18d Mon Sep 17 00:00:00 2001 From: Jaehwang Jerry Jung Date: Tue, 8 Jun 2021 02:13:01 +0900 Subject: [PATCH] Simplify and fix NERDCommenterInsert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Simplify comment delimiter insertion. * Remove the code that unnecessarily touches the leading spaces/tabs. * Fix a bug in which `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. --- autoload/nerdcommenter.vim | 77 +++++++------------------------------- plugin/nerdcommenter.vim | 2 +- 2 files changed, 14 insertions(+), 65 deletions(-) diff --git a/autoload/nerdcommenter.vim b/autoload/nerdcommenter.vim index 8be39c1..fa9848d 100644 --- a/autoload/nerdcommenter.vim +++ b/autoload/nerdcommenter.vim @@ -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 (:h i_CTRL-\_CTRL-O) to + " maintain the cursor position (from 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("\", strchars(right)) . "\\" 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 diff --git a/plugin/nerdcommenter.vim b/plugin/nerdcommenter.vim index 276a0ae..e47636b 100644 --- a/plugin/nerdcommenter.vim +++ b/plugin/nerdcommenter.vim @@ -125,7 +125,7 @@ function! NERDCommentIsCharCommented(line, col) return nerdcommenter#IsCharCommented(a:line, a:col) endfunction -inoremap NERDCommenterInsert :call nerdcommenter#Comment('i', "insert") +inoremap NERDCommenterInsert :call nerdcommenter#Comment('i', "Insert") " switch to/from alternative delimiters (does not use wrapper function) nnoremap NERDCommenterAltDelims :call nerdcommenter#SwitchToAlternativeDelimiters(1)