mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
wip: map key combos to custom text strings (including escapes)
With this, it is now possible to map key combos to custom escapes. The new bindings are defined in a new section, “text-bindings”, on the form “string=key combo”. The string can consist of printable characters, or \xNN style hex digits: [text-bindings] abcd = Control+a \x1b[A = Control+b Control+c Control+d # map ctrl+b/c/d to UP
This commit is contained in:
parent
8fa16f616c
commit
422d94fb46
5 changed files with 132 additions and 4 deletions
115
config.c
115
config.c
|
|
@ -111,6 +111,7 @@ static const char *const binding_action_map[] = {
|
|||
[BIND_ACTION_PIPE_SELECTED] = "pipe-selected",
|
||||
[BIND_ACTION_SHOW_URLS_COPY] = "show-urls-copy",
|
||||
[BIND_ACTION_SHOW_URLS_LAUNCH] = "show-urls-launch",
|
||||
[BIND_ACTION_TEXT_BINDING] = "text-binding",
|
||||
|
||||
/* Mouse-specific actions */
|
||||
[BIND_ACTION_SELECT_BEGIN] = "select-begin",
|
||||
|
|
@ -1480,7 +1481,8 @@ free_binding_aux(struct binding_aux *aux)
|
|||
{
|
||||
switch (aux->type) {
|
||||
case BINDING_AUX_NONE: break;
|
||||
case BINDING_AUX_PIPE: free_argv(&aux->pipe);
|
||||
case BINDING_AUX_PIPE: free_argv(&aux->pipe); break;
|
||||
case BINDING_AUX_TEXT: free(aux->text.data); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1578,8 +1580,15 @@ binding_aux_equal(const struct binding_aux *a,
|
|||
return false;
|
||||
|
||||
switch (a->type) {
|
||||
case BINDING_AUX_NONE: return true;
|
||||
case BINDING_AUX_PIPE: return argv_compare(&a->pipe, &b->pipe) == 0;
|
||||
case BINDING_AUX_NONE:
|
||||
return true;
|
||||
|
||||
case BINDING_AUX_PIPE:
|
||||
return argv_compare(&a->pipe, &b->pipe) == 0;
|
||||
|
||||
case BINDING_AUX_TEXT:
|
||||
return a->text.len == b->text.len &&
|
||||
memcmp(a->text.data, b->text.data, a->text.len) == 0;
|
||||
}
|
||||
|
||||
BUG("invalid AUX type: %d", a->type);
|
||||
|
|
@ -2230,6 +2239,81 @@ parse_section_mouse_bindings(struct context *ctx)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_section_text_bindings(struct context *ctx)
|
||||
{
|
||||
struct config *conf = ctx->conf;
|
||||
const char *key = ctx->key;
|
||||
|
||||
const size_t key_len = strlen(key);
|
||||
|
||||
uint8_t *data = xmalloc(key_len + 1);
|
||||
size_t data_len = 0;
|
||||
bool esc = false;
|
||||
|
||||
for (size_t i = 0; i < key_len; i++) {
|
||||
if (key[i] == '\\') {
|
||||
if (i + 1 >= key_len) {
|
||||
ctx->value = "";
|
||||
LOG_CONTEXTUAL_ERR("trailing backslash");
|
||||
goto err;
|
||||
}
|
||||
|
||||
esc = true;
|
||||
}
|
||||
|
||||
else if (esc) {
|
||||
if (key[i] != 'x') {
|
||||
ctx->value = "";
|
||||
LOG_CONTEXTUAL_ERR("invalid escaped character: %c", key[i]);
|
||||
goto err;
|
||||
}
|
||||
if (i + 2 >= key_len) {
|
||||
ctx->value = "";
|
||||
LOG_CONTEXTUAL_ERR("\\x sequence too short");
|
||||
goto err;
|
||||
}
|
||||
|
||||
const uint8_t nib1 = hex2nibble(key[i + 1]);
|
||||
const uint8_t nib2 = hex2nibble(key[i + 2]);
|
||||
|
||||
if (nib1 >= HEX_DIGIT_INVALID || nib2 >= HEX_DIGIT_INVALID) {
|
||||
ctx->value = "";
|
||||
LOG_CONTEXTUAL_ERR("invalid \\x sequence: \\x%c%c",
|
||||
key[i + 1], key[i + 2]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
data[data_len++] = nib1 << 4 | nib2;
|
||||
esc = false;
|
||||
i += 2;
|
||||
}
|
||||
|
||||
else
|
||||
data[data_len++] = key[i];
|
||||
}
|
||||
|
||||
struct binding_aux aux = {
|
||||
.type = BINDING_AUX_TEXT,
|
||||
.text = {
|
||||
.data = data,
|
||||
.len = data_len,
|
||||
},
|
||||
};
|
||||
|
||||
if (!value_to_key_combos(ctx, BIND_ACTION_TEXT_BINDING, &aux,
|
||||
&conf->bindings.key, KEY_BINDING))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
err:
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_section_tweak(struct context *ctx)
|
||||
{
|
||||
|
|
@ -2429,6 +2513,7 @@ enum section {
|
|||
SECTION_SEARCH_BINDINGS,
|
||||
SECTION_URL_BINDINGS,
|
||||
SECTION_MOUSE_BINDINGS,
|
||||
SECTION_TEXT_BINDINGS,
|
||||
SECTION_TWEAK,
|
||||
SECTION_COUNT,
|
||||
};
|
||||
|
|
@ -2452,6 +2537,7 @@ static const struct {
|
|||
[SECTION_SEARCH_BINDINGS] = {&parse_section_search_bindings, "search-bindings"},
|
||||
[SECTION_URL_BINDINGS] = {&parse_section_url_bindings, "url-bindings"},
|
||||
[SECTION_MOUSE_BINDINGS] = {&parse_section_mouse_bindings, "mouse-bindings"},
|
||||
[SECTION_TEXT_BINDINGS] = {&parse_section_text_bindings, "text-bindings"},
|
||||
[SECTION_TWEAK] = {&parse_section_tweak, "tweak"},
|
||||
};
|
||||
|
||||
|
|
@ -3085,6 +3171,8 @@ key_binding_list_clone(struct config_key_binding_list *dst,
|
|||
const struct config_key_binding_list *src)
|
||||
{
|
||||
struct argv *last_master_argv = NULL;
|
||||
uint8_t *last_master_text_data = NULL;
|
||||
size_t last_master_text_len = 0;
|
||||
|
||||
dst->count = src->count;
|
||||
dst->arr = xmalloc(src->count * sizeof(dst->arr[0]));
|
||||
|
|
@ -3098,6 +3186,8 @@ key_binding_list_clone(struct config_key_binding_list *dst,
|
|||
switch (old->aux.type) {
|
||||
case BINDING_AUX_NONE:
|
||||
last_master_argv = NULL;
|
||||
last_master_text_data = NULL;
|
||||
last_master_text_len = 0;
|
||||
break;
|
||||
|
||||
case BINDING_AUX_PIPE:
|
||||
|
|
@ -3108,6 +3198,25 @@ key_binding_list_clone(struct config_key_binding_list *dst,
|
|||
xassert(last_master_argv != NULL);
|
||||
new->aux.pipe = *last_master_argv;
|
||||
}
|
||||
last_master_text_data = NULL;
|
||||
last_master_text_len = 0;
|
||||
break;
|
||||
|
||||
case BINDING_AUX_TEXT:
|
||||
if (old->aux.master_copy) {
|
||||
const size_t len = old->aux.text.len;
|
||||
new->aux.text.len = len;
|
||||
new->aux.text.data = xmalloc(len);
|
||||
memcpy(new->aux.text.data, old->aux.text.data, len);
|
||||
|
||||
last_master_text_len = len;
|
||||
last_master_text_data = new->aux.text.data;
|
||||
} else {
|
||||
xassert(last_master_text_data != NULL);
|
||||
new->aux.text.len = last_master_text_len;
|
||||
new->aux.text.data = last_master_text_data;
|
||||
}
|
||||
last_master_argv = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
config.h
11
config.h
|
|
@ -47,6 +47,7 @@ struct argv {
|
|||
enum binding_aux_type {
|
||||
BINDING_AUX_NONE,
|
||||
BINDING_AUX_PIPE,
|
||||
BINDING_AUX_TEXT,
|
||||
};
|
||||
|
||||
struct binding_aux {
|
||||
|
|
@ -55,6 +56,11 @@ struct binding_aux {
|
|||
|
||||
union {
|
||||
struct argv pipe;
|
||||
|
||||
struct {
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
} text;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -63,6 +69,11 @@ enum key_binding_type {
|
|||
MOUSE_BINDING,
|
||||
};
|
||||
|
||||
struct config_key_binding_text {
|
||||
char *text;
|
||||
bool master_copy;
|
||||
};
|
||||
|
||||
struct config_key_binding {
|
||||
int action; /* One of the varios bind_action_* enums from wayland.h */
|
||||
struct config_key_modifiers modifiers;
|
||||
|
|
|
|||
3
foot.ini
3
foot.ini
|
|
@ -178,4 +178,7 @@
|
|||
# select-word-whitespace=Control+BTN_LEFT-2
|
||||
# select-row=BTN_LEFT-3
|
||||
|
||||
[text-bindings]
|
||||
# \x01=Mod4+a # Map Super+a -> Ctrl+a
|
||||
|
||||
# vim: ft=conf
|
||||
|
|
|
|||
5
input.c
5
input.c
|
|
@ -313,6 +313,11 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
return true;
|
||||
}
|
||||
|
||||
case BIND_ACTION_TEXT_BINDING:
|
||||
xassert(binding->aux->type == BINDING_AUX_TEXT);
|
||||
term_to_slave(term, binding->aux->text.data, binding->aux->text.len);
|
||||
return true;
|
||||
|
||||
case BIND_ACTION_SELECT_BEGIN:
|
||||
selection_start(
|
||||
term, seat->mouse.col, seat->mouse.row, SELECTION_CHAR_WISE, false);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ enum bind_action_normal {
|
|||
BIND_ACTION_PIPE_SELECTED,
|
||||
BIND_ACTION_SHOW_URLS_COPY,
|
||||
BIND_ACTION_SHOW_URLS_LAUNCH,
|
||||
BIND_ACTION_TEXT_BINDING,
|
||||
|
||||
/* Mouse specific actions - i.e. they require a mouse coordinate */
|
||||
BIND_ACTION_SELECT_BEGIN,
|
||||
|
|
@ -119,7 +120,6 @@ struct key_binding {
|
|||
};
|
||||
|
||||
const struct binding_aux *aux;
|
||||
|
||||
};
|
||||
typedef tll(struct key_binding) key_binding_list_t;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue