mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-15 08:21:03 -04:00
implement search
This commit is contained in:
parent
e2c4ea3535
commit
67120e9940
5 changed files with 262 additions and 156 deletions
6
config.c
6
config.c
|
|
@ -177,7 +177,8 @@ static const char *const vimode_binding_action_map[] = {
|
||||||
[BIND_ACTION_VIMODE_FIRST_LINE] = "vimode-first-line",
|
[BIND_ACTION_VIMODE_FIRST_LINE] = "vimode-first-line",
|
||||||
[BIND_ACTION_VIMODE_LAST_LINE] = "vimode-last-line",
|
[BIND_ACTION_VIMODE_LAST_LINE] = "vimode-last-line",
|
||||||
[BIND_ACTION_VIMODE_CANCEL] = "vimode-cancel",
|
[BIND_ACTION_VIMODE_CANCEL] = "vimode-cancel",
|
||||||
[BIND_ACTION_VIMODE_START_SEARCH] = "vimode-start-search",
|
[BIND_ACTION_VIMODE_START_SEARCH_FORWARD] = "vimode-start-search-forward",
|
||||||
|
[BIND_ACTION_VIMODE_START_SEARCH_BACKWARD] = "vimode-start-search-backward",
|
||||||
[BIND_ACTION_VIMODE_FIND_NEXT] = "vimode-find-next",
|
[BIND_ACTION_VIMODE_FIND_NEXT] = "vimode-find-next",
|
||||||
[BIND_ACTION_VIMODE_FIND_PREV] = "vimode-find-prev",
|
[BIND_ACTION_VIMODE_FIND_PREV] = "vimode-find-prev",
|
||||||
[BIND_ACTION_VIMODE_ENTER_VISUAL] = "vimode-enter-visual",
|
[BIND_ACTION_VIMODE_ENTER_VISUAL] = "vimode-enter-visual",
|
||||||
|
|
@ -3283,7 +3284,8 @@ add_default_vimode_bindings(struct config *conf)
|
||||||
{BIND_ACTION_VIMODE_LAST_LINE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_g}}},
|
{BIND_ACTION_VIMODE_LAST_LINE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_g}}},
|
||||||
{BIND_ACTION_VIMODE_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_c}}},
|
{BIND_ACTION_VIMODE_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_c}}},
|
||||||
{BIND_ACTION_VIMODE_CANCEL, m("none"), {{XKB_KEY_Escape}}},
|
{BIND_ACTION_VIMODE_CANCEL, m("none"), {{XKB_KEY_Escape}}},
|
||||||
{BIND_ACTION_VIMODE_START_SEARCH, m("none"), {{XKB_KEY_slash}}},
|
{BIND_ACTION_VIMODE_START_SEARCH_FORWARD, m("none"), {{XKB_KEY_slash}}},
|
||||||
|
{BIND_ACTION_VIMODE_START_SEARCH_BACKWARD, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_slash}}},
|
||||||
{BIND_ACTION_VIMODE_FIND_NEXT, m("none"), {{XKB_KEY_n}}},
|
{BIND_ACTION_VIMODE_FIND_NEXT, m("none"), {{XKB_KEY_n}}},
|
||||||
{BIND_ACTION_VIMODE_FIND_PREV, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_n}}},
|
{BIND_ACTION_VIMODE_FIND_PREV, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_n}}},
|
||||||
{BIND_ACTION_VIMODE_ENTER_VISUAL, m("none"), {{XKB_KEY_v}}},
|
{BIND_ACTION_VIMODE_ENTER_VISUAL, m("none"), {{XKB_KEY_v}}},
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,8 @@ enum bind_action_vimode {
|
||||||
BIND_ACTION_VIMODE_FIRST_LINE,
|
BIND_ACTION_VIMODE_FIRST_LINE,
|
||||||
BIND_ACTION_VIMODE_LAST_LINE,
|
BIND_ACTION_VIMODE_LAST_LINE,
|
||||||
BIND_ACTION_VIMODE_CANCEL,
|
BIND_ACTION_VIMODE_CANCEL,
|
||||||
BIND_ACTION_VIMODE_START_SEARCH,
|
BIND_ACTION_VIMODE_START_SEARCH_FORWARD,
|
||||||
|
BIND_ACTION_VIMODE_START_SEARCH_BACKWARD,
|
||||||
BIND_ACTION_VIMODE_FIND_NEXT,
|
BIND_ACTION_VIMODE_FIND_NEXT,
|
||||||
BIND_ACTION_VIMODE_FIND_PREV,
|
BIND_ACTION_VIMODE_FIND_PREV,
|
||||||
BIND_ACTION_VIMODE_ENTER_VISUAL,
|
BIND_ACTION_VIMODE_ENTER_VISUAL,
|
||||||
|
|
|
||||||
2
render.c
2
render.c
|
|
@ -5317,8 +5317,6 @@ render_refresh_csd(struct terminal *term)
|
||||||
term->render.refresh.csd = true;
|
term->render.refresh.csd = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (kociap): Rename to something more indicative, e.g.
|
|
||||||
// render_refresh_vimode_search_box_search_box
|
|
||||||
void
|
void
|
||||||
render_refresh_vimode_search_box(struct terminal *term)
|
render_refresh_vimode_search_box(struct terminal *term)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ enum selection_kind {
|
||||||
};
|
};
|
||||||
enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
|
enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
|
||||||
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
|
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
|
||||||
enum search_direction { SEARCH_BACKWARD_SAME_POSITION, SEARCH_BACKWARD, SEARCH_FORWARD };
|
enum search_direction { SEARCH_BACKWARD, SEARCH_FORWARD };
|
||||||
|
|
||||||
struct ptmx_buffer {
|
struct ptmx_buffer {
|
||||||
void *data;
|
void *data;
|
||||||
|
|
@ -632,6 +632,7 @@ struct terminal {
|
||||||
bool is_vimming;
|
bool is_vimming;
|
||||||
struct {
|
struct {
|
||||||
enum vi_mode mode;
|
enum vi_mode mode;
|
||||||
|
// The position of the cursor (offset relative).
|
||||||
struct coord cursor;
|
struct coord cursor;
|
||||||
bool is_searching;
|
bool is_searching;
|
||||||
|
|
||||||
|
|
@ -646,9 +647,10 @@ struct terminal {
|
||||||
size_t cursor;
|
size_t cursor;
|
||||||
|
|
||||||
enum search_direction direction;
|
enum search_direction direction;
|
||||||
int original_view;
|
|
||||||
struct coord match;
|
struct coord match;
|
||||||
size_t match_len;
|
size_t match_len;
|
||||||
|
int original_view;
|
||||||
|
struct coord original_cursor;
|
||||||
} search;
|
} search;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
401
vimode.c
401
vimode.c
|
|
@ -16,6 +16,8 @@
|
||||||
#include "vimode.h"
|
#include "vimode.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
// TODO (kociap): consider adding scrolloff.
|
||||||
|
|
||||||
static bool is_mode_visual(enum vi_mode const mode) {
|
static bool is_mode_visual(enum vi_mode const mode) {
|
||||||
return mode == VI_MODE_VISUAL || mode == VI_MODE_VLINE ||
|
return mode == VI_MODE_VISUAL || mode == VI_MODE_VLINE ||
|
||||||
mode == VI_MODE_VBLOCK;
|
mode == VI_MODE_VBLOCK;
|
||||||
|
|
@ -36,6 +38,10 @@ selection_kind_from_vi_mode(enum vi_mode const mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum search_direction invert_direction(enum search_direction direction) {
|
||||||
|
return direction == SEARCH_FORWARD ? SEARCH_BACKWARD : SEARCH_FORWARD;
|
||||||
|
}
|
||||||
|
|
||||||
static struct coord offset_to_view_relative(struct terminal *const term,
|
static struct coord offset_to_view_relative(struct terminal *const term,
|
||||||
struct coord coord) {
|
struct coord coord) {
|
||||||
coord.row += term->grid->offset;
|
coord.row += term->grid->offset;
|
||||||
|
|
@ -50,6 +56,34 @@ static struct coord view_to_offset_relative(struct terminal *const term,
|
||||||
return coord;
|
return coord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cursor_to_scrollback_relative(struct terminal *const term, int row) {
|
||||||
|
row = grid_row_abs_to_sb(term->grid, term->rows,
|
||||||
|
grid_row_absolute(term->grid, row));
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cursor_from_scrollback_relative(struct terminal *const term,
|
||||||
|
int row) {
|
||||||
|
row = grid_row_sb_to_abs(term->grid, term->rows, row);
|
||||||
|
row -= term->grid->offset;
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int view_to_scrollback_relative(struct terminal *const term) {
|
||||||
|
return grid_row_abs_to_sb(term->grid, term->rows, term->grid->view);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct coord delta_cursor_to_abs_coord(struct terminal *const term,
|
||||||
|
struct coord const coord) {
|
||||||
|
int const location = grid_row_abs_to_sb(term->grid, term->rows, coord.row);
|
||||||
|
int const cursor =
|
||||||
|
cursor_to_scrollback_relative(term, term->vimode.cursor.row);
|
||||||
|
return (struct coord){
|
||||||
|
.row = location - cursor,
|
||||||
|
.col = coord.col - term->vimode.cursor.col,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static void damage_cursor_cell(struct terminal *const term) {
|
static void damage_cursor_cell(struct terminal *const term) {
|
||||||
struct coord const cursor =
|
struct coord const cursor =
|
||||||
offset_to_view_relative(term, term->vimode.cursor);
|
offset_to_view_relative(term, term->vimode.cursor);
|
||||||
|
|
@ -61,21 +95,41 @@ static void clip_cursor_to_view(struct terminal *const term) {
|
||||||
printf("CLIP CURSOR BEFORE (%d, %d) [view=%d; offset=%d]\n",
|
printf("CLIP CURSOR BEFORE (%d, %d) [view=%d; offset=%d]\n",
|
||||||
term->vimode.cursor.row, term->vimode.cursor.col, term->grid->view,
|
term->vimode.cursor.row, term->vimode.cursor.col, term->grid->view,
|
||||||
term->grid->offset);
|
term->grid->offset);
|
||||||
struct coord cursor = offset_to_view_relative(term, term->vimode.cursor);
|
int cursor_row = cursor_to_scrollback_relative(term, term->vimode.cursor.row);
|
||||||
printf("CLIP CURSOR VIEW RELATIVE BEFORE (%d, %d)\n", cursor.row, cursor.col);
|
int const view_row = view_to_scrollback_relative(term);
|
||||||
if (cursor.row < 0) {
|
printf("CLIP CURSOR VIEW RELATIVE BEFORE (%d, %d) [cursor_row=%d; "
|
||||||
cursor.row = 0;
|
"view_row=%d]\n",
|
||||||
} else if (cursor.row >= term->rows) {
|
cursor_row, term->vimode.cursor.col, cursor_row, view_row);
|
||||||
cursor.row = term->rows - 1;
|
if (cursor_row < view_row) {
|
||||||
|
cursor_row = view_row;
|
||||||
|
} else if (cursor_row - view_row >= term->rows) {
|
||||||
|
cursor_row = view_row + term->rows - 1;
|
||||||
}
|
}
|
||||||
printf("CLIP CURSOR VIEW RELATIVE AFTER (%d, %d)\n", cursor.row, cursor.col);
|
printf("CLIP CURSOR VIEW RELATIVE AFTER (%d, %d)\n", cursor_row,
|
||||||
term->vimode.cursor = view_to_offset_relative(term, cursor);
|
term->vimode.cursor.col);
|
||||||
|
term->vimode.cursor.row = cursor_from_scrollback_relative(term, cursor_row);
|
||||||
printf("CLIP CURSOR AFTER (%d, %d)\n", term->vimode.cursor.row,
|
printf("CLIP CURSOR AFTER (%d, %d)\n", term->vimode.cursor.row,
|
||||||
term->vimode.cursor.col);
|
term->vimode.cursor.col);
|
||||||
damage_cursor_cell(term);
|
damage_cursor_cell(term);
|
||||||
render_refresh(term);
|
render_refresh(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void center_view_on_cursor(struct terminal *const term) {
|
||||||
|
int const cursor =
|
||||||
|
cursor_to_scrollback_relative(term, term->vimode.cursor.row);
|
||||||
|
int const current_view = view_to_scrollback_relative(term);
|
||||||
|
int const half_viewport = term->rows / 2;
|
||||||
|
int const delta = (cursor - half_viewport) - current_view;
|
||||||
|
printf("CENTER VIEW [cursor=(%d, %d); current_view=%d; half_viewport=%d; "
|
||||||
|
"delta=%d]\n",
|
||||||
|
cursor, term->vimode.cursor.col, current_view, half_viewport, delta);
|
||||||
|
if (delta < 0) {
|
||||||
|
cmd_scrollback_up(term, -delta);
|
||||||
|
} else if (delta > 0) {
|
||||||
|
cmd_scrollback_down(term, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void update_selection(struct seat *const seat,
|
static void update_selection(struct seat *const seat,
|
||||||
struct terminal *const term) {
|
struct terminal *const term) {
|
||||||
enum vi_mode const mode = term->vimode.mode;
|
enum vi_mode const mode = term->vimode.mode;
|
||||||
|
|
@ -141,7 +195,8 @@ static bool search_ensure_size(struct terminal *term, size_t wanted_size) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_search(struct terminal *term) {
|
static void start_search(struct terminal *term,
|
||||||
|
enum search_direction const direction) {
|
||||||
if (term->vimode.is_searching) {
|
if (term->vimode.is_searching) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -150,12 +205,15 @@ static void start_search(struct terminal *term) {
|
||||||
|
|
||||||
const struct grid *grid = term->grid;
|
const struct grid *grid = term->grid;
|
||||||
term->vimode.search.original_view = grid->view;
|
term->vimode.search.original_view = grid->view;
|
||||||
|
term->vimode.search.original_cursor = term->vimode.cursor;
|
||||||
term->vimode.search.len = 0;
|
term->vimode.search.len = 0;
|
||||||
term->vimode.search.sz = 64;
|
term->vimode.search.sz = 64;
|
||||||
term->vimode.search.buf =
|
term->vimode.search.buf =
|
||||||
xmalloc(term->vimode.search.sz * sizeof(term->vimode.search.buf[0]));
|
xmalloc(term->vimode.search.sz * sizeof(term->vimode.search.buf[0]));
|
||||||
term->vimode.search.buf[0] = U'\0';
|
term->vimode.search.buf[0] = U'\0';
|
||||||
term->vimode.search.direction = SEARCH_FORWARD;
|
term->vimode.search.direction = direction;
|
||||||
|
term->vimode.search.match = (struct coord){-1, -1};
|
||||||
|
term->vimode.search.match_len = 0;
|
||||||
term->vimode.is_searching = true;
|
term->vimode.is_searching = true;
|
||||||
|
|
||||||
/* On-demand instantiate wayland surface */
|
/* On-demand instantiate wayland surface */
|
||||||
|
|
@ -166,14 +224,30 @@ static void start_search(struct terminal *term) {
|
||||||
render_refresh_vimode_search_box(term);
|
render_refresh_vimode_search_box(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cancel_search(struct terminal *const term) {
|
static void restore_pre_search_state(struct terminal *const term) {
|
||||||
|
// TODO (kociap): update selection.
|
||||||
|
damage_cursor_cell(term);
|
||||||
|
term->vimode.cursor = term->vimode.search.original_cursor;
|
||||||
|
damage_cursor_cell(term);
|
||||||
|
term->grid->view =
|
||||||
|
ensure_view_is_allocated(term, term->vimode.search.original_view);
|
||||||
|
term_damage_view(term);
|
||||||
|
render_refresh(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cancel_search(struct terminal *const term,
|
||||||
|
bool const restore_original) {
|
||||||
if (!term->vimode.is_searching) {
|
if (!term->vimode.is_searching) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wayl_win_subsurface_destroy(&term->window->search);
|
wayl_win_subsurface_destroy(&term->window->search);
|
||||||
|
|
||||||
term->vimode.is_searching = false;
|
term->vimode.is_searching = false;
|
||||||
struct vimode_search *const search = &term->vimode.search;
|
struct vimode_search *const search = &term->vimode.search;
|
||||||
|
if (restore_original) {
|
||||||
|
restore_pre_search_state(term);
|
||||||
|
}
|
||||||
if (search->buf != NULL) {
|
if (search->buf != NULL) {
|
||||||
free(search->buf);
|
free(search->buf);
|
||||||
search->buf = NULL;
|
search->buf = NULL;
|
||||||
|
|
@ -184,15 +258,22 @@ static void cancel_search(struct terminal *const term) {
|
||||||
search->match = (struct coord){-1, -1};
|
search->match = (struct coord){-1, -1};
|
||||||
search->match_len = 0;
|
search->match_len = 0;
|
||||||
term->render.search_glyph_offset = 0;
|
term->render.search_glyph_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
term->grid->view = ensure_view_is_allocated(term, search->original_view);
|
static void confirm_search(struct terminal *const term) {
|
||||||
term_damage_view(term);
|
if (term->vimode.confirmed_search.buf != NULL) {
|
||||||
render_refresh(term);
|
free(term->vimode.confirmed_search.buf);
|
||||||
|
}
|
||||||
|
term->vimode.confirmed_search.buf = term->vimode.search.buf;
|
||||||
|
term->vimode.confirmed_search.len = term->vimode.search.len;
|
||||||
|
term->vimode.confirmed_search.direction = term->vimode.search.direction;
|
||||||
|
term->vimode.search.buf = NULL;
|
||||||
|
cancel_search(term, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vimode_search_begin(struct terminal *term) {
|
void vimode_search_begin(struct terminal *term) {
|
||||||
vimode_begin(term);
|
vimode_begin(term);
|
||||||
start_search(term);
|
start_search(term, SEARCH_FORWARD);
|
||||||
term_xcursor_update(term);
|
term_xcursor_update(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,6 +300,7 @@ void vimode_begin(struct terminal *term) {
|
||||||
term_xcursor_update(term);
|
term_xcursor_update(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO (kociap): vimode is being cancelled by cursor input.
|
||||||
void vimode_cancel(struct terminal *term) {
|
void vimode_cancel(struct terminal *term) {
|
||||||
if (!term->is_vimming) {
|
if (!term->is_vimming) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -226,7 +308,7 @@ void vimode_cancel(struct terminal *term) {
|
||||||
|
|
||||||
printf("VIMODE CANCEL\n");
|
printf("VIMODE CANCEL\n");
|
||||||
|
|
||||||
cancel_search(term);
|
cancel_search(term, false);
|
||||||
|
|
||||||
term->is_vimming = false;
|
term->is_vimming = false;
|
||||||
|
|
||||||
|
|
@ -245,8 +327,9 @@ void vimode_cancel(struct terminal *term) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t matches_cell(const struct terminal *term,
|
static ssize_t matches_cell(const struct terminal *term,
|
||||||
const struct cell *cell, size_t search_ofs) {
|
const struct cell *cell, char32_t const *const buf,
|
||||||
assert(search_ofs < term->vimode.search.len);
|
size_t const len, size_t search_ofs) {
|
||||||
|
assert(search_ofs < len);
|
||||||
|
|
||||||
char32_t base = cell->wc;
|
char32_t base = cell->wc;
|
||||||
const struct composed *composed = NULL;
|
const struct composed *composed = NULL;
|
||||||
|
|
@ -256,19 +339,18 @@ static ssize_t matches_cell(const struct terminal *term,
|
||||||
base = composed->chars[0];
|
base = composed->chars[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (composed == NULL && base == 0 &&
|
if (composed == NULL && base == 0 && buf[search_ofs] == U' ')
|
||||||
term->vimode.search.buf[search_ofs] == U' ')
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (c32ncasecmp(&base, &term->vimode.search.buf[search_ofs], 1) != 0)
|
if (c32ncasecmp(&base, &buf[search_ofs], 1) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (composed != NULL) {
|
if (composed != NULL) {
|
||||||
if (search_ofs + composed->count > term->vimode.search.len)
|
if (search_ofs + composed->count > len)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (size_t j = 1; j < composed->count; j++) {
|
for (size_t j = 1; j < composed->count; j++) {
|
||||||
if (composed->chars[j] != term->vimode.search.buf[search_ofs + j])
|
if (composed->chars[j] != buf[search_ofs + j])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +358,8 @@ static ssize_t matches_cell(const struct terminal *term,
|
||||||
return composed != NULL ? composed->count : 1;
|
return composed != NULL ? composed->count : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool find_next(struct terminal *term, enum search_direction direction,
|
static bool find_next(struct terminal *term, char32_t const *const buf,
|
||||||
|
size_t const len, enum search_direction direction,
|
||||||
struct coord abs_start, struct coord abs_end,
|
struct coord abs_start, struct coord abs_end,
|
||||||
struct range *match) {
|
struct range *match) {
|
||||||
#define ROW_DEC(_r) ((_r) = ((_r) - 1 + grid->num_rows) & (grid->num_rows - 1))
|
#define ROW_DEC(_r) ((_r) = ((_r) - 1 + grid->num_rows) & (grid->num_rows - 1))
|
||||||
|
|
@ -310,7 +393,7 @@ static bool find_next(struct terminal *term, enum search_direction direction,
|
||||||
|
|
||||||
for (; backward ? match_start_col >= 0 : match_start_col < term->cols;
|
for (; backward ? match_start_col >= 0 : match_start_col < term->cols;
|
||||||
backward ? match_start_col-- : match_start_col++) {
|
backward ? match_start_col-- : match_start_col++) {
|
||||||
if (matches_cell(term, &row->cells[match_start_col], 0) < 0) {
|
if (matches_cell(term, &row->cells[match_start_col], buf, len, 0) < 0) {
|
||||||
if (match_start_row == abs_end.row && match_start_col == abs_end.col) {
|
if (match_start_row == abs_end.row && match_start_col == abs_end.col) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -330,7 +413,7 @@ static bool find_next(struct terminal *term, enum search_direction direction,
|
||||||
const struct row *match_row = row;
|
const struct row *match_row = row;
|
||||||
size_t match_len = 0;
|
size_t match_len = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < term->vimode.search.len;) {
|
for (size_t i = 0; i < len;) {
|
||||||
if (match_end_col >= term->cols) {
|
if (match_end_col >= term->cols) {
|
||||||
ROW_INC(match_end_row);
|
ROW_INC(match_end_row);
|
||||||
match_end_col = 0;
|
match_end_col = 0;
|
||||||
|
|
@ -346,7 +429,7 @@ static bool find_next(struct terminal *term, enum search_direction direction,
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t additional_chars =
|
ssize_t additional_chars =
|
||||||
matches_cell(term, &match_row->cells[match_end_col], i);
|
matches_cell(term, &match_row->cells[match_end_col], buf, len, i);
|
||||||
if (additional_chars < 0)
|
if (additional_chars < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -360,7 +443,7 @@ static bool find_next(struct terminal *term, enum search_direction direction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_len != term->vimode.search.len) {
|
if (match_len != len) {
|
||||||
/* Didn't match (completely) */
|
/* Didn't match (completely) */
|
||||||
|
|
||||||
if (match_start_row == abs_end.row && match_start_col == abs_end.col) {
|
if (match_start_row == abs_end.row && match_start_col == abs_end.col) {
|
||||||
|
|
@ -385,79 +468,52 @@ static bool find_next(struct terminal *term, enum search_direction direction,
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
#undef ROW_DEC
|
||||||
}
|
}
|
||||||
|
|
||||||
static void search_find_next(struct terminal *term,
|
static bool find_next_from_cursor(struct terminal *const term,
|
||||||
enum search_direction direction) {
|
char32_t *const buf, size_t const len,
|
||||||
|
enum search_direction const direction,
|
||||||
|
struct range *const match) {
|
||||||
|
if (len == 0 || buf == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct grid *grid = term->grid;
|
struct grid *grid = term->grid;
|
||||||
|
|
||||||
if (term->vimode.search.len == 0) {
|
struct coord start = {
|
||||||
term->vimode.search.match = (struct coord){-1, -1};
|
.row = grid_row_absolute(grid, term->vimode.cursor.row),
|
||||||
return;
|
.col = term->vimode.cursor.col,
|
||||||
}
|
};
|
||||||
|
|
||||||
struct coord start = term->vimode.search.match;
|
switch (direction) {
|
||||||
size_t len = term->vimode.search.match_len;
|
case SEARCH_FORWARD:
|
||||||
|
start.col += 1;
|
||||||
xassert((len == 0 && start.row == -1 && start.col == -1) ||
|
if (start.col >= term->cols) {
|
||||||
(len > 0 && start.row >= 0 && start.col >= 0));
|
|
||||||
|
|
||||||
if (len == 0) {
|
|
||||||
/* No previous match, start from the top, or bottom, of the scrollback */
|
|
||||||
switch (direction) {
|
|
||||||
case SEARCH_FORWARD:
|
|
||||||
start.row = grid_row_absolute_in_view(grid, 0);
|
|
||||||
start.col = 0;
|
start.col = 0;
|
||||||
break;
|
start.row++;
|
||||||
|
start.row &= grid->num_rows - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SEARCH_BACKWARD:
|
case SEARCH_BACKWARD:
|
||||||
case SEARCH_BACKWARD_SAME_POSITION:
|
start.col -= 1;
|
||||||
start.row = grid_row_absolute_in_view(grid, term->rows - 1);
|
if (start.col < 0) {
|
||||||
start.col = term->cols - 1;
|
start.col = term->cols - 1;
|
||||||
break;
|
start.row += grid->num_rows - 1;
|
||||||
|
start.row &= grid->num_rows - 1;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
/* Continue from last match */
|
|
||||||
xassert(start.row >= 0);
|
|
||||||
xassert(start.col >= 0);
|
|
||||||
|
|
||||||
switch (direction) {
|
|
||||||
case SEARCH_BACKWARD_SAME_POSITION:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SEARCH_BACKWARD:
|
|
||||||
if (--start.col < 0) {
|
|
||||||
start.col = term->cols - 1;
|
|
||||||
start.row += grid->num_rows - 1;
|
|
||||||
start.row &= grid->num_rows - 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SEARCH_FORWARD:
|
|
||||||
if (++start.col >= term->cols) {
|
|
||||||
start.col = 0;
|
|
||||||
start.row++;
|
|
||||||
start.row &= grid->num_rows - 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
xassert(start.row >= 0);
|
|
||||||
xassert(start.row < grid->num_rows);
|
|
||||||
xassert(start.col >= 0);
|
|
||||||
xassert(start.col < term->cols);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("update: %s: starting at row=%d col=%d "
|
xassert(start.row >= 0 && start.col >= 0);
|
||||||
"(offset = %d, view = %d)",
|
|
||||||
direction != SEARCH_FORWARD ? "backward" : "forward", start.row,
|
|
||||||
start.col, grid->offset, grid->view);
|
|
||||||
|
|
||||||
struct coord end = start;
|
struct coord end = start;
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case SEARCH_FORWARD:
|
case SEARCH_FORWARD:
|
||||||
/* Search forward, until we reach the cell *before* current start */
|
/* Search forward, until we reach the cell *before* current start */
|
||||||
if (--end.col < 0) {
|
end.col -= 1;
|
||||||
|
if (end.col < 0) {
|
||||||
end.col = term->cols - 1;
|
end.col = term->cols - 1;
|
||||||
end.row += grid->num_rows - 1;
|
end.row += grid->num_rows - 1;
|
||||||
end.row &= grid->num_rows - 1;
|
end.row &= grid->num_rows - 1;
|
||||||
|
|
@ -465,28 +521,17 @@ static void search_find_next(struct terminal *term,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEARCH_BACKWARD:
|
case SEARCH_BACKWARD:
|
||||||
case SEARCH_BACKWARD_SAME_POSITION:
|
|
||||||
/* Search backwards, until we reach the cell *after* current start */
|
/* Search backwards, until we reach the cell *after* current start */
|
||||||
if (++end.col >= term->cols) {
|
end.col += 1;
|
||||||
|
if (end.col >= term->cols) {
|
||||||
end.col = 0;
|
end.col = 0;
|
||||||
end.row++;
|
end.row += 1;
|
||||||
end.row &= grid->num_rows - 1;
|
end.row &= grid->num_rows - 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct range match;
|
return find_next(term, buf, len, direction, start, end, match);
|
||||||
bool found = find_next(term, direction, start, end, &match);
|
|
||||||
if (found) {
|
|
||||||
LOG_DBG("primary match found at %dx%d", match.start.row, match.start.col);
|
|
||||||
term->vimode.search.match = match.start;
|
|
||||||
term->vimode.search.match_len = term->vimode.search.len;
|
|
||||||
} else {
|
|
||||||
LOG_DBG("no match");
|
|
||||||
term->vimode.search.match = (struct coord){-1, -1};
|
|
||||||
term->vimode.search.match_len = 0;
|
|
||||||
}
|
|
||||||
#undef ROW_DEC
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct search_match_iterator search_matches_new_iter(struct terminal *term) {
|
struct search_match_iterator search_matches_new_iter(struct terminal *term) {
|
||||||
|
|
@ -520,7 +565,10 @@ struct range search_matches_next(struct search_match_iterator *iter) {
|
||||||
/* BUG: matches *starting* outside the view, but ending *inside*, aren't
|
/* BUG: matches *starting* outside the view, but ending *inside*, aren't
|
||||||
* matched */
|
* matched */
|
||||||
struct range match;
|
struct range match;
|
||||||
bool found = find_next(term, SEARCH_FORWARD, abs_start, abs_end, &match);
|
// TODO (kociap): consider whether using active search buffer is
|
||||||
|
// reasonable.
|
||||||
|
bool found = find_next(term, term->vimode.search.buf, term->vimode.search.len,
|
||||||
|
SEARCH_FORWARD, abs_start, abs_end, &match);
|
||||||
if (!found)
|
if (!found)
|
||||||
goto no_match;
|
goto no_match;
|
||||||
|
|
||||||
|
|
@ -671,19 +719,13 @@ void vimode_view_down(struct terminal *const term, int const delta) {
|
||||||
clip_cursor_to_view(term);
|
clip_cursor_to_view(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
// move_cursor_vertical
|
static void move_cursor_delta(struct terminal *const term,
|
||||||
//
|
struct coord const delta) {
|
||||||
// Moves the cursor up or down within the scrollback. If the cursor goes outside
|
|
||||||
// the view bounds, the view is scrolled.
|
|
||||||
//
|
|
||||||
// Parameters:
|
|
||||||
// count - the number of rows to move by. Negative values move up, positive
|
|
||||||
// down.
|
|
||||||
//
|
|
||||||
static void move_cursor_vertical(struct terminal *const term, int const count) {
|
|
||||||
damage_cursor_cell(term);
|
damage_cursor_cell(term);
|
||||||
struct coord cursor = offset_to_view_relative(term, term->vimode.cursor);
|
struct coord cursor = offset_to_view_relative(term, term->vimode.cursor);
|
||||||
cursor.row += count;
|
cursor.row += delta.row;
|
||||||
|
cursor.col += delta.col;
|
||||||
|
|
||||||
if (cursor.row < 0) {
|
if (cursor.row < 0) {
|
||||||
int const overflow = -cursor.row;
|
int const overflow = -cursor.row;
|
||||||
cmd_scrollback_up(term, overflow);
|
cmd_scrollback_up(term, overflow);
|
||||||
|
|
@ -694,14 +736,32 @@ static void move_cursor_vertical(struct terminal *const term, int const count) {
|
||||||
cursor.row = term->rows - 1;
|
cursor.row = term->rows - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cursor.col < 0) {
|
||||||
|
cursor.col = 0;
|
||||||
|
} else if (cursor.col >= term->cols) {
|
||||||
|
cursor.col = term->cols - 1;
|
||||||
|
}
|
||||||
|
|
||||||
term->vimode.cursor = view_to_offset_relative(term, cursor);
|
term->vimode.cursor = view_to_offset_relative(term, cursor);
|
||||||
printf("DIRTYING CELL (%d, %d) [offset=%d; view=%d]\n",
|
printf("CURSOR MOVED (%d, %d) [delta=(%d, %d)]\n", term->vimode.cursor.row,
|
||||||
term->vimode.cursor.row, term->vimode.cursor.col, term->grid->offset,
|
term->vimode.cursor.col, delta.row, delta.col);
|
||||||
term->grid->view);
|
|
||||||
damage_cursor_cell(term);
|
damage_cursor_cell(term);
|
||||||
render_refresh(term);
|
render_refresh(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move_cursor_vertical
|
||||||
|
//
|
||||||
|
// Moves the cursor up or down within the scrollback. If the cursor goes outside
|
||||||
|
// the view bounds, the view is scrolled.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// count - the number of rows to move by. Negative values move up, positive
|
||||||
|
// down.
|
||||||
|
//
|
||||||
|
static void move_cursor_vertical(struct terminal *const term, int const count) {
|
||||||
|
move_cursor_delta(term, (struct coord){.row = count, .col = 0});
|
||||||
|
}
|
||||||
|
|
||||||
// move_cursor_horizontal
|
// move_cursor_horizontal
|
||||||
//
|
//
|
||||||
// Moves the cursor left or right within the scrollback. The cursor is
|
// Moves the cursor left or right within the scrollback. The cursor is
|
||||||
|
|
@ -713,18 +773,7 @@ static void move_cursor_vertical(struct terminal *const term, int const count) {
|
||||||
//
|
//
|
||||||
static void move_cursor_horizontal(struct terminal *const term,
|
static void move_cursor_horizontal(struct terminal *const term,
|
||||||
int const count) {
|
int const count) {
|
||||||
damage_cursor_cell(term);
|
move_cursor_delta(term, (struct coord){.row = 0, .col = count});
|
||||||
struct coord cursor = term->vimode.cursor;
|
|
||||||
cursor.col += count;
|
|
||||||
if (cursor.col < 0) {
|
|
||||||
cursor.col = 0;
|
|
||||||
} else if (cursor.col >= term->cols) {
|
|
||||||
cursor.col = term->cols - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
term->vimode.cursor = cursor;
|
|
||||||
damage_cursor_cell(term);
|
|
||||||
render_refresh(term);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
||||||
|
|
@ -798,15 +847,17 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_FIRST_LINE:
|
case BIND_ACTION_VIMODE_FIRST_LINE:
|
||||||
cmd_scrollback_up(term, term->grid->num_rows);
|
cmd_scrollback_up(term, term->grid->num_rows);
|
||||||
term->vimode.cursor.row = -term->grid->num_rows;
|
damage_cursor_cell(term);
|
||||||
clip_cursor_to_view(term);
|
term->vimode.cursor.row = cursor_from_scrollback_relative(term, 0);
|
||||||
|
damage_cursor_cell(term);
|
||||||
update_selection(seat, term);
|
update_selection(seat, term);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_LAST_LINE:
|
case BIND_ACTION_VIMODE_LAST_LINE:
|
||||||
cmd_scrollback_down(term, term->grid->num_rows);
|
cmd_scrollback_down(term, term->grid->num_rows);
|
||||||
term->vimode.cursor.row = term->grid->num_rows;
|
damage_cursor_cell(term);
|
||||||
clip_cursor_to_view(term);
|
term->vimode.cursor.row = term->rows - 1;
|
||||||
|
damage_cursor_cell(term);
|
||||||
update_selection(seat, term);
|
update_selection(seat, term);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -824,15 +875,40 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_START_SEARCH:
|
case BIND_ACTION_VIMODE_START_SEARCH_FORWARD:
|
||||||
start_search(term);
|
start_search(term, SEARCH_FORWARD);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// TODO (kociap): Implement.
|
case BIND_ACTION_VIMODE_START_SEARCH_BACKWARD:
|
||||||
case BIND_ACTION_VIMODE_FIND_NEXT:
|
start_search(term, SEARCH_BACKWARD);
|
||||||
case BIND_ACTION_VIMODE_FIND_PREV:
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BIND_ACTION_VIMODE_FIND_PREV:
|
||||||
|
case BIND_ACTION_VIMODE_FIND_NEXT: {
|
||||||
|
enum search_direction const direction =
|
||||||
|
(action == BIND_ACTION_VIMODE_FIND_NEXT)
|
||||||
|
? term->vimode.confirmed_search.direction
|
||||||
|
: invert_direction(term->vimode.confirmed_search.direction);
|
||||||
|
struct range match;
|
||||||
|
bool const matched = find_next_from_cursor(
|
||||||
|
term, term->vimode.confirmed_search.buf,
|
||||||
|
term->vimode.confirmed_search.len, direction, &match);
|
||||||
|
// TODO (kociap): feedback for the user when no match?
|
||||||
|
if (matched) {
|
||||||
|
struct coord const delta = delta_cursor_to_abs_coord(term, match.start);
|
||||||
|
printf("SEARCH %s [direction=%s; location=%d; cursor=%d; match=(%d, "
|
||||||
|
"%d)]\n",
|
||||||
|
(action == BIND_ACTION_VIMODE_FIND_NEXT) ? "NEXT" : "PREV",
|
||||||
|
(direction == SEARCH_FORWARD ? "forward" : "backward"),
|
||||||
|
grid_row_abs_to_sb(term->grid, term->rows, match.start.row),
|
||||||
|
cursor_to_scrollback_relative(term, term->vimode.cursor.row),
|
||||||
|
match.start.row, match.start.col);
|
||||||
|
// TODO (kociap): update selection.
|
||||||
|
move_cursor_delta(term, delta);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_ENTER_VISUAL:
|
case BIND_ACTION_VIMODE_ENTER_VISUAL:
|
||||||
case BIND_ACTION_VIMODE_ENTER_VLINE:
|
case BIND_ACTION_VIMODE_ENTER_VLINE:
|
||||||
case BIND_ACTION_VIMODE_ENTER_VBLOCK: {
|
case BIND_ACTION_VIMODE_ENTER_VBLOCK: {
|
||||||
|
|
@ -913,11 +989,13 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execute_vimode_search_binding(struct seat *seat,
|
static void execute_vimode_search_binding(struct seat *seat,
|
||||||
struct terminal *term,
|
struct terminal *const term,
|
||||||
const struct key_binding *binding,
|
const struct key_binding *binding,
|
||||||
uint32_t serial) {
|
uint32_t serial,
|
||||||
|
bool *search_string_changed) {
|
||||||
const enum bind_action_vimode action = binding->action;
|
const enum bind_action_vimode action = binding->action;
|
||||||
struct vimode_search *const search = &term->vimode.search;
|
struct vimode_search *const search = &term->vimode.search;
|
||||||
|
*search_string_changed = false;
|
||||||
|
|
||||||
if (term->grid != &term->normal) {
|
if (term->grid != &term->normal) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -927,12 +1005,22 @@ static void execute_vimode_search_binding(struct seat *seat,
|
||||||
case BIND_ACTION_VIMODE_SEARCH_NONE:
|
case BIND_ACTION_VIMODE_SEARCH_NONE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// TODO (kociap): implement
|
|
||||||
case BIND_ACTION_VIMODE_SEARCH_CONFIRM:
|
case BIND_ACTION_VIMODE_SEARCH_CONFIRM:
|
||||||
|
if (search->match_len > 0) {
|
||||||
|
struct coord const delta = delta_cursor_to_abs_coord(term, search->match);
|
||||||
|
printf("CONFIRM SEARCH [location=%d; cursor=%d; match=(%d, %d)]\n",
|
||||||
|
grid_row_abs_to_sb(term->grid, term->rows, search->match.row),
|
||||||
|
cursor_to_scrollback_relative(term, term->vimode.cursor.row),
|
||||||
|
search->match.row, search->match.col);
|
||||||
|
// TODO (kociap): update selection.
|
||||||
|
move_cursor_delta(term, delta);
|
||||||
|
center_view_on_cursor(term);
|
||||||
|
}
|
||||||
|
confirm_search(term);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_SEARCH_CANCEL:
|
case BIND_ACTION_VIMODE_SEARCH_CANCEL:
|
||||||
cancel_search(term);
|
cancel_search(term, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_SEARCH_DELETE_PREV_CHAR:
|
case BIND_ACTION_VIMODE_SEARCH_DELETE_PREV_CHAR:
|
||||||
|
|
@ -943,6 +1031,7 @@ static void execute_vimode_search_binding(struct seat *seat,
|
||||||
search->len -= 1;
|
search->len -= 1;
|
||||||
search->buf[search->len] = U'\0';
|
search->buf[search->len] = U'\0';
|
||||||
render_refresh_vimode_search_box(term);
|
render_refresh_vimode_search_box(term);
|
||||||
|
*search_string_changed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -1027,8 +1116,6 @@ void vimode_input(struct seat *seat, struct terminal *term,
|
||||||
? xkb_compose_state_get_status(seat->kbd.xkb_compose_state)
|
? xkb_compose_state_get_status(seat->kbd.xkb_compose_state)
|
||||||
: XKB_COMPOSE_NOTHING;
|
: XKB_COMPOSE_NOTHING;
|
||||||
|
|
||||||
// bool update_search_result = false;
|
|
||||||
|
|
||||||
if (!term->vimode.is_searching) {
|
if (!term->vimode.is_searching) {
|
||||||
struct key_binding const *const binding = match_binding(
|
struct key_binding const *const binding = match_binding(
|
||||||
&bindings->vimode, key, sym, mods, consumed, raw_syms, raw_count);
|
&bindings->vimode, key, sym, mods, consumed, raw_syms, raw_count);
|
||||||
|
|
@ -1039,8 +1126,10 @@ void vimode_input(struct seat *seat, struct terminal *term,
|
||||||
struct key_binding const *const binding =
|
struct key_binding const *const binding =
|
||||||
match_binding(&bindings->vimode_search, key, sym, mods, consumed,
|
match_binding(&bindings->vimode_search, key, sym, mods, consumed,
|
||||||
raw_syms, raw_count);
|
raw_syms, raw_count);
|
||||||
|
bool search_string_updated = false;
|
||||||
if (binding != NULL) {
|
if (binding != NULL) {
|
||||||
execute_vimode_search_binding(seat, term, binding, serial);
|
execute_vimode_search_binding(seat, term, binding, serial,
|
||||||
|
&search_string_updated);
|
||||||
} else {
|
} else {
|
||||||
// If not a binding, then handle it as text input.
|
// If not a binding, then handle it as text input.
|
||||||
uint8_t buf[64] = {0};
|
uint8_t buf[64] = {0};
|
||||||
|
|
@ -1057,16 +1146,30 @@ void vimode_input(struct seat *seat, struct terminal *term,
|
||||||
sizeof(buf));
|
sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
// update_search_result = redraw = count > 0;
|
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
search_add_chars(term, (const char *)buf, count);
|
search_add_chars(term, (const char *)buf, count);
|
||||||
render_refresh_vimode_search_box(term);
|
render_refresh_vimode_search_box(term);
|
||||||
|
search_string_updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("search: buffer: %ls", (const wchar_t *)term->vimode.search.buf);
|
||||||
|
if (search_string_updated) {
|
||||||
|
struct range match;
|
||||||
|
bool const matched = find_next_from_cursor(
|
||||||
|
term, term->vimode.search.buf, term->vimode.search.len,
|
||||||
|
term->vimode.search.direction, &match);
|
||||||
|
if (matched > 0) {
|
||||||
|
term->vimode.search.match = match.start;
|
||||||
|
term->vimode.search.match_len = term->vimode.search.len;
|
||||||
|
struct coord const delta =
|
||||||
|
delta_cursor_to_abs_coord(term, term->vimode.search.match);
|
||||||
|
// TODO (kociap): update selection.
|
||||||
|
move_cursor_delta(term, delta);
|
||||||
|
center_view_on_cursor(term);
|
||||||
|
} else {
|
||||||
|
restore_pre_search_state(term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("search: buffer: %ls", (const wchar_t *)term->vimode.search.buf);
|
|
||||||
// if (update_search_result)
|
|
||||||
// search_find_next(term, search_direction);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue