mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-15 05:33:58 -04: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_DELETE_PREV_CHAR] = "vimode-search-delete-prev",
|
||||||
[BIND_ACTION_VIMODE_SEARCH_LEFT] = "vimode-search-left",
|
[BIND_ACTION_VIMODE_SEARCH_LEFT] = "vimode-search-left",
|
||||||
[BIND_ACTION_VIMODE_SEARCH_RIGHT] = "vimode-search-right",
|
[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[] = {
|
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_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(XKB_MOD_NAME_CTRL), {{XKB_KEY_l}}},
|
||||||
{BIND_ACTION_VIMODE_SEARCH_RIGHT, m("none"), {{XKB_KEY_rightarrow}}},
|
{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);
|
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);
|
size_t len = strlen(text);
|
||||||
|
|
||||||
if (term != NULL) {
|
if (term != NULL) {
|
||||||
if (term->vimode.searching) {
|
if (term->vimode.searching)
|
||||||
vimode_search_add_chars(term, text, len);
|
vimode_search_add_chars(term, text, len);
|
||||||
render_refresh_vimode_search_box(term);
|
else
|
||||||
} else
|
|
||||||
term_to_slave(term, text, len);
|
term_to_slave(term, text, len);
|
||||||
}
|
}
|
||||||
ime_reset_pending_commit(seat);
|
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_DELETE_PREV_CHAR,
|
||||||
BIND_ACTION_VIMODE_SEARCH_LEFT,
|
BIND_ACTION_VIMODE_SEARCH_LEFT,
|
||||||
BIND_ACTION_VIMODE_SEARCH_RIGHT,
|
BIND_ACTION_VIMODE_SEARCH_RIGHT,
|
||||||
|
BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE,
|
||||||
|
BIND_ACTION_VIMODE_SEARCH_PRIMARY_PASTE,
|
||||||
|
|
||||||
BIND_ACTION_VIMODE_SEARCH_COUNT,
|
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)
|
static void update_selection(struct terminal *const term)
|
||||||
{
|
{
|
||||||
enum vi_mode const mode = term->vimode.mode;
|
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.
|
* 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);
|
match_start_col);
|
||||||
|
|
||||||
int match_end_row = match_start_row;
|
int match_end_row = match_start_row;
|
||||||
|
|
@ -733,12 +783,47 @@ struct range search_matches_next(struct search_match_iterator *iter)
|
||||||
return match;
|
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 */
|
/* Strip non-printable characters */
|
||||||
for (size_t i = 0, j = 0, orig_count = count; i < orig_count; i++) {
|
for (size_t i = 0, j = 0, orig_count = count; i < orig_count; i++) {
|
||||||
if (isc32print(src[i]))
|
if (isc32print(c32s[i]))
|
||||||
src[j++] = src[i];
|
c32s[j++] = c32s[i];
|
||||||
else
|
else
|
||||||
count--;
|
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) *
|
(term->vimode.search.len - term->vimode.search.cursor) *
|
||||||
sizeof(char32_t));
|
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));
|
count * sizeof(char32_t));
|
||||||
|
|
||||||
term->vimode.search.len += count;
|
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,
|
void vimode_search_add_chars(struct terminal *term, const char *src,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
size_t chars = mbsntoc32(NULL, src, count, 0);
|
add_chars_to_search(term, src, count);
|
||||||
if (chars == (size_t)-1) {
|
on_search_string_updated(term);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vimode_view_down(struct terminal *const term, int const delta)
|
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);
|
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 {
|
enum c32_class {
|
||||||
CLASS_BLANK,
|
CLASS_BLANK,
|
||||||
CLASS_PUNCTUATION,
|
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,
|
static void execute_vimode_search_binding(struct seat *seat,
|
||||||
struct terminal *const term,
|
struct terminal *const term,
|
||||||
const struct key_binding *binding,
|
const struct key_binding *binding,
|
||||||
|
|
@ -1438,7 +1478,6 @@ static void execute_vimode_search_binding(struct seat *seat,
|
||||||
search->cursor -= 1;
|
search->cursor -= 1;
|
||||||
search->len -= 1;
|
search->len -= 1;
|
||||||
search->buf[search->len] = U'\0';
|
search->buf[search->len] = U'\0';
|
||||||
render_refresh_vimode_search_box(term);
|
|
||||||
*search_string_changed = true;
|
*search_string_changed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1446,34 +1485,28 @@ static void execute_vimode_search_binding(struct seat *seat,
|
||||||
case BIND_ACTION_VIMODE_SEARCH_LEFT:
|
case BIND_ACTION_VIMODE_SEARCH_LEFT:
|
||||||
if (search->cursor > 0) {
|
if (search->cursor > 0) {
|
||||||
search->cursor -= 1;
|
search->cursor -= 1;
|
||||||
render_refresh_vimode_search_box(term);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_SEARCH_RIGHT:
|
case BIND_ACTION_VIMODE_SEARCH_RIGHT:
|
||||||
if (search->cursor < search->len) {
|
if (search->cursor < search->len) {
|
||||||
search->cursor += 1;
|
search->cursor += 1;
|
||||||
render_refresh_vimode_search_box(term);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case BIND_ACTION_SEARCH_CLIPBOARD_PASTE:
|
case BIND_ACTION_VIMODE_SEARCH_CLIPBOARD_PASTE:
|
||||||
// text_from_clipboard(seat, term, &from_clipboard_cb,
|
text_from_clipboard(seat, term, &from_clipboard_cb,
|
||||||
// &from_clipboard_done,
|
&from_clipboard_done, term);
|
||||||
// term);
|
break;
|
||||||
// *update_search_result = *redraw = true;
|
|
||||||
// return true;
|
case BIND_ACTION_VIMODE_SEARCH_PRIMARY_PASTE:
|
||||||
//
|
text_from_primary(seat, term, &from_clipboard_cb, &from_clipboard_done,
|
||||||
// case BIND_ACTION_SEARCH_PRIMARY_PASTE:
|
term);
|
||||||
// text_from_primary(seat, term, &from_clipboard_cb,
|
break;
|
||||||
// &from_clipboard_done,
|
|
||||||
// term);
|
// case BIND_ACTION_VIMODE_SEARCH_UNICODE_INPUT:
|
||||||
// *update_search_result = *redraw = true;
|
// unicode_mode_activate(term);
|
||||||
// return true;
|
// break;
|
||||||
//
|
|
||||||
// case BIND_ACTION_SEARCH_UNICODE_INPUT:
|
|
||||||
// unicode_mode_activate(term);
|
|
||||||
// return true;
|
|
||||||
|
|
||||||
case BIND_ACTION_VIMODE_COUNT:
|
case BIND_ACTION_VIMODE_COUNT:
|
||||||
BUG("Invalid action type");
|
BUG("Invalid action type");
|
||||||
|
|
@ -1579,34 +1612,13 @@ void vimode_input(struct seat *seat, struct terminal *term,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
vimode_search_add_chars(term, (const char *)buf, count);
|
add_chars_to_search(term, (const char *)buf, count);
|
||||||
render_refresh_vimode_search_box(term);
|
|
||||||
search_string_updated = true;
|
search_string_updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (search_string_updated) {
|
if (search_string_updated) {
|
||||||
LOG_DBG("SEARCH UPDATED [%ls]",
|
on_search_string_updated(term);
|
||||||
(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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue