aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-07-06 12:41:56 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-07-06 19:58:44 +0800
commitff111b615a33e574fb020831bcb2e63eaa52c9a4 (patch)
treee8a9bf252d1da2c7a8c46f328235acf41652fa6f
parent1b5f53ca9574611273282dfbed91021d75242335 (diff)
downloadrneovim-ff111b615a33e574fb020831bcb2e63eaa52c9a4.tar.gz
rneovim-ff111b615a33e574fb020831bcb2e63eaa52c9a4.tar.bz2
rneovim-ff111b615a33e574fb020831bcb2e63eaa52c9a4.zip
vim-patch:8.2.4165: the nv_g_cmd() function is too long
Problem: The nv_g_cmd() function is too long. Solution: Move code to separate functions. (Yegappan Lakshmanan, closes vim/vim#9576) https://github.com/vim/vim/commit/05386ca1d4823e5c98c24b8cd038af49aee62577
-rw-r--r--src/nvim/normal.c421
1 files changed, 226 insertions, 195 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index c9b62db31c..628ebee6c3 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -5879,13 +5879,218 @@ static void nv_suspend(cmdarg_T *cap)
do_cmdline_cmd("st");
}
+/// "gv": Reselect the previous Visual area. If Visual already active,
+/// exchange previous and current Visual area.
+static void nv_gv_cmd(cmdarg_T *cap)
+{
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ if (curbuf->b_visual.vi_start.lnum == 0
+ || curbuf->b_visual.vi_start.lnum > curbuf->b_ml.ml_line_count
+ || curbuf->b_visual.vi_end.lnum == 0) {
+ beep_flush();
+ return;
+ }
+
+ pos_T tpos;
+ // set w_cursor to the start of the Visual area, tpos to the end
+ if (VIsual_active) {
+ int i = VIsual_mode;
+ VIsual_mode = curbuf->b_visual.vi_mode;
+ curbuf->b_visual.vi_mode = i;
+ curbuf->b_visual_mode_eval = i;
+ i = curwin->w_curswant;
+ curwin->w_curswant = curbuf->b_visual.vi_curswant;
+ curbuf->b_visual.vi_curswant = i;
+
+ tpos = curbuf->b_visual.vi_end;
+ curbuf->b_visual.vi_end = curwin->w_cursor;
+ curwin->w_cursor = curbuf->b_visual.vi_start;
+ curbuf->b_visual.vi_start = VIsual;
+ } else {
+ VIsual_mode = curbuf->b_visual.vi_mode;
+ curwin->w_curswant = curbuf->b_visual.vi_curswant;
+ tpos = curbuf->b_visual.vi_end;
+ curwin->w_cursor = curbuf->b_visual.vi_start;
+ }
+
+ VIsual_active = true;
+ VIsual_reselect = true;
+
+ // Set Visual to the start and w_cursor to the end of the Visual
+ // area. Make sure they are on an existing character.
+ check_cursor();
+ VIsual = curwin->w_cursor;
+ curwin->w_cursor = tpos;
+ check_cursor();
+ update_topline(curwin);
+
+ // When called from normal "g" command: start Select mode when
+ // 'selectmode' contains "cmd". When called for K_SELECT, always
+ // start Select mode.
+ if (cap->arg) {
+ VIsual_select = true;
+ VIsual_select_reg = 0;
+ } else {
+ may_start_select('c');
+ }
+ setmouse();
+ redraw_curbuf_later(INVERTED);
+ showmode();
+}
+
+/// "g0", "g^" : Like "0" and "^" but for screen lines.
+/// "gm": middle of "g0" and "g$".
+static void nv_g_home_m_cmd(cmdarg_T *cap)
+{
+ int i;
+ const bool flag = cap->nchar == '^';
+
+ cap->oap->motion_type = kMTCharWise;
+ cap->oap->inclusive = false;
+ if (curwin->w_p_wrap
+ && curwin->w_width_inner != 0) {
+ int width1 = curwin->w_width_inner - curwin_col_off();
+ int width2 = width1 + curwin_col_off2();
+
+ validate_virtcol();
+ i = 0;
+ if (curwin->w_virtcol >= (colnr_T)width1 && width2 > 0) {
+ i = (curwin->w_virtcol - width1) / width2 * width2 + width1;
+ }
+ } else {
+ i = curwin->w_leftcol;
+ }
+ // Go to the middle of the screen line. When 'number' or
+ // 'relativenumber' is on and lines are wrapping the middle can be more
+ // to the left.
+ if (cap->nchar == 'm') {
+ i += (curwin->w_width_inner - curwin_col_off()
+ + ((curwin->w_p_wrap && i > 0) ? curwin_col_off2() : 0)) / 2;
+ }
+ coladvance((colnr_T)i);
+ if (flag) {
+ do {
+ i = gchar_cursor();
+ } while (ascii_iswhite(i) && oneright());
+ curwin->w_valid &= ~VALID_WCOL;
+ }
+ curwin->w_set_curswant = true;
+}
+
+/// "g_": to the last non-blank character in the line or <count> lines downward.
+static void nv_g_underscore_cmd(cmdarg_T *cap)
+{
+ cap->oap->motion_type = kMTCharWise;
+ cap->oap->inclusive = true;
+ curwin->w_curswant = MAXCOL;
+ if (cursor_down(cap->count1 - 1, cap->oap->op_type == OP_NOP) == false) {
+ clearopbeep(cap->oap);
+ return;
+ }
+
+ char_u *ptr = get_cursor_line_ptr();
+
+ // In Visual mode we may end up after the line.
+ if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL) {
+ curwin->w_cursor.col--;
+ }
+
+ // Decrease the cursor column until it's on a non-blank.
+ while (curwin->w_cursor.col > 0 && ascii_iswhite(ptr[curwin->w_cursor.col])) {
+ curwin->w_cursor.col--;
+ }
+ curwin->w_set_curswant = true;
+ adjust_for_sel(cap);
+}
+
+/// "g$" : Like "$" but for screen lines.
+static void nv_g_dollar_cmd(cmdarg_T *cap)
+{
+ oparg_T *oap = cap->oap;
+ int i;
+ int col_off = curwin_col_off();
+
+ oap->motion_type = kMTCharWise;
+ oap->inclusive = true;
+ if (curwin->w_p_wrap && curwin->w_width_inner != 0) {
+ curwin->w_curswant = MAXCOL; // so we stay at the end
+ if (cap->count1 == 1) {
+ int width1 = curwin->w_width_inner - col_off;
+ int width2 = width1 + curwin_col_off2();
+
+ validate_virtcol();
+ i = width1 - 1;
+ if (curwin->w_virtcol >= (colnr_T)width1) {
+ i += ((curwin->w_virtcol - width1) / width2 + 1) * width2;
+ }
+ coladvance((colnr_T)i);
+
+ // Make sure we stick in this column.
+ validate_virtcol();
+ curwin->w_curswant = curwin->w_virtcol;
+ curwin->w_set_curswant = false;
+ if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) {
+ // Check for landing on a character that got split at
+ // the end of the line. We do not want to advance to
+ // the next screen line.
+ if (curwin->w_virtcol > (colnr_T)i) {
+ curwin->w_cursor.col--;
+ }
+ }
+ } else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == false) {
+ clearopbeep(oap);
+ }
+ } else {
+ if (cap->count1 > 1) {
+ // if it fails, let the cursor still move to the last char
+ (void)cursor_down(cap->count1 - 1, false);
+ }
+ i = curwin->w_leftcol + curwin->w_width_inner - col_off - 1;
+ coladvance((colnr_T)i);
+
+ // if the character doesn't fit move one back
+ if (curwin->w_cursor.col > 0 && utf_ptr2cells((const char *)get_cursor_pos_ptr()) > 1) {
+ colnr_T vcol;
+
+ getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &vcol);
+ if (vcol >= curwin->w_leftcol + curwin->w_width - col_off) {
+ curwin->w_cursor.col--;
+ }
+ }
+
+ // Make sure we stick in this column.
+ validate_virtcol();
+ curwin->w_curswant = curwin->w_virtcol;
+ curwin->w_set_curswant = false;
+ }
+}
+
+/// "gi": start Insert at the last position.
+static void nv_gi_cmd(cmdarg_T *cap)
+{
+ if (curbuf->b_last_insert.mark.lnum != 0) {
+ curwin->w_cursor = curbuf->b_last_insert.mark;
+ check_cursor_lnum();
+ int i = (int)STRLEN(get_cursor_line_ptr());
+ if (curwin->w_cursor.col > (colnr_T)i) {
+ if (virtual_active()) {
+ curwin->w_cursor.coladd += curwin->w_cursor.col - i;
+ }
+ curwin->w_cursor.col = i;
+ }
+ }
+ cap->cmdchar = 'i';
+ nv_edit(cap);
+}
+
/// Commands starting with "g".
static void nv_g_cmd(cmdarg_T *cap)
{
oparg_T *oap = cap->oap;
- pos_T tpos;
int i;
- bool flag = false;
switch (cap->nchar) {
// "g^A/g^X": Sequentially increment visually selected region.
@@ -5916,61 +6121,9 @@ static void nv_g_cmd(cmdarg_T *cap)
break;
// "gv": Reselect the previous Visual area. If Visual already active,
- // exchange previous and current Visual area.
+ // exchange previous and current Visual area.
case 'v':
- if (checkclearop(oap)) {
- break;
- }
-
- if (curbuf->b_visual.vi_start.lnum == 0
- || curbuf->b_visual.vi_start.lnum > curbuf->b_ml.ml_line_count
- || curbuf->b_visual.vi_end.lnum == 0) {
- beep_flush();
- } else {
- // set w_cursor to the start of the Visual area, tpos to the end
- if (VIsual_active) {
- i = VIsual_mode;
- VIsual_mode = curbuf->b_visual.vi_mode;
- curbuf->b_visual.vi_mode = i;
- curbuf->b_visual_mode_eval = i;
- i = curwin->w_curswant;
- curwin->w_curswant = curbuf->b_visual.vi_curswant;
- curbuf->b_visual.vi_curswant = i;
-
- tpos = curbuf->b_visual.vi_end;
- curbuf->b_visual.vi_end = curwin->w_cursor;
- curwin->w_cursor = curbuf->b_visual.vi_start;
- curbuf->b_visual.vi_start = VIsual;
- } else {
- VIsual_mode = curbuf->b_visual.vi_mode;
- curwin->w_curswant = curbuf->b_visual.vi_curswant;
- tpos = curbuf->b_visual.vi_end;
- curwin->w_cursor = curbuf->b_visual.vi_start;
- }
-
- VIsual_active = true;
- VIsual_reselect = true;
-
- // Set Visual to the start and w_cursor to the end of the Visual
- // area. Make sure they are on an existing character.
- check_cursor();
- VIsual = curwin->w_cursor;
- curwin->w_cursor = tpos;
- check_cursor();
- update_topline(curwin);
- // When called from normal "g" command: start Select mode when
- // 'selectmode' contains "cmd". When called for K_SELECT, always
- // start Select mode.
- if (cap->arg) {
- VIsual_select = true;
- VIsual_select_reg = 0;
- } else {
- may_start_select('c');
- }
- setmouse();
- redraw_curbuf_later(INVERTED);
- showmode();
- }
+ nv_gv_cmd(cap);
break;
// "gV": Don't reselect the previous Visual area after a Select mode mapping of menu.
case 'V':
@@ -6036,47 +6189,14 @@ static void nv_g_cmd(cmdarg_T *cap)
nv_join(cap);
break;
- // "g0", "g^" and "g$": Like "0", "^" and "$" but for screen lines.
+ // "g0", "g^" : Like "0" and "^" but for screen lines.
// "gm": middle of "g0" and "g$".
case '^':
- flag = true;
- FALLTHROUGH;
-
case '0':
case 'm':
case K_HOME:
case K_KHOME:
- oap->motion_type = kMTCharWise;
- oap->inclusive = false;
- if (curwin->w_p_wrap
- && curwin->w_width_inner != 0) {
- int width1 = curwin->w_width_inner - curwin_col_off();
- int width2 = width1 + curwin_col_off2();
-
- validate_virtcol();
- i = 0;
- if (curwin->w_virtcol >= (colnr_T)width1 && width2 > 0) {
- i = (curwin->w_virtcol - width1) / width2 * width2 + width1;
- }
- } else {
- i = curwin->w_leftcol;
- }
- // Go to the middle of the screen line. When 'number' or
- // 'relativenumber' is on and lines are wrapping the middle can be more
- // to the left.
- if (cap->nchar == 'm') {
- i += (curwin->w_width_inner - curwin_col_off()
- + ((curwin->w_p_wrap && i > 0)
- ? curwin_col_off2() : 0)) / 2;
- }
- coladvance((colnr_T)i);
- if (flag) {
- do {
- i = gchar_cursor();
- } while (ascii_iswhite(i) && oneright());
- curwin->w_valid &= ~VALID_WCOL;
- }
- curwin->w_set_curswant = true;
+ nv_g_home_m_cmd(cap);
break;
case 'M':
@@ -6091,94 +6211,17 @@ static void nv_g_cmd(cmdarg_T *cap)
curwin->w_set_curswant = true;
break;
+ // "g_": to the last non-blank character in the line or <count> lines downward.
case '_':
- // "g_": to the last non-blank character in the line or <count> lines downward.
- cap->oap->motion_type = kMTCharWise;
- cap->oap->inclusive = true;
- curwin->w_curswant = MAXCOL;
- if (cursor_down(cap->count1 - 1,
- cap->oap->op_type == OP_NOP) == false) {
- clearopbeep(cap->oap);
- } else {
- char_u *ptr = get_cursor_line_ptr();
-
- // In Visual mode we may end up after the line.
- if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL) {
- curwin->w_cursor.col--;
- }
-
- // Decrease the cursor column until it's on a non-blank.
- while (curwin->w_cursor.col > 0
- && ascii_iswhite(ptr[curwin->w_cursor.col])) {
- curwin->w_cursor.col--;
- }
- curwin->w_set_curswant = true;
- adjust_for_sel(cap);
- }
+ nv_g_underscore_cmd(cap);
break;
+ // "g$" : Like "$" but for screen lines.
case '$':
case K_END:
- case K_KEND: {
- int col_off = curwin_col_off();
-
- oap->motion_type = kMTCharWise;
- oap->inclusive = true;
- if (curwin->w_p_wrap
- && curwin->w_width_inner != 0) {
- curwin->w_curswant = MAXCOL; // so we stay at the end
- if (cap->count1 == 1) {
- int width1 = curwin->w_width_inner - col_off;
- int width2 = width1 + curwin_col_off2();
-
- validate_virtcol();
- i = width1 - 1;
- if (curwin->w_virtcol >= (colnr_T)width1) {
- i += ((curwin->w_virtcol - width1) / width2 + 1)
- * width2;
- }
- coladvance((colnr_T)i);
-
- // Make sure we stick in this column.
- validate_virtcol();
- curwin->w_curswant = curwin->w_virtcol;
- curwin->w_set_curswant = false;
- if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) {
- // Check for landing on a character that got split at
- // the end of the line. We do not want to advance to
- // the next screen line.
- if (curwin->w_virtcol > (colnr_T)i) {
- curwin->w_cursor.col--;
- }
- }
- } else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == false) {
- clearopbeep(oap);
- }
- } else {
- if (cap->count1 > 1) {
- // if it fails, let the cursor still move to the last char
- (void)cursor_down(cap->count1 - 1, false);
- }
- i = curwin->w_leftcol + curwin->w_width_inner - col_off - 1;
- coladvance((colnr_T)i);
-
- // if the character doesn't fit move one back
- if (curwin->w_cursor.col > 0 && utf_ptr2cells((const char *)get_cursor_pos_ptr()) > 1) {
- colnr_T vcol;
-
- getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &vcol);
- if (vcol >= curwin->w_leftcol + curwin->w_width - col_off) {
- curwin->w_cursor.col--;
- }
- }
-
- // Make sure we stick in this column.
- validate_virtcol();
- curwin->w_curswant = curwin->w_virtcol;
- curwin->w_set_curswant = false;
- }
- }
- break;
+ case K_KEND:
+ nv_g_dollar_cmd(cap);
+ break;
// "g*" and "g#", like "*" and "#" but without using "\<" and "\>"
case '*':
@@ -6209,19 +6252,7 @@ static void nv_g_cmd(cmdarg_T *cap)
// "gi": start Insert at the last position.
case 'i':
- if (curbuf->b_last_insert.mark.lnum != 0) {
- curwin->w_cursor = curbuf->b_last_insert.mark;
- check_cursor_lnum();
- i = (int)STRLEN(get_cursor_line_ptr());
- if (curwin->w_cursor.col > (colnr_T)i) {
- if (virtual_active()) {
- curwin->w_cursor.coladd += curwin->w_cursor.col - i;
- }
- curwin->w_cursor.col = i;
- }
- }
- cap->cmdchar = 'i';
- nv_edit(cap);
+ nv_gi_cmd(cap);
break;
// "gI": Start insert in column 1.
@@ -6280,14 +6311,14 @@ static void nv_g_cmd(cmdarg_T *cap)
nv_goto(cap);
break;
- // Two-character operators:
- // "gq" Format text
- // "gw" Format text and keep cursor position
- // "g~" Toggle the case of the text.
- // "gu" Change text to lower case.
- // "gU" Change text to upper case.
- // "g?" rot13 encoding
- // "g@" call 'operatorfunc'
+ // Two-character operators:
+ // "gq" Format text
+ // "gw" Format text and keep cursor position
+ // "g~" Toggle the case of the text.
+ // "gu" Change text to lower case.
+ // "gU" Change text to upper case.
+ // "g?" rot13 encoding
+ // "g@" call 'operatorfunc'
case 'q':
case 'w':
oap->cursor_start = curwin->w_cursor;