mirror of
https://gitlab.com/interception/linux/plugins/caps2esc.git
synced 2025-07-06 11:03:22 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
230f5c70d3 | |||
15636b64e7 | |||
6ab17c7d1a | |||
220ca0bc71 | |||
bb09cd8d9a | |||
0d88388a9e | |||
9f353f96c6 | |||
27efcbbf96 | |||
6fa3ad14b3 | |||
40137670a4 |
70
README.md
70
README.md
@ -4,9 +4,7 @@ _Transforming the most useless key **ever** in the most useful one._
|
||||
<sub>_For vi/Vim/NeoVim addicts at least_.</sub>
|
||||
|
||||
<a href="http://www.catonmat.net/blog/why-vim-uses-hjkl-as-arrow-keys/">
|
||||
|
||||

|
||||
|
||||
<img src="http://www.catonmat.net/images/why-vim-uses-hjkl/lsi-adm3a-full-keyboard.jpg" alt="ADM-3A terminal">
|
||||
</a>
|
||||
|
||||
## What is it?
|
||||
@ -28,21 +26,37 @@ ESC when pressed alone is quite handy, specially in vi.
|
||||
## Building
|
||||
|
||||
```
|
||||
$ git clone git@gitlab.com:interception/linux/tools.git
|
||||
$ cd tools
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ git clone git@gitlab.com:interception/linux/plugins/caps2esc.git
|
||||
$ cd caps2esc
|
||||
$ cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
$ cmake --build build
|
||||
```
|
||||
|
||||
## Execution
|
||||
|
||||
```
|
||||
caps2esc - transforming the most useless key ever in the most useful one
|
||||
|
||||
usage: caps2esc [-h] [-m mode]
|
||||
|
||||
options:
|
||||
-h show this message and exit
|
||||
-m mode 0: default
|
||||
- caps as esc/ctrl
|
||||
- esc as caps
|
||||
1: minimal
|
||||
- caps as esc/ctrl
|
||||
2: useful on 60% layouts
|
||||
- caps as esc/ctrl
|
||||
- esc as grave accent
|
||||
- grave accent as caps
|
||||
```
|
||||
|
||||
`caps2esc` is an [_Interception Tools_][interception-tools] plugin. A suggested
|
||||
`udevmon` job configuration is:
|
||||
|
||||
```yaml
|
||||
- JOB: "intercept -g $DEVNODE | caps2esc | uinput -d $DEVNODE"
|
||||
- JOB: intercept -g $DEVNODE | caps2esc | uinput -d $DEVNODE
|
||||
DEVICE:
|
||||
EVENTS:
|
||||
EV_KEY: [KEY_CAPSLOCK, KEY_ESC]
|
||||
@ -52,11 +66,43 @@ $ make
|
||||
For more information about the [_Interception Tools_][interception-tools], check
|
||||
the project's website.
|
||||
|
||||
## Mouse button support
|
||||
|
||||
After _Interception Tools_ 0.3, `caps2esc` can work with mouse clicks. An
|
||||
example configuration taken from my laptop:
|
||||
|
||||
```yaml
|
||||
SHELL: [zsh, -c]
|
||||
---
|
||||
- JOB: mux -c caps2esc
|
||||
- JOB:
|
||||
- intercept -g $DEVNODE | mux -o caps2esc
|
||||
- mux -i caps2esc | caps2esc | uinput -d $DEVNODE
|
||||
DEVICE:
|
||||
LINK: /dev/input/by-path/platform-i8042-serio-0-event-kbd
|
||||
- JOB:
|
||||
- intercept $DEVNODE | mux -o caps2esc
|
||||
DEVICE:
|
||||
LINK: /dev/input/by-path/platform-i8042-serio-4-event-mouse
|
||||
```
|
||||
|
||||
For more information on the topic, check the [_Interception Tools_
|
||||
README][interception-tools] about usage of the `mux` tool and device specific
|
||||
setups.
|
||||
|
||||
## Installation
|
||||
|
||||
I'm maintaining an Archlinux package on AUR:
|
||||
It's available from [community](https://archlinux.org/packages/community/x86_64/interception-caps2esc/):
|
||||
|
||||
- <https://aur.archlinux.org/packages/interception-caps2esc>
|
||||
```
|
||||
$ pacman -S interception-caps2esc
|
||||
```
|
||||
|
||||
I don't use Ubuntu and recommend Archlinux instead, as it provides the AUR, so I
|
||||
don't maintain PPAs. For more information on Ubuntu/Debian installation check
|
||||
this:
|
||||
|
||||
- <https://askubuntu.com/questions/979359/how-do-i-install-caps2esc>
|
||||
|
||||
## Caveats
|
||||
|
||||
|
67
caps2esc.c
67
caps2esc.c
@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
// clang-format off
|
||||
@ -13,9 +14,32 @@ ctrl_down = {.type = EV_KEY, .code = KEY_LEFTCTRL, .value = 1},
|
||||
capslock_down = {.type = EV_KEY, .code = KEY_CAPSLOCK, .value = 1},
|
||||
esc_repeat = {.type = EV_KEY, .code = KEY_ESC, .value = 2},
|
||||
ctrl_repeat = {.type = EV_KEY, .code = KEY_LEFTCTRL, .value = 2},
|
||||
capslock_repeat = {.type = EV_KEY, .code = KEY_CAPSLOCK, .value = 2};
|
||||
capslock_repeat = {.type = EV_KEY, .code = KEY_CAPSLOCK, .value = 2},
|
||||
syn = {.type = EV_SYN, .code = SYN_REPORT, .value = 0};
|
||||
// clang-format on
|
||||
|
||||
void print_usage(FILE *stream, const char *program) {
|
||||
// clang-format off
|
||||
fprintf(stream,
|
||||
"caps2esc - transforming the most useless key ever in the most useful one\n"
|
||||
"\n"
|
||||
"usage: %s [-h] [-m mode]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -h show this message and exit\n"
|
||||
" -m mode 0: default\n"
|
||||
" - caps as esc/ctrl\n"
|
||||
" - esc as caps\n"
|
||||
" 1: minimal\n"
|
||||
" - caps as esc/ctrl\n"
|
||||
" 2: useful on 60%% layouts\n"
|
||||
" - caps as esc/ctrl\n"
|
||||
" - esc as grave accent\n"
|
||||
" - grave accent as caps\n",
|
||||
program);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
int equal(const struct input_event *first, const struct input_event *second) {
|
||||
return first->type == second->type && first->code == second->code &&
|
||||
first->value == second->value;
|
||||
@ -30,13 +54,29 @@ void write_event(const struct input_event *event) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int main(int argc, char *argv[]) {
|
||||
int opt, mode = 0;
|
||||
while ((opt = getopt(argc, argv, "hm:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
return print_usage(stdout, argv[0]), EXIT_SUCCESS;
|
||||
case 'm':
|
||||
mode = optarg[0] - '0';
|
||||
continue;
|
||||
}
|
||||
|
||||
return print_usage(stderr, argv[0]), EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int capslock_is_down = 0, esc_give_up = 0;
|
||||
struct input_event input;
|
||||
|
||||
setbuf(stdin, NULL), setbuf(stdout, NULL);
|
||||
|
||||
while (read_event(&input)) {
|
||||
if (input.type == EV_MSC && input.code == MSC_SCAN)
|
||||
continue;
|
||||
|
||||
if (input.type != EV_KEY) {
|
||||
write_event(&input);
|
||||
continue;
|
||||
@ -55,6 +95,8 @@ int main(void) {
|
||||
continue;
|
||||
}
|
||||
write_event(&esc_down);
|
||||
write_event(&syn);
|
||||
usleep(20000);
|
||||
write_event(&esc_up);
|
||||
continue;
|
||||
}
|
||||
@ -62,14 +104,31 @@ int main(void) {
|
||||
if (!esc_give_up && input.value) {
|
||||
esc_give_up = 1;
|
||||
write_event(&ctrl_down);
|
||||
write_event(&syn);
|
||||
usleep(20000);
|
||||
}
|
||||
} else if (equal(&input, &capslock_down)) {
|
||||
capslock_is_down = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (input.code == KEY_ESC)
|
||||
input.code = KEY_CAPSLOCK;
|
||||
switch (mode) {
|
||||
case 0:
|
||||
if (input.code == KEY_ESC)
|
||||
input.code = KEY_CAPSLOCK;
|
||||
break;
|
||||
case 2:
|
||||
switch (input.code) {
|
||||
case KEY_ESC:
|
||||
input.code = KEY_GRAVE;
|
||||
break;
|
||||
case KEY_GRAVE:
|
||||
input.code = KEY_CAPSLOCK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
write_event(&input);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user