From aff4ade39be53fd4443238dd99ab84385471eae1 Mon Sep 17 00:00:00 2001 From: Jacob Niehus Date: Thu, 7 May 2015 20:19:16 -0700 Subject: [PATCH 1/4] Add option to update indent after exchange --- doc/exchange.txt | 8 ++++++++ plugin/exchange.vim | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/doc/exchange.txt b/doc/exchange.txt index 7a9ed68..af492b9 100644 --- a/doc/exchange.txt +++ b/doc/exchange.txt @@ -75,6 +75,14 @@ g:exchange_no_mappings ~ If this variable is defined, the default mappings will not be created. + *g:exchange_indent* +g:exchange_indent ~ + +If this variable is defined and non-zero, linewise exchanges will swap +indents. Alternatively, setting the option to '==' will re-indent the +exchanged text with |==|. This behavior can be configured per buffer by +setting b:exchange_indent. + ISSUES AND TODO *exchange-issues* *exchange-todo* diff --git a/plugin/exchange.vim b/plugin/exchange.vim index 2a61967..08942ac 100644 --- a/plugin/exchange.vim +++ b/plugin/exchange.vim @@ -20,6 +20,20 @@ function! s:exchange(x, y, reverse, expand) silent exe "normal! `[" . a:x[1] . "`]\"zp" endif + if exists("b:exchange_indent") ? (b:exchange_indent !~ 0) : + \ (exists("g:exchange_indent") && (g:exchange_indent !~ 0)) + let xlines = 1 + a:x[3][1] - a:x[2][1] + let xindent = matchstr(getline(nextnonblank(a:x[2][1])), '^\s*') + let ylines = 1 + a:y[3][1] - a:y[2][1] + let yindent = matchstr(getline(nextnonblank(a:y[2][1])), '^\s*') + if a:y[1] ==# 'V' + call s:reindent(a:x[2][1], ylines, yindent) + endif + if a:x[1] ==# 'V' + call s:reindent(a:y[2][1] - xlines + ylines, xlines, xindent) + endif + endif + if a:reverse call cursor(a:x[2][1], a:x[2][2]) else @@ -33,6 +47,40 @@ function! s:exchange(x, y, reverse, expand) call s:restore_reg('+', reg_plus) endfunction +function! s:reindent(start, lines, new_indent) + if g:exchange_indent == '==' + let lnum = nextnonblank(a:start) + let line = getline(lnum) + execute "silent normal! " . lnum . "G==" + let new_indent = matchstr(getline(lnum), '^\s*') + call setline(a:start, line) + else + let new_indent = a:new_indent + endif + let indent = matchstr(getline(nextnonblank(a:start)), '^\s*') + if strdisplaywidth(new_indent) > strdisplaywidth(indent) + for lnum in range(a:start, a:start + a:lines - 1) + if lnum =~ '\S' + call setline(lnum, new_indent . getline(lnum)[len(indent):]) + endif + endfor + elseif strdisplaywidth(new_indent) < strdisplaywidth(indent) + let can_dedent = 1 + for lnum in range(a:start, a:start + a:lines - 1) + if stridx(getline(lnum), new_indent) != 0 && nextnonblank(lnum) == lnum + let can_dedent = 0 + endif + endfor + if can_dedent + for lnum in range(a:start, a:start + a:lines - 1) + if stridx(getline(lnum), new_indent) == 0 + call setline(lnum, new_indent . getline(lnum)[len(indent):]) + endif + endfor + endif + endif +endfunction + function! s:exchange_get(type, vis) let reg = s:save_reg('"') let reg_star = s:save_reg('*') From 3b4b4b38ab440c500d5a5c5860cc1e33cd6f8458 Mon Sep 17 00:00:00 2001 From: Jacob Niehus Date: Sun, 31 May 2015 10:21:32 -0700 Subject: [PATCH 2/4] Indent overlapping regions correctly --- plugin/exchange.vim | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/plugin/exchange.vim b/plugin/exchange.vim index 08942ac..2265383 100644 --- a/plugin/exchange.vim +++ b/plugin/exchange.vim @@ -8,6 +8,13 @@ function! s:exchange(x, y, reverse, expand) let selection = &selection set selection=inclusive + let indent = exists("b:exchange_indent") ? (b:exchange_indent !~ 0) : + \ (exists("g:exchange_indent") && (g:exchange_indent !~ 0)) + if indent + let xindent = matchstr(getline(nextnonblank(a:y[2][1])), '^\s*') + let yindent = matchstr(getline(nextnonblank(a:x[2][1])), '^\s*') + endif + call setpos("'[", a:y[2]) call setpos("']", a:y[3]) call setreg('z', a:x[0], a:x[1]) @@ -20,13 +27,10 @@ function! s:exchange(x, y, reverse, expand) silent exe "normal! `[" . a:x[1] . "`]\"zp" endif - if exists("b:exchange_indent") ? (b:exchange_indent !~ 0) : - \ (exists("g:exchange_indent") && (g:exchange_indent !~ 0)) + if indent let xlines = 1 + a:x[3][1] - a:x[2][1] - let xindent = matchstr(getline(nextnonblank(a:x[2][1])), '^\s*') - let ylines = 1 + a:y[3][1] - a:y[2][1] - let yindent = matchstr(getline(nextnonblank(a:y[2][1])), '^\s*') - if a:y[1] ==# 'V' + let ylines = a:expand ? xlines : 1 + a:y[3][1] - a:y[2][1] + if !a:expand && a:y[1] ==# 'V' call s:reindent(a:x[2][1], ylines, yindent) endif if a:x[1] ==# 'V' From 8bd96c3e0d714673b6ead6812c61ae7ac0ae12cf Mon Sep 17 00:00:00 2001 From: Jacob Niehus Date: Fri, 12 Jun 2015 13:12:24 -0700 Subject: [PATCH 3/4] Use b:exchange_indent if present --- plugin/exchange.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/exchange.vim b/plugin/exchange.vim index 2265383..cc08815 100644 --- a/plugin/exchange.vim +++ b/plugin/exchange.vim @@ -52,7 +52,7 @@ function! s:exchange(x, y, reverse, expand) endfunction function! s:reindent(start, lines, new_indent) - if g:exchange_indent == '==' + if (exists('b:exchange_indent') ? b:exchange_indent : g:exchange_indent) == '==' let lnum = nextnonblank(a:start) let line = getline(lnum) execute "silent normal! " . lnum . "G==" From 1394aa3a9bdbfdfcdd276a7f3c674a028131deaf Mon Sep 17 00:00:00 2001 From: Jacob Niehus Date: Tue, 16 Jun 2015 18:43:26 -0700 Subject: [PATCH 4/4] Only reindent when both selections are linewise --- plugin/exchange.vim | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugin/exchange.vim b/plugin/exchange.vim index cc08815..4c6dd9a 100644 --- a/plugin/exchange.vim +++ b/plugin/exchange.vim @@ -8,8 +8,9 @@ function! s:exchange(x, y, reverse, expand) let selection = &selection set selection=inclusive - let indent = exists("b:exchange_indent") ? (b:exchange_indent !~ 0) : - \ (exists("g:exchange_indent") && (g:exchange_indent !~ 0)) + let indent = (exists("b:exchange_indent") ? (b:exchange_indent !~ 0) : + \ (exists("g:exchange_indent") && (g:exchange_indent !~ 0))) + \ && a:x[1] ==# 'V' && a:y[1] ==# 'V' if indent let xindent = matchstr(getline(nextnonblank(a:y[2][1])), '^\s*') let yindent = matchstr(getline(nextnonblank(a:x[2][1])), '^\s*') @@ -30,12 +31,10 @@ function! s:exchange(x, y, reverse, expand) if indent let xlines = 1 + a:x[3][1] - a:x[2][1] let ylines = a:expand ? xlines : 1 + a:y[3][1] - a:y[2][1] - if !a:expand && a:y[1] ==# 'V' + if !a:expand call s:reindent(a:x[2][1], ylines, yindent) endif - if a:x[1] ==# 'V' - call s:reindent(a:y[2][1] - xlines + ylines, xlines, xindent) - endif + call s:reindent(a:y[2][1] - xlines + ylines, xlines, xindent) endif if a:reverse