aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2017-03-02 00:19:06 +0100
committerJustin M. Keyes <justinkz@gmail.com>2017-03-02 00:19:06 +0100
commit286aacb2aa46c1fdcee5ab3908e0d01d91497e0d (patch)
tree5a5afad73c682bb3972f83cea12c99e4b7a8125e
parent985bc6c6e055785e9cee22c1fd70127f82cdbffb (diff)
parentb1731fe1b5d7a9b89acb6c2292b1e3e8f9f33544 (diff)
downloadrneovim-286aacb2aa46c1fdcee5ab3908e0d01d91497e0d.tar.gz
rneovim-286aacb2aa46c1fdcee5ab3908e0d01d91497e0d.tar.bz2
rneovim-286aacb2aa46c1fdcee5ab3908e0d01d91497e0d.zip
Merge #6194 'filtering manually folded lines'
-rw-r--r--src/nvim/ex_docmd.c30
-rw-r--r--src/nvim/fold.c9
-rw-r--r--src/nvim/ops.c5
-rw-r--r--src/nvim/testdir/test_fold.vim114
-rw-r--r--test/functional/normal/fold_spec.lua47
5 files changed, 190 insertions, 15 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 03f943b1b1..87b6959101 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1244,6 +1244,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
cmdmod_T save_cmdmod;
int ni; /* set when Not Implemented */
char_u *cmd;
+ int address_count = 1;
memset(&ea, 0, sizeof(ea));
ea.line1 = 1;
@@ -1405,7 +1406,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
continue;
case 't': if (checkforcmd(&p, "tab", 3)) {
- long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, ea.skip, false);
+ long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, ea.skip, false, 1);
if (tabnr == MAXLNUM) {
cmdmod.tab = tabpage_index(curtab) + 1;
} else {
@@ -1543,7 +1544,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
ea.cmd = skipwhite(ea.cmd);
lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip,
- ea.addr_count == 0);
+ ea.addr_count == 0, address_count++);
if (ea.cmd == NULL) { // error detected
goto doend;
}
@@ -3422,8 +3423,8 @@ static linenr_T get_address(exarg_T *eap,
char_u **ptr,
int addr_type, // flag: one of ADDR_LINES, ...
int skip, // only skip the address, don't use it
- int to_other_file // flag: may jump to other file
- )
+ int to_other_file, // flag: may jump to other file
+ int address_count) // 1 for first, >1 after comma
{
int c;
int i;
@@ -3653,13 +3654,22 @@ static linenr_T get_address(exarg_T *eap,
n = 1;
else
n = getdigits(&cmd);
- if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS)
+ if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_BUFFERS) {
lnum = compute_buffer_local_count(
addr_type, lnum, (i == '-') ? -1 * n : n);
- else if (i == '-')
- lnum -= n;
- else
- lnum += n;
+ } else {
+ // Relative line addressing, need to adjust for folded lines
+ // now, but only do it after the first address.
+ if (addr_type == ADDR_LINES && (i == '-' || i == '+')
+ && address_count >= 2) {
+ (void)hasFolding(lnum, NULL, &lnum);
+ }
+ if (i == '-') {
+ lnum -= n;
+ } else {
+ lnum += n;
+ }
+ }
}
} while (*cmd == '/' || *cmd == '?');
@@ -7237,7 +7247,7 @@ static void ex_put(exarg_T *eap)
*/
static void ex_copymove(exarg_T *eap)
{
- long n = get_address(eap, &eap->arg, eap->addr_type, false, false);
+ long n = get_address(eap, &eap->arg, eap->addr_type, false, false, 1);
if (eap->arg == NULL) { // error detected
eap->nextcmd = NULL;
return;
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index d964da371a..1423463800 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -1438,13 +1438,16 @@ static void foldMarkAdjustRecurse(garray_T *gap, linenr_T line1, linenr_T line2,
} else {
/* 5. fold is below line1 and contains line2; need to
* correct nested folds too */
- foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top,
- line2 - fp->fd_top, amount,
- amount_after + (fp->fd_top - top));
if (amount == MAXLNUM) {
+ foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top,
+ line2 - fp->fd_top, amount,
+ amount_after + (fp->fd_top - top));
fp->fd_len -= line2 - fp->fd_top + 1;
fp->fd_top = line1;
} else {
+ foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top,
+ line2 - fp->fd_top, amount,
+ amount_after - amount);
fp->fd_len += amount_after - amount;
fp->fd_top += amount;
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 8bfda3c193..530193bd41 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -210,8 +210,6 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
}
changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
- /* The cursor line is not in a closed fold */
- foldOpenCursor();
if (oap->motion_type == kMTBlockWise) {
curwin->w_cursor.lnum = oap->start.lnum;
@@ -222,6 +220,9 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
} else
--curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */
+ // The cursor line is not in a closed fold
+ foldOpenCursor();
+
if (oap->line_count > p_report) {
if (oap->op_type == OP_RSHIFT)
s = (char_u *)">";
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
new file mode 100644
index 0000000000..1f835b876f
--- /dev/null
+++ b/src/nvim/testdir/test_fold.vim
@@ -0,0 +1,114 @@
+" Test for folding
+
+func! Test_address_fold()
+ new
+ call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
+ \ 'after fold 1', 'after fold 2', 'after fold 3'])
+ setl fen fdm=marker
+ " The next ccommands should all copy the same part of the buffer,
+ " regardless of the adressing type, since the part to be copied
+ " is folded away
+ :1y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+ :.y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+ :.+y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+ :.,.y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+ :sil .1,.y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+ " use silent to make E493 go away
+ :sil .+,.y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+ :,y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+ :,+y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/','after fold 1'], getreg(0,1,1))
+ " using .+3 as second address should copy the whole folded line + the next 3
+ " lines
+ :.,+3y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/',
+ \ 'after fold 1', 'after fold 2', 'after fold 3'], getreg(0,1,1))
+ :sil .,-2y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
+
+ " now test again with folding disabled
+ set nofoldenable
+ :1y
+ call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
+ :.y
+ call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
+ :.+y
+ call assert_equal(['1'], getreg(0,1,1))
+ :.,.y
+ call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
+ " use silent to make E493 go away
+ :sil .1,.y
+ call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
+ " use silent to make E493 go away
+ :sil .+,.y
+ call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
+ :,y
+ call assert_equal(['int FuncName() {/*{{{*/'], getreg(0,1,1))
+ :,+y
+ call assert_equal(['int FuncName() {/*{{{*/', '1'], getreg(0,1,1))
+ " using .+3 as second address should copy the whole folded line + the next 3
+ " lines
+ :.,+3y
+ call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3'], getreg(0,1,1))
+ :7
+ :sil .,-2y
+ call assert_equal(['4', '5', '}/*}}}*/'], getreg(0,1,1))
+
+ quit!
+endfunc
+
+func! Test_indent_fold()
+ new
+ call setline(1, ['', 'a', ' b', ' c'])
+ setl fen fdm=indent
+ 2
+ norm! >>
+ let a=map(range(1,4), 'foldclosed(v:val)')
+ call assert_equal([-1,-1,-1,-1], a)
+endfunc
+
+func! Test_indent_fold()
+ new
+ call setline(1, ['', 'a', ' b', ' c'])
+ setl fen fdm=indent
+ 2
+ norm! >>
+ let a=map(range(1,4), 'foldclosed(v:val)')
+ call assert_equal([-1,-1,-1,-1], a)
+ bw!
+endfunc
+
+func! Test_indent_fold2()
+ new
+ call setline(1, ['', '{{{', '}}}', '{{{', '}}}'])
+ setl fen fdm=marker
+ 2
+ norm! >>
+ let a=map(range(1,5), 'foldclosed(v:val)')
+ call assert_equal([-1,-1,-1,4,4], a)
+ bw!
+endfunc
+
+func Test_manual_fold_with_filter()
+ if !executable('cat')
+ return
+ endif
+ new
+ call setline(1, range(1, 20))
+ 4,$fold
+ %foldopen
+ 10,$fold
+ %foldopen
+ " This filter command should not have an effect
+ 1,8! cat
+ call feedkeys('5ggzdzMGdd', 'xt')
+ call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
+ bwipe!
+endfunc
diff --git a/test/functional/normal/fold_spec.lua b/test/functional/normal/fold_spec.lua
new file mode 100644
index 0000000000..a2a2a35a8b
--- /dev/null
+++ b/test/functional/normal/fold_spec.lua
@@ -0,0 +1,47 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local insert = helpers.insert
+local feed = helpers.feed
+local expect = helpers.expect
+local execute = helpers.execute
+
+describe('Folds', function()
+ clear()
+ it('manual folding adjusts with filter', function()
+ insert([[
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20]])
+ execute('4,$fold', '%foldopen', '10,$fold', '%foldopen')
+ execute('1,8! cat')
+ feed('5ggzdzMGdd')
+ expect([[
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9]])
+ end)
+end)