mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-07 04:06:07 -05:00
implement paste
This commit is contained in:
parent
c1eee29fbe
commit
9f9c1e11e2
4 changed files with 130 additions and 110 deletions
7
config.c
7
config.c
|
|
@ -201,6 +201,8 @@ static const char *const vimode_search_binding_action_map[] = {
|
|||
[BIND_ACTION_VIMODE_SEARCH_DELETE_PREV_CHAR] = "vimode-search-delete-prev",
|
||||
[BIND_ACTION_VIMODE_SEARCH_LEFT] = "vimode-search-left",
|
||||
[BIND_ACTION_VIMODE_SEARCH_RIGHT] = "vimode-search-right",
|
||||
[BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE] = "vimode-search-clipboard-paste",
|
||||
[BIND_ACTION_VIMODE_SEARCH_PRIMARY_PASTE] = "vimode-search-primary-paste",
|
||||
};
|
||||
|
||||
static const char *const url_binding_action_map[] = {
|
||||
|
|
@ -3339,6 +3341,11 @@ add_default_vimode_search_bindings(struct config *conf)
|
|||
{BIND_ACTION_VIMODE_SEARCH_LEFT, m("none"), {{XKB_KEY_leftarrow}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_RIGHT, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_l}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_RIGHT, m("none"), {{XKB_KEY_rightarrow}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_p}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_v}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_v}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE, m("none"), {{XKB_KEY_XF86Paste}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_PRIMARY_PASTE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Insert}}},
|
||||
};
|
||||
|
||||
conf->bindings.vimode_search.count = ALEN(bindings);
|
||||
|
|
|
|||
5
ime.c
5
ime.c
|
|
@ -198,10 +198,9 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
size_t len = strlen(text);
|
||||
|
||||
if (term != NULL) {
|
||||
if (term->vimode.searching) {
|
||||
if (term->vimode.searching)
|
||||
vimode_search_add_chars(term, text, len);
|
||||
render_refresh_vimode_search_box(term);
|
||||
} else
|
||||
else
|
||||
term_to_slave(term, text, len);
|
||||
}
|
||||
ime_reset_pending_commit(seat);
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ enum bind_action_vimode_search {
|
|||
BIND_ACTION_VIMODE_SEARCH_DELETE_PREV_CHAR,
|
||||
BIND_ACTION_VIMODE_SEARCH_LEFT,
|
||||
BIND_ACTION_VIMODE_SEARCH_RIGHT,
|
||||
BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE,
|
||||
BIND_ACTION_VIMODE_SEARCH_PRIMARY_PASTE,
|
||||
|
||||
BIND_ACTION_VIMODE_SEARCH_COUNT,
|
||||
};
|
||||
|
|
|
|||
226
vimode.c
226
vimode.c
|
|
@ -142,6 +142,56 @@ static void center_view_on_cursor(struct terminal *const term)
|
|||
}
|
||||
}
|
||||
|
||||
// move_cursor_delta
|
||||
//
|
||||
// Moves the cursor within the scrollback by the vector delta. If the
|
||||
// cursor goes outside the view bounds, the view is scrolled.
|
||||
//
|
||||
// Parameters:
|
||||
// delta - the number of rows/columns to move by. Negative values move
|
||||
// up/left, positive down/right.
|
||||
//
|
||||
static void move_cursor_delta(struct terminal *const term,
|
||||
struct coord const delta)
|
||||
{
|
||||
damage_cursor_cell(term);
|
||||
struct coord cursor = cursor_to_view_relative(term, term->vimode.cursor);
|
||||
cursor.row += delta.row;
|
||||
cursor.col += delta.col;
|
||||
|
||||
if (cursor.row < 0) {
|
||||
int const overflow = -cursor.row;
|
||||
cmd_scrollback_up(term, overflow);
|
||||
cursor.row = 0;
|
||||
} else if (cursor.row >= term->rows) {
|
||||
int const overflow = cursor.row - term->rows + 1;
|
||||
cmd_scrollback_down(term, overflow);
|
||||
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 = cursor_from_view_relative(term, cursor);
|
||||
LOG_DBG("CURSOR MOVED (%d, %d) [delta=(%d, %d)]", term->vimode.cursor.row,
|
||||
term->vimode.cursor.col, delta.row, delta.col);
|
||||
damage_cursor_cell(term);
|
||||
render_refresh(term);
|
||||
}
|
||||
|
||||
static void move_cursor_vertical(struct terminal *const term, int const count)
|
||||
{
|
||||
move_cursor_delta(term, (struct coord){.row = count, .col = 0});
|
||||
}
|
||||
|
||||
static void move_cursor_horizontal(struct terminal *const term, int const count)
|
||||
{
|
||||
move_cursor_delta(term, (struct coord){.row = 0, .col = count});
|
||||
}
|
||||
|
||||
static void update_selection(struct terminal *const term)
|
||||
{
|
||||
enum vi_mode const mode = term->vimode.mode;
|
||||
|
|
@ -527,7 +577,7 @@ static bool find_next(struct terminal *term, char32_t const *const buf,
|
|||
* rest of the search buffer matches.
|
||||
*/
|
||||
|
||||
LOG_DBG("search: initial match at row=%d, col=%d", match_start_row,
|
||||
LOG_DBG("search: initial match at (%d, %d)", match_start_row,
|
||||
match_start_col);
|
||||
|
||||
int match_end_row = match_start_row;
|
||||
|
|
@ -733,12 +783,47 @@ struct range search_matches_next(struct search_match_iterator *iter)
|
|||
return match;
|
||||
}
|
||||
|
||||
static void add_wchars(struct terminal *term, char32_t *src, size_t count)
|
||||
static void on_search_string_updated(struct terminal *const term)
|
||||
{
|
||||
LOG_DBG("SEARCH UPDATED [%ls]", (const wchar_t *)term->vimode.search.buf);
|
||||
struct range match;
|
||||
// TODO (kociap): when several consecutive searches succeed, the
|
||||
// cursor is not moved to its original position in-between
|
||||
// searches.
|
||||
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_in_abs_coord(term, term->vimode.search.match);
|
||||
move_cursor_delta(term, delta);
|
||||
center_view_on_cursor(term);
|
||||
update_selection(term);
|
||||
} else {
|
||||
restore_pre_search_state(term);
|
||||
}
|
||||
update_highlights(term);
|
||||
render_refresh_vimode_search_box(term);
|
||||
}
|
||||
|
||||
static void add_chars_to_search(struct terminal *term, char const *buffer,
|
||||
size_t const length)
|
||||
{
|
||||
size_t count = mbsntoc32(NULL, buffer, length, 0);
|
||||
if (count == (size_t)-1) {
|
||||
LOG_ERRNO("failed to convert %.*s to Unicode", (int)length, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
char32_t c32s[count + 1];
|
||||
mbsntoc32(c32s, buffer, length, count);
|
||||
|
||||
/* Strip non-printable characters */
|
||||
for (size_t i = 0, j = 0, orig_count = count; i < orig_count; i++) {
|
||||
if (isc32print(src[i]))
|
||||
src[j++] = src[i];
|
||||
if (isc32print(c32s[i]))
|
||||
c32s[j++] = c32s[i];
|
||||
else
|
||||
count--;
|
||||
}
|
||||
|
|
@ -753,7 +838,7 @@ static void add_wchars(struct terminal *term, char32_t *src, size_t count)
|
|||
(term->vimode.search.len - term->vimode.search.cursor) *
|
||||
sizeof(char32_t));
|
||||
|
||||
memcpy(&term->vimode.search.buf[term->vimode.search.cursor], src,
|
||||
memcpy(&term->vimode.search.buf[term->vimode.search.cursor], c32s,
|
||||
count * sizeof(char32_t));
|
||||
|
||||
term->vimode.search.len += count;
|
||||
|
|
@ -764,15 +849,8 @@ static void add_wchars(struct terminal *term, char32_t *src, size_t count)
|
|||
void vimode_search_add_chars(struct terminal *term, const char *src,
|
||||
size_t count)
|
||||
{
|
||||
size_t chars = mbsntoc32(NULL, src, count, 0);
|
||||
if (chars == (size_t)-1) {
|
||||
LOG_ERRNO("failed to convert %.*s to Unicode", (int)count, src);
|
||||
return;
|
||||
}
|
||||
|
||||
char32_t c32s[chars + 1];
|
||||
mbsntoc32(c32s, src, count, chars);
|
||||
add_wchars(term, c32s, chars);
|
||||
add_chars_to_search(term, src, count);
|
||||
on_search_string_updated(term);
|
||||
}
|
||||
|
||||
void vimode_view_down(struct terminal *const term, int const delta)
|
||||
|
|
@ -788,56 +866,6 @@ void vimode_view_down(struct terminal *const term, int const delta)
|
|||
update_highlights(term);
|
||||
}
|
||||
|
||||
// move_cursor_delta
|
||||
//
|
||||
// Moves the cursor within the scrollback by the vector delta. If the
|
||||
// cursor goes outside the view bounds, the view is scrolled.
|
||||
//
|
||||
// Parameters:
|
||||
// delta - the number of rows/columns to move by. Negative values move
|
||||
// up/left, positive down/right.
|
||||
//
|
||||
static void move_cursor_delta(struct terminal *const term,
|
||||
struct coord const delta)
|
||||
{
|
||||
damage_cursor_cell(term);
|
||||
struct coord cursor = cursor_to_view_relative(term, term->vimode.cursor);
|
||||
cursor.row += delta.row;
|
||||
cursor.col += delta.col;
|
||||
|
||||
if (cursor.row < 0) {
|
||||
int const overflow = -cursor.row;
|
||||
cmd_scrollback_up(term, overflow);
|
||||
cursor.row = 0;
|
||||
} else if (cursor.row >= term->rows) {
|
||||
int const overflow = cursor.row - term->rows + 1;
|
||||
cmd_scrollback_down(term, overflow);
|
||||
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 = cursor_from_view_relative(term, cursor);
|
||||
LOG_DBG("CURSOR MOVED (%d, %d) [delta=(%d, %d)]", term->vimode.cursor.row,
|
||||
term->vimode.cursor.col, delta.row, delta.col);
|
||||
damage_cursor_cell(term);
|
||||
render_refresh(term);
|
||||
}
|
||||
|
||||
static void move_cursor_vertical(struct terminal *const term, int const count)
|
||||
{
|
||||
move_cursor_delta(term, (struct coord){.row = count, .col = 0});
|
||||
}
|
||||
|
||||
static void move_cursor_horizontal(struct terminal *const term, int const count)
|
||||
{
|
||||
move_cursor_delta(term, (struct coord){.row = 0, .col = count});
|
||||
}
|
||||
|
||||
enum c32_class {
|
||||
CLASS_BLANK,
|
||||
CLASS_PUNCTUATION,
|
||||
|
|
@ -1396,6 +1424,18 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
|||
}
|
||||
}
|
||||
|
||||
static void from_clipboard_cb(char *text, size_t size, void *user)
|
||||
{
|
||||
struct terminal *term = user;
|
||||
add_chars_to_search(term, text, size);
|
||||
}
|
||||
|
||||
static void from_clipboard_done(void *user)
|
||||
{
|
||||
struct terminal *term = user;
|
||||
on_search_string_updated(term);
|
||||
}
|
||||
|
||||
static void execute_vimode_search_binding(struct seat *seat,
|
||||
struct terminal *const term,
|
||||
const struct key_binding *binding,
|
||||
|
|
@ -1438,7 +1478,6 @@ static void execute_vimode_search_binding(struct seat *seat,
|
|||
search->cursor -= 1;
|
||||
search->len -= 1;
|
||||
search->buf[search->len] = U'\0';
|
||||
render_refresh_vimode_search_box(term);
|
||||
*search_string_changed = true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1446,34 +1485,28 @@ static void execute_vimode_search_binding(struct seat *seat,
|
|||
case BIND_ACTION_VIMODE_SEARCH_LEFT:
|
||||
if (search->cursor > 0) {
|
||||
search->cursor -= 1;
|
||||
render_refresh_vimode_search_box(term);
|
||||
}
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_SEARCH_RIGHT:
|
||||
if (search->cursor < search->len) {
|
||||
search->cursor += 1;
|
||||
render_refresh_vimode_search_box(term);
|
||||
}
|
||||
break;
|
||||
|
||||
// case BIND_ACTION_SEARCH_CLIPBOARD_PASTE:
|
||||
// text_from_clipboard(seat, term, &from_clipboard_cb,
|
||||
// &from_clipboard_done,
|
||||
// term);
|
||||
// *update_search_result = *redraw = true;
|
||||
// return true;
|
||||
//
|
||||
// case BIND_ACTION_SEARCH_PRIMARY_PASTE:
|
||||
// text_from_primary(seat, term, &from_clipboard_cb,
|
||||
// &from_clipboard_done,
|
||||
// term);
|
||||
// *update_search_result = *redraw = true;
|
||||
// return true;
|
||||
//
|
||||
// case BIND_ACTION_SEARCH_UNICODE_INPUT:
|
||||
// unicode_mode_activate(term);
|
||||
// return true;
|
||||
case BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE:
|
||||
text_from_clipboard(seat, term, &from_clipboard_cb,
|
||||
&from_clipboard_done, term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_SEARCH_PRIMARY_PASTE:
|
||||
text_from_primary(seat, term, &from_clipboard_cb, &from_clipboard_done,
|
||||
term);
|
||||
break;
|
||||
|
||||
// case BIND_ACTION_VIMODE_SEARCH_UNICODE_INPUT:
|
||||
// unicode_mode_activate(term);
|
||||
// break;
|
||||
|
||||
case BIND_ACTION_VIMODE_COUNT:
|
||||
BUG("Invalid action type");
|
||||
|
|
@ -1579,34 +1612,13 @@ void vimode_input(struct seat *seat, struct terminal *term,
|
|||
}
|
||||
|
||||
if (count > 0) {
|
||||
vimode_search_add_chars(term, (const char *)buf, count);
|
||||
render_refresh_vimode_search_box(term);
|
||||
add_chars_to_search(term, (const char *)buf, count);
|
||||
search_string_updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (search_string_updated) {
|
||||
LOG_DBG("SEARCH UPDATED [%ls]",
|
||||
(const wchar_t *)term->vimode.search.buf);
|
||||
struct range match;
|
||||
// TODO (kociap): when several consecutive searches succeed, the
|
||||
// cursor is not moved to its original position in-between
|
||||
// searches.
|
||||
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_in_abs_coord(term, term->vimode.search.match);
|
||||
move_cursor_delta(term, delta);
|
||||
center_view_on_cursor(term);
|
||||
update_selection(term);
|
||||
} else {
|
||||
restore_pre_search_state(term);
|
||||
}
|
||||
update_highlights(term);
|
||||
on_search_string_updated(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue