config: Add aliases

master
Raheman Vaiya 4 years ago
parent 9bbf048554
commit 1135ec29c2
  1. BIN
      data/keyd-application-mapper.1.gz
  2. BIN
      data/keyd.1.gz
  3. 54
      docs/keyd.scdoc
  4. 160
      src/config.c
  5. 11
      src/config.h

Binary file not shown.

Binary file not shown.

@ -177,7 +177,7 @@ and each modifier is one of:
Finally, each layer heading is followed by a set of bindings which take the form:
<key> = <keycode>|<macro>|<action>
<key> | <alias> = <key>|<macro>|<action>
for a description of <action> and <macro> see _ACTIONS_ and _MACROS_.
@ -277,6 +277,58 @@ E.G
*Note:* You may have to restart your applications for this to take effect.
## Aliases
A config file may include *aliases* which can be used as valid left hand values
in place of one or more keycodes. For example, the default alias *meta* is bound
to leftmeta and rightmeta. Thus the binding 'meta = a' is equivalent to the
bindings 'leftmeta = a' and 'rightmeta = a'.
Aliases are defined in a special section called 'aliases' where each line takes the form:
<name> = <key>
and _<key>_ must be a valid key name.
Note that <name> may itself be a valid key, in which case all references to the
key will be replaced with the new key. When used judiciously, aliases can be
used in conjunction with the include directive to share bindings between
keyboards with different physical layouts.
For example:
```
/etc/keyd/common:
meta = oneshot(meta)
alt = oneshot(alt)
a = a
s = o
# etc..
/etc/keyd/default.conf:
[ids]
*
[main]
include common
/etc/keyd/magic_keyboard.conf:
[ids]
004c:0267
[aliases]
meta = leftalt
meta = rightalt
alt = leftmeta
alt = rightmeta
[main]
include common
```
Allows the user to define a set of universal bindings in /etc/keyd/common without having to explicitly account for the transposed meta and alt keys on an apple keyboard.
## File Inclusion
Config files may include other files located within the config directory using

@ -120,39 +120,21 @@ fail:
/* Return up to two keycodes associated with the given name. */
static int lookup_keycodes(const char *name, uint8_t *code1, uint8_t *code2)
static uint8_t lookup_keycode(const char *name)
{
size_t i;
/*
* If the name is a modifier like 'control' we associate it with both
* corresponding key codes (e.g 'rightcontrol'/'leftcontrol')
*/
for (i = 0; i < MAX_MOD; i++) {
const struct modifier_table_ent *mod = &modifier_table[i];
if (!strcmp(mod->name, name)) {
*code1 = mod->code1;
*code2 = mod->code2;
return 0;
}
}
for (i = 0; i < 256; i++) {
const struct keycode_table_ent *ent = &keycode_table[i];
if (ent->name &&
(!strcmp(ent->name, name) ||
(ent->alt_name && !strcmp(ent->alt_name, name)))) {
*code1 = i;
*code2 = 0;
return 0;
return i;
}
}
return -1;
return 0;
}
int config_get_layer_index(const struct config *config, const char *name)
@ -166,12 +148,41 @@ int config_get_layer_index(const struct config *config, const char *name)
return -1;
}
/*
* Consumes a string of the form `[<layer>.]<key> = <descriptor>` and adds the
* mapping to the corresponding layer in the config.
*/
int set_layer_entry(const struct config *config, struct layer *layer,
const char *key, const struct descriptor *d)
{
size_t i;
int found = 0;
for (i = 0; i < config->nr_aliases; i++) {
const struct alias *alias = &config->aliases[i];
if (!strcmp(alias->name, key)) {
layer->keymap[alias->code] = *d;
found = 1;
}
}
if (!found) {
uint8_t code;
if (!(code = lookup_keycode(key))) {
err("%s is not a valid keycode or alias.", key);
return -1;
}
layer->keymap[code] = *d;
}
return 0;
}
int config_add_entry(struct config *config, const char *exp)
{
uint8_t code1, code2;
@ -210,21 +221,10 @@ int config_add_entry(struct config *config, const char *exp)
layer = &config->layers[idx];
if (lookup_keycodes(keyname, &code1, &code2) < 0) {
err("%s is not a valid key.", keyname);
return -1;
}
if (parse_descriptor(descstr, &d, config) < 0)
return -1;
if (code1)
layer->keymap[code1] = d;
if (code2)
layer->keymap[code2] = d;
return 0;
return set_layer_entry(config, layer, keyname, &d);
}
/*
@ -325,6 +325,71 @@ static void parse_globals(const char *path, struct config *config, struct ini_se
}
}
static void add_alias(struct config *config, const char *name, uint8_t code)
{
if (config->nr_aliases >= MAX_ALIASES) {
fprintf(stderr, "\tERROR: Max aliases (%d) exceeded\n",
MAX_ALIASES);
return;
}
struct alias *alias = &config->aliases[config->nr_aliases];
alias->name[sizeof(alias->name)-1] = 0;
strncpy(alias->name, name, sizeof(alias->name)-1);
alias->code = code;
config->nr_aliases++;
}
void create_modifier_aliases(struct config *config)
{
uint8_t aliased_mods[MAX_MOD] = { 0 };
size_t i;
for (i = 0; i < config->nr_aliases; i++) {
size_t j;
for (j = 0; j < MAX_MOD; j++) {
const struct modifier_table_ent *mod = &modifier_table[j];
const struct alias *alias = &config->aliases[i];
if (!strcmp(alias->name, mod->name))
aliased_mods[j] = 1;
}
}
for (i = 0; i < MAX_MOD; i++) {
const struct modifier_table_ent *mod = &modifier_table[i];
// Don't create modifier aliases for modifier names which are explicitly
// redefined by the user.
if (!aliased_mods[i]) {
add_alias(config, mod->name, mod->code1);
add_alias(config, mod->name, mod->code2);
}
}
}
static void parse_aliases(const char *path, struct config *config, struct ini_section *section)
{
size_t i;
for (i = 0; i < section->nr_entries;i++) {
uint8_t code;
struct ini_entry *ent = &section->entries[i];
if ((code = lookup_keycode(ent->val))) {
add_alias(config, ent->key, code);
} else {
fprintf(stderr,
"\tERROR %s:%zd: Failed to define alias %s, %s is not a valid keycode\n",
path, ent->lnum,
ent->key, ent->val);
}
}
}
int config_parse(struct config *config, const char *path)
{
size_t i;
@ -345,28 +410,29 @@ int config_parse(struct config *config, const char *path)
for (i = 0; i < ini->nr_sections; i++) {
section = &ini->sections[i];
if (!strcmp(section->name, "ids") ||
!strcmp(section->name, "global"))
continue;
if (config_add_layer(config, section->name) < 0)
fprintf(stderr, "\tERROR %s:%zd: %s\n", path, section->lnum, errstr);
if (!strcmp(section->name, "ids")) {
;;
} else if (!strcmp(section->name, "aliases")) {
parse_aliases(path, config, section);
} else if (!strcmp(section->name, "global")) {
parse_globals(path, config, section);
} else {
if (config_add_layer(config, section->name) < 0)
fprintf(stderr, "\tERROR %s:%zd: %s\n", path, section->lnum, errstr);
}
}
create_modifier_aliases(config);
/* Populate each layer. */
for (i = 0; i < ini->nr_sections; i++) {
size_t j;
char *layername;
section = &ini->sections[i];
if (!strcmp(section->name, "ids"))
continue;
if (!strcmp(section->name, "global")) {
parse_globals(path, config, section);
if (!strcmp(section->name, "ids") ||
!strcmp(section->name, "aliases") ||
!strcmp(section->name, "globals"))
continue;
}
layername = strtok(section->name, ":");

@ -13,12 +13,20 @@
#define MAX_MACROS 256
#define MAX_AUX_DESCRIPTORS 64
#define MAX_ALIAS_LEN 32
#define MAX_ALIASES 64
#include "layer.h"
#include "descriptor.h"
#include "macro.h"
#include "command.h"
struct alias {
char name[MAX_ALIAS_LEN];
uint8_t code;
};
struct config {
struct layer layers[MAX_LAYERS];
@ -26,9 +34,10 @@ struct config {
struct descriptor descriptors[MAX_AUX_DESCRIPTORS];
struct macro macros[MAX_MACROS];
struct command commands[MAX_COMMANDS];
struct alias aliases[MAX_ALIASES];
size_t nr_aliases;
size_t nr_layers;
size_t nr_macros;
size_t nr_descriptors;
size_t nr_commands;

Loading…
Cancel
Save