diff options
author | Thomas Voss <mail@thomasvoss.com> | 2023-10-05 22:10:51 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2023-10-05 22:10:51 +0200 |
commit | d010a1c7ad683ca40b2eb978ef0535a40c7dc17a (patch) | |
tree | d6f4b8d01266ed2e7212cf3f0db57febd289ffff /src | |
parent | 61a639cb94b030eaeb408f28a05df03778c77ea4 (diff) |
Add a new post on GSP
Diffstat (limited to 'src')
-rw-r--r-- | src/srp/gsp/abbr.m4.gsp | 1 | ||||
-rw-r--r-- | src/srp/gsp/example.gsp.gsp | 11 | ||||
-rw-r--r-- | src/srp/gsp/folds.scm.gsp | 4 | ||||
-rw-r--r-- | src/srp/gsp/grammar.js.gsp | 12 | ||||
-rw-r--r-- | src/srp/gsp/highlights.scm.gsp | 9 | ||||
-rw-r--r-- | src/srp/gsp/index.gsp | 310 | ||||
-rw-r--r-- | src/srp/gsp/markdown.md.gsp | 3 | ||||
-rw-r--r-- | src/srp/gsp/pug.pug.gsp | 8 | ||||
-rw-r--r-- | src/srp/index.gsp | 1 | ||||
-rw-r--r-- | src/style.css | 26 |
10 files changed, 385 insertions, 0 deletions
diff --git a/src/srp/gsp/abbr.m4.gsp b/src/srp/gsp/abbr.m4.gsp new file mode 100644 index 0000000..48626e0 --- /dev/null +++ b/src/srp/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/srp/gsp/example.gsp.gsp b/src/srp/gsp/example.gsp.gsp new file mode 100644 index 0000000..7f30bf0 --- /dev/null +++ b/src/srp/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/srp/gsp/folds.scm.gsp b/src/srp/gsp/folds.scm.gsp new file mode 100644 index 0000000..8c7cb61 --- /dev/null +++ b/src/srp/gsp/folds.scm.gsp @@ -0,0 +1,4 @@ +[ + (@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 new file mode 100644 index 0000000..278fff0 --- /dev/null +++ b/src/srp/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/srp/gsp/highlights.scm.gsp b/src/srp/gsp/highlights.scm.gsp new file mode 100644 index 0000000..37f445e --- /dev/null +++ b/src/srp/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/srp/gsp/index.gsp b/src/srp/gsp/index.gsp new file mode 100644 index 0000000..1ff3686 --- /dev/null +++ b/src/srp/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-poluting 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 targetting just makes + everyones 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 sematic 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 classses 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. I do this via the m4_abbr(HTML) + @code{-<abbr>} 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 annotions + 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 anyones 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 new file mode 100644 index 0000000..3d5f51a --- /dev/null +++ b/src/srp/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/srp/gsp/pug.pug.gsp b/src/srp/gsp/pug.pug.gsp new file mode 100644 index 0000000..ac3e026 --- /dev/null +++ b/src/srp/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/srp/index.gsp b/src/srp/index.gsp index da62301..f829644 100644 --- a/src/srp/index.gsp +++ b/src/srp/index.gsp @@ -29,6 +29,7 @@ html lang="en" { p {-Posts:} ul { + li {a href="gsp" {-Writing an HTML Preprocessor (feat. Tree-Sitter)}} li {a href="fw-ec" {-Patching My Laptop’s Embedded Controller}} } } diff --git a/src/style.css b/src/style.css index aab4147..b642fad 100644 --- a/src/style.css +++ b/src/style.css @@ -11,6 +11,8 @@ --blue: #81A2BE; --red: #C66; --salmon: #FA8072; + --yellow: #F0E68C; + --grey: #B3B3B3; } @font-face { @@ -62,6 +64,9 @@ pre, code, kbd, samp { pre > code { color: var(--fg); } :not(pre) > code { white-space: nowrap; } +pre.js { tab-size: 4; } +pre.pug, pre.gsp { tab-size: 2; } + h1 { font-size: 1.8rem; margin-bottom: 0; @@ -164,6 +169,7 @@ dl { grid-template-columns: max-content auto; } +/* Old classes */ .c-cmt, .sh-cmt { color: var(--lesser); font-style: italic; } .sh-var { color: var(--blue); font-style: italic; } .c-fn, .sh-fn { color: var(--accent); } @@ -173,11 +179,28 @@ dl { .sh-hd { color: var(--aqua); } .sh-ex { color: var(--salmon); } +/* New classes */ +.fn { color: var(--accent); } +.var { color: var(--blue); } +.str { color: var(--aqua); } + .diff-ins { color: var(--green); } .diff-del { color: var(--red); } .diff-loc { color: var(--lesser); } .diff-meta { font-weight: bold; } +.md-delim { color: var(--grey); } +.md-head { + color: var(--yellow); + font-weight: bold; +} + +.pug-node, .gsp-node { color: var(--accent); } +.pug-cont { color: var(--lesser); } +.gsp-attr { color: var(--green); } +.gsp-val { color: var(--aqua); } +.gsp-op { color: var(--lesser); } + @media (min-width: 40em) { body { font-size: 1.3rem; @@ -221,6 +244,7 @@ dl { pointer-events: none; } + abbr.ast::before { content: 'Abstract Syntax Tree'; } abbr.cli::before { content: 'Command-Line Interface'; } abbr.cpu::before { content: 'Central Processing Unit'; } abbr.css::before { content: 'Cascading Stylesheets'; } @@ -230,8 +254,10 @@ dl { abbr.gsp::before { content: 'German Shorthaired Pointer'; } abbr.html::before { content: 'Hypertext Markup Language'; } abbr.it::before { content: 'Information Technology'; } + abbr.js::before { content: 'JavaScript'; } abbr.led::before { content: 'Light-Emitting Diode'; } abbr.nas::before { content: 'Network Attached Storage'; } + abbr.pdf::before { content: 'Portable Document Format'; } abbr.qr::before { content: 'Quick Response'; } abbr.rgb::before { content: 'Red Green Blue'; } abbr.sha::before { content: 'Secure Hash Algorithm'; } |