ref: 4df727b57afa439027df111205b29ed4590f6a72
parent: 444ba84bc1bb4ce22e6675cd49470b437e7bc3a7
author: Jacob Moody <moody@posixcafe.org>
date: Mon May 22 12:36:32 EDT 2023
kbremap: switch keyboard maps with a keyboard shortcut
--- a/sys/man/1/kbmap
+++ b/sys/man/1/kbmap
@@ -1,11 +1,22 @@
.TH KBMAP 1
.SH NAME
-kbmap \- show a list of available keyboard maps and switch between them.
+kbmap, kbremap \- show a list of available keyboard maps and switch between them.
.SH SYNOPSIS
.B kbmap
[
.IR file ...
]
+.PP
+.B kbremap
+[
+.B -m
+.I mod
+]
+[
+.B -k
+.I scancode
+]
+map1 map2 ...
.SH DESCRIPTION
.I Kbmap
shows a single column consisting of the names of keyboard maps for different
@@ -18,16 +29,49 @@
keyboard mapping defined in the corresponding file to become current
for the system; typing 'q' quits.
.PP
+.I Kbremap
+reads keyboard events from standard input, filters out a shortcut
+to change the keyboard map, and writes the result to standard
+output. The shortcut cycles through the keyboard maps provided
+as arguments. By default this shortcut is mapped to
+.LR Ctrl
++
+.LR Space .
+The
+.B -m
+and
+.B -k
+flags change the default mod and key used respectfully.
+.I Mod
+is given as a numeric shift layer as understood by
+.IR kbdfs (8).
+.PP
.I Kbmap
-requires that the file
+and
+.I kbremap
+require that the file
.B /dev/kbmap
served by
.IR kbdfs (8)
exists and is writable.
-..SH FILES
-.TF /lib/kbmap/*
+.SH EXAMPLES
+Use
+.I kbremap
+with
+.B /dev/kbdtap
+provided by
+.IR rio (4):
+.IP
+.EX
+kbremap us de uk </dev/kbdtap >/dev/kbdtap
+.EE
+.PP
+.SH FILES
+.B /sys/lib/kbmap/*
.SH SOURCE
.B /sys/src/cmd/kbmap.c
+.br
+.B /sys/src/cmd/kbremap.c
.SH "SEE ALSO"
.IR kbdfs (8)
.SH BUGS
--- /dev/null
+++ b/sys/src/cmd/kbremap.c
@@ -1,0 +1,80 @@
+#include <u.h>
+#include <libc.h>
+
+char *mod = "4";
+char *key = "57";
+enum{ Kswitch = 0xF000|0x0701 };
+
+static void
+writemap(char *file)
+{
+ int i, fd, ofd;
+ char buf[8192];
+
+ if((fd = open(file, OREAD)) < 0)
+ sysfatal("cannot open %s: %r", file);
+
+ if((ofd = open("/dev/kbmap", OWRITE)) < 0)
+ sysfatal("cannot open /dev/kbmap: %r");
+
+ while((i = read(fd, buf, sizeof buf)) > 0)
+ if(write(ofd, buf, i) != i)
+ sysfatal("writing /dev/kbmap: %r");
+
+ fprint(ofd, "%s\t%s\t0x%X\n", mod, key, Kswitch);
+ close(fd);
+ close(ofd);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [ -m mod ] [ -k scancode ] map1 map2 ...\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ char *p, buf[8192];
+ Rune r;
+ long n;
+ int index;
+
+ index = 0;
+ ARGBEGIN{
+ case 'm':
+ mod = EARGF(usage());
+ break;
+ case 'k':
+ key = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND;
+ if(argc < 2)
+ usage();
+
+ chdir("/sys/lib/kbmap");
+ writemap("ascii");
+ writemap(argv[0]);
+ for(;;){
+ n = read(0, buf, sizeof buf - 1);
+ if(n <= 0)
+ break;
+ buf[n] = '\0';
+ for(p = buf; p < buf+n; p += strlen(p) + 1){
+ chartorune(&r, p+1);
+ if(*p != 'c' || r != Kswitch){
+ write(1, p, strlen(p));
+ continue;
+ }
+ index++;
+ if(argv[index] == nil)
+ index = 0;
+ writemap("ascii");
+ writemap(argv[index]);
+ }
+ }
+ exits(nil);
+}