You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

700 lines
32 KiB

4 years ago
4 years ago
5 years ago
4 years ago
  1. #!/usr/bin/env ruby
  2. # -*- encoding: utf-8 -*-
  3. # Copyright muflax <mail@muflax.com>, 2015
  4. # License: GNU GPLv3 (or later) <http://www.gnu.org/copyleft/gpl.html>
  5. GC.disable
  6. # avoid having to require muflax
  7. class Object
  8. def blank?
  9. respond_to?(:empty?) ? !!empty? : !self
  10. end
  11. end
  12. class String
  13. BLANK_RE = /\A[[:space:]]*\z/
  14. def blank?
  15. BLANK_RE === self
  16. end
  17. end
  18. LayoutDir = "src/keyboard"
  19. LayoutFile = "#{LayoutDir}/layout.c"
  20. puts "generating #{LayoutFile}..."
  21. class Layer
  22. @@layers = {}
  23. @@primitives = 0
  24. def initialize name
  25. case name
  26. when Symbol
  27. raise "layer already defined: #{name}" if @@layers.include? name
  28. @@primitives += 1
  29. @@layers[name] = @@primitives
  30. when Array
  31. name.each do |prim|
  32. raise "unknown layers: #{prim}" if not @@layers.include? prim
  33. raise "can only combo primitive layers: #{prim}" if not prim.is_a? Symbol
  34. end
  35. combo = name.reduce(0) do |code, prim|
  36. code | (@@layers[prim])
  37. end
  38. combo_name = name.sort_by{|p| @@layers[p]}.join("_").to_sym
  39. @@layers[combo_name] = combo
  40. else
  41. raise "invalid layer definition: #{name}"
  42. end
  43. end
  44. end
  45. Keydef = Struct.new :code, :func
  46. class Key
  47. attr_reader :keydefs, :name, :row, :col
  48. Layers = [ :LB, :LP, :LN, :LF, :LD ]
  49. Functions = {
  50. #
  51. "basic" => "&kbfun_normal_press_release",
  52. "media" => "&kbfun_mediakey_press_release",
  53. #
  54. "mod" => "&kbfun_modifier_press_release",
  55. "sticky_mod" => "&kbfun_modifier_sticky",
  56. #
  57. "layer" => "&kbfun_layer_press_release",
  58. "sticky" => "&kbfun_layer_sticky",
  59. #
  60. "shift" => "&kbfun_shift_press_release",
  61. "ctrl" => "&kbfun_control_press_release",
  62. "alt" => "&kbfun_alt_press_release",
  63. "win" => "&kbfun_win_press_release",
  64. #
  65. "shift_once" => "&kbfun_shift_press_release_once",
  66. "ctrl_once" => "&kbfun_control_press_release_once",
  67. "alt_once" => "&kbfun_alt_press_release_once",
  68. "win_once" => "&kbfun_win_press_release_once",
  69. #
  70. "shift_layer" => "&kbfun_shift_layer_press_release",
  71. "ctrl_layer" => "&kbfun_control_layer_press_release",
  72. "alt_layer" => "&kbfun_alt_layer_press_release",
  73. "win_layer" => "&kbfun_win_layer_press_release",
  74. #
  75. "capslock" => "&kbfun_capslock_press_release",
  76. #
  77. "S" => "&kbfun_shift_press_release",
  78. "C" => "&kbfun_control_press_release",
  79. "A" => "&kbfun_alt_press_release",
  80. "M" => "&kbfun_alt_press_release",
  81. "W" => "&kbfun_win_press_release",
  82. "CL" => "&kbfun_capslock_press_release",
  83. "_L" => "&kbfun_layer_sticky",
  84. "_M" => "&kbfun_modifier_sticky",
  85. "_C" => "&kbfun_control_layer_press_release",
  86. "_A" => "&kbfun_alt_layer_press_release",
  87. "_W" => "&kbfun_win_layer_press_release",
  88. }
  89. Keys = {
  90. # letters
  91. "a" => "KEY_a_A",
  92. "b" => "KEY_b_B",
  93. "c" => "KEY_c_C",
  94. "d" => "KEY_d_D",
  95. "e" => "KEY_e_E",
  96. "f" => "KEY_f_F",
  97. "g" => "KEY_g_G",
  98. "h" => "KEY_h_H",
  99. "i" => "KEY_i_I",
  100. "j" => "KEY_j_J",
  101. "k" => "KEY_k_K",
  102. "l" => "KEY_l_L",
  103. "m" => "KEY_m_M",
  104. "n" => "KEY_n_N",
  105. "o" => "KEY_o_O",
  106. "p" => "KEY_p_P",
  107. "q" => "KEY_q_Q",
  108. "r" => "KEY_r_R",
  109. "s" => "KEY_s_S",
  110. "t" => "KEY_t_T",
  111. "u" => "KEY_u_U",
  112. "v" => "KEY_v_V",
  113. "w" => "KEY_w_W",
  114. "x" => "KEY_x_X",
  115. "y" => "KEY_y_Y",
  116. "z" => "KEY_z_Z",
  117. # numbers
  118. "0" => "KEY_0_RightParenthesis",
  119. "1" => "KEY_1_Exclamation",
  120. "2" => "KEY_2_At",
  121. "3" => "KEY_3_Pound",
  122. "4" => "KEY_4_Dollar",
  123. "5" => "KEY_5_Percent",
  124. "6" => "KEY_6_Caret",
  125. "7" => "KEY_7_Ampersand",
  126. "8" => "KEY_8_Asterisk",
  127. "9" => "KEY_9_LeftParenthesis",
  128. # punctuation
  129. "\\" => "KEY_Backslash_Pipe",
  130. "{" => ["KEY_LeftBracket_LeftBrace", "shift_once"],
  131. "}" => ["KEY_RightBracket_RightBrace", "shift_once"],
  132. "[" => "KEY_LeftBracket_LeftBrace",
  133. "]" => "KEY_RightBracket_RightBrace",
  134. "," => "KEY_Comma_LessThan",
  135. "-" => "KEY_Dash_Underscore",
  136. "=" => "KEY_Equal_Plus",
  137. "`" => "KEY_GraveAccent_Tilde",
  138. "." => "KEY_Period_GreaterThan",
  139. "\'" => "KEY_SingleQuote_DoubleQuote",
  140. ";" => "KEY_Semicolon_Colon",
  141. "/" => "KEY_Slash_Question",
  142. "~" => ["KEY_GraveAccent_Tilde", "shift_once"],
  143. "%" => ["KEY_5_Percent", "shift_once"],
  144. "*" => ["KEY_8_Asterisk", "shift_once"],
  145. ":" => ["KEY_Semicolon_Colon", "shift_once"],
  146. "^" => ["KEY_6_Caret", "shift_once"],
  147. "<" => ["KEY_Comma_LessThan", "shift_once"],
  148. ">" => ["KEY_Period_GreaterThan", "shift_once"],
  149. "?" => ["KEY_Slash_Question", "shift_once"],
  150. "!" => ["KEY_1_Exclamation", "shift_once"],
  151. "(" => ["KEY_9_LeftParenthesis", "shift_once"],
  152. ")" => ["KEY_0_RightParenthesis", "shift_once"],
  153. "|" => ["KEY_Backslash_Pipe", "shift_once"],
  154. "@" => ["KEY_2_At", "shift_once"],
  155. "\"" => ["KEY_SingleQuote_DoubleQuote", "shift_once"],
  156. "_" => ["KEY_Dash_Underscore", "shift_once"],
  157. "+" => ["KEY_Equal_Plus", "shift_once"],
  158. "$" => ["KEY_4_Dollar", "shift_once"],
  159. "&" => ["KEY_7_Ampersand", "shift_once"],
  160. "#" => ["KEY_3_Pound", "shift_once"],
  161. "hash" => ["KEY_3_Pound", "shift_once"],
  162. "hsh" => ["KEY_3_Pound", "shift_once"],
  163. # enter etc
  164. "enter" => "KEY_ReturnEnter",
  165. "return" => "KEY_ReturnEnter",
  166. "ret" => "KEY_ReturnEnter",
  167. "space" => "KEY_Spacebar",
  168. "spc" => "KEY_Spacebar",
  169. "tab" => "KEY_Tab",
  170. "backspace" => "KEY_DeleteBackspace",
  171. "bksp" => "KEY_DeleteBackspace",
  172. "bs" => "KEY_DeleteBackspace",
  173. "delete" => "KEY_DeleteForward",
  174. "del" => "KEY_DeleteForward",
  175. "home" => "KEY_Home",
  176. "hom" => "KEY_Home",
  177. "end" => "KEY_End",
  178. "page_up" => "KEY_PageUp",
  179. "pgup" => "KEY_PageUp",
  180. "p-^" => "KEY_PageUp",
  181. "page_down" => "KEY_PageDown",
  182. "pgdn" => "KEY_PageDown",
  183. "p-v" => "KEY_PageDown",
  184. "up" => "KEY_UpArrow",
  185. "a-^" => "KEY_UpArrow",
  186. "down" => "KEY_DownArrow",
  187. "a-v" => "KEY_DownArrow",
  188. "left" => "KEY_LeftArrow",
  189. "a-<" => "KEY_LeftArrow",
  190. "right" => "KEY_RightArrow",
  191. "a->" => "KEY_RightArrow",
  192. "escape" => "KEY_Escape",
  193. "esc" => "KEY_Escape",
  194. "insert" => "KEY_Insert",
  195. "ins" => "KEY_Insert",
  196. "menu" => "KEY_Application",
  197. "men" => "KEY_Application",
  198. # modifiers
  199. "alt" => ["MOD_KEY_LeftAlt", "mod" ],
  200. "A" => ["MOD_KEY_LeftAlt", "mod" ],
  201. "M" => ["MOD_KEY_LeftAlt", "mod" ],
  202. "alt_gr" => ["MOD_KEY_RightAlt", "mod" ],
  203. "umlaut" => ["MOD_KEY_RightAlt", "mod" ],
  204. # "UM" => ["MOD_KEY_RightAlt", "mod" ],
  205. "UM" => ["MOD_KEY_RightAlt", "sticky_mod" ],
  206. "ctrl" => ["MOD_KEY_LeftControl", "mod" ],
  207. "C" => ["MOD_KEY_LeftControl", "mod" ],
  208. "control_l" => ["MOD_KEY_LeftControl", "mod" ],
  209. "control_r" => ["MOD_KEY_RightControl", "mod" ],
  210. "win" => ["MOD_KEY_LeftGUI", "mod" ],
  211. "W" => ["MOD_KEY_LeftGUI", "mod" ],
  212. "shift_l" => ["MOD_KEY_LeftShift", "mod" ],
  213. "S_l" => ["MOD_KEY_LeftShift", "mod" ],
  214. "shift_r" => ["MOD_KEY_RightShift", "mod" ],
  215. "S_r" => ["MOD_KEY_RightShift", "mod" ],
  216. "scroll_lock" => "KEY_ScrollLock",
  217. "SCL" => "KEY_ScrollLock",
  218. # null
  219. "NULL" => "KEY_NULL",
  220. "NUL" => "KEY_NULL",
  221. "" => "KEY_NULL",
  222. # functions 1..24
  223. "f1" => "KEY_F1",
  224. "f2" => "KEY_F2",
  225. "f3" => "KEY_F3",
  226. "f4" => "KEY_F4",
  227. "f5" => "KEY_F5",
  228. "f6" => "KEY_F6",
  229. "f7" => "KEY_F7",
  230. "f8" => "KEY_F8",
  231. "f9" => "KEY_F9",
  232. "f10" => "KEY_F10",
  233. "f11" => "KEY_F11",
  234. "f12" => "KEY_F12",
  235. "f13" => "KEY_F13",
  236. "f14" => "KEY_F14",
  237. "f15" => "KEY_F15",
  238. "f16" => "KEY_F16",
  239. "f17" => "KEY_F17",
  240. "f18" => "KEY_F18",
  241. "f19" => "KEY_F19",
  242. "f20" => "KEY_F20",
  243. "f21" => "KEY_F21",
  244. "f22" => "KEY_F22",
  245. "f23" => "KEY_F23",
  246. "f24" => "KEY_F24",
  247. # keypad stuff
  248. "kp_1" => "KEYPAD_1_End",
  249. "kp_2" => "KEYPAD_2_DownArrow",
  250. "kp_3" => "KEYPAD_3_PageDown",
  251. "kp_4" => "KEYPAD_4_LeftArrow",
  252. "kp_5" => "KEYPAD_5",
  253. "kp_6" => "KEYPAD_6_RightArrow",
  254. "kp_7" => "KEYPAD_7_Home",
  255. "kp_8" => "KEYPAD_8_UpArrow",
  256. "kp_9" => "KEYPAD_9_PageUp",
  257. "kp_0" => "KEYPAD_0_Insert",
  258. #
  259. "kp_." => "KEYPAD_Period_Delete",
  260. "kp_/" => "KEYPAD_Slash",
  261. "kp_*" => "KEYPAD_Asterisk",
  262. "kp_-" => "KEYPAD_Minus",
  263. "kp_+" => "KEYPAD_Plus",
  264. "kp_en" => "KEYPAD_ENTER",
  265. # mediakeys
  266. "MD_PP" => ["MEDIAKEY_PLAY_PAUSE", "media"],
  267. "MD_PT" => ["MEDIAKEY_PREV_TRACK", "media"],
  268. "MD_NT" => ["MEDIAKEY_NEXT_TRACK", "media"],
  269. "MD_S" => ["MEDIAKEY_STOP", "media"],
  270. "MD_M" => ["MEDIAKEY_AUDIO_MUTE", "media"],
  271. "MD_VU" => ["MEDIAKEY_AUDIO_VOL_UP", "media"],
  272. "MD_VD" => ["MEDIAKEY_AUDIO_VOL_DOWN", "media"],
  273. "record" => ["MEDIAKEY_RECORD", "media"],
  274. "rewind" => ["MEDIAKEY_REWIND", "media"],
  275. "eject" => ["MEDIAKEY_EJECT", "media"],
  276. "cc_config" => ["MEDIAKEY_CC_CONFIG", "media"],
  277. "email" => ["MEDIAKEY_EMAIL", "media"],
  278. "calculator" => ["MEDIAKEY_CALCULATOR", "media"],
  279. "local_browser" => ["MEDIAKEY_LOCAL_BROWSER", "media"],
  280. "bs_search" => ["MEDIAKEY_BROWSER_SEARCH", "media"],
  281. "bs_home" => ["MEDIAKEY_BROWSER_HOME", "media"],
  282. "bs_b" => ["MEDIAKEY_BROWSER_BACK", "media"],
  283. "bs_f" => ["MEDIAKEY_BROWSER_FORWARD", "media"],
  284. "bs_stop" => ["MEDIAKEY_BROWSER_STOP", "media"],
  285. "bs_refresh" => ["MEDIAKEY_BROWSER_REFRESH", "media"],
  286. "bs_bookmarks" => ["MEDIAKEY_BROWSER_BOOKMARKS", "media"],
  287. # other weird shit
  288. "pause" => "KEY_Pause",
  289. "sysreq" => "KEY_SysReq_Attention",
  290. "sreq" => "KEY_SysReq_Attention",
  291. "SR" => "KEY_SysReq_Attention",
  292. #
  293. "clear" => "KEY_Clear",
  294. # "Clear_Again" => "KEY_Clear_Again", # wut
  295. "printscreen" => "KEY_PrintScreen",
  296. "prtscr" => "KEY_PrintScreen",
  297. "PS" => "KEY_PrintScreen",
  298. #
  299. "execute" => "KEY_Execute",
  300. "exe" => "KEY_Execute",
  301. "help" => "KEY_Help",
  302. # "menu" => "KEY_Menu", # NOT normal menu!
  303. "select" => "KEY_Select",
  304. "selct" => "KEY_Select",
  305. "sel" => "KEY_Select",
  306. "stop" => "KEY_Stop",
  307. #
  308. "again" => "KEY_Again",
  309. "redo" => "KEY_Again",
  310. "undo" => "KEY_Undo",
  311. #
  312. "cut" => "KEY_Cut",
  313. "copy" => "KEY_Copy",
  314. "paste" => "KEY_Paste",
  315. #
  316. "find" => "KEY_Find",
  317. #
  318. "mute" => "KEY_Mute",
  319. #
  320. "volume_up" => "KEY_VolumeUp",
  321. "volume_down" => "KEY_VolumeDown",
  322. "vol_up" => "KEY_VolumeUp",
  323. "vol_down" => "KEY_VolumeDown",
  324. "volumeup" => "KEY_VolumeUp",
  325. "volumedown" => "KEY_VolumeDown",
  326. "voldown" => "KEY_VolumeDown",
  327. "volup" => "KEY_VolumeUp",
  328. "voldn" => "KEY_VolumeDown",
  329. "vlup" => "KEY_VolumeUp",
  330. "vldn" => "KEY_VolumeDown",
  331. "vup" => "KEY_VolumeUp",
  332. "vdn" => "KEY_VolumeDown",
  333. }
  334. Names = {
  335. # unique key identifiers, must have a name for each of the 80 physical keys
  336. # NOTE: the mapping to the matrix is a bit weird, so be careful
  337. # name row col
  338. "Ln┳o" => [ 5, 0 ],
  339. "Ln┳4" => [ 5, 1 ],
  340. "Ln┳3" => [ 5, 2 ],
  341. "Ln┳2" => [ 5, 3 ],
  342. "Ln┳1" => [ 5, 4 ],
  343. "Ln┳0" => [ 5, 5 ],
  344. "Ln┳d" => [ 5, 6 ],
  345. "Lt┳o" => [ 4, 0 ],
  346. "Lt┳4" => [ 4, 1 ],
  347. "Lt┳3" => [ 4, 2 ],
  348. "Lt┳2" => [ 4, 3 ],
  349. "Lt┳1" => [ 4, 4 ],
  350. "Lt┳0" => [ 4, 5 ],
  351. "Lt┳d" => [ 4, 6 ],
  352. "Lh┳o" => [ 3, 0 ],
  353. "Lh┳4" => [ 3, 1 ],
  354. "Lh┳3" => [ 3, 2 ],
  355. "Lh┳2" => [ 3, 3 ],
  356. "Lh┳1" => [ 3, 4 ],
  357. "Lh┳0" => [ 3, 5 ],
  358. "Lb┳o" => [ 2, 0 ],
  359. "Lb┳4" => [ 2, 1 ],
  360. "Lb┳3" => [ 2, 2 ],
  361. "Lb┳2" => [ 2, 3 ],
  362. "Lb┳1" => [ 2, 4 ],
  363. "Lb┳0" => [ 2, 5 ],
  364. "Lb┳d" => [ 2, 6 ],
  365. "Lu┳o" => [ 1, 0 ],
  366. "Lu┳4" => [ 1, 1 ],
  367. "Lu┳3" => [ 1, 2 ],
  368. "Lu┳2" => [ 1, 3 ],
  369. "Lu┳1" => [ 1, 4 ],
  370. "Lz┳b" => [ 0, 5 ],
  371. "Lz┳c" => [ 0, 6 ],
  372. "Ly┳a" => [ 1, 5 ],
  373. "Ly┳b" => [ 1, 6 ],
  374. "Ly┳c" => [ 0, 4 ],
  375. "Lx┳a" => [ 0, 3 ],
  376. "Lx┳b" => [ 0, 2 ],
  377. "Lx┳c" => [ 0, 1 ],
  378. "Rn┳d" => [ 5, 7 ],
  379. "Rn┳0" => [ 5, 8 ],
  380. "Rn┳1" => [ 5, 9 ],
  381. "Rn┳2" => [ 5, 10 ],
  382. "Rn┳3" => [ 5, 11 ],
  383. "Rn┳4" => [ 5, 12 ],
  384. "Rn┳o" => [ 5, 13 ],
  385. "Rt┳d" => [ 4, 7 ],
  386. "Rt┳0" => [ 4, 8 ],
  387. "Rt┳1" => [ 4, 9 ],
  388. "Rt┳2" => [ 4, 10 ],
  389. "Rt┳3" => [ 4, 11 ],
  390. "Rt┳4" => [ 4, 12 ],
  391. "Rt┳o" => [ 4, 13 ],
  392. "Rh┳0" => [ 3, 8 ],
  393. "Rh┳1" => [ 3, 9 ],
  394. "Rh┳2" => [ 3, 10 ],
  395. "Rh┳3" => [ 3, 11 ],
  396. "Rh┳4" => [ 3, 12 ],
  397. "Rh┳o" => [ 3, 13 ],
  398. "Rb┳d" => [ 2, 7 ],
  399. "Rb┳0" => [ 2, 8 ],
  400. "Rb┳1" => [ 2, 9 ],
  401. "Rb┳2" => [ 2, 10 ],
  402. "Rb┳3" => [ 2, 11 ],
  403. "Rb┳4" => [ 2, 12 ],
  404. "Rb┳o" => [ 2, 13 ],
  405. "Ru┳1" => [ 1, 9 ],
  406. "Ru┳2" => [ 1, 10 ],
  407. "Ru┳3" => [ 1, 11 ],
  408. "Ru┳4" => [ 1, 12 ],
  409. "Ru┳o" => [ 1, 13 ],
  410. "Rz┳c" => [ 0, 7 ],
  411. "Rz┳b" => [ 0, 8 ],
  412. "Ry┳c" => [ 0, 9 ],
  413. "Ry┳b" => [ 1, 7 ],
  414. "Ry┳a" => [ 1, 8 ],
  415. "Rx┳c" => [ 0, 12 ],
  416. "Rx┳b" => [ 0, 11 ],
  417. "Rx┳a" => [ 0, 10 ],
  418. }
  419. Layers.each.with_index do |layer, i|
  420. Keys["#{layer}"] = ["#{i}", "layer"]
  421. end
  422. def initialize layers, name
  423. @keydefs = Array.new(layers.size)
  424. @name = name
  425. @pos = Key::Names[name]
  426. @row, @col = @pos
  427. if layers.all?(&:empty?)
  428. layers[0] = ["NUL"]
  429. end
  430. layers.each.with_index do |(key, type), i|
  431. if type.nil? and key.nil?
  432. @keydefs[i] = @keydefs[i-1]
  433. next
  434. end
  435. # keycode and default keyfunc
  436. keycode, default_type = Keys[key]
  437. # keyfunc
  438. type ||= default_type || "basic"
  439. keyfunc = Functions[type]
  440. raise "overwriting shift key: #{key}, #{type}" if default_type == "shift" and type != default_type
  441. raise "key not found: #{key}" if keycode.nil?
  442. raise "func not found: #{type}" if keyfunc.nil?
  443. case type
  444. when "layer", "sticky", "_L"
  445. raise "invalid layer: #{key}" unless key.to_i < Key::Layers.size
  446. when "mod", "sticky_mod", "_M"
  447. raise "invalid modifier: #{key}" unless keycode.start_with? "MOD_KEY"
  448. end
  449. case keycode
  450. when /^MOD_KEY/
  451. case type
  452. when "mod", "sticky_mod", "CL", "_M"; # pass
  453. else
  454. raise "invalid modifier keyfunc: #{key}, #{type}"
  455. end
  456. end
  457. @keydefs[i] = Keydef.new(keycode, keyfunc)
  458. end
  459. raise "transparency error: #{layers}" if @keydefs.any?(&:nil?)
  460. end
  461. Dummy = Key.new(Key::Layers.map{"NULL"}, "dummy")
  462. end
  463. class Layout
  464. def initialize name, keys
  465. @name = name
  466. @keys = keys
  467. @rows = @keys.map(&:row).max + 1
  468. @cols = @keys.map(&:col).max + 1
  469. @matrix = @rows.times.map{Array.new(@cols)}
  470. @keys.each do |key|
  471. @matrix[key.row][key.col] = key
  472. end
  473. end
  474. def keys_to_matrix type, method
  475. matrix = []
  476. @matrix.each.with_index do |row, row_i|
  477. matrix << "{"
  478. row.each.with_index do |key, col_i|
  479. key ||= Key::Dummy # some matrix positions are empty
  480. matrix << "\t{ // row #{row_i} x col #{col_i}"
  481. Key::Layers.each.with_index do |layer_name, layer|
  482. matrix << "\t\t(#{type}) #{key.keydefs[layer].send(method)},".ljust(60) + "// #{key.name} on #{layer_name}"
  483. end
  484. matrix << "\t},"
  485. end
  486. matrix << "},"
  487. end
  488. matrix.join("\n")
  489. end
  490. def save! file
  491. puts "saving #{@name}..."
  492. header =<<HEADER
  493. // ----------------------------------------------------------------------------
  494. // ergoDOX layout : saneo (generated)
  495. // ----------------------------------------------------------------------------
  496. HEADER
  497. keys = keys_to_matrix "keycode", :code
  498. funcs = keys_to_matrix "keyfunc", :func
  499. File.open(LayoutFile, "w+") do |f|
  500. f.puts header
  501. f.puts "#define KB_LAYERS #{Key::Layers.size}"
  502. f.puts "static const keycode PROGMEM _kb_layout_code[KB_ROWS][KB_COLUMNS][KB_LAYERS] = {", keys, "};"
  503. f.puts "static const keyfunc PROGMEM _kb_layout_func[KB_ROWS][KB_COLUMNS][KB_LAYERS] = {", funcs, "};"
  504. end
  505. end
  506. end
  507. left =<<EOL
  508. Lno ___ __ Ln4 ___ __ Ln3 ___ __ Ln2 ___ __ Ln1 ___ __ Ln0 ___ __ Lnd ___ __
  509. _LB 0 1 2 3 4 5 6
  510. _LP f11 f1 f2 f3 f4 f5 f6
  511. _LN f11 f1 f2 f3 f4 f5 f6
  512. _LF f11 f1 f2 f3 f4 f5 f6
  513. _LD 0 1 2 3 4 5 6
  514. Lto ___ __ Lt4 ___ __ Lt3 ___ __ Lt2 ___ __ Lt1 ___ __ Lt0 ___ __ Ltd ___ __
  515. _LB tab x v l c w pause
  516. _LP ~ [ ' < \\
  517. _LN esc bs ret del ins
  518. _LF f24 f23 f22 f21 f24
  519. _LD 8 7 6 5 9
  520. Lho ___ __ Lh4 ___ __ Lh3 ___ __ Lh2 ___ __ Lh1 ___ __ Lh0 ___ __
  521. _LB UM u i a e o
  522. _LP , \{ ? ! (
  523. _LN a-< a-^ a-v a-> tab
  524. _LF f14 f13 f12 f11 f20
  525. _LD 4 3 2 1 0
  526. Lbo ___ __ Lb4 ___ __ Lb3 ___ __ Lb2 ___ __ Lb1 ___ __ Lb0 ___ __ Lbd ___ __
  527. _LB S_l CL % * : p z ret
  528. _LP ` ┃ ^ ┃ | ┃ - ┃ @ ┃
  529. _LN hom p-^ p-v end NUL
  530. _LF f18 f17 f16 f15 f19
  531. _LD 8 7 6 5 9
  532. Luo ___ __ Lu4 ___ __ Lu3 ___ __ Lu2 ___ __ Lu1 ___ __
  533. _LB a-< a-^ a-v a-> W
  534. _LP
  535. _LN
  536. _LF
  537. _LD
  538. Lzb ___ __ Lzc ___ __
  539. _LB esc SCL
  540. _LP
  541. _LN
  542. _LF
  543. _LD
  544. Lya ___ __ Lyb ___ __ Lyc ___ __
  545. _LB spc C A
  546. _LP
  547. _LN
  548. _LF
  549. _LD
  550. Lxa ___ __ Lxb ___ __ Lxc ___ __
  551. _LB spc C A
  552. _LP
  553. _LN
  554. _LF
  555. _LD
  556. EOL
  557. right =<<EOL
  558. Rnd ___ __ Rn0 ___ __ Rn1 ___ __ Rn2 ___ __ Rn3 ___ __ Rn4 ___ __ Rno ___ __
  559. _LB 5 6 7 8 9 0 0
  560. _LP f5 f6 f7 f8 f9 f10 f12
  561. _LN f5 f6 f7 f8 f9 f10 f12
  562. _LF f5 f6 f7 f8 f9 f10 f12
  563. _LD 5 6 7 8 9 0 0
  564. Rtd ___ __ Rt0 ___ __ Rt1 ___ __ Rt2 ___ __ Rt3 ___ __ Rt4 ___ __ Rto ___ __
  565. _LB NUL k h g f q q
  566. _LP = > " ┃ ] ┃ ` ┃ `
  567. _LN 9 5 6 7 8 8
  568. _LF f24 f21 f22 f23 f24 f24
  569. _LD 9 5 6 7 8 8
  570. Rh0 ___ __ Rh1 ___ __ Rh2 ___ __ Rh3 ___ __ Rh4 ___ __ Rho ___ __
  571. _LB s n r t d UM
  572. _LP ) _ / \} .
  573. _LN 0 1 2 3 4
  574. _LF f10 f1 f2 f3 f4
  575. _LD 0 1 2 3 4
  576. Rbd ___ __ Rb0 ___ __ Rb1 ___ __ Rb2 ___ __ Rb3 ___ __ Rb4 ___ __ Rbo ___ __
  577. _LB ret b m j y ; S_r CL
  578. _LP + $ & hsh ^
  579. _LN 9 5 6 7 8
  580. _LF f9 f5 f6 f7 f8
  581. _LD 9 5 6 7 8
  582. Ru1 ___ __ Ru2 ___ __ Ru3 ___ __ Ru4 ___ __ Ruo ___ __
  583. _LB LN a-< a-^ a-v a->
  584. _LP
  585. _LN
  586. _LF
  587. _LD
  588. Rzc ___ __ Rzb ___ __
  589. _LB LF LF _C
  590. _LP
  591. _LN
  592. _LF
  593. _LD
  594. Ryc ___ __ Ryb ___ __ Rya ___ __
  595. _LB men LF LP _L
  596. _LP
  597. _LN
  598. _LF
  599. _LD
  600. Rxc ___ __ Rxb ___ __ Rxa ___ __
  601. _LB men LF LP _L
  602. _LP
  603. _LN
  604. _LF
  605. _LD
  606. EOL
  607. keys_string = [
  608. left,
  609. right,
  610. ]
  611. groups = keys_string.flat_map do |str|
  612. str.gsub(/#.*$/, '').split(//).reject(&:blank?).map(&:lines)
  613. end
  614. keys_parsed = {}
  615. groups.each.with_index(1) do |group, group_id|
  616. layers = Key::Layers.size
  617. # extract names
  618. names = group.first
  619. names = names.scan(/(\S+)(?:[ ]*\t[^\t]*){2}/).map{|name, _| name.strip}
  620. keyrow = group[1..-1].reject(&:blank?)
  621. # sanity check
  622. if keyrow.size != layers
  623. raise "wrong number of key layers in group ##{group_id}: #{keyrow}"
  624. end
  625. # remove first label
  626. keyrow = keyrow.map{|l| l.split("").drop(1)}
  627. (0..(keyrow.size-1)).step(layers).each do |row|
  628. keyrow[row].size.times do |col|
  629. key = layers.times.map do |layer|
  630. keyrow[row+layer][col]
  631. end
  632. key = key.map{|l| l.strip.split(/\s+/, 2)}
  633. name = names[col]
  634. raise "name not unique: #{name}" if keys_parsed.include? name
  635. raise "unknown name: #{name}" unless Key::Names.include? name
  636. keys_parsed[name] = key
  637. end
  638. end
  639. end
  640. keys = keys_parsed.map {|name, layers| Key.new(layers, name)}
  641. saneo = Layout.new :saneo, keys
  642. saneo.save! LayoutFile