Bram,
attached is a patch, that changes slightly how addresses are being 
calculated when on a folded line and using an relative offset.

Best,
Christian
-- 
Mißtrauen ist eine schlechte Rüstung, die mehr hindern als schirmen
kann.
                -- George Gordon

-- 
-- 
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_use+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
From efda08039b1b6d4f9941d9888ebd82e2a10b460d Mon Sep 17 00:00:00 2001
From: Christian Brabandt <c...@256bit.org>
Date: Thu, 15 Dec 2016 19:10:47 +0100
Subject: [PATCH] Correct ex range  for folded lines

This will make :.,+3y work as expected for lines that are folded away
e.g. it will adjust the second adress to included the complete fold
(until the end of the folded lines) + 2 separate lines.
---
 src/ex_docmd.c            | 28 ++++++++++++++------
 src/testdir/Make_all.mak  |  1 +
 src/testdir/test_fold.vim | 65 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+), 8 deletions(-)
 create mode 100644 src/testdir/test_fold.vim

diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 2b0f15e..374f29a 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -137,7 +137,7 @@ static int	getargopt(exarg_T *eap);
 #endif
 
 static int	check_more(int, int);
-static linenr_T get_address(exarg_T *, char_u **, int addr_type, int skip, int to_other_file);
+static linenr_T get_address(exarg_T *, char_u **, int addr_type, int skip, int to_other_file, int count);
 static void	get_flags(exarg_T *eap);
 #if !defined(FEAT_PERL) \
 	|| !defined(FEAT_PYTHON) || !defined(FEAT_PYTHON3) \
@@ -1791,6 +1791,7 @@ do_one_cmd(
     cmdmod_T		save_cmdmod;
     int			ni;			/* set when Not Implemented */
     char_u		*cmd;
+    int			count = 1;
 
     vim_memset(&ea, 0, sizeof(ea));
     ea.line1 = 1;
@@ -2015,7 +2016,7 @@ do_one_cmd(
 			{
 #ifdef FEAT_WINDOWS
 			    long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS,
-								ea.skip, FALSE);
+								ea.skip, FALSE, 1);
 			    if (tabnr == MAXLNUM)
 				cmdmod.tab = tabpage_index(curtab) + 1;
 			    else
@@ -2175,7 +2176,7 @@ do_one_cmd(
 	}
 	ea.cmd = skipwhite(ea.cmd);
 	lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip,
-							  ea.addr_count == 0);
+							  ea.addr_count == 0, count++);
 	if (ea.cmd == NULL)		    /* error detected */
 	    goto doend;
 	if (lnum == MAXLNUM)
@@ -4363,7 +4364,8 @@ get_address(
     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		count)	    /* being called first or second time */
 {
     int		c;
     int		i;
@@ -4639,10 +4641,20 @@ get_address(
 		    || addr_type == ADDR_BUFFERS)
 		lnum = compute_buffer_local_count(
 				    addr_type, lnum, (i == '-') ? -1 * n : n);
-	    else if (i == '-')
-		lnum -= n;
 	    else
-		lnum += n;
+	    {
+#ifdef FEAT_FOLDING
+		/* relative line addressing, need to adjust for folded lines now,
+		 * but only do it for the second address */
+		if (addr_type == ADDR_LINES && (i == '-' || i == '+')
+			&& count == 2)
+		    (void)hasFolding(lnum, NULL, &lnum);
+#endif
+		if (i == '-')
+		    lnum -= n;
+		else
+		    lnum += n;
+	    }
 	}
     } while (*cmd == '/' || *cmd == '?');
 
@@ -9301,7 +9313,7 @@ ex_copymove(exarg_T *eap)
 {
     long	n;
 
-    n = get_address(eap, &eap->arg, eap->addr_type, FALSE, FALSE);
+    n = get_address(eap, &eap->arg, eap->addr_type, FALSE, FALSE, 1);
     if (eap->arg == NULL)	    /* error detected */
     {
 	eap->nextcmd = NULL;
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index c78e34b..7f69303 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -150,6 +150,7 @@ NEW_TESTS = test_arglist.res \
 	    test_digraph.res \
 	    test_display.res \
 	    test_farsi.res \
+	    test_fold.res \
 	    test_fnameescape.res \
 	    test_gf.res \
 	    test_gn.res \
diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim
new file mode 100644
index 0000000..1b52e92
--- /dev/null
+++ b/src/testdir/test_fold.vim
@@ -0,0 +1,65 @@
+" Test for folding
+
+function! 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!
+endfunction
-- 
2.10.2

Reply via email to