Initial commit....

main
BurnyLlama 2022-02-28 20:50:34 +01:00
parent 7b5dbd8134
commit f395278c6b
4 changed files with 2290 additions and 0 deletions

146
index.js Executable file
View File

@ -0,0 +1,146 @@
#!/bin/env node
// ---
const TYPE_CHARS = /^[@!:=\s]/
const KEY_SYMS = require("./keys.js")
const KEY_SYMS_KEYS = KEY_SYMS.keys.map(keySym => keySym.toUpperCase())
const KEY_SYMS_MODS = KEY_SYMS.modifiers.map(keySym => keySym.toUpperCase())
// ---
const fs = require("fs")
const { exec } = require("child_process")
if (!process.argv[2]) {
console.error("You need to provide a path to the config!")
exit(1)
}
if (!fs.existsSync(process.argv[2])) {
console.error("That file doesn't exist!")
process.exit(2)
}
const CONFIG = fs.readFileSync(process.argv[2]).toString()
// Remove irrelevant lines. (Empty and comments)
const LINES = CONFIG.split('\n').filter(LINE => LINE && !LINE.match(/^#[\S\s]*$/))
// Tokenize the lines into KBD (keyboard shortcuts), CMD (commands), and DEF (variable definitions)
const TOKENS = LINES.map(
LINE => {
const TYPES = LINE.match(TYPE_CHARS)
if (!TYPES)
return {
type: "KBD",
repeat: false,
release: false,
mode: "normal",
binding: LINE.replace(TYPE_CHARS, ''),
}
if (TYPES[0].match(/^\s/))
return {
type: "CMD",
command: LINE.replace(/^\s*/, '')
}
if (TYPES[0].match(/^=/))
return {
type: "DEF",
key: LINE.replace(/=\s*/, '').split(/\s+/)[0],
value: LINE.replace(/=\s*/, '').split(/\s+/).slice(1).join(' ')
}
const IS_REPEATING = TYPES[0].match(/!/) ? true : false
const IS_ON_RELEASE = TYPES[0].match(/@/) ? true : false
const IS_IN_DIFFERENT_MODE = TYPES[0].match(/:/) ? true : false
return {
type: "KBD",
repeat: IS_REPEATING,
release: IS_ON_RELEASE && IS_REPEATING ? false : IS_ON_RELEASE,
mode: IS_IN_DIFFERENT_MODE
? LINE.replace(TYPE_CHARS, '').match(/^\S+/)[0]
: "normal",
binding: IS_IN_DIFFERENT_MODE
? LINE.replace(TYPE_CHARS, '').replace(/^\S+\s+/, '')
: LINE.replace(TYPE_CHARS, '')
}
}
)
const parseVariables = (input, defMap) =>
input.replace(
/\$\w+/,
match => {
const VAR_NAME = match.replace("$", "")
if (defMap[VAR_NAME])
return defMap[VAR_NAME]
console.error("\nUsed undefined or empty variable:", VAR_NAME,
"\nContext:", input,
"\nVariables in scope:", defMap,
)
}
)
let defMap = {}
let cursor = 0
while (cursor < TOKENS.length) {
const TOKEN = TOKENS[cursor]
switch (TOKEN.type) {
case "DEF":
defMap[TOKEN.key] = TOKEN.value
++cursor
break
case "KBD":
const PARSE_VARS = parseVariables(TOKEN.binding, defMap)
const ALL_KEYS = PARSE_VARS.split(/\s*\+\s*/)
const MOD_KEYS = ALL_KEYS.filter(key => KEY_SYMS_MODS.includes(key.toUpperCase()))
const NORM_KEY = ALL_KEYS.filter(key => KEY_SYMS_KEYS.includes(key.toUpperCase()))
const WTF_KEYS = ALL_KEYS.filter(key => !KEY_SYMS_KEYS.includes(key.toUpperCase()) && !KEY_SYMS_MODS.includes(key.toUpperCase()))
const WTF_KEYS_ERR = WTF_KEYS[0] ? true : false
const NORM_KEY_ERR = NORM_KEY.length > 1
const NO_KEY_ERR = !NORM_KEY[0] ? true : false
const NXT_TKN_ERR = TOKENS[cursor + 1]?.type !== "CMD"
if (WTF_KEYS_ERR || NORM_KEY_ERR || NO_KEY_ERR || NXT_TKN_ERR) {
WTF_KEYS_ERR ? console.error("\nWtf do you mean with these keys?", WTF_KEYS) : null
NORM_KEY_ERR ? console.error("\nYou have more than one key specified!", NORM_KEY) : null
NO_KEY_ERR ? console.error("\nYou haven't specified a key!") : null
NXT_TKN_ERR ? console.error("\nKeybinding is not followed by command!", ALL_KEYS.join(" + ")) : null
++cursor
break
}
const MODE = TOKEN.mode
const REPEAT = TOKEN.repeat ? "-repeat " : ""
const RELEASE = TOKEN.release ? "-release " : ""
const MOD = MOD_KEYS[0] ? MOD_KEYS.join("+") : "None"
const KEY = NORM_KEY[0] ?? ""
const COMMAND = TOKENS[cursor + 1].command
const RUN_CMD = `riverctl map ${REPEAT}${RELEASE}${MODE} ${MOD} ${KEY} ${COMMAND}`
console.log("\nRunning command:", RUN_CMD)
exec(
RUN_CMD,
(err, stdout, stderr) => {
err && console.error("\nError while running command!\n", err)
stdout && console.log("\nSTDOUT:", stdout)
stderr && console.log("\nSTDOUT:", stderr)
}
)
cursor += 2
break
default:
++cursor
break
}
}

528
keys.js Normal file
View File

@ -0,0 +1,528 @@
module.exports = {
// All modifiers relevant for river.
modifiers: [
"Super",
"Alt",
"Shift",
"Control",
"Mod1", // Alt
"Mod2",
"Mod3",
"Mod4", // Super
"None", // For bindings without modifiers.
],
// Some keys of the gazillion that can be used from:
// - /usr/include/xkbcommon/xkbcommon-keysyms.h
keys: [
"BackSpace",
"Tab",
"Linefeed",
"Clear",
"Return",
"Pause",
"Scroll_Lock",
"Sys_Req",
"Escape",
"Delete",
"Home",
"Left",
"Up",
"Right",
"Down",
"Prior",
"Page_Up",
"Next",
"Page_Down",
"End",
"Begin",
"Select",
"Print",
"Execute",
"Insert",
"Undo",
"Redo",
"Menu",
"Find",
"Cancel",
"Help",
"Break",
"Mode_switch",
"script_switch",
"Num_Lock",
"KP_Space",
"KP_Tab",
"KP_Enter",
"KP_F1",
"KP_F2",
"KP_F3",
"KP_F4",
"KP_Home",
"KP_Left",
"KP_Up",
"KP_Right",
"KP_Down",
"KP_Prior",
"KP_Page_Up",
"KP_Next",
"KP_Page_Down",
"KP_End",
"KP_Begin",
"KP_Insert",
"KP_Delete",
"KP_Equal",
"KP_Multiply",
"KP_Add",
"KP_Separator",
"KP_Subtract",
"KP_Decimal",
"KP_Divide",
"KP_0",
"KP_1",
"KP_2",
"KP_3",
"KP_4",
"KP_5",
"KP_6",
"KP_7",
"KP_8",
"KP_9",
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"L1",
"F12",
"L2",
"F13",
"L3",
"F14",
"L4",
"F15",
"L5",
"F16",
"L6",
"F17",
"L7",
"F18",
"L8",
"F19",
"L9",
"F20",
"L10",
"F21",
"R1",
"F22",
"R2",
"F23",
"R3",
"F24",
"R4",
"F25",
"R5",
"F26",
"R6",
"F27",
"R7",
"F28",
"R8",
"F29",
"R9",
"F30",
"R10",
"F31",
"R11",
"F32",
"R12",
"F33",
"R13",
"F34",
"R14",
"F35",
"R15",
"space",
"exclam",
"quotedbl",
"numbersign",
"dollar",
"percent",
"ampersand",
"apostrophe",
"quoteright",
"parenleft",
"parenright",
"asterisk",
"plus",
"comma",
"minus",
"period",
"slash",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"colon",
"semicolon",
"less",
"equal",
"greater",
"question",
"at",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"bracketleft",
"backslash",
"bracketright",
"asciicircum",
"underscore",
"grave",
"quoteleft",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"braceleft",
"bar",
"braceright",
"asciitilde",
"nobreakspace",
"exclamdown",
"cent",
"sterling",
"currency",
"yen",
"brokenbar",
"section",
"diaeresis",
"copyright",
"ordfeminine",
"guillemotleft",
"notsign",
"hyphen",
"registered",
"macron",
"degree",
"plusminus",
"twosuperior",
"threesuperior",
"acute",
"mu",
"paragraph",
"periodcentered",
"cedilla",
"onesuperior",
"masculine",
"guillemotright",
"onequarter",
"onehalf",
"threequarters",
"questiondown",
"Agrave",
"Aacute",
"Acircumflex",
"Atilde",
"Adiaeresis",
"Aring",
"AE",
"Ccedilla",
"Egrave",
"Eacute",
"Ecircumflex",
"Ediaeresis",
"Igrave",
"Iacute",
"Icircumflex",
"Idiaeresis",
"ETH",
"Eth",
"Ntilde",
"Ograve",
"Oacute",
"Ocircumflex",
"Otilde",
"Odiaeresis",
"multiply",
"Oslash",
"Ooblique",
"Ugrave",
"Uacute",
"Ucircumflex",
"Udiaeresis",
"Yacute",
"THORN",
"Thorn",
"ssharp",
"agrave",
"aacute",
"acircumflex",
"atilde",
"adiaeresis",
"aring",
"ae",
"ccedilla",
"egrave",
"eacute",
"ecircumflex",
"ediaeresis",
"igrave",
"iacute",
"icircumflex",
"idiaeresis",
"eth",
"ntilde",
"ograve",
"oacute",
"ocircumflex",
"otilde",
"odiaeresis",
"division",
"oslash",
"ooblique",
"ugrave",
"uacute",
"ucircumflex",
"udiaeresis",
"yacute",
"thorn",
"ydiaeresis",
"leftcaret",
"rightcaret",
"downcaret",
"upcaret",
"overbar",
"downtack",
"upshoe",
"downstile",
"underbar",
"jot",
"quad",
"uptack",
"circle",
"upstile",
"downshoe",
"rightshoe",
"leftshoe",
"lefttack",
"righttack",
"XF86MonBrightnessUp",
"XF86MonBrightnessDown",
"XF86KbdLightOnOff",
"XF86KbdBrightnessUp",
"XF86KbdBrightnessDown",
"XF86MonBrightnessCycle",
"XF86Standby",
"XF86AudioLowerVolume",
"XF86AudioMute",
"XF86AudioRaiseVolume",
"XF86AudioPlay",
"XF86AudioStop",
"XF86AudioPrev",
"XF86AudioNext",
"XF86HomePage",
"XF86Mail",
"XF86Start",
"XF86Search",
"XF86AudioRecord",
"XF86Calculator",
"XF86Memo",
"XF86ToDoList",
"XF86Calendar",
"XF86PowerDown",
"XF86ContrastAdju",
"XF86RockerUp",
"XF86RockerDown",
"XF86RockerEnter",
"XF86Back",
"XF86Forward",
"XF86Stop",
"XF86Refresh",
"XF86PowerOff",
"XF86WakeUp",
"XF86Eject",
"XF86ScreenSaver",
"XF86WWW",
"XF86Sleep",
"XF86Favorites",
"XF86AudioPause",
"XF86AudioMedia",
"XF86MyComputer",
"XF86VendorHome",
"XF86LightBulb",
"XF86Shop",
"XF86History",
"XF86OpenURL",
"XF86AddFavorite",
"XF86HotLinks",
"XF86BrightnessAdjust",
"XF86Finance",
"XF86Community",
"XF86AudioRewind",
"XF86BackForward",
"XF86Launch0",
"XF86Launch1",
"XF86Launch2",
"XF86Launch3",
"XF86Launch4",
"XF86Launch5",
"XF86Launch6",
"XF86Launch7",
"XF86Launch8",
"XF86Launch9",
"XF86LaunchA",
"XF86LaunchB",
"XF86LaunchC",
"XF86LaunchD",
"XF86LaunchE",
"XF86LaunchF",
"XF86ApplicationLeft",
"XF86ApplicationRight",
"XF86Book",
"XF86CD",
"XF86Calculater",
"XF86Clear",
"XF86Close",
"XF86Copy",
"XF86Cut",
"XF86Display",
"XF86DOS",
"XF86Documents",
"XF86Excel",
"XF86Explorer",
"XF86Game",
"XF86Go",
"XF86iTouch",
"XF86LogOff",
"XF86Market",
"XF86Meeting",
"XF86MenuKB",
"XF86MenuPB",
"XF86MySites",
"XF86New",
"XF86News",
"XF86OfficeHome",
"XF86Open",
"XF86Option",
"XF86Paste",
"XF86Phone",
"XF86Q",
"XF86Reply",
"XF86Reload",
"XF86RotateWindows",
"XF86RotationPB",
"XF86RotationKB",
"XF86Save",
"XF86ScrollUp",
"XF86ScrollDown",
"XF86ScrollClick",
"XF86Send",
"XF86Spell",
"XF86SplitScreen",
"XF86Support",
"XF86TaskPane",
"XF86Terminal",
"XF86Tools",
"XF86Travel",
"XF86UserPB",
"XF86User1KB",
"XF86User2KB",
"XF86Video",
"XF86WheelButton",
"XF86Word",
"XF86Xfer",
"XF86ZoomIn",
"XF86ZoomOut",
"XF86Away",
"XF86Messenger",
"XF86WebCam",
"XF86MailForward",
"XF86Pictures",
"XF86Music",
"XF86Battery",
"XF86Bluetooth",
"XF86WLAN",
"XF86UWB",
"XF86AudioForward",
"XF86AudioRepeat",
"XF86AudioRandomPlay",
"XF86Subtitle",
"XF86AudioCycleTrack",
"XF86CycleAngle",
"XF86FrameBack",
"XF86FrameForward",
"XF86Time",
"XF86Select",
"XF86View",
"XF86TopMenu",
"XF86Suspend",
"XF86Hibernate",
"XF86TouchpadToggle",
"XF86TouchpadOn",
"XF86TouchpadOff",
"XF86AudioMicMute",
"XF86Keyboard",
"XF86WWAN",
"XF86RFKill",
"XF86AudioPreset",
"XF86RotationLockToggle",
"XF86FullScreen",
]
}

1602
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

14
package.json Normal file
View File

@ -0,0 +1,14 @@
{
"name": "river-binder",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "BurnyLlama",
"license": "WTFPL",
"devDependencies": {
"eslint": "^8.10.0"
}
}