Hi Bram!
On Do, 09 Mär 2017, Bram Moolenaar wrote:
> This can use skipwhite(). There are several other places where this
> computation is done, e.g. in misc1.c, open_line():
>
> p = ml_get_curline();
> ai_col = (colnr_T)(skipwhite(p) - p);
>
> Similar one a bit further down.
>
> Would be good to put this function close to skipwhite() to make it
> easeri to find.
Attached patch does that.
>
> > + /* if indent kicked in, the firstline might have changed
> > + * but only do that, if the indent actually increased */
> > + ind_post = get_whitespace_line_start(curwin->w_cursor.lnum);
> > + if (curbuf->b_op_start.col > ind_pre && ind_post > ind_pre)
> > + {
> > + bd.textcol += ind_post - ind_pre;
> > + bd.start_vcol += ind_post - ind_pre;
> > + }
>
> Why only for when the indent increases?
To be on the safe side. Currently blockwise editing only allows for
actually adding text. This expectation isn't documented yet, so I
documented it.
Best,
Christian
--
Ohne Spekulation gibt es keine neue Beobachtung.
-- Charles Darwin
--
--
You received this message from the "vim_dev" 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_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
From acb35eb468a2b34fe86d730685f90adf84d2d2a4 Mon Sep 17 00:00:00 2001
From: Christian Brabandt <[email protected]>
Date: Sun, 26 Feb 2017 21:48:21 +0100
Subject: [PATCH] Fix block-insert when indenting kicks in
This fixes #1269 /
https://groups.google.com/d/msg/vim_dev/uMsaEfGexoI/j8NlqiHeCgAJ
---
runtime/doc/visual.txt | 3 ++-
src/charset.c | 23 +++++++++++++++++++++++
src/edit.c | 7 +++----
src/misc1.c | 6 ++----
src/ops.c | 19 +++++++++++++++----
src/proto/charset.pro | 3 +++
src/proto/misc1.pro | 1 +
src/screen.c | 2 +-
src/spell.c | 6 +++---
src/testdir/test_cindent.vim | 19 +++++++++++++++++++
10 files changed, 72 insertions(+), 17 deletions(-)
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt
index 0a91b9f48..039aac958 100644
--- a/runtime/doc/visual.txt
+++ b/runtime/doc/visual.txt
@@ -314,7 +314,7 @@ Visual-block Insert *v_b_I*
With a blockwise selection, I{string}<ESC> will insert {string} at the start
of block on every line of the block, provided that the line extends into the
block. Thus lines that are short will remain unmodified. TABs are split to
-retain visual columns.
+retain visual columns. Works only for adding text to a line, no deletions.
See |v_b_I_example|.
Visual-block Append *v_b_A*
@@ -331,6 +331,7 @@ See |v_b_A_example|.
Note: "I" and "A" behave differently for lines that don't extend into the
selected block. This was done intentionally, so that you can do it the way
you want.
+Works only for adding text to a line, no deletions.
Visual-block change *v_b_c*
All selected text in the block will be replaced by the same text string. When
diff --git a/src/charset.c b/src/charset.c
index 29c587b52..867961dff 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1536,6 +1536,29 @@ skipwhite(char_u *q)
}
/*
+ * getwhitecols: return the number of whitespace
+ * columns (bytes) at the start of a given line
+ */
+ int
+getwhitecols_line(linenr_T lnum)
+{
+
+ return getwhitecols(ml_get(lnum));
+}
+
+ int
+getwhitecols_curline()
+{
+ return getwhitecols(ml_get_curline());
+}
+
+ int
+getwhitecols(char_u *p)
+{
+ return skipwhite(p) - p;
+}
+
+/*
* skip over digits
*/
char_u *
diff --git a/src/edit.c b/src/edit.c
index 35fa23b7d..1dedcd425 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -5151,7 +5151,7 @@ ins_complete(int c, int enable_pum)
* first non_blank in the line, if it is not a wordchar
* include it to get a better pattern, but then we don't
* want the "\\<" prefix, check it bellow */
- compl_col = (colnr_T)(skipwhite(line) - line);
+ compl_col = (colnr_T)getwhitecols(line);
compl_startpos.col = compl_col;
compl_startpos.lnum = curwin->w_cursor.lnum;
compl_cont_status &= ~CONT_SOL; /* clear SOL if present */
@@ -5317,7 +5317,7 @@ ins_complete(int c, int enable_pum)
}
else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
{
- compl_col = (colnr_T)(skipwhite(line) - line);
+ compl_col = (colnr_T)getwhitecols(line);
compl_length = (int)curs_col - (int)compl_col;
if (compl_length < 0) /* cursor in indent: empty pattern */
compl_length = 0;
@@ -8175,8 +8175,7 @@ in_cinkeys(
{
/* "0=word": Check if there are only blanks before the
* word. */
- line = ml_get_curline();
- if ((int)(skipwhite(line) - line) !=
+ if (getwhitecols(line) !=
(int)(curwin->w_cursor.col - (p - look)))
match = FALSE;
}
diff --git a/src/misc1.c b/src/misc1.c
index 3379e757d..158c77b26 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -1586,8 +1586,7 @@ open_line(
&& curbuf->b_p_ai)
{
fixthisline(get_lisp_indent);
- p = ml_get_curline();
- ai_col = (colnr_T)(skipwhite(p) - p);
+ ai_col = (colnr_T)getwhitecols_curline();
}
#endif
#ifdef FEAT_CINDENT
@@ -1605,8 +1604,7 @@ open_line(
: KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
{
do_c_expr_indent();
- p = ml_get_curline();
- ai_col = (colnr_T)(skipwhite(p) - p);
+ ai_col = (colnr_T)getwhitecols_curline();
}
#endif
#if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
diff --git a/src/ops.c b/src/ops.c
index d3e97f07f..770baa181 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -2502,6 +2502,7 @@ op_insert(oparg_T *oap, long count1)
{
long ins_len, pre_textlen = 0;
char_u *firstline, *ins_text;
+ colnr_T ind_pre, ind_post;
struct block_def bd;
int i;
pos_T t1;
@@ -2536,7 +2537,10 @@ op_insert(oparg_T *oap, long count1)
#endif
/* Get the info about the block before entering the text */
block_prep(oap, &bd, oap->start.lnum, TRUE);
+ /* Get indent information */
+ ind_pre = (colnr_T)getwhitecols_curline();
firstline = ml_get(oap->start.lnum) + bd.textcol;
+
if (oap->op_type == OP_APPEND)
firstline += bd.textlen;
pre_textlen = (long)STRLEN(firstline);
@@ -2588,6 +2592,14 @@ op_insert(oparg_T *oap, long count1)
&& LT_POS(curbuf->b_op_start_orig, t1))
oap->start = curbuf->b_op_start_orig;
+ /* if indent kicked in, the firstline might have changed
+ * but only do that, if the indent actually increased */
+ ind_post = (colnr_T)getwhitecols_curline();
+ if (curbuf->b_op_start.col > ind_pre && ind_post > ind_pre)
+ {
+ bd.textcol += ind_post - ind_pre;
+ bd.start_vcol += ind_post - ind_pre;
+ }
/* If user has moved off this line, we don't know what to do, so do
* nothing.
* Also don't repeat the insert when Insert mode ended with CTRL-C. */
@@ -2749,7 +2761,7 @@ op_change(oparg_T *oap)
# endif
firstline = ml_get(oap->start.lnum);
pre_textlen = (long)STRLEN(firstline);
- pre_indent = (long)(skipwhite(firstline) - firstline);
+ pre_indent = (long)getwhitecols(firstline);
bd.textcol = curwin->w_cursor.col;
}
#endif
@@ -2774,7 +2786,7 @@ op_change(oparg_T *oap)
firstline = ml_get(oap->start.lnum);
if (bd.textcol > (colnr_T)pre_indent)
{
- long new_indent = (long)(skipwhite(firstline) - firstline);
+ long new_indent = (long)getwhitecols(firstline);
pre_textlen += new_indent - pre_indent;
bd.textcol += new_indent - pre_indent;
@@ -5050,8 +5062,7 @@ format_lines(
#endif
if (second_indent > 0) /* the "leader" for FO_Q_SECOND */
{
- char_u *p = ml_get_curline();
- int indent = (int)(skipwhite(p) - p);
+ int indent = getwhitecols_curline();
if (indent > 0)
{
diff --git a/src/proto/charset.pro b/src/proto/charset.pro
index 52b741a74..6a6e6a98d 100644
--- a/src/proto/charset.pro
+++ b/src/proto/charset.pro
@@ -35,6 +35,9 @@ colnr_T getvcol_nolist(pos_T *posp);
void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right);
char_u *skipwhite(char_u *q);
+int getwhitecols_line(linenr_T lnum);
+int getwhitecols_curline(void);
+int getwhitecols(char_u *p);
char_u *skipdigits(char_u *q);
char_u *skipbin(char_u *q);
char_u *skiphex(char_u *q);
diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro
index cac644969..4e299e5f9 100644
--- a/src/proto/misc1.pro
+++ b/src/proto/misc1.pro
@@ -1,4 +1,5 @@
/* misc1.c */
+int get_whitespace_line_start(linenr_T lnum);
int get_indent(void);
int get_indent_lnum(linenr_T lnum);
int get_indent_buf(buf_T *buf, linenr_T lnum);
diff --git a/src/screen.c b/src/screen.c
index 206b50fc0..137e46bfa 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -3329,7 +3329,7 @@ win_line(
{
/* For checking first word with a capital skip white space. */
if (cap_col == 0)
- cap_col = (int)(skipwhite(line) - line);
+ cap_col = getwhitecols(line);
/* To be able to spell-check over line boundaries copy the end of the
* current line into nextline[]. Above the start of the next line was
diff --git a/src/spell.c b/src/spell.c
index 1700bba0e..9cfbdda02 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -1625,11 +1625,11 @@ spell_move_to(
/* For checking first word with a capital skip white space. */
if (capcol == 0)
- capcol = (int)(skipwhite(line) - line);
+ capcol = getwhitecols(line);
else if (curline && wp == curwin)
{
/* For spellbadword(): check if first word needs a capital. */
- col = (int)(skipwhite(line) - line);
+ col = getwhitecols(line);
if (check_need_cap(lnum, col))
capcol = col;
@@ -3593,7 +3593,7 @@ check_need_cap(linenr_T lnum, colnr_T col)
line = ml_get_curline();
endcol = 0;
- if ((int)(skipwhite(line) - line) >= (int)col)
+ if (getwhitecols(line) >= (int)col)
{
/* At start of line, check if previous line is empty or sentence
* ends there. */
diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim
index 444c4c410..5f9d9fd5b 100644
--- a/src/testdir/test_cindent.vim
+++ b/src/testdir/test_cindent.vim
@@ -73,4 +73,23 @@ func Test_cino_extern_c()
bwipe!
endfunc
+func! Test_cindent_expr()
+ new
+ func! MyIndentFunction()
+ return v:lnum == 1 ? shiftwidth() : 0
+ endfunc
+ setl expandtab sw=8 indentkeys+=; indentexpr=MyIndentFunction()
+ call setline(1, ['var_a = something()', 'b = something()'])
+ call cursor(1, 1)
+ call feedkeys("^\<c-v>j$A;\<esc>", 'tnix')
+ call assert_equal([' var_a = something();', 'b = something();'], getline(1, '$'))
+
+ %d
+ call setline(1, [' var_a = something()', ' b = something()'])
+ call cursor(1, 1)
+ call feedkeys("^\<c-v>j$A;\<esc>", 'tnix')
+ call assert_equal([' var_a = something();', ' b = something()'], getline(1, '$'))
+ bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.11.0