commit 6cc582a9b5ff623c7f8f6986d08adf9c852586e1
parent 4eb6607e874a08c30f9b23e43d822f45a3a1dd26
Author: Bastien Dejean <nihilhill@gmail.com>
Date: Wed, 9 Jan 2013 12:59:05 +0100
Extend sequences to the hotkeys
Diffstat:
M | README.md | | | 2 | +- |
M | keys.c | | | 99 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
M | keys.h | | | 3 | ++- |
M | sxhkd.1 | | | 7 | ++----- |
M | sxhkd.c | | | 30 | ++++++++++-------------------- |
5 files changed, 76 insertions(+), 65 deletions(-)
diff --git a/README.md b/README.md
@@ -36,7 +36,7 @@ The keysym names are those your will get from `xev` (minus the prefix if any).
Mouse hotkeys can be defined by using one of the following special keysym names: `button1`, `button2`, `button3`, ..., `button24`.
-`KEYSYM` can contain a sequence of the form `{STRING_1,…,STRING_N}`, in which case, `COMMAND` must also contain a sequence with *N* elements: the pairing of the two sequences generates *N* hotkeys.
+The hotkey can contain a sequence of the form `{STRING_1,…,STRING_N}`, in which case, the command must also contain a sequence with *N* elements: the pairing of the two sequences generates *N* hotkeys.
In addition, the sequences can contain ranges of the form `A-Z` where *A* and *Z* are alphanumeric characters.
diff --git a/keys.c b/keys.c
@@ -2454,6 +2454,29 @@ xcb_keycode_t *keycodes_from_keysym(xcb_keysym_t keysym)
return result;
}
+bool parse_hotkey(char *string, xcb_keysym_t *keysym, xcb_button_t *button, uint16_t *modfield, uint8_t *event_type) {
+ char backup[MAXLEN];
+ strncpy(backup, string, sizeof(backup));
+ backup[strlen(string)] = '\0';
+ for (char *name = strtok(string, TOK_SEP); name != NULL; name = strtok(NULL, TOK_SEP)) {
+ if (name[0] == RELEASE_PREFIX) {
+ *event_type = XCB_KEY_RELEASE;
+ name++;
+ } else if (name[0] == MOTION_PREFIX) {
+ *event_type = XCB_MOTION_NOTIFY;
+ name++;
+ }
+ if (!parse_modifier(name, modfield) && !parse_key(name, keysym) && !parse_button(name, button)) {
+ warn("Unrecognized key name: '%s'.\n", name);
+ }
+ }
+ if (*keysym == XCB_NO_SYMBOL && *button == XCB_NONE) {
+ warn("Invalid hotkey: '%s'.\n", backup);
+ return false;
+ }
+ return true;
+}
+
bool parse_key(char *name, xcb_keysym_t *keysym)
{
for (unsigned int i = 0; i < LENGTH(nks_dict); i++) {
@@ -2517,11 +2540,11 @@ bool parse_modifier(char *name, uint16_t *modfield)
return false;
}
-bool parse_fold(char *name, char *folded_keysym)
+bool parse_fold(char *string, char *folded_string)
{
- if (strchr(name, SEQ_BEGIN) != NULL && strrchr(name, SEQ_END) != NULL) {
- strncpy(folded_keysym, name, strlen(name));
- folded_keysym[strlen(name)] = '\0';
+ if (strchr(string, SEQ_BEGIN) != NULL && strrchr(string, SEQ_END) != NULL) {
+ strncpy(folded_string, string, strlen(string));
+ folded_string[strlen(string)] = '\0';
return true;
}
return false;
@@ -2559,51 +2582,51 @@ bool extract_sequence(char *string, char *prefix, char *sequence, char *suffix)
return true;
}
-void unfold_hotkeys(char *folded_keysym, uint16_t modfield, uint8_t event_type, char *folded_command)
+void unfold_hotkeys(char *folded_hotkey, char *folded_command)
{
- char keysym_sequence[MAXLEN];
- char keysym_prefix[MAXLEN];
- char keysym_suffix[MAXLEN];
+ char hotkey_sequence[MAXLEN];
+ char hotkey_prefix[MAXLEN];
+ char hotkey_suffix[MAXLEN];
char command_sequence[MAXLEN];
char command_prefix[MAXLEN];
char command_suffix[MAXLEN];
- if (!extract_sequence(folded_keysym, keysym_prefix, keysym_sequence, keysym_suffix) || !extract_sequence(folded_command, command_prefix, command_sequence, command_suffix)) {
- warn("Couldn't extract sequence from '%s' or '%s'.\n", folded_keysym, folded_command);
+ if (!extract_sequence(folded_hotkey, hotkey_prefix, hotkey_sequence, hotkey_suffix) || !extract_sequence(folded_command, command_prefix, command_sequence, command_suffix)) {
+ warn("Couldn't extract sequence from '%s' or '%s'.\n", folded_hotkey, folded_command);
return;
}
- char unfolded_keysym[MAXLEN], unfolded_command[MAXLEN];
+ char unfolded_hotkey[MAXLEN], unfolded_command[MAXLEN];
xcb_keysym_t keysym = XCB_NO_SYMBOL;
xcb_button_t button = XCB_NONE;
- char *ks_ptr, *cmd_ptr;
- char ks_a = 1, ks_z = 0, cmd_a = 1, cmd_z = 0;
- char *ks_item = strtok_r(keysym_sequence, SEQ_SEP, &ks_ptr);
+ uint16_t modfield = 0;
+ uint8_t event_type = XCB_KEY_PRESS;
+ char *hk_ptr, *cmd_ptr;
+ char hk_a = 1, hk_z = 0, cmd_a = 1, cmd_z = 0;
+ char *hk_item = strtok_r(hotkey_sequence, SEQ_SEP, &hk_ptr);
char *cmd_item = strtok_r(command_sequence, SEQ_SEP, &cmd_ptr);
- while ((ks_item != NULL || ks_a <= ks_z) && (cmd_item != NULL || cmd_a <= cmd_z)) {
- if (ks_a > ks_z && strlen(ks_item) == 3 && sscanf(ks_item, "%c-%c", &ks_a, &ks_z) == 2 && ks_a >= ks_z)
- ks_a = 1, ks_z = 0;
- if (cmd_a > cmd_z && strlen(cmd_item) == 3 && sscanf(cmd_item, "%c-%c", &cmd_a, &cmd_z) == 2 && cmd_a >= cmd_z)
- cmd_a = 1, cmd_z = 0;
- if (ks_a <= ks_z)
- snprintf(unfolded_keysym, sizeof(unfolded_keysym), "%s%c%s", keysym_prefix, ks_a, keysym_suffix);
- else
- snprintf(unfolded_keysym, sizeof(unfolded_keysym), "%s%s%s", keysym_prefix, ks_item, keysym_suffix);
- if (cmd_a <= cmd_z)
- snprintf(unfolded_command, sizeof(unfolded_command), "%s%c%s", command_prefix, cmd_a, command_suffix);
- else
- snprintf(unfolded_command, sizeof(unfolded_command), "%s%s%s", command_prefix, cmd_item, command_suffix);
- if (parse_key(unfolded_keysym, &keysym) || parse_button(unfolded_keysym, &button))
+ while ((hk_item != NULL || hk_a <= hk_z) && (cmd_item != NULL || cmd_a <= cmd_z)) {
+#define PREGEN(elt, ra, rz, prefix, suffix, unf) \
+ if (ra > rz && strlen(elt) == 3 && sscanf(elt, "%c-%c", &ra, &rz) == 2 && ra >= rz) \
+ ra = 1, rz = 0; \
+ if (ra <= rz) \
+ snprintf(unf, sizeof(unf), "%s%c%s", prefix, ra, suffix); \
+ else \
+ snprintf(unf, sizeof(unf), "%s%s%s", prefix, elt, suffix);
+ PREGEN(hk_item, hk_a, hk_z, hotkey_prefix, hotkey_suffix, unfolded_hotkey);
+ PREGEN(cmd_item, cmd_a, cmd_z, command_prefix, command_suffix, unfolded_command);
+#undef PREGEN
+
+ if (parse_hotkey(unfolded_hotkey, &keysym, &button, &modfield, &event_type))
generate_hotkeys(keysym, button, modfield, event_type, unfolded_command);
- else
- warn("Unknown sequence keysym: '%s'.\n", ks_item);
- if (ks_a >= ks_z)
- ks_item = strtok_r(NULL, SEQ_SEP, &ks_ptr), ks_a = 1, ks_z = 0;
- else
- ks_a++;
- if (cmd_a >= cmd_z)
- cmd_item = strtok_r(NULL, SEQ_SEP, &cmd_ptr), cmd_a = 1, cmd_z = 0;
- else
- cmd_a++;
+
+#define POSTGEN(elt, ra, rz, ptr) \
+ if (ra > rz) \
+ elt = strtok_r(NULL, SEQ_SEP, &ptr), ra = 1, rz = 0; \
+ else \
+ ra++;
+ POSTGEN(hk_item, hk_a, hk_z, hk_ptr);
+ POSTGEN(cmd_item, cmd_a, cmd_z, cmd_ptr);
+#undef POSTGEN
}
}
diff --git a/keys.h b/keys.h
@@ -21,13 +21,14 @@ void grab_key_button_checked(xcb_keycode_t, xcb_button_t, uint16_t);
void ungrab(void);
int16_t modfield_from_keysym(xcb_keysym_t);
xcb_keycode_t *keycodes_from_keysym(xcb_keysym_t);
+bool parse_hotkey(char *, xcb_keysym_t *, xcb_button_t *, uint16_t *, uint8_t *);
bool parse_key(char *, xcb_keysym_t *);
bool parse_button(char *, xcb_button_t *);
bool parse_modifier(char *, uint16_t *);
bool parse_fold(char *, char *);
uint8_t key_to_button(uint8_t);
void get_lock_fields(void);
-void unfold_hotkeys(char *, uint16_t, uint8_t, char *);
+void unfold_hotkeys(char *, char *);
void generate_hotkeys(xcb_keysym_t, xcb_button_t, uint16_t, uint8_t, char *);
hotkey_t *make_hotkey(xcb_keysym_t, xcb_button_t, uint16_t, uint8_t, char *);
hotkey_t *find_hotkey(xcb_keysym_t, xcb_button_t, uint16_t, uint8_t);
diff --git a/sxhkd.1 b/sxhkd.1
@@ -60,12 +60,9 @@ The keysym names are those your will get from
Mouse hotkeys can be defined by using one of the following special keysym names:
.BR button1 ", " button2 ", " button3 ", ..., " button24 .
.PP
-.I KEYSYM
-can contain a sequence of the form
+The hotkey can contain a sequence of the form
.IR {STRING_1,…,STRING_N} ,
-in which case,
-.I COMMAND
-must also contain a sequence with
+in which case, the command must also contain a sequence with
.I N
elements: the pairing of the two sequences generates
.I N
diff --git a/sxhkd.c b/sxhkd.c
@@ -80,13 +80,13 @@ void load_config(char *config_file)
xcb_button_t button = XCB_NONE;
uint16_t modfield = 0;
uint8_t event_type = XCB_KEY_PRESS;
- char folded_keysym[MAXLEN] = {'\0'};
+ char folded_hotkey[MAXLEN] = {'\0'};
while (fgets(line, sizeof(line), cfg) != NULL) {
if (strlen(line) < 2 || line[0] == START_COMMENT) {
continue;
} else if (isspace(line[0])) {
- if (keysym == XCB_NO_SYMBOL && button == XCB_NONE && strlen(folded_keysym) == 0)
+ if (keysym == XCB_NO_SYMBOL && button == XCB_NONE && strlen(folded_hotkey) == 0)
continue;
unsigned int i = strlen(line) - 1;
while (i > 0 && isspace(line[i]))
@@ -96,32 +96,22 @@ void load_config(char *config_file)
i++;
if (i < strlen(line)) {
char *command = line + i;
- if (strlen(folded_keysym) == 0)
+ if (strlen(folded_hotkey) == 0)
generate_hotkeys(keysym, button, modfield, event_type, command);
else
- unfold_hotkeys(folded_keysym, modfield, event_type, command);
+ unfold_hotkeys(folded_hotkey, command);
}
keysym = XCB_NO_SYMBOL;
button = XCB_NONE;
modfield = 0;
event_type = XCB_KEY_PRESS;
- folded_keysym[0] = '\0';
+ folded_hotkey[0] = '\0';
} else {
- char *name = strtok(line, TOK_SEP);
- if (name == NULL)
- continue;
- do {
- if (name[0] == RELEASE_PREFIX) {
- event_type = XCB_KEY_RELEASE;
- name++;
- } else if (name[0] == MOTION_PREFIX) {
- event_type = XCB_MOTION_NOTIFY;
- name++;
- }
- if (!parse_modifier(name, &modfield) && !parse_key(name, &keysym) && !parse_button(name, &button) && !parse_fold(name, folded_keysym)) {
- warn("Unrecognized key name: '%s'.\n", name);
- }
- } while ((name = strtok(NULL, TOK_SEP)) != NULL);
+ unsigned int i = strlen(line) - 1;
+ while (i > 0 && isspace(line[i]))
+ line[i--] = '\0';
+ if (!parse_fold(line, folded_hotkey))
+ parse_hotkey(line, &keysym, &button, &modfield, &event_type);
}
}