generate-mods.clj
Pinchord · pinchord.git · Tickets · Changelog
Branches > main > latest > files / generate-mods.clj
(def symbol-names
{"á" "aacute"
"â" "acircumflex"
"´" "acute"
"ä" "adiaeresis"
"æ" "ae"
"à" "agrave"
"&" "ampersand"
"'" "apostrophe"
"å" "aring"
"^" "asciicircum"
"~" "asciitilde"
"*" "asterisk"
"@" "at"
"ã" "atilde"
"\\" "backslash"
"|" "bar"
"\\{" "braceleft"
"\\}" "braceright"
"[" "bracketleft"
"]" "bracketright"
"¦" "brokenbar"
"ç" "ccedilla"
"¸" "cedilla"
"¢" "cent"
":" "colon"
"{^ ^}" "space"
"," "comma"
"©" "copyright"
"¤" "currency"
"°" "degree"
"¨" "diaeresis"
"÷" "division"
"$" "dollar"
"é" "eacute"
"ê" "ecircumflex"
"ë" "ediaeresis"
"è" "egrave"
"=" "equal"
"ð" "eth"
"!" "exclam"
"¡" "exclamdown"
"`" "grave"
">" "greater"
"«" "guillemotleft"
"»" "guillemotright"
"" "hyphen"
"í" "iacute"
"î" "icircumflex"
"ï" "idiaeresis"
"ì" "igrave"
"<" "less"
"¯" "macron"
"º" "masculine"
"-" "minus"
"µ" "mu"
"×" "multiply"
"¬" "notsign"
"ñ" "ntilde"
"#" "numbersign"
"ó" "oacute"
"ô" "ocircumflex"
"ö" "odiaeresis"
"ò" "ograve"
"½" "onehalf"
"¼" "onequarter"
"¹" "onesuperior"
"Ø" "ooblique"
"ª" "ordfeminine"
"ø" "oslash"
"õ" "otilde"
"¶" "paragraph"
"(" "parenleft"
")" "parenright"
"%" "percent"
"." "period"
"·" "periodcentered"
"+" "plus"
"±" "plusminus"
"?" "question"
"¿" "questiondown"
"\"" "quotedbl"
"®" "registered"
"\r" "return"
"§" "section"
";" "semicolon"
"/" "slash"
"ß" "ssharp"
"£" "sterling"
"\t" "tab"
"þ" "thorn"
"¾" "threequarters"
"³" "threesuperior"
"²" "twosuperior"
"ú" "uacute"
"û" "ucircumflex"
"ü" "udiaeresis"
"ù" "ugrave"
"_" "underscore"
"ý" "yacute"
"ÿ" "ydiaeresis"
"¥" "yen"})
(defn symbol-name [x]
(or (symbol-names x) (throw (ex-info (str "No such symbol! " x) {:symbol x}))))
(def symbols
{:starter "TSHR"
:chords {"P" "."
"RP" "/"
"RPS" "^"
"LRPKS" "&"
"LRPKFS" "@"
"K" ","
"PS" "\\"
"FS" ":" "^FS" ";"
"RPKF" "$"
"LRFS" "#"
"L" "'" "^L" "`"
"PK" "|"
"LR" "!"
"F" "*"
"LP" "\""
"PKFS" "="
"LPK" "?"
"RPKS" "+"
; Unfortunately, Plover does not see the vision
; Will have to implement these separately
#_["LRPKF" "€" "^LRPKF" "£"]
#_["LPKF" "¥"]
"PF" "-"
"KS" "_"
"LRPK" "%"
"LPKS" "~"
"LRK" "("
"LK" "<"
"LRP" "[" "^LRP" "\\{"
"" "{^ ^}"
"RPK" ")"
"KF" ">"
"PFS" "]"
"^PFS" "\\}"}
:shortcuts {"RK" "backspace" "^RK" "delete"
"LPF" "escape"}
:mod-shortcuts {"RF" {:no-mods "{^}\n"
:with-mods "return"}
"LS" {:no-mods "{^}\t"
:with-mods "tab"}}})
(def shifted-symbols
"Symbols that need to be sent with {#shift(sym)} on Plover."
#{"^" "&" "@" ":" "$" "#" "|" "!" "*" "\"" "?" "+" "_" "%" "~" "\\{" ">" "\\}"})
(defn apply-mods [mod-set chord repetitions]
(str "{#"
(->> (reduce (fn [acc mod]
(str mod "(" acc ")"))
chord mod-set)
(repeat repetitions)
(str/join " "))
"}"))
(defn apply-symbol-mods
"Like apply-mods, but takes a symbol, and adds shift to the mods if the symbol
needs it."
[mod-set symbol repetitions]
(apply-mods (if (and (shifted-symbols symbol) (not-any? #{"shift"} mod-set))
(cons "shift" mod-set)
mod-set)
(symbol-name symbol)
repetitions))
(def vowel-chords
{"A" ["control"]
"O" ["shift"]
"I" ["super"]
"U" ["alt"]
"AO" ["control" "shift"]
"AI" ["control" "super"]
"AU" ["control" "alt"]
"OI" ["shift" "super"]
"OU" ["shift" "alt"]
"IU" ["super" "alt"]
"AOI" ["control" "shift" "super"]
"AOU" ["control" "shift" "alt"]
"AIU" ["control" "super" "alt"]
"OIU" ["shift" "super" "alt"]
"AOIU" ["control" "shift" "super" "alt"]})
(def no-mods {"-" []})
(def all-mods (merge vowel-chords no-mods))
(def repetitions
{"" 1
"*" 2
"T" 3
"T*" 4})
(def no-repetition
{"" 1})
(def always-attach {"" "{^}"
"+" "{^}"})
(def never-attach {"" ""
"+" ""})
(def attach {"" "{}"
"+" "{^}"})
(def attach-and-capitalize
(assoc attach
"#" "{}{-|}"
"#+" "{^}{-|}"))
(defn flatten-map
"Flattens a nested sequence of key value pairs into a map."
[xs]
(apply hash-map (flatten xs)))
(defn with-mod-chord
"Joins a chord with a mod chord. If the mod chord is -, and the chord
contains ^, properly formats the returned chord."
[mod-chord chord]
(if (and (= mod-chord "-") (str/starts-with? chord "^"))
chord
(str mod-chord chord)))
(defn generate-entries
"Generates a nested sequence of key value pair entries for each combination
of prefixes, the starter, the mods, the chords, and the suffixes.
Calls ->translation with the set of mods, the chord translation, and the
suffix translation."
[prefixes starter mods chords suffixes ->translation]
(for [[prefix-chord prefix-translation] prefixes
[mod-chord mod-set] mods
[chord translation] chords
[suffix-chord suffix-translation] suffixes]
[(str prefix-chord starter (with-mod-chord mod-chord chord) suffix-chord)
(str prefix-translation (->translation mod-set translation suffix-translation))]))
(defn repeated [_ translation suffix]
(apply str (repeat suffix translation)))
(def symbols-dict
(flatten-map
(let [{:keys [starter chords shortcuts mod-shortcuts]} symbols
symbols-without-mods (update-vals mod-shortcuts :no-mods)
symbols-with-mods (update-vals mod-shortcuts :with-mods)
e-repetitions (update-keys repetitions #(str % "e"))
repeated= #(str (apply repeated %&) "=")]
[(generate-entries always-attach starter vowel-chords chords repetitions apply-symbol-mods)
(generate-entries never-attach starter all-mods shortcuts repetitions apply-mods)
(generate-entries never-attach starter no-mods symbols-without-mods repetitions repeated)
(generate-entries never-attach starter vowel-chords symbols-with-mods repetitions apply-mods)
(generate-entries attach starter no-mods chords repetitions repeated)
(generate-entries attach starter no-mods chords e-repetitions repeated=)])))
(def numbers
{:starter "TPWHR"
:left {"R" "1"
"RK" "2"
"K" "3"
"LR" "4"
"LRPK" "5"
"PK" "6"
"L" "7"
"LP" "8"
"P" "9"
"LRK" "0"
"LRP" "0"
"RPK" "0"
"LPK" "0"
"" ""}
:right {"S" "1"
"S*" "2"
"*" "3"
"FS" "4"
"FST*" "5"
"T*" "6"
"F" "7"
"FT" "8"
"T" "9"
"FST" "0"
"FS*" "0"
"ST*" "0"
"FT*" "0"
"" ""}
:F-starter "TPWHR&"
:F-keys {"R" "F1" "S" "F1"
"RK" "F2" "S*" "F2"
"K" "F3" "*" "F3"
"LR" "F4" "FS" "F4"
"LRPK" "F5" "FST*" "F5"
"PK" "F6" "T*" "F6"
"L" "F7" "F" "F7"
"LP" "F8" "FT" "F8"
"P" "F9" "T" "F9"
"RFST" "F10"
"RFS*" "F10"
"RST*" "F10"
"RFT*" "F10"
"RS" "F11"
"RS*" "F12"}})
(def numbers-dict
(flatten-map
(let [{:keys [starter left right F-starter F-keys]} numbers]
[(generate-entries always-attach starter vowel-chords (merge left right) no-repetition apply-mods)
(generate-entries never-attach F-starter all-mods F-keys no-repetition apply-mods)
(generate-entries attach starter
{"" "" "^" "0"}
(for [[left-chord left-number] left
[right-chord right-number] right]
[(str left-chord right-chord) (str left-number right-number)])
{"" "" "e" "00"}
(fn [zeroes n suffix] (str n zeroes suffix)))])))
(def movement-starter "PWH")
(def movement-chords
{"R" "left"
"P" "up"
"K" "down"
"S" "right"
"LPF" "page_up"
"RKS" "page_down"
"LR" "home"
"FS" "end"})
(def movement-dict
(flatten-map
(generate-entries never-attach movement-starter all-mods movement-chords repetitions apply-mods)))
(def fingerspelling-starter "TWR")
(def letters
{"LRPK" "a"
"PK" "b"
"PKS" "c"
"PKF" "d"
"LRPKS" "e"
"F" "f"
"PKFS" "g"
"KT" "h"
"KT*" "h" ; Porque no
"LR" "i"
"KST*" "j"
"KST" "j" ; Here as a misstroke because why not
"K" "k"
"L" "l"
"PS" "m"
"PF" "n"
"LRPKFS" "o"
"P" "p"
"KF*" "q"
"KF" "q" ; Again, why not
"R" "r"
"S" "s"
"T" "t"
"LRKFS" "u"
"FS" "v"
"PF*" "w"
"KS" "x"
"PFT" "y"
"PFS" "z"})
(def fingerspelling-dict
(flatten-map
[(generate-entries never-attach fingerspelling-starter
vowel-chords letters no-repetition apply-mods)
(generate-entries attach-and-capitalize fingerspelling-starter
no-mods letters no-repetition (fn [_ translation _] translation))]))
(spit "pinchord-mods.json" (json/generate-string (merge symbols-dict fingerspelling-dict numbers-dict movement-dict)))