summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2023-10-05 22:10:51 +0200
committerThomas Voss <mail@thomasvoss.com> 2023-10-05 22:10:51 +0200
commitd010a1c7ad683ca40b2eb978ef0535a40c7dc17a (patch)
treed6f4b8d01266ed2e7212cf3f0db57febd289ffff /src
parent61a639cb94b030eaeb408f28a05df03778c77ea4 (diff)
Add a new post on GSP
Diffstat (limited to 'src')
-rw-r--r--src/srp/gsp/abbr.m4.gsp1
-rw-r--r--src/srp/gsp/example.gsp.gsp11
-rw-r--r--src/srp/gsp/folds.scm.gsp4
-rw-r--r--src/srp/gsp/grammar.js.gsp12
-rw-r--r--src/srp/gsp/highlights.scm.gsp9
-rw-r--r--src/srp/gsp/index.gsp310
-rw-r--r--src/srp/gsp/markdown.md.gsp3
-rw-r--r--src/srp/gsp/pug.pug.gsp8
-rw-r--r--src/srp/index.gsp1
-rw-r--r--src/style.css26
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'; }