summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/capsremap.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/bin/capsremap.c b/bin/capsremap.c
new file mode 100644
index 0000000..284eadd
--- /dev/null
+++ b/bin/capsremap.c
@@ -0,0 +1,90 @@
+// SPDX-FIleCopyrightText: 2017 Francisco Lopes da Silva
+// SPDX-FIleCopyrightText: 2023 Sam Nystrom <sam@samnystrom.dev>
+// SPDX-License-Identifier: MIT
+
+// Map the caps lock key to escape and caps+hjkl to the arrow keys
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <linux/input.h>
+
+const struct input_event
+syn = {.type = EV_SYN, .code = SYN_REPORT, .value = 0},
+esc_up = {.type = EV_KEY, .code = KEY_ESC , .value = 0},
+esc_down = {.type = EV_KEY, .code = KEY_ESC , .value = 1};
+
+const int delay = 10000;
+
+void hjkl_to_arrow(struct input_event *event) {
+ switch (event->code) {
+ case KEY_H:
+ event->code = KEY_LEFT;
+ break;
+ case KEY_J:
+ event->code = KEY_DOWN;
+ break;
+ case KEY_K:
+ event->code = KEY_UP;
+ break;
+ case KEY_L:
+ event->code = KEY_RIGHT;
+ break;
+ }
+}
+
+int main(int argc, char** argv) {
+ setbuf(stdin, NULL);
+ setbuf(stdout, NULL);
+
+ enum { START, CAPSLOCK_HELD, CAPSLOCK_IS_MODIFIER } state = START;
+
+ struct input_event event;
+ while (fread(&event, sizeof(event), 1, stdin) == 1) {
+ if (event.type == EV_MSC && event.code == MSC_SCAN) {
+ continue;
+ }
+ if (event.type != EV_KEY && event.type != EV_REL && event.type != EV_ABS) {
+ fwrite(&event, sizeof(event), 1, stdout);
+ continue;
+ }
+
+ switch (state) {
+ case START:
+ if (event.type == EV_KEY && event.code == KEY_CAPSLOCK && event.value) {
+ state = CAPSLOCK_HELD;
+ } else {
+ fwrite(&event, sizeof(event), 1, stdout);
+ }
+ break;
+ case CAPSLOCK_HELD:
+ if (event.type == EV_KEY && event.code == KEY_CAPSLOCK) {
+ if (event.value == 0) {
+ fwrite(&esc_down, sizeof(esc_down), 1, stdout);
+ fwrite(&syn, sizeof(syn), 1, stdout);
+ usleep(delay);
+ fwrite(&esc_up, sizeof(esc_up), 1, stdout);
+ state = START;
+ }
+ } else if (event.type == EV_KEY && event.value) {
+ hjkl_to_arrow(&event);
+ fwrite(&event, sizeof(event), 1, stdout);
+ state = CAPSLOCK_IS_MODIFIER;
+ } else {
+ fwrite(&event, sizeof(event), 1, stdout);
+ }
+ break;
+ case CAPSLOCK_IS_MODIFIER:
+ if (event.type == EV_KEY && event.code == KEY_CAPSLOCK) {
+ if (event.value == 0) {
+ state = START;
+ }
+ } else {
+ hjkl_to_arrow(&event);
+ fwrite(&event, sizeof(event), 1, stdout);
+ }
+ break;
+ }
+ }
+}