Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vimode: Handle folded lines correctly #1338

Merged
merged 2 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions vimode/src/cmd-runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ static gboolean process_cmd(CmdDef *cmds, CmdContext *ctx, gboolean ins_mode)
{
if (orig_mode == VI_MODE_COMMAND_SINGLE)
vi_set_mode(VI_MODE_INSERT);
ensure_current_line_expanded(ctx->sci);
}
else if (!consumed && ctx->kpl)
{
Expand Down
74 changes: 56 additions & 18 deletions vimode/src/cmds/motion.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,39 @@ void cmd_goto_right(CmdContext *c, CmdParams *p)
}


static gint doc_line_from_visible_delta(CmdParams *p, gint line, gint delta, gboolean *overflow)
{
gboolean oflow = FALSE;
gint new_line = line;
gint i = 0;

while (i < ABS(delta))
{
gint inc = delta > 0 ? 1 : -1;
gint tmp = new_line + inc;

if (tmp < 0 || tmp >= p->line_num)
{
oflow = TRUE;
break;
}
new_line = tmp;

if (SSM(p->sci, SCI_GETLINEVISIBLE, new_line, 0))
i++;
}

if (overflow)
*overflow = oflow;

return new_line;
}


void cmd_goto_up(CmdContext *c, CmdParams *p)
{
gint one_above, pos;
gboolean line_underflow;

if (p->line == 0)
return;
Expand All @@ -53,8 +83,8 @@ void cmd_goto_up(CmdContext *c, CmdParams *p)
* SCI_CHOOSECARETX which we cannot read directly from Scintilla and which
* we want to keep - perform jump to previous/following line and add
* one final SCI_LINEUP/SCI_LINEDOWN which recovers SCI_CHOOSECARETX for us. */
one_above = p->line - p->num - 1;
if (one_above >= 0)
one_above = doc_line_from_visible_delta(p, p->line, -p->num - 1, &line_underflow);
if (!line_underflow)
{
/* Every case except for the first line - go one line above and perform
* SCI_LINEDOWN. This ensures that even with wrapping on, we get the
Expand All @@ -70,7 +100,7 @@ void cmd_goto_up(CmdContext *c, CmdParams *p)
* on, we need to repeat SCI_LINEUP to get to the first line of wrapping.
* This may lead to visible slow scrolling which is why there's the
* fast case above for anything else but the first line. */
gint one_below = p->line - p->num + 1;
gint one_below = doc_line_from_visible_delta(p, p->line, -p->num + 1, NULL);
gint wrap_count;

one_below = one_below > 0 ? one_below : 1;
Expand Down Expand Up @@ -98,15 +128,13 @@ void cmd_goto_up_nonempty(CmdContext *c, CmdParams *p)
static void goto_down(CmdParams *p, gint num)
{
gint one_above, pos;
gint last_line = p->line_num - 1;

if (p->line == last_line)
if (p->line >= p->line_num - 1)
return;

/* see cmd_goto_up() for explanation */
one_above = p->line + num - 1;
one_above = one_above < last_line ? one_above : last_line - 1;
one_above = doc_line_from_visible_delta(p, p->line, p->num - 1, NULL);
pos = SSM(p->sci, SCI_GETLINEENDPOSITION, one_above, 0);

SET_POS_NOX(p->sci, pos, FALSE);
SSM(p->sci, SCI_LINEDOWN, 0, 0);
}
Expand Down Expand Up @@ -136,39 +164,40 @@ void cmd_goto_down_one_less_nonempty(CmdContext *c, CmdParams *p)
void cmd_goto_page_up(CmdContext *c, CmdParams *p)
{
gint shift = p->line_visible_num * p->num;
gint new_line = get_line_number_rel(p->sci, -shift);
gint new_line = doc_line_from_visible_delta(p, p->line, -shift, NULL);
goto_nonempty(p->sci, new_line, TRUE);
}


void cmd_goto_page_down(CmdContext *c, CmdParams *p)
{
gint shift = p->line_visible_num * p->num;
gint new_line = get_line_number_rel(p->sci, shift);
gint new_line = doc_line_from_visible_delta(p, p->line, shift, NULL);
goto_nonempty(p->sci, new_line, TRUE);
}


void cmd_goto_halfpage_up(CmdContext *c, CmdParams *p)
{
gint shift = p->num_present ? p->num : p->line_visible_num / 2;
gint new_line = get_line_number_rel(p->sci, -shift);
gint new_line = doc_line_from_visible_delta(p, p->line, -shift, NULL);
goto_nonempty(p->sci, new_line, TRUE);
}


void cmd_goto_halfpage_down(CmdContext *c, CmdParams *p)
{
gint shift = p->num_present ? p->num : p->line_visible_num / 2;
gint new_line = get_line_number_rel(p->sci, shift);
gint new_line = doc_line_from_visible_delta(p, p->line, shift, NULL);
goto_nonempty(p->sci, new_line, TRUE);
}


void cmd_goto_line(CmdContext *c, CmdParams *p)
{
gint num = p->num > p->line_num ? p->line_num : p->num;
goto_nonempty(p->sci, num - 1, TRUE);
num = doc_line_from_visible_delta(p, num, -1, NULL);
goto_nonempty(p->sci, num, TRUE);
}


Expand All @@ -177,30 +206,39 @@ void cmd_goto_line_last(CmdContext *c, CmdParams *p)
gint num = p->num > p->line_num ? p->line_num : p->num;
if (!p->num_present)
num = p->line_num;
goto_nonempty(p->sci, num - 1, TRUE);
num = doc_line_from_visible_delta(p, num, -1, NULL);
goto_nonempty(p->sci, num, TRUE);
}


void cmd_goto_screen_top(CmdContext *c, CmdParams *p)
{
gint line;
gint top = p->line_visible_first;
gint count = p->line_visible_num;
gint line = top + p->num;
goto_nonempty(p->sci, line > top + count ? top + count : line, FALSE);
gint max = doc_line_from_visible_delta(p, top, count, NULL);
gint num = p->num;

if (!p->num_present)
num = 0;

line = doc_line_from_visible_delta(p, top, num, NULL);
goto_nonempty(p->sci, line > max ? max : line, FALSE);
}


void cmd_goto_screen_middle(CmdContext *c, CmdParams *p)
{
goto_nonempty(p->sci, p->line_visible_first + p->line_visible_num/2, FALSE);
gint num = doc_line_from_visible_delta(p, p->line_visible_first, p->line_visible_num / 2, NULL);
goto_nonempty(p->sci, num, FALSE);
}


void cmd_goto_screen_bottom(CmdContext *c, CmdParams *p)
{
gint top = p->line_visible_first;
gint count = p->line_visible_num;
gint line = top + count - p->num;
gint line = doc_line_from_visible_delta(p, top, count - p->num, NULL);
goto_nonempty(p->sci, line < top ? top : line, FALSE);
}

Expand Down
2 changes: 2 additions & 0 deletions vimode/src/excmd-runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ void excmd_perform(CmdContext *ctx, const gchar *cmd)
{
case ':':
perform_simple_ex_cmd(ctx, cmd + 1);
ensure_current_line_expanded(ctx->sci);
break;
case '/':
case '?':
Expand All @@ -483,6 +484,7 @@ void excmd_perform(CmdContext *ctx, const gchar *cmd)
pos = perform_search(ctx->sci, ctx->search_text, ctx->num, FALSE);
if (pos >= 0)
SET_POS(ctx->sci, pos, TRUE);
ensure_current_line_expanded(ctx->sci);
break;
}
}
Expand Down
8 changes: 8 additions & 0 deletions vimode/src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,11 @@ void goto_nonempty(ScintillaObject *sci, gint line, gboolean scroll)
pos = NEXT(sci, pos);
SET_POS(sci, pos, scroll);
}


void ensure_current_line_expanded(ScintillaObject *sci)
{
gint line = GET_CUR_LINE(sci);
if (!SSM(sci, SCI_GETLINEVISIBLE, line, 0))
SSM(sci, SCI_ENSUREVISIBLE, line, 0);
}
1 change: 1 addition & 0 deletions vimode/src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ void perform_substitute(ScintillaObject *sci, const gchar *cmd, gint from, gint
const gchar *flag_override);

gint get_line_number_rel(ScintillaObject *sci, gint shift);
void ensure_current_line_expanded(ScintillaObject *sci);

#endif