From 234a47f69f0957bf3e3d268749b01e112d53bb6c Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Tue, 14 Nov 2023 10:03:19 +0100 Subject: Move /srp to /blog --- include/lib.m4 | 4 +- src/blog/fw-ec/1172.png | Bin 0 -> 17531 bytes src/blog/fw-ec/fn-lock-1.diff.gsp | 12 ++ src/blog/fw-ec/fn-lock-2.diff.gsp | 36 +++++ src/blog/fw-ec/hybrid.diff.gsp | 88 +++++++++++ src/blog/fw-ec/index.gsp | 229 ++++++++++++++++++++++++++++ src/blog/fw-ec/kbd-sc-cb.c.gsp | 6 + src/blog/fw-ec/led.diff.gsp | 32 ++++ src/blog/gsp/abbr.m4.gsp | 1 + src/blog/gsp/example.gsp.gsp | 11 ++ src/blog/gsp/folds.scm.gsp | 4 + src/blog/gsp/grammar.js.gsp | 12 ++ src/blog/gsp/highlights.scm.gsp | 9 ++ src/blog/gsp/index.gsp | 310 ++++++++++++++++++++++++++++++++++++++ src/blog/gsp/markdown.md.gsp | 3 + src/blog/gsp/pug.pug.gsp | 8 + src/blog/index.gsp | 40 +++++ src/index.gsp | 8 +- src/srp/fw-ec/1172.png | Bin 17531 -> 0 bytes src/srp/fw-ec/fn-lock-1.diff.gsp | 12 -- src/srp/fw-ec/fn-lock-2.diff.gsp | 36 ----- src/srp/fw-ec/hybrid.diff.gsp | 88 ----------- src/srp/fw-ec/index.gsp | 229 ---------------------------- src/srp/fw-ec/kbd-sc-cb.c.gsp | 6 - src/srp/fw-ec/led.diff.gsp | 32 ---- src/srp/gsp/abbr.m4.gsp | 1 - src/srp/gsp/example.gsp.gsp | 11 -- src/srp/gsp/folds.scm.gsp | 4 - src/srp/gsp/grammar.js.gsp | 12 -- src/srp/gsp/highlights.scm.gsp | 9 -- src/srp/gsp/index.gsp | 310 -------------------------------------- src/srp/gsp/markdown.md.gsp | 3 - src/srp/gsp/pug.pug.gsp | 8 - src/srp/index.gsp | 41 ----- 34 files changed, 807 insertions(+), 808 deletions(-) create mode 100644 src/blog/fw-ec/1172.png create mode 100644 src/blog/fw-ec/fn-lock-1.diff.gsp create mode 100644 src/blog/fw-ec/fn-lock-2.diff.gsp create mode 100644 src/blog/fw-ec/hybrid.diff.gsp create mode 100644 src/blog/fw-ec/index.gsp create mode 100644 src/blog/fw-ec/kbd-sc-cb.c.gsp create mode 100644 src/blog/fw-ec/led.diff.gsp create mode 100644 src/blog/gsp/abbr.m4.gsp create mode 100644 src/blog/gsp/example.gsp.gsp create mode 100644 src/blog/gsp/folds.scm.gsp create mode 100644 src/blog/gsp/grammar.js.gsp create mode 100644 src/blog/gsp/highlights.scm.gsp create mode 100644 src/blog/gsp/index.gsp create mode 100644 src/blog/gsp/markdown.md.gsp create mode 100644 src/blog/gsp/pug.pug.gsp create mode 100644 src/blog/index.gsp delete mode 100644 src/srp/fw-ec/1172.png delete mode 100644 src/srp/fw-ec/fn-lock-1.diff.gsp delete mode 100644 src/srp/fw-ec/fn-lock-2.diff.gsp delete mode 100644 src/srp/fw-ec/hybrid.diff.gsp delete mode 100644 src/srp/fw-ec/index.gsp delete mode 100644 src/srp/fw-ec/kbd-sc-cb.c.gsp delete mode 100644 src/srp/fw-ec/led.diff.gsp delete mode 100644 src/srp/gsp/abbr.m4.gsp delete mode 100644 src/srp/gsp/example.gsp.gsp delete mode 100644 src/srp/gsp/folds.scm.gsp delete mode 100644 src/srp/gsp/grammar.js.gsp delete mode 100644 src/srp/gsp/highlights.scm.gsp delete mode 100644 src/srp/gsp/index.gsp delete mode 100644 src/srp/gsp/markdown.md.gsp delete mode 100644 src/srp/gsp/pug.pug.gsp delete mode 100644 src/srp/index.gsp diff --git a/include/lib.m4 b/include/lib.m4 index 345e670..ead0887 100644 --- a/include/lib.m4 +++ b/include/lib.m4 @@ -22,8 +22,8 @@ m4_dnl Macro for generating abbrevations m4_define(m4_abbr, ⁨@abbr .m4_translit($1, A-Z2, a-zt) {-$1}⁩) m4_define(m4_file_create_date, ⁨m4_esyscmd( - git log --reverse --pretty='format:%cI' $(dirname m4___file__)/$1/index.gsp \ - | head -n1 \ + git log --follow --pretty='format:%cI' $(dirname m4___file__)/$1/index.gsp \ + | tail -n1 \ | ifne xargs date +'%-d %B %Y' -d \ | ifne -n echo 'No date yet…' )⁩) diff --git a/src/blog/fw-ec/1172.png b/src/blog/fw-ec/1172.png new file mode 100644 index 0000000..14b3be1 Binary files /dev/null and b/src/blog/fw-ec/1172.png differ diff --git a/src/blog/fw-ec/fn-lock-1.diff.gsp b/src/blog/fw-ec/fn-lock-1.diff.gsp new file mode 100644 index 0000000..f847e41 --- /dev/null +++ b/src/blog/fw-ec/fn-lock-1.diff.gsp @@ -0,0 +1,12 @@ +@span .diff-meta {-diff --git a/board/hx20/board.h b/board/hx20/board.h} +@span .diff-meta {-index 7b4ea288a..cfc6a61a2 100644} +@span .diff-meta {---- a/board/hx20/board.h} +@span .diff-meta {-+++ b/board/hx20/board.h} +@span .diff-loc {-\@\@ -218,7 +218,6 \@\@} + #define CONFIG_CMD_LEDTEST + #define CONFIG_LED_PWM_COUNT 3 + #define CONFIG_LED_PWM_TASK_DISABLED +@span .diff-del {--#define CONFIG_CAPSLED_SUPPORT} + + #ifdef CONFIG_ACCEL_KX022 + #define CONFIG_LID_ANGLE diff --git a/src/blog/fw-ec/fn-lock-2.diff.gsp b/src/blog/fw-ec/fn-lock-2.diff.gsp new file mode 100644 index 0000000..7f9e702 --- /dev/null +++ b/src/blog/fw-ec/fn-lock-2.diff.gsp @@ -0,0 +1,36 @@ +@span .diff-meta {-diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c} +@span .diff-meta {-index 2b91f2e0c..9a5050a0f 100644} +@span .diff-meta {---- a/board/hx20/keyboard_customization.c} +@span .diff-meta {-+++ b/board/hx20/keyboard_customization.c} +@span .diff-loc {-\@\@ -249,6 +249,23 \@\@ int fn_table_set(int8_t pressed, uint32_t fn_bit)} + return false; + \} + +@span .diff-ins {-+static void hx20_update_fnkey_led(void) {} +@span .diff-ins {-+ /* Turn the capslock light into a fn-lock light */} +@span .diff-ins {-+ gpio_set_level(GPIO_CAP_LED_L, (Fn_key & FN_LOCKED) ? 1 : 0);} +@span .diff-ins {-+\}} +@span .diff-ins {-+} +@span .diff-ins {-+/* Set the fn-lock light to the correct setting when the system resumes */} +@span .diff-ins {-+void hx20_fnkey_resume(void) {} +@span .diff-ins {-+ hx20_update_fnkey_led();} +@span .diff-ins {-+\}} +@span .diff-ins {-+DECLARE_HOOK(HOOK_CHIPSET_RESUME, hx20_fnkey_resume, HOOK_PRIO_DEFAULT);} +@span .diff-ins {-+} +@span .diff-ins {-+/* Disable the fn-lock light on suspend */} +@span .diff-ins {-+void hx20_fnkey_suspend(void) {} +@span .diff-ins {-+ gpio_set_level(GPIO_CAP_LED_L, 0);} +@span .diff-ins {-+\}} +@span .diff-ins {-+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, hx20_fnkey_suspend, HOOK_PRIO_DEFAULT);} +@span .diff-ins {-+} + void fnkey_shutdown(void) { + uint8_t current_kb = 0; + +@span .diff-loc {-\@\@ -420,6 +437,7 \@\@ int functional_hotkey(uint16_t *key_code, int8_t pressed)} + Fn_key &= ~FN_LOCKED; + else + Fn_key |= FN_LOCKED; +@span .diff-ins {-+ hx20_update_fnkey_led();} + \} + return EC_ERROR_UNIMPLEMENTED; + \} diff --git a/src/blog/fw-ec/hybrid.diff.gsp b/src/blog/fw-ec/hybrid.diff.gsp new file mode 100644 index 0000000..dfd4518 --- /dev/null +++ b/src/blog/fw-ec/hybrid.diff.gsp @@ -0,0 +1,88 @@ +@span .diff-meta {-diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c} +@span .diff-meta {-index 9a5050a0f..2756f17ce 100644} +@span .diff-meta {---- a/board/hx20/keyboard_customization.c} +@span .diff-meta {-+++ b/board/hx20/keyboard_customization.c} +@span .diff-loc {-\@\@ -22,12 +22,15 \@\@} + #define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) + #define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args) + +@span .diff-ins {-+/* The scancode for the caps-lock key, which is now a hybrid key */} +@span .diff-ins {-+#define SCANCODE_CTRL_ESC 0x0101} +@span .diff-ins {-+} + uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + {0x0021, 0x007B, 0x0079, 0x0072, 0x007A, 0x0071, 0x0069, 0xe04A\}, + {0xe071, 0xe070, 0x007D, 0xe01f, 0x006c, 0xe06c, 0xe07d, 0x0077\}, + {0x0015, 0x0070, 0x00ff, 0x000D, 0x000E, 0x0016, 0x0067, 0x001c\}, + {0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000\}, +@span .diff-del {-- {0xe05a, 0x0029, 0x0024, 0x000c, 0x0058, 0x0026, 0x0004, 0xe07a\},} +@span .diff-ins {-+ {0xe05a, 0x0029, 0x0024, 0x000c, 0x0101, 0x0026, 0x0004, 0xe07a\},} + {0x0022, 0x001a, 0x0006, 0x0005, 0x001b, 0x001e, 0x001d, 0x0076\}, + {0x002A, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b\}, + {0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b\}, +@span .diff-loc {-\@\@ -497,6 +500,55 \@\@ int functional_hotkey(uint16_t *key_code, int8_t pressed)} + return EC_SUCCESS; + \} + +@span .diff-ins {-+int try_ctrl_esc(uint16_t *key_code, int8_t pressed) {} +@span .diff-ins {-+ static enum {} +@span .diff-ins {-+ NONE,} +@span .diff-ins {-+ HELD,} +@span .diff-ins {-+ CTRL} +@span .diff-ins {-+ \} ctrl_esc_state;} +@span .diff-ins {-+} +@span .diff-ins {-+ if (*key_code == SCANCODE_CTRL_ESC) {} +@span .diff-ins {-+ /* If we pressed the caps key, enter the HELD state. Otherwise,} +@span .diff-ins {-+ * we are either releasing from the HELD state or the CTRL} +@span .diff-ins {-+ * state. In both cases we should reset the state to NONE, but} +@span .diff-ins {-+ * when releasing from the HELD state we want to send an ESC and} +@span .diff-ins {-+ * when releasing from the CTRL state we want to end the CTRL.} +@span .diff-ins {-+ *} +@span .diff-ins {-+ * Also important to note is that even before we know if we’re} +@span .diff-ins {-+ * going to be acting as ESC or CTRL, we need to send a press-} +@span .diff-ins {-+ * event of the CTRL key because you can chord CTRL with mouse-} +@span .diff-ins {-+ * clicks too, not just other keys.} +@span .diff-ins {-+ */} +@span .diff-ins {-+ if (pressed) {} +@span .diff-ins {-+ ctrl_esc_state = HELD;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);} +@span .diff-ins {-+ \} else if (ctrl_esc_state == HELD) {} +@span .diff-ins {-+ ctrl_esc_state = NONE;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_ESC, 1);} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_ESC, 0);} +@span .diff-ins {-+ \} else if (ctrl_esc_state == CTRL) {} +@span .diff-ins {-+ ctrl_esc_state = NONE;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);} +@span .diff-ins {-+ \}} +@span .diff-ins {-+} +@span .diff-ins {-+ return EC_ERROR_UNIMPLEMENTED;} +@span .diff-ins {-+ \}} +@span .diff-ins {-+} +@span .diff-ins {-+ /* If we get here then we are dealing with a key that isn’t the caps} +@span .diff-ins {-+ * key. In that case we need to handle all 3 states. If the state is} +@span .diff-ins {-+ * NONE then we can just exit from this function. If it’s HELD and we} +@span .diff-ins {-+ * are pressing a key, then that’s a key-chord and we need to start a} +@span .diff-ins {-+ * CTRL. Finally, if we are in the CTRL state, there is nothing to do.} +@span .diff-ins {-+ */} +@span .diff-ins {-+ if (ctrl_esc_state == HELD && pressed) {} +@span .diff-ins {-+ ctrl_esc_state = CTRL;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);} +@span .diff-ins {-+ \}} +@span .diff-ins {-+} +@span .diff-ins {-+ return EC_SUCCESS;} +@span .diff-ins {-+\}} +@span .diff-ins {-+} + enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, + int8_t pressed) + { +@span .diff-loc {-\@\@ -521,6 +573,10 \@\@ enum ec_error_list keyboard_scancode_callback(uint16_t *make_code,} + if (!pos_get_state()) + return EC_SUCCESS; + +@span .diff-ins {-+ r = try_ctrl_esc(make_code, pressed);} +@span .diff-ins {-+ if (r != EC_SUCCESS)} +@span .diff-ins {-+ return r;} +@span .diff-ins {-+} + r = hotkey_F1_F12(make_code, Fn_key, pressed); + if (r != EC_SUCCESS) + return r; diff --git a/src/blog/fw-ec/index.gsp b/src/blog/fw-ec/index.gsp new file mode 100644 index 0000000..acd39b9 --- /dev/null +++ b/src/blog/fw-ec/index.gsp @@ -0,0 +1,229 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Framework is Awesome} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + UNIX was not designed to stop its users from doing stupid things, as + that would also stop them from doing clever things. + } + } + figcaption {-Doug Gywn} + } + } + + main { + h2 {-Table of Contents} + + ul { + li {a href="#framework" {-Framework and the EC}} + li {a href="#led" {-LED Fun!}} + li {a href="#more" {-There’s More Than One LED‽}} + li {a href="#hybrid" {-The Hybrid Key}} + li {a href="#next" {-What’s Next?}} + } + + h2 #framework {-Framework and the m4_abbr(EC)} + p {- + @a href="https://frame.work" target="_blank" {-Framework} + — for those unaware — is the coolest laptop manufacturer ever. Their + whole @em{-shtick} is producing laptops that give the user the ability + to easily and effortlessly disassemble, repair, and modify their + hardware. I highly suggest checking them out if you’re interested in + computer hardware at all. The laptops even have hotswappable I/O! + } + + p {- + Anyways getting back on topic, Framework has also been giving power to + the user on the software-side of things too! A good while ago they + open-sourced the + @a + href="https://github.com/FrameworkComputer/EmbeddedController" + target="_blank" + {-code for the embedded controller} + of their laptops, which offers all sorts of possibilities for + customization of the keyboard, m4_abbr(LED) lights, and more. + } + + h2 #led {-m4_abbr(LED) Fun!} + p {- + This is an area of the m4_abbr(EC) which I have not really looked at or + touched much. I do want to play around with this a lot more in the + coming future though! So far just for shits-and-giggles, I’ve patched + the m4_abbr(EC) to make the power-button m4_abbr(LED) green instead of + the normal boring white: + } + + aside { + p {- + Just a tip: if you want to try any of these patches out, + simply copy the diffs and paste them + into @code {-git apply}. + } + } + + figure { + figcaption { + code {-~/board/hx20/led.c} + } + pre {= m4_fmt_code(led.diff.gsp) } + } + + p {- + As you can see, it’s all fairly simple. I just had to change our + @code{-EC_LED_COLOR_WHITE} for @code{-EC_LED_COLOR_GREEN}. The codebase + defines a few colors, but they’re defined as m4_abbr(RGB) tuples which + is awesome, because it opens the door to custom m4_abbr(RGB) effects in + the future! + } + + h2 #more {-There’s More Than One m4_abbr(LED)‽} + p {- + That’s right! The Framework laptop I own (13″; the 16″ releases soon + though!) has 3 more m4_abbr(LED) lights. One on the left of the + chassis, one on right of the chassis, and one on the capslock key. The + capslock m4_abbr(LED) acts as an indicator of whether or not you’ve got + capslock enabled. This is useless to me though, because my custom + keyboard layout doesn’t even support capslock (see the next section) — + so I patched it to be a function-lock indicator instead! + } + + p {- + Here’s the diff — but do take care if you want to apply similar patches + to your laptop! The files I’m editing are under @code{-board/hx20} + since I’m on an 11th Gen Intel m4_abbr(CPU). If you have a different + m4_abbr(CPU), you will probably need to fuck with different code: + } + + figure { + figcaption { + code {-~/board/hx20/board.h} + } + pre {= m4_fmt_code(fn-lock-1.diff.gsp) } + } + + figure { + figcaption { + code {-~/board/hx20/keyboard-customization.c} + } + pre {= m4_fmt_code(fn-lock-2.diff.gsp) } + } + + p {- + As you can see, toggling the capslock m4_abbr(LED) is as simple as + invoking @code{-gpio_set_level()}. Not only that, but disabling its + functionality with the capslock key is as easy as undefining the + @code{-CONFIG_CAPSLOCK_SUPPORT} macro. Figuring out if the function key + is locked is also really easy. The @code{-Fn_key} global variable is a + bit-field containing information pertaining to the function key, and we + also conveniently already have the @code{-FN_LOCKED} constant defined + that we can bitwise-AND with @code{-Fn_key} to check the locked state! + } + + p {- + We also setup some hooks with the @code{-DECLARE_HOOK()} macro. These + just ensure that we are behaving properly on system resume and -suspend. + } + + h2 #hybrid {-The Hybrid Key} + p {- + Wouldn’t it be cool if a physical key could represent two keys at the + same time? I thought so too. Like all Emacs users, I suffer from a + distinct lack of easily-accessible modifier keys. I need escape because + I use Vim bindings; I need left-control because all the Emacs bindings + use it; I need super for my window-managers’ bindings; I need left-alt + so I can type characters that don’t come on a standard American keyboard + (such as @em{-ß}, @em{-€}, and @em{-é}), and now I have a problem. All + my modifiers are taken, but Emacs still needs a meta key to work! + } + + figure { + figcaption {- + @cite{-Workflow} by Randall Munroe + } + img alt="XKCD Comic 1172" src="1172.png" {} + } + + p {- + What will I ever do‽ Well thanks to Framework making the m4_abbr(EC) + open-source, and conveniently giving me a file called + @code{-keyboard_customization.c}, I’m going to take two keys and stick + them in one! The basic premise is this: the capslock key is arguably + the easiest modifier key to hit, and it’s currently bound to the escape + key on my system. This is inefficient though, because nobody makes + key-bindings that chord the escape-key with another key; + chords @x-ref{-1} are always done with a modifier like control, and + Emacs is no different. So my plan was to make it so that the capslock + key when used on its own mimics an escape-key, while instead mimicking + the left-control-key when used in a chord with another key. + } + + p {- + It took me a little longer this time to figure out how to implement what + I wanted since the code isn’t as clear, but it was still a surprisingly + easy feature to patch into the m4_abbr(EC)! I basically just updated + the scancode table, swapping out the capslock scancode for my own random + one that I called @code{-SCANCODE_CTRL_ESC}. I then created a new + function called @code{-try_ctrl_esc()} which is called in the on-keyup + and -down callback function. The @code{-try_ctrl_esc()} function + handles all of the logic as you can see in the following diff; it’s + basically just a state machine: + } + + aside { + p data-ref="1" {- + If you’re confused by what I mean by a ‘key-chord’, I am simply + referring to pressing multiple keys in conjunction, such as when you + press ‘@kbd{-Ctrl + C}’ to copy text. + } + } + + figure { + figcaption { + code {-~/board/hx20/keyboard_customization.c} + } + pre {= m4_fmt_code(hybrid.diff.gsp) } + } + + p {- + One thing that’s good to take note of is what I return from + @code{-try_ctrl_esc()}. The general pattern for handling a keyup or + -down event is to stick the following code into + @code{-keyboard_scancode_callback()}: + } + + figure { + figcaption {- + @code{-keyboard_scancode_callback()} in + @code{-~/board/hx20/keyboard_customization.c} + } + pre {= m4_fmt_code(kbd-sc-cb.c.gsp) } + } + + p {- + In @code{-my_handler_function()} (or whatever you decide to name it), + you attempt to handle the event. If you don’t want to handle a + particular event and instead want to pass it on to the next handler, you + need to return @code{-EC_SUCCESS}. If you managed to successfully + handle the event though, then you need to return an error such as + @code{-EC_ERROR_UNIMPLEMENTED}. It’s pretty stupid and makes very + little sense from a naming perspective, but oh well… + } + + h2 #next {-What’s Next?} + p {- + m4_abbr(RGB) m4_abbr(LED)s maybe. + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/blog/fw-ec/kbd-sc-cb.c.gsp b/src/blog/fw-ec/kbd-sc-cb.c.gsp new file mode 100644 index 0000000..31524de --- /dev/null +++ b/src/blog/fw-ec/kbd-sc-cb.c.gsp @@ -0,0 +1,6 @@ +@span .c-cmt {-/* ‘make_code’ is the scancode. ‘pressed’ is a boolean that is true if this is a} + @span .c-cmt {-keydown event, and false if it’s a keyup. */} + +r = @span .c-fn {-my_handler_function}(make_code, pressed); +@span .c-kw {-if} (r != @span .c-pp {-EC_SUCCESS}) + @span .c-kw {-return} r; diff --git a/src/blog/fw-ec/led.diff.gsp b/src/blog/fw-ec/led.diff.gsp new file mode 100644 index 0000000..ac7642f --- /dev/null +++ b/src/blog/fw-ec/led.diff.gsp @@ -0,0 +1,32 @@ +@span .diff-meta {-diff --git a/board/hx20/led.c b/board/hx20/led.c} +@span .diff-meta {-index a4dc4564e..dacf73fda 100644} +@span .diff-meta {---- a/board/hx20/led.c} +@span .diff-meta {-+++ b/board/hx20/led.c} +@span .diff-loc {-\@\@ -283,22 +283,22 \@\@ static void led_set_power(void)} + /* don’t light up when at lid close */ + if (!lid_is_open()) { + set_pwr_led_color(PWM_LED2, -1); +@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0);} +@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0);} + return; + \} + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) +@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 1);} +@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 1);} + else +@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0);} +@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0);} + + if (chipset_in_state(CHIPSET_STATE_ON) | power_button_enable) { + if (charge_prevent_power_on(0)) + set_pwr_led_color(PWM_LED2, (power_tick % + LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? +@span .diff-del {-- EC_LED_COLOR_WHITE : -1);} +@span .diff-ins {-+ EC_LED_COLOR_GREEN : -1);} + else +@span .diff-del {-- set_pwr_led_color(PWM_LED2, EC_LED_COLOR_WHITE);} +@span .diff-ins {-+ set_pwr_led_color(PWM_LED2, EC_LED_COLOR_GREEN);} + \} else + set_pwr_led_color(PWM_LED2, -1); + \} diff --git a/src/blog/gsp/abbr.m4.gsp b/src/blog/gsp/abbr.m4.gsp new file mode 100644 index 0000000..99ac1d7 --- /dev/null +++ b/src/blog/gsp/abbr.m4.gsp @@ -0,0 +1 @@ +@span .fn {-⁨m4_define⁩}(⁨m4_abbr⁩, `\@abbr .@span .fn {-⁨m4_translit⁩}(@span .var {-$1}, A-Z, a-z) {-@span .var {-$1}\}') diff --git a/src/blog/gsp/example.gsp.gsp b/src/blog/gsp/example.gsp.gsp new file mode 100644 index 0000000..7f30bf0 --- /dev/null +++ b/src/blog/gsp/example.gsp.gsp @@ -0,0 +1,11 @@ +@span .gsp-node {-html} @span .gsp-attr {-lang}@span .gsp-op {-=}@span .gsp-val {-"en"} @span .gsp-op {-{} + @span .gsp-node {-body} @span .gsp-op {-{} + @span .gsp-node {-p} @span .gsp-op {-{-} Hello, World!@span .gsp-op {-\}} + + @span .gsp-node {-ul} @span .gsp-op {-{} + @span .gsp-node {-li} @span .gsp-op {-{}@span .gsp-node {-a} @span .gsp-attr {-href}@span .gsp-op {-=}@span .gsp-val {-"#"} @span .gsp-attr {-#home} @span .gsp-op {-{-}Home Page@span .gsp-op {-\}\}} + @span .gsp-node {-li} @span .gsp-op {-{}@span .gsp-node {-a} @span .gsp-attr {-href}@span .gsp-op {-=}@span .gsp-val {-"#"} @span .gsp-attr {-#about} @span .gsp-op {-{-}About Me@span .gsp-op {-\}\}} + @span .gsp-node {-li} @span .gsp-op {-{}@span .gsp-node {-a} @span .gsp-attr {-href}@span .gsp-op {-=}@span .gsp-val {-"#"} @span .gsp-attr {-#links} @span .gsp-op {-{-}Fun Links@span .gsp-op {-\}\}} + @span .gsp-op {-\}} + @span .gsp-op {-\}} +@span .gsp-op {-\}} diff --git a/src/blog/gsp/folds.scm.gsp b/src/blog/gsp/folds.scm.gsp new file mode 100644 index 0000000..fb8ce45 --- /dev/null +++ b/src/blog/gsp/folds.scm.gsp @@ -0,0 +1,4 @@ +[ + (@span .fn {-node}) + (@span .fn {-attribute_list}) +] @span .var {-\@fold} diff --git a/src/blog/gsp/grammar.js.gsp b/src/blog/gsp/grammar.js.gsp new file mode 100644 index 0000000..7a06e7f --- /dev/null +++ b/src/blog/gsp/grammar.js.gsp @@ -0,0 +1,12 @@ +{ + @span .var {-node}: @span .var {-$} => @span .fn {-seq}( + @span .fn {-optional}('>'), + @span .var {-$.node_name}, + @span .fn {-optional}(@span .var {-$.attribute_list}), + @span .str {-'{'}, + @span .fn {-optional}(@span .var {-$.node_body}), + @span .str {-'\}'}, + ), + + @span .var {-node_name}: @span .var {-$} => @span .str {-/[a-zA-Z:_][a-zA-Z0-9:_\\-​.]*​/}, +\} diff --git a/src/blog/gsp/highlights.scm.gsp b/src/blog/gsp/highlights.scm.gsp new file mode 100644 index 0000000..6deeb8a --- /dev/null +++ b/src/blog/gsp/highlights.scm.gsp @@ -0,0 +1,9 @@ +[@span .str {-">"} @span .str {-"-"} @span .str {-"="} @span .str {-"\@"}] @span .var {-\@operator} +[@span .str {-"{"} @span .str {-"\}"}] @span .var {-\@tag.delimiter} +(@span .fn {-node_name}) @span .var {-\@tag} +[ + (@span .fn {-attribute_name}) + (@span .fn {-class_shorthand}) + (@span .fn {-id_shorthand}) +] @span .var {-\@tag.attribute} +(@span .fn {-attribute_value}) @span .var {-\@string} diff --git a/src/blog/gsp/index.gsp b/src/blog/gsp/index.gsp new file mode 100644 index 0000000..8c56883 --- /dev/null +++ b/src/blog/gsp/index.gsp @@ -0,0 +1,310 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Never Settle For Trash} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + 🚨🚨 BREAKING: TYPESCRIPT SNATCHES DEFEAT FROM THE JAWS OF VICTORY + 🚨🚨 + } + } + figcaption {-Lane Wagner} + } + } + + main { + h2 {-Table of Contents} + + ul { + li {a href="#simple" {-Simplicity and Abstraction}} + li {a href="#sucks" {-Most Software Sucks}} + li {a href="#solution" {-My Solution}} + li {a href="#syntax" {-Syntax Highlighting}} + li {a href="#takeaway" {-The Takeaway}} + } + + h2 #simple {-Simplicity and Abstraction} + p {- + I like my software simple and devoid of useless abstraction. I often + find myself in positions where I’m searching for scissors to cut a sheet + of paper, and am instead greeted with a chainsaw. The urge to + over-complicate and -abstract your software can be strong; I often see + people who preach simple software writing programs to solve basic + problems that have 30 different command-line flags, and require a 50 + page m4_abbr(PDF) explaining its operation. + } + + p {- + Why do I mention all of this? Well as anyone who’s ever tried their + hand at web-development knows, websites are written in m4_abbr(HTML). I + wish I could say that’s a good thing, but as anyone who’s ever looked at + m4_abbr(HTML) before would know, that language is — to put it lightly — + really not great. It’s extremely verbose, and awkward to write- and + edit (angle brackets are not the easiest-to-reach keys on the keyboard). + } + + p {- + So what’s the solution? The most obvious to me is to create a nicer to + read- and write language which I can easily transpile down to + m4_abbr(HTML). Ideally the m4_abbr(CLI) is very simple and works on the + standard input and -output like all good UNIX utilities. I should be + able to transpile my site by simply running ‘@code{-cmd in.xyz + out.html}’, where my input reflects the structure of my output will + nicer, less-polluting syntax such as in ‘@code{-div .cls { … \}}’. + } + + p {- + The kind of tool I am describing here is what I imagine the ideal + solution to be. A @em{-simple} tool with a @em{-simple} function. It + takes an input language and produces an output language. There is also + minimal abstraction. The input language should reflect the structure of + m4_abbr(HTML), because that’s exactly what we’re trying to output. It + makes little sense to create a fundamentally different language when + m4_abbr(HTML) not only does a good job at defining a websites structure, + but sticking close to the language we are targeting just makes + everyone’s life easier in every way. + } + + h2 #sucks {-Most Software Sucks} + + p {- + So with my ideal solution being a simple language with a simple + m4_abbr(CLI) that sticks close to the structure of m4_abbr(HTML), let’s + take a look at what other people have come up with: + } + + figure { + pre {= m4_fmt_code(markdown.md.gsp) } + } + + p {- Oh no.} + + p {- + Now most readers probably had the initial reaction of ‘@em{-What’s wrong + with Markdown?}’. To answer your question: everything. The issue I + have with these highly-prevalent Markdown-based replacements for + m4_abbr(HTML) is that they ignore the fundamental fact that + m4_abbr(HTML) and Markdown are @em{-not} compatible languages with each + other. m4_abbr(HTML) is designed around making websites (with the added + autism of m4_abbr(XML)). It gives us things like semantic tags for + describing input forms, navigation bars, figures, and more. With the + addition of classes and IDs, we can even style two paragraphs on the + same page in different ways. This is fundamentally not possible in + Markdown. If we ignore the fact that Markdown is just poorly designed, + it offers us basically none of what we need to make an even + slightly-complex static page as it’s not meant for website-design but + simply to be a readable plain-text format you can use for documentation + or your email or something. + } + + p {- + How do you make your navigation bar in Markdown? Or style two + paragraphs differently? You can’t. Some try to get around this by + adding extensions to the Markdown language, but they never manage to + cover all bases. Another problem I @em{-always} come across when trying + to use Markdown-to-m4_abbr(HTML) tools is code blocks. I always make + sure to use tabs for indentation in my code blocks instead of spaces, so + that I can vary the tab-width based on the screen size of the reader. + You obviously can’t do this with spaces since the fundamental (and + retarded) purpose of space-indentation is to force everyone to view code + with the same indentation, which sucks for users on mobile when you have + nice large indents. To this day I have yet to find a + Markdown-to-m4_abbr(HTML) converter that will let me have tab indents + without error-prone post-processing of the generated m4_abbr(HTML). + } + + p {- + Ok well… there are other ways of generating m4_abbr(HTML); one rather + popular option is Pug: + } + + figure { + pre .pug {= m4_fmt_code(pug.pug.gsp) } + } + + p {- + While Pug certainly hits the ‘maintain the same structure’ point right + on the head, it fails in one very crucial area — it’s a JavaScript + library @em{-only}, and so requires a whole m4_abbr(JS) setup simply to + transpile your site to m4_abbr(HTML). What a bummer. There is also a + second issue which is that it uses an indentation-sensitive syntax. + Normally I am actually a fan of languages like this — such as Python — + but in the case of a markup language like Pug, this is terrible as it + makes macros and templating with tools such as @code{-m4} exceptionally + difficult. Pug @em{-does} offer templating faculties via JavaScript, + but I really try to minimize the amount of JavaScript I need to write + whenever possible. + } + + h2 #solution {-My Solution} + + p {- + So with no existing tools fitting my entry criteria, I did the only + reasonable next thing and made my own tool. It tries to stick to the + format of m4_abbr(HTML) as closely as possible while offering an + @em{-extremely} easy-to-use transpiler. It also has no added bullshit + like filters, templates, etc. If you want macros, use a macro-processor + like @code{-m4}. I called it m4_abbr(GSP) because everyone knows that + German Shorthaired Pointers are better than pugs. Here is a quick + syntax example: + } + + figure { + pre .gsp {= m4_fmt_code(example.gsp.gsp) } + } + + p {- + Here you can see almost all of m4_abbr(GSP). The document follows the + same structure as m4_abbr(HTML), but thanks to the use of braces instead + of opening- and closing tags, the syntax is far less verbose and easier + to read. The language also provides shorthands for classes and IDs + through m4_abbr(CSS)-selector syntax. + } + + p {- + Templating and macros are also very easy via macro processors thanks to + the use of braces instead of whitespace-based scoping. You may have + noticed that I like to make use of abbreviations on this website that + expand when hovered over (unless you’re on mobile, in which case you + might not see them). I do this via the m4_abbr(HTML) @code{-} + tag, providing the appropriate class. For example, many times on this + very page I’ve made use of @code{-\@abbr .html {-HTML\}}. Obviously + repeating that everywhere in my document can be quite annoying, so I’ve + gotten around this by making use of the following @code{-m4} macro: + } + + figure { + pre {= m4_fmt_code(abbr.m4.gsp) } + } + + p {- + I can then insert abbreviations by simply writing something along the + lines of ‘@code{-⁨m4_abbr(HTML)⁩}’ in my document. + } + + aside { + p {- + The first thing I did after finishing the transpiler was to rewrite + this entire site in m4_abbr(GSP). There is something that just feels + so great about writing a tool that you actually use in your day-to-day + life. + } + } + + p {- + The transpiler itself is also incredibly easy to use, something + JavaScript developers would never be able to comprehend. In order to + transpile a m4_abbr(GSP) document into an m4_abbr(HTML) document, I + simply run ‘@code{-gsp index.gsp >index.html}’. Yep, that’s it. + } + + h2 #syntax {-Syntax Highlighting} + + p {- + One problem that I came across writing m4_abbr(GSP) was the lack of + syntax highlighting. It can seem not so important, but syntax + highlighting is crucial for helping you quickly identify different + syntax elements. The awesome solution I found for this ended being + Tree-Sitter. Tree-Sitter is a parser-generator that various text + editors such as Vim and Emacs can integrate with to offer efficient- and + high quality syntax highlighting, amongst other features such as + syntax-aware code folding and movement. + } + + p {- + After a bit of research and reading the documentation, I found that + creating your own parsers is actually really easy. You effectively just + define a JavaScript object that describes the language grammar, and a C + parser is generated from that. If you’re interested, you can find the + m4_abbr(GSP) parser @a href="https://git.sr.ht/~mango/tree-sitter-gsp" + {-here}. To give you a bit of an idea of just how simple a Tree-Sitter + parser is, here’s a simplified example of how you describe the + definition of a node, and a node name @x-ref{-1}: + } + + figure { + pre .js {= m4_fmt_code(grammar.js.gsp) } + } + + aside { + p data-ref="1" {- + The definition for what constitutes a node name is simplified in the + example. In actuality node names can contain all sorts of unicode + characters too (because m4_abbr(XML) said so), but I would like the + regex to actually fit on the screen. + } + } + + p {- + As you can see, the grammar syntax is extremely simple. You simply + define your core syntax elements via regular expressions, and then + compose them together via helper functions such as @code{-optional} and + @code{-repeat} to define the full structure of your language. + } + + p {- + This isn’t enough though. We now have a parser for our language that + can create a syntax tree that our editor can take advantage of, but our + editor still doesn’t know what each node actually @em{-is} so that it + can be syntax highlighted properly. Tree Sitter solves this through a + query file written in Scheme where we can describe how to syntax + highlight our m4_abbr(AST). This is what the configuration for + m4_abbr(GSP) looks like: + } + + figure { + figcaption { + code {-queries/highlights.scm} + } + pre {= m4_fmt_code(highlights.scm.gsp) } + } + + p {- + As you can see, this is all really simple stuff, which is what I love so + much about Tree Sitter — it’s just so easy! With these basic + annotations your editor knows that attribute values should be + highlighted like strings, braces like tag delimiters, etc. In a similar + vein, writing a query to describe code-folding is really easy: + } + + figure { + figcaption { + code {-queries/folds.scm} + } + pre {= m4_fmt_code(folds.scm.gsp) } + } + + h2 #takeaway {-The Takeaway} + + p {- + So what’s the takeaway? I think it’s that when you have a problem, + often times the best solution is not to fundamentally redesign something + from the ground up, or to completely change the way a system works, but + to instead identify the specific thing that annoys you and find a fix + for it. I thought that the syntax of m4_abbr(HTML) was annoying and + bad, so I found a solution for the syntax, while keeping the core + structure the same. In the same line of thinking, try not to + over-abstract — I’m looking at you, Java developers. Abstraction often + leads to exponentially increased complications the moment we want to do + anything different or out of the ordinary, so unless you can find a + really nice abstraction that doesn’t really make anyone’s life harder, + try to avoid them when you can. + } + + p {- + If you’re interested in m4_abbr(GSP), you can find the git repository + over at @a href="https://git.sr.ht/~mango/gsp" {-Sourcehut}. + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/blog/gsp/markdown.md.gsp b/src/blog/gsp/markdown.md.gsp new file mode 100644 index 0000000..3d5f51a --- /dev/null +++ b/src/blog/gsp/markdown.md.gsp @@ -0,0 +1,3 @@ +@span .md-delim {-#} @span .md-head {-Markdown 4 Lyfe} + +Welcome to my website written in Hugo! diff --git a/src/blog/gsp/pug.pug.gsp b/src/blog/gsp/pug.pug.gsp new file mode 100644 index 0000000..de816e3 --- /dev/null +++ b/src/blog/gsp/pug.pug.gsp @@ -0,0 +1,8 @@ +@span .pug-node {-div} + @span .pug-node {-p} + @span .pug-cont {-|} Hello world! This is a + @span .pug-cont {-|} multiline paragraph. + @span .pug-node {-ul} + @span .pug-node {-li} foo + @span .pug-node {-li} bar + @span .pug-node {-li} baz diff --git a/src/blog/index.gsp b/src/blog/index.gsp new file mode 100644 index 0000000..68b53f8 --- /dev/null +++ b/src/blog/index.gsp @@ -0,0 +1,40 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Blog Posts} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + Object-oriented programming is an exceptionally bad idea which could + only have originated in California. + } + } + figcaption {-Edsgar W. Dijkstra} + } + } + + main { + p {- + On this section of the site you will find my blog. Most of what I post + here is related to software-development and -design, although maybe + you’ll find something unrelated on here too. + } + + p {-Posts:} + + ul { + m4_article(gsp, {-Writing an HTML Preprocessor (feat. Tree-Sitter)}) + m4_article(fw-ec, {-Patching My Laptop’s Embedded Controller}) + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/index.gsp b/src/index.gsp index 78d6239..b9fa5a4 100644 --- a/src/index.gsp +++ b/src/index.gsp @@ -41,10 +41,10 @@ html lang="en" { } ul { - li {a href="prj" {-My Projects}} - li {a href="srp" {-Software-Related Posts}} - li {a href="www" {-Other Websites}} - li {a href="ame" {-About Me}} + li {a href="prj" {-Documentation}} + li {a href="blog" {-Blog Posts}} + li {a href="www" {-Other Websites}} + li {a href="ame" {-About Me}} } hr{} diff --git a/src/srp/fw-ec/1172.png b/src/srp/fw-ec/1172.png deleted file mode 100644 index 14b3be1..0000000 Binary files a/src/srp/fw-ec/1172.png and /dev/null differ diff --git a/src/srp/fw-ec/fn-lock-1.diff.gsp b/src/srp/fw-ec/fn-lock-1.diff.gsp deleted file mode 100644 index f847e41..0000000 --- a/src/srp/fw-ec/fn-lock-1.diff.gsp +++ /dev/null @@ -1,12 +0,0 @@ -@span .diff-meta {-diff --git a/board/hx20/board.h b/board/hx20/board.h} -@span .diff-meta {-index 7b4ea288a..cfc6a61a2 100644} -@span .diff-meta {---- a/board/hx20/board.h} -@span .diff-meta {-+++ b/board/hx20/board.h} -@span .diff-loc {-\@\@ -218,7 +218,6 \@\@} - #define CONFIG_CMD_LEDTEST - #define CONFIG_LED_PWM_COUNT 3 - #define CONFIG_LED_PWM_TASK_DISABLED -@span .diff-del {--#define CONFIG_CAPSLED_SUPPORT} - - #ifdef CONFIG_ACCEL_KX022 - #define CONFIG_LID_ANGLE diff --git a/src/srp/fw-ec/fn-lock-2.diff.gsp b/src/srp/fw-ec/fn-lock-2.diff.gsp deleted file mode 100644 index 7f9e702..0000000 --- a/src/srp/fw-ec/fn-lock-2.diff.gsp +++ /dev/null @@ -1,36 +0,0 @@ -@span .diff-meta {-diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c} -@span .diff-meta {-index 2b91f2e0c..9a5050a0f 100644} -@span .diff-meta {---- a/board/hx20/keyboard_customization.c} -@span .diff-meta {-+++ b/board/hx20/keyboard_customization.c} -@span .diff-loc {-\@\@ -249,6 +249,23 \@\@ int fn_table_set(int8_t pressed, uint32_t fn_bit)} - return false; - \} - -@span .diff-ins {-+static void hx20_update_fnkey_led(void) {} -@span .diff-ins {-+ /* Turn the capslock light into a fn-lock light */} -@span .diff-ins {-+ gpio_set_level(GPIO_CAP_LED_L, (Fn_key & FN_LOCKED) ? 1 : 0);} -@span .diff-ins {-+\}} -@span .diff-ins {-+} -@span .diff-ins {-+/* Set the fn-lock light to the correct setting when the system resumes */} -@span .diff-ins {-+void hx20_fnkey_resume(void) {} -@span .diff-ins {-+ hx20_update_fnkey_led();} -@span .diff-ins {-+\}} -@span .diff-ins {-+DECLARE_HOOK(HOOK_CHIPSET_RESUME, hx20_fnkey_resume, HOOK_PRIO_DEFAULT);} -@span .diff-ins {-+} -@span .diff-ins {-+/* Disable the fn-lock light on suspend */} -@span .diff-ins {-+void hx20_fnkey_suspend(void) {} -@span .diff-ins {-+ gpio_set_level(GPIO_CAP_LED_L, 0);} -@span .diff-ins {-+\}} -@span .diff-ins {-+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, hx20_fnkey_suspend, HOOK_PRIO_DEFAULT);} -@span .diff-ins {-+} - void fnkey_shutdown(void) { - uint8_t current_kb = 0; - -@span .diff-loc {-\@\@ -420,6 +437,7 \@\@ int functional_hotkey(uint16_t *key_code, int8_t pressed)} - Fn_key &= ~FN_LOCKED; - else - Fn_key |= FN_LOCKED; -@span .diff-ins {-+ hx20_update_fnkey_led();} - \} - return EC_ERROR_UNIMPLEMENTED; - \} diff --git a/src/srp/fw-ec/hybrid.diff.gsp b/src/srp/fw-ec/hybrid.diff.gsp deleted file mode 100644 index dfd4518..0000000 --- a/src/srp/fw-ec/hybrid.diff.gsp +++ /dev/null @@ -1,88 +0,0 @@ -@span .diff-meta {-diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c} -@span .diff-meta {-index 9a5050a0f..2756f17ce 100644} -@span .diff-meta {---- a/board/hx20/keyboard_customization.c} -@span .diff-meta {-+++ b/board/hx20/keyboard_customization.c} -@span .diff-loc {-\@\@ -22,12 +22,15 \@\@} - #define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) - #define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args) - -@span .diff-ins {-+/* The scancode for the caps-lock key, which is now a hybrid key */} -@span .diff-ins {-+#define SCANCODE_CTRL_ESC 0x0101} -@span .diff-ins {-+} - uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { - {0x0021, 0x007B, 0x0079, 0x0072, 0x007A, 0x0071, 0x0069, 0xe04A\}, - {0xe071, 0xe070, 0x007D, 0xe01f, 0x006c, 0xe06c, 0xe07d, 0x0077\}, - {0x0015, 0x0070, 0x00ff, 0x000D, 0x000E, 0x0016, 0x0067, 0x001c\}, - {0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000\}, -@span .diff-del {-- {0xe05a, 0x0029, 0x0024, 0x000c, 0x0058, 0x0026, 0x0004, 0xe07a\},} -@span .diff-ins {-+ {0xe05a, 0x0029, 0x0024, 0x000c, 0x0101, 0x0026, 0x0004, 0xe07a\},} - {0x0022, 0x001a, 0x0006, 0x0005, 0x001b, 0x001e, 0x001d, 0x0076\}, - {0x002A, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b\}, - {0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b\}, -@span .diff-loc {-\@\@ -497,6 +500,55 \@\@ int functional_hotkey(uint16_t *key_code, int8_t pressed)} - return EC_SUCCESS; - \} - -@span .diff-ins {-+int try_ctrl_esc(uint16_t *key_code, int8_t pressed) {} -@span .diff-ins {-+ static enum {} -@span .diff-ins {-+ NONE,} -@span .diff-ins {-+ HELD,} -@span .diff-ins {-+ CTRL} -@span .diff-ins {-+ \} ctrl_esc_state;} -@span .diff-ins {-+} -@span .diff-ins {-+ if (*key_code == SCANCODE_CTRL_ESC) {} -@span .diff-ins {-+ /* If we pressed the caps key, enter the HELD state. Otherwise,} -@span .diff-ins {-+ * we are either releasing from the HELD state or the CTRL} -@span .diff-ins {-+ * state. In both cases we should reset the state to NONE, but} -@span .diff-ins {-+ * when releasing from the HELD state we want to send an ESC and} -@span .diff-ins {-+ * when releasing from the CTRL state we want to end the CTRL.} -@span .diff-ins {-+ *} -@span .diff-ins {-+ * Also important to note is that even before we know if we’re} -@span .diff-ins {-+ * going to be acting as ESC or CTRL, we need to send a press-} -@span .diff-ins {-+ * event of the CTRL key because you can chord CTRL with mouse-} -@span .diff-ins {-+ * clicks too, not just other keys.} -@span .diff-ins {-+ */} -@span .diff-ins {-+ if (pressed) {} -@span .diff-ins {-+ ctrl_esc_state = HELD;} -@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);} -@span .diff-ins {-+ \} else if (ctrl_esc_state == HELD) {} -@span .diff-ins {-+ ctrl_esc_state = NONE;} -@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);} -@span .diff-ins {-+ simulate_keyboard(SCANCODE_ESC, 1);} -@span .diff-ins {-+ simulate_keyboard(SCANCODE_ESC, 0);} -@span .diff-ins {-+ \} else if (ctrl_esc_state == CTRL) {} -@span .diff-ins {-+ ctrl_esc_state = NONE;} -@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);} -@span .diff-ins {-+ \}} -@span .diff-ins {-+} -@span .diff-ins {-+ return EC_ERROR_UNIMPLEMENTED;} -@span .diff-ins {-+ \}} -@span .diff-ins {-+} -@span .diff-ins {-+ /* If we get here then we are dealing with a key that isn’t the caps} -@span .diff-ins {-+ * key. In that case we need to handle all 3 states. If the state is} -@span .diff-ins {-+ * NONE then we can just exit from this function. If it’s HELD and we} -@span .diff-ins {-+ * are pressing a key, then that’s a key-chord and we need to start a} -@span .diff-ins {-+ * CTRL. Finally, if we are in the CTRL state, there is nothing to do.} -@span .diff-ins {-+ */} -@span .diff-ins {-+ if (ctrl_esc_state == HELD && pressed) {} -@span .diff-ins {-+ ctrl_esc_state = CTRL;} -@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);} -@span .diff-ins {-+ \}} -@span .diff-ins {-+} -@span .diff-ins {-+ return EC_SUCCESS;} -@span .diff-ins {-+\}} -@span .diff-ins {-+} - enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, - int8_t pressed) - { -@span .diff-loc {-\@\@ -521,6 +573,10 \@\@ enum ec_error_list keyboard_scancode_callback(uint16_t *make_code,} - if (!pos_get_state()) - return EC_SUCCESS; - -@span .diff-ins {-+ r = try_ctrl_esc(make_code, pressed);} -@span .diff-ins {-+ if (r != EC_SUCCESS)} -@span .diff-ins {-+ return r;} -@span .diff-ins {-+} - r = hotkey_F1_F12(make_code, Fn_key, pressed); - if (r != EC_SUCCESS) - return r; diff --git a/src/srp/fw-ec/index.gsp b/src/srp/fw-ec/index.gsp deleted file mode 100644 index acd39b9..0000000 --- a/src/srp/fw-ec/index.gsp +++ /dev/null @@ -1,229 +0,0 @@ -html lang="en" { - head { m4_include(head.gsp) } - body { - header { - div { - h1 {-Framework is Awesome} - m4_include(nav.gsp) - } - - figure .quote { - blockquote { - p {= - UNIX was not designed to stop its users from doing stupid things, as - that would also stop them from doing clever things. - } - } - figcaption {-Doug Gywn} - } - } - - main { - h2 {-Table of Contents} - - ul { - li {a href="#framework" {-Framework and the EC}} - li {a href="#led" {-LED Fun!}} - li {a href="#more" {-There’s More Than One LED‽}} - li {a href="#hybrid" {-The Hybrid Key}} - li {a href="#next" {-What’s Next?}} - } - - h2 #framework {-Framework and the m4_abbr(EC)} - p {- - @a href="https://frame.work" target="_blank" {-Framework} - — for those unaware — is the coolest laptop manufacturer ever. Their - whole @em{-shtick} is producing laptops that give the user the ability - to easily and effortlessly disassemble, repair, and modify their - hardware. I highly suggest checking them out if you’re interested in - computer hardware at all. The laptops even have hotswappable I/O! - } - - p {- - Anyways getting back on topic, Framework has also been giving power to - the user on the software-side of things too! A good while ago they - open-sourced the - @a - href="https://github.com/FrameworkComputer/EmbeddedController" - target="_blank" - {-code for the embedded controller} - of their laptops, which offers all sorts of possibilities for - customization of the keyboard, m4_abbr(LED) lights, and more. - } - - h2 #led {-m4_abbr(LED) Fun!} - p {- - This is an area of the m4_abbr(EC) which I have not really looked at or - touched much. I do want to play around with this a lot more in the - coming future though! So far just for shits-and-giggles, I’ve patched - the m4_abbr(EC) to make the power-button m4_abbr(LED) green instead of - the normal boring white: - } - - aside { - p {- - Just a tip: if you want to try any of these patches out, - simply copy the diffs and paste them - into @code {-git apply}. - } - } - - figure { - figcaption { - code {-~/board/hx20/led.c} - } - pre {= m4_fmt_code(led.diff.gsp) } - } - - p {- - As you can see, it’s all fairly simple. I just had to change our - @code{-EC_LED_COLOR_WHITE} for @code{-EC_LED_COLOR_GREEN}. The codebase - defines a few colors, but they’re defined as m4_abbr(RGB) tuples which - is awesome, because it opens the door to custom m4_abbr(RGB) effects in - the future! - } - - h2 #more {-There’s More Than One m4_abbr(LED)‽} - p {- - That’s right! The Framework laptop I own (13″; the 16″ releases soon - though!) has 3 more m4_abbr(LED) lights. One on the left of the - chassis, one on right of the chassis, and one on the capslock key. The - capslock m4_abbr(LED) acts as an indicator of whether or not you’ve got - capslock enabled. This is useless to me though, because my custom - keyboard layout doesn’t even support capslock (see the next section) — - so I patched it to be a function-lock indicator instead! - } - - p {- - Here’s the diff — but do take care if you want to apply similar patches - to your laptop! The files I’m editing are under @code{-board/hx20} - since I’m on an 11th Gen Intel m4_abbr(CPU). If you have a different - m4_abbr(CPU), you will probably need to fuck with different code: - } - - figure { - figcaption { - code {-~/board/hx20/board.h} - } - pre {= m4_fmt_code(fn-lock-1.diff.gsp) } - } - - figure { - figcaption { - code {-~/board/hx20/keyboard-customization.c} - } - pre {= m4_fmt_code(fn-lock-2.diff.gsp) } - } - - p {- - As you can see, toggling the capslock m4_abbr(LED) is as simple as - invoking @code{-gpio_set_level()}. Not only that, but disabling its - functionality with the capslock key is as easy as undefining the - @code{-CONFIG_CAPSLOCK_SUPPORT} macro. Figuring out if the function key - is locked is also really easy. The @code{-Fn_key} global variable is a - bit-field containing information pertaining to the function key, and we - also conveniently already have the @code{-FN_LOCKED} constant defined - that we can bitwise-AND with @code{-Fn_key} to check the locked state! - } - - p {- - We also setup some hooks with the @code{-DECLARE_HOOK()} macro. These - just ensure that we are behaving properly on system resume and -suspend. - } - - h2 #hybrid {-The Hybrid Key} - p {- - Wouldn’t it be cool if a physical key could represent two keys at the - same time? I thought so too. Like all Emacs users, I suffer from a - distinct lack of easily-accessible modifier keys. I need escape because - I use Vim bindings; I need left-control because all the Emacs bindings - use it; I need super for my window-managers’ bindings; I need left-alt - so I can type characters that don’t come on a standard American keyboard - (such as @em{-ß}, @em{-€}, and @em{-é}), and now I have a problem. All - my modifiers are taken, but Emacs still needs a meta key to work! - } - - figure { - figcaption {- - @cite{-Workflow} by Randall Munroe - } - img alt="XKCD Comic 1172" src="1172.png" {} - } - - p {- - What will I ever do‽ Well thanks to Framework making the m4_abbr(EC) - open-source, and conveniently giving me a file called - @code{-keyboard_customization.c}, I’m going to take two keys and stick - them in one! The basic premise is this: the capslock key is arguably - the easiest modifier key to hit, and it’s currently bound to the escape - key on my system. This is inefficient though, because nobody makes - key-bindings that chord the escape-key with another key; - chords @x-ref{-1} are always done with a modifier like control, and - Emacs is no different. So my plan was to make it so that the capslock - key when used on its own mimics an escape-key, while instead mimicking - the left-control-key when used in a chord with another key. - } - - p {- - It took me a little longer this time to figure out how to implement what - I wanted since the code isn’t as clear, but it was still a surprisingly - easy feature to patch into the m4_abbr(EC)! I basically just updated - the scancode table, swapping out the capslock scancode for my own random - one that I called @code{-SCANCODE_CTRL_ESC}. I then created a new - function called @code{-try_ctrl_esc()} which is called in the on-keyup - and -down callback function. The @code{-try_ctrl_esc()} function - handles all of the logic as you can see in the following diff; it’s - basically just a state machine: - } - - aside { - p data-ref="1" {- - If you’re confused by what I mean by a ‘key-chord’, I am simply - referring to pressing multiple keys in conjunction, such as when you - press ‘@kbd{-Ctrl + C}’ to copy text. - } - } - - figure { - figcaption { - code {-~/board/hx20/keyboard_customization.c} - } - pre {= m4_fmt_code(hybrid.diff.gsp) } - } - - p {- - One thing that’s good to take note of is what I return from - @code{-try_ctrl_esc()}. The general pattern for handling a keyup or - -down event is to stick the following code into - @code{-keyboard_scancode_callback()}: - } - - figure { - figcaption {- - @code{-keyboard_scancode_callback()} in - @code{-~/board/hx20/keyboard_customization.c} - } - pre {= m4_fmt_code(kbd-sc-cb.c.gsp) } - } - - p {- - In @code{-my_handler_function()} (or whatever you decide to name it), - you attempt to handle the event. If you don’t want to handle a - particular event and instead want to pass it on to the next handler, you - need to return @code{-EC_SUCCESS}. If you managed to successfully - handle the event though, then you need to return an error such as - @code{-EC_ERROR_UNIMPLEMENTED}. It’s pretty stupid and makes very - little sense from a naming perspective, but oh well… - } - - h2 #next {-What’s Next?} - p {- - m4_abbr(RGB) m4_abbr(LED)s maybe. - } - } - - hr{} - - footer { m4_footer } - } -} diff --git a/src/srp/fw-ec/kbd-sc-cb.c.gsp b/src/srp/fw-ec/kbd-sc-cb.c.gsp deleted file mode 100644 index 31524de..0000000 --- a/src/srp/fw-ec/kbd-sc-cb.c.gsp +++ /dev/null @@ -1,6 +0,0 @@ -@span .c-cmt {-/* ‘make_code’ is the scancode. ‘pressed’ is a boolean that is true if this is a} - @span .c-cmt {-keydown event, and false if it’s a keyup. */} - -r = @span .c-fn {-my_handler_function}(make_code, pressed); -@span .c-kw {-if} (r != @span .c-pp {-EC_SUCCESS}) - @span .c-kw {-return} r; diff --git a/src/srp/fw-ec/led.diff.gsp b/src/srp/fw-ec/led.diff.gsp deleted file mode 100644 index ac7642f..0000000 --- a/src/srp/fw-ec/led.diff.gsp +++ /dev/null @@ -1,32 +0,0 @@ -@span .diff-meta {-diff --git a/board/hx20/led.c b/board/hx20/led.c} -@span .diff-meta {-index a4dc4564e..dacf73fda 100644} -@span .diff-meta {---- a/board/hx20/led.c} -@span .diff-meta {-+++ b/board/hx20/led.c} -@span .diff-loc {-\@\@ -283,22 +283,22 \@\@ static void led_set_power(void)} - /* don’t light up when at lid close */ - if (!lid_is_open()) { - set_pwr_led_color(PWM_LED2, -1); -@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0);} -@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0);} - return; - \} - - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) -@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 1);} -@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 1);} - else -@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0);} -@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0);} - - if (chipset_in_state(CHIPSET_STATE_ON) | power_button_enable) { - if (charge_prevent_power_on(0)) - set_pwr_led_color(PWM_LED2, (power_tick % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? -@span .diff-del {-- EC_LED_COLOR_WHITE : -1);} -@span .diff-ins {-+ EC_LED_COLOR_GREEN : -1);} - else -@span .diff-del {-- set_pwr_led_color(PWM_LED2, EC_LED_COLOR_WHITE);} -@span .diff-ins {-+ set_pwr_led_color(PWM_LED2, EC_LED_COLOR_GREEN);} - \} else - set_pwr_led_color(PWM_LED2, -1); - \} diff --git a/src/srp/gsp/abbr.m4.gsp b/src/srp/gsp/abbr.m4.gsp deleted file mode 100644 index 99ac1d7..0000000 --- a/src/srp/gsp/abbr.m4.gsp +++ /dev/null @@ -1 +0,0 @@ -@span .fn {-⁨m4_define⁩}(⁨m4_abbr⁩, `\@abbr .@span .fn {-⁨m4_translit⁩}(@span .var {-$1}, A-Z, a-z) {-@span .var {-$1}\}') diff --git a/src/srp/gsp/example.gsp.gsp b/src/srp/gsp/example.gsp.gsp deleted file mode 100644 index 7f30bf0..0000000 --- a/src/srp/gsp/example.gsp.gsp +++ /dev/null @@ -1,11 +0,0 @@ -@span .gsp-node {-html} @span .gsp-attr {-lang}@span .gsp-op {-=}@span .gsp-val {-"en"} @span .gsp-op {-{} - @span .gsp-node {-body} @span .gsp-op {-{} - @span .gsp-node {-p} @span .gsp-op {-{-} Hello, World!@span .gsp-op {-\}} - - @span .gsp-node {-ul} @span .gsp-op {-{} - @span .gsp-node {-li} @span .gsp-op {-{}@span .gsp-node {-a} @span .gsp-attr {-href}@span .gsp-op {-=}@span .gsp-val {-"#"} @span .gsp-attr {-#home} @span .gsp-op {-{-}Home Page@span .gsp-op {-\}\}} - @span .gsp-node {-li} @span .gsp-op {-{}@span .gsp-node {-a} @span .gsp-attr {-href}@span .gsp-op {-=}@span .gsp-val {-"#"} @span .gsp-attr {-#about} @span .gsp-op {-{-}About Me@span .gsp-op {-\}\}} - @span .gsp-node {-li} @span .gsp-op {-{}@span .gsp-node {-a} @span .gsp-attr {-href}@span .gsp-op {-=}@span .gsp-val {-"#"} @span .gsp-attr {-#links} @span .gsp-op {-{-}Fun Links@span .gsp-op {-\}\}} - @span .gsp-op {-\}} - @span .gsp-op {-\}} -@span .gsp-op {-\}} diff --git a/src/srp/gsp/folds.scm.gsp b/src/srp/gsp/folds.scm.gsp deleted file mode 100644 index fb8ce45..0000000 --- a/src/srp/gsp/folds.scm.gsp +++ /dev/null @@ -1,4 +0,0 @@ -[ - (@span .fn {-node}) - (@span .fn {-attribute_list}) -] @span .var {-\@fold} diff --git a/src/srp/gsp/grammar.js.gsp b/src/srp/gsp/grammar.js.gsp deleted file mode 100644 index 7a06e7f..0000000 --- a/src/srp/gsp/grammar.js.gsp +++ /dev/null @@ -1,12 +0,0 @@ -{ - @span .var {-node}: @span .var {-$} => @span .fn {-seq}( - @span .fn {-optional}('>'), - @span .var {-$.node_name}, - @span .fn {-optional}(@span .var {-$.attribute_list}), - @span .str {-'{'}, - @span .fn {-optional}(@span .var {-$.node_body}), - @span .str {-'\}'}, - ), - - @span .var {-node_name}: @span .var {-$} => @span .str {-/[a-zA-Z:_][a-zA-Z0-9:_\\-​.]*​/}, -\} diff --git a/src/srp/gsp/highlights.scm.gsp b/src/srp/gsp/highlights.scm.gsp deleted file mode 100644 index 6deeb8a..0000000 --- a/src/srp/gsp/highlights.scm.gsp +++ /dev/null @@ -1,9 +0,0 @@ -[@span .str {-">"} @span .str {-"-"} @span .str {-"="} @span .str {-"\@"}] @span .var {-\@operator} -[@span .str {-"{"} @span .str {-"\}"}] @span .var {-\@tag.delimiter} -(@span .fn {-node_name}) @span .var {-\@tag} -[ - (@span .fn {-attribute_name}) - (@span .fn {-class_shorthand}) - (@span .fn {-id_shorthand}) -] @span .var {-\@tag.attribute} -(@span .fn {-attribute_value}) @span .var {-\@string} diff --git a/src/srp/gsp/index.gsp b/src/srp/gsp/index.gsp deleted file mode 100644 index 8c56883..0000000 --- a/src/srp/gsp/index.gsp +++ /dev/null @@ -1,310 +0,0 @@ -html lang="en" { - head { m4_include(head.gsp) } - body { - header { - div { - h1 {-Never Settle For Trash} - m4_include(nav.gsp) - } - - figure .quote { - blockquote { - p {= - 🚨🚨 BREAKING: TYPESCRIPT SNATCHES DEFEAT FROM THE JAWS OF VICTORY - 🚨🚨 - } - } - figcaption {-Lane Wagner} - } - } - - main { - h2 {-Table of Contents} - - ul { - li {a href="#simple" {-Simplicity and Abstraction}} - li {a href="#sucks" {-Most Software Sucks}} - li {a href="#solution" {-My Solution}} - li {a href="#syntax" {-Syntax Highlighting}} - li {a href="#takeaway" {-The Takeaway}} - } - - h2 #simple {-Simplicity and Abstraction} - p {- - I like my software simple and devoid of useless abstraction. I often - find myself in positions where I’m searching for scissors to cut a sheet - of paper, and am instead greeted with a chainsaw. The urge to - over-complicate and -abstract your software can be strong; I often see - people who preach simple software writing programs to solve basic - problems that have 30 different command-line flags, and require a 50 - page m4_abbr(PDF) explaining its operation. - } - - p {- - Why do I mention all of this? Well as anyone who’s ever tried their - hand at web-development knows, websites are written in m4_abbr(HTML). I - wish I could say that’s a good thing, but as anyone who’s ever looked at - m4_abbr(HTML) before would know, that language is — to put it lightly — - really not great. It’s extremely verbose, and awkward to write- and - edit (angle brackets are not the easiest-to-reach keys on the keyboard). - } - - p {- - So what’s the solution? The most obvious to me is to create a nicer to - read- and write language which I can easily transpile down to - m4_abbr(HTML). Ideally the m4_abbr(CLI) is very simple and works on the - standard input and -output like all good UNIX utilities. I should be - able to transpile my site by simply running ‘@code{-cmd in.xyz - out.html}’, where my input reflects the structure of my output will - nicer, less-polluting syntax such as in ‘@code{-div .cls { … \}}’. - } - - p {- - The kind of tool I am describing here is what I imagine the ideal - solution to be. A @em{-simple} tool with a @em{-simple} function. It - takes an input language and produces an output language. There is also - minimal abstraction. The input language should reflect the structure of - m4_abbr(HTML), because that’s exactly what we’re trying to output. It - makes little sense to create a fundamentally different language when - m4_abbr(HTML) not only does a good job at defining a websites structure, - but sticking close to the language we are targeting just makes - everyone’s life easier in every way. - } - - h2 #sucks {-Most Software Sucks} - - p {- - So with my ideal solution being a simple language with a simple - m4_abbr(CLI) that sticks close to the structure of m4_abbr(HTML), let’s - take a look at what other people have come up with: - } - - figure { - pre {= m4_fmt_code(markdown.md.gsp) } - } - - p {- Oh no.} - - p {- - Now most readers probably had the initial reaction of ‘@em{-What’s wrong - with Markdown?}’. To answer your question: everything. The issue I - have with these highly-prevalent Markdown-based replacements for - m4_abbr(HTML) is that they ignore the fundamental fact that - m4_abbr(HTML) and Markdown are @em{-not} compatible languages with each - other. m4_abbr(HTML) is designed around making websites (with the added - autism of m4_abbr(XML)). It gives us things like semantic tags for - describing input forms, navigation bars, figures, and more. With the - addition of classes and IDs, we can even style two paragraphs on the - same page in different ways. This is fundamentally not possible in - Markdown. If we ignore the fact that Markdown is just poorly designed, - it offers us basically none of what we need to make an even - slightly-complex static page as it’s not meant for website-design but - simply to be a readable plain-text format you can use for documentation - or your email or something. - } - - p {- - How do you make your navigation bar in Markdown? Or style two - paragraphs differently? You can’t. Some try to get around this by - adding extensions to the Markdown language, but they never manage to - cover all bases. Another problem I @em{-always} come across when trying - to use Markdown-to-m4_abbr(HTML) tools is code blocks. I always make - sure to use tabs for indentation in my code blocks instead of spaces, so - that I can vary the tab-width based on the screen size of the reader. - You obviously can’t do this with spaces since the fundamental (and - retarded) purpose of space-indentation is to force everyone to view code - with the same indentation, which sucks for users on mobile when you have - nice large indents. To this day I have yet to find a - Markdown-to-m4_abbr(HTML) converter that will let me have tab indents - without error-prone post-processing of the generated m4_abbr(HTML). - } - - p {- - Ok well… there are other ways of generating m4_abbr(HTML); one rather - popular option is Pug: - } - - figure { - pre .pug {= m4_fmt_code(pug.pug.gsp) } - } - - p {- - While Pug certainly hits the ‘maintain the same structure’ point right - on the head, it fails in one very crucial area — it’s a JavaScript - library @em{-only}, and so requires a whole m4_abbr(JS) setup simply to - transpile your site to m4_abbr(HTML). What a bummer. There is also a - second issue which is that it uses an indentation-sensitive syntax. - Normally I am actually a fan of languages like this — such as Python — - but in the case of a markup language like Pug, this is terrible as it - makes macros and templating with tools such as @code{-m4} exceptionally - difficult. Pug @em{-does} offer templating faculties via JavaScript, - but I really try to minimize the amount of JavaScript I need to write - whenever possible. - } - - h2 #solution {-My Solution} - - p {- - So with no existing tools fitting my entry criteria, I did the only - reasonable next thing and made my own tool. It tries to stick to the - format of m4_abbr(HTML) as closely as possible while offering an - @em{-extremely} easy-to-use transpiler. It also has no added bullshit - like filters, templates, etc. If you want macros, use a macro-processor - like @code{-m4}. I called it m4_abbr(GSP) because everyone knows that - German Shorthaired Pointers are better than pugs. Here is a quick - syntax example: - } - - figure { - pre .gsp {= m4_fmt_code(example.gsp.gsp) } - } - - p {- - Here you can see almost all of m4_abbr(GSP). The document follows the - same structure as m4_abbr(HTML), but thanks to the use of braces instead - of opening- and closing tags, the syntax is far less verbose and easier - to read. The language also provides shorthands for classes and IDs - through m4_abbr(CSS)-selector syntax. - } - - p {- - Templating and macros are also very easy via macro processors thanks to - the use of braces instead of whitespace-based scoping. You may have - noticed that I like to make use of abbreviations on this website that - expand when hovered over (unless you’re on mobile, in which case you - might not see them). I do this via the m4_abbr(HTML) @code{-} - tag, providing the appropriate class. For example, many times on this - very page I’ve made use of @code{-\@abbr .html {-HTML\}}. Obviously - repeating that everywhere in my document can be quite annoying, so I’ve - gotten around this by making use of the following @code{-m4} macro: - } - - figure { - pre {= m4_fmt_code(abbr.m4.gsp) } - } - - p {- - I can then insert abbreviations by simply writing something along the - lines of ‘@code{-⁨m4_abbr(HTML)⁩}’ in my document. - } - - aside { - p {- - The first thing I did after finishing the transpiler was to rewrite - this entire site in m4_abbr(GSP). There is something that just feels - so great about writing a tool that you actually use in your day-to-day - life. - } - } - - p {- - The transpiler itself is also incredibly easy to use, something - JavaScript developers would never be able to comprehend. In order to - transpile a m4_abbr(GSP) document into an m4_abbr(HTML) document, I - simply run ‘@code{-gsp index.gsp >index.html}’. Yep, that’s it. - } - - h2 #syntax {-Syntax Highlighting} - - p {- - One problem that I came across writing m4_abbr(GSP) was the lack of - syntax highlighting. It can seem not so important, but syntax - highlighting is crucial for helping you quickly identify different - syntax elements. The awesome solution I found for this ended being - Tree-Sitter. Tree-Sitter is a parser-generator that various text - editors such as Vim and Emacs can integrate with to offer efficient- and - high quality syntax highlighting, amongst other features such as - syntax-aware code folding and movement. - } - - p {- - After a bit of research and reading the documentation, I found that - creating your own parsers is actually really easy. You effectively just - define a JavaScript object that describes the language grammar, and a C - parser is generated from that. If you’re interested, you can find the - m4_abbr(GSP) parser @a href="https://git.sr.ht/~mango/tree-sitter-gsp" - {-here}. To give you a bit of an idea of just how simple a Tree-Sitter - parser is, here’s a simplified example of how you describe the - definition of a node, and a node name @x-ref{-1}: - } - - figure { - pre .js {= m4_fmt_code(grammar.js.gsp) } - } - - aside { - p data-ref="1" {- - The definition for what constitutes a node name is simplified in the - example. In actuality node names can contain all sorts of unicode - characters too (because m4_abbr(XML) said so), but I would like the - regex to actually fit on the screen. - } - } - - p {- - As you can see, the grammar syntax is extremely simple. You simply - define your core syntax elements via regular expressions, and then - compose them together via helper functions such as @code{-optional} and - @code{-repeat} to define the full structure of your language. - } - - p {- - This isn’t enough though. We now have a parser for our language that - can create a syntax tree that our editor can take advantage of, but our - editor still doesn’t know what each node actually @em{-is} so that it - can be syntax highlighted properly. Tree Sitter solves this through a - query file written in Scheme where we can describe how to syntax - highlight our m4_abbr(AST). This is what the configuration for - m4_abbr(GSP) looks like: - } - - figure { - figcaption { - code {-queries/highlights.scm} - } - pre {= m4_fmt_code(highlights.scm.gsp) } - } - - p {- - As you can see, this is all really simple stuff, which is what I love so - much about Tree Sitter — it’s just so easy! With these basic - annotations your editor knows that attribute values should be - highlighted like strings, braces like tag delimiters, etc. In a similar - vein, writing a query to describe code-folding is really easy: - } - - figure { - figcaption { - code {-queries/folds.scm} - } - pre {= m4_fmt_code(folds.scm.gsp) } - } - - h2 #takeaway {-The Takeaway} - - p {- - So what’s the takeaway? I think it’s that when you have a problem, - often times the best solution is not to fundamentally redesign something - from the ground up, or to completely change the way a system works, but - to instead identify the specific thing that annoys you and find a fix - for it. I thought that the syntax of m4_abbr(HTML) was annoying and - bad, so I found a solution for the syntax, while keeping the core - structure the same. In the same line of thinking, try not to - over-abstract — I’m looking at you, Java developers. Abstraction often - leads to exponentially increased complications the moment we want to do - anything different or out of the ordinary, so unless you can find a - really nice abstraction that doesn’t really make anyone’s life harder, - try to avoid them when you can. - } - - p {- - If you’re interested in m4_abbr(GSP), you can find the git repository - over at @a href="https://git.sr.ht/~mango/gsp" {-Sourcehut}. - } - } - - hr{} - - footer { m4_footer } - } -} diff --git a/src/srp/gsp/markdown.md.gsp b/src/srp/gsp/markdown.md.gsp deleted file mode 100644 index 3d5f51a..0000000 --- a/src/srp/gsp/markdown.md.gsp +++ /dev/null @@ -1,3 +0,0 @@ -@span .md-delim {-#} @span .md-head {-Markdown 4 Lyfe} - -Welcome to my website written in Hugo! diff --git a/src/srp/gsp/pug.pug.gsp b/src/srp/gsp/pug.pug.gsp deleted file mode 100644 index de816e3..0000000 --- a/src/srp/gsp/pug.pug.gsp +++ /dev/null @@ -1,8 +0,0 @@ -@span .pug-node {-div} - @span .pug-node {-p} - @span .pug-cont {-|} Hello world! This is a - @span .pug-cont {-|} multiline paragraph. - @span .pug-node {-ul} - @span .pug-node {-li} foo - @span .pug-node {-li} bar - @span .pug-node {-li} baz diff --git a/src/srp/index.gsp b/src/srp/index.gsp deleted file mode 100644 index ae8e597..0000000 --- a/src/srp/index.gsp +++ /dev/null @@ -1,41 +0,0 @@ -html lang="en" { - head { m4_include(head.gsp) } - body { - header { - div { - h1 {-Software-Related Posts} - m4_include(nav.gsp) - } - - figure .quote { - blockquote { - p {= - Object-oriented programming is an exceptionally bad idea which could - only have originated in California. - } - } - figcaption {-Edsgar W. Dijkstra} - } - } - - main { - p {- - In this section of the website I cover random software-related stuff - that isn’t related to actual projects of mine. Posts here could be - about anything from a cool program I found, to a patch I wrote, to me - complaining about bad software design. - } - - p {-Posts:} - - ul { - m4_article(gsp, {-Writing an HTML Preprocessor (feat. Tree-Sitter)}) - m4_article(fw-ec, {-Patching My Laptop’s Embedded Controller}) - } - } - - hr{} - - footer { m4_footer } - } -} -- cgit v1.2.3