summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2023-12-10 02:50:39 +0100
committerThomas Voss <mail@thomasvoss.com> 2023-12-10 02:50:39 +0100
commit9e337a2309c9dcadd91fb3878c2194c477b92bf7 (patch)
tree23f5a916acaaa206e3c6b926cceffff51f1bf9a0
parent54219327782db0b5c78aebf2d982f20ea1bef47f (diff)
Add another Andy post
-rw-r--r--src/blog/andy-val/angle-bracket.an.gsp11
-rw-r--r--src/blog/andy-val/cartesian.an.gsp4
-rw-r--r--src/blog/andy-val/dynamic-func.an.gsp4
-rw-r--r--src/blog/andy-val/index.gsp160
-rw-r--r--src/blog/andy-val/naïve.an.gsp6
-rw-r--r--src/blog/andy-val/posix-fail.sh.gsp3
-rw-r--r--src/blog/andy-val/smart.an.gsp7
-rw-r--r--src/blog/andy-val/trap.sh.gsp1
-rw-r--r--src/blog/index.gsp1
-rw-r--r--src/style.css5
10 files changed, 200 insertions, 2 deletions
diff --git a/src/blog/andy-val/angle-bracket.an.gsp b/src/blog/andy-val/angle-bracket.an.gsp
new file mode 100644
index 0000000..1599dce
--- /dev/null
+++ b/src/blog/andy-val/angle-bracket.an.gsp
@@ -0,0 +1,11 @@
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}@span .cmt {-# `(D…){P…\} is syntax for splitting a process P’s}
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}@span .cmt {-# output on the delimiters D.}
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}@span .fn {-printf} %s\\n @span .str {-'> '}@span .op {-`}(\\n)@span .op {-{}@span .fn {-grep} MHz /proc/cpuinfo@span .op {-\}}
+>cpu MHz : 1127.333
+>cpu MHz : 1199.957
+>cpu MHz : 1139.098
+>cpu MHz : 1200.000
+>cpu MHz : 1172.249
+>cpu MHz : 1199.957
+>cpu MHz : 1151.501
+>cpu MHz : 1199.996
diff --git a/src/blog/andy-val/cartesian.an.gsp b/src/blog/andy-val/cartesian.an.gsp
new file mode 100644
index 0000000..fb09f2c
--- /dev/null
+++ b/src/blog/andy-val/cartesian.an.gsp
@@ -0,0 +1,4 @@
+@span .cmt {-# foo.c foo.h bar.c bar.h baz.c baz.h}
+@span .fn {-echo} (foo bar baz)(.c .h)
+@span .cmt {-# Or alternatively:}
+@span .fn {-echo} (foo bar baz).(c h)
diff --git a/src/blog/andy-val/dynamic-func.an.gsp b/src/blog/andy-val/dynamic-func.an.gsp
new file mode 100644
index 0000000..abacc80
--- /dev/null
+++ b/src/blog/andy-val/dynamic-func.an.gsp
@@ -0,0 +1,4 @@
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}@span .fn {-set} foo bar
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}@span .kw {-func} @span .var {-$foo} {\}
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}@span .fn {-type} bar
+function
diff --git a/src/blog/andy-val/index.gsp b/src/blog/andy-val/index.gsp
new file mode 100644
index 0000000..63f0699
--- /dev/null
+++ b/src/blog/andy-val/index.gsp
@@ -0,0 +1,160 @@
+html lang="en" {
+ head { m4_include(head.gsp) }
+ body {
+ header {
+ div {
+ h1 {-So Much Value}
+ m4_include(nav.gsp)
+ }
+
+ figure .quote {
+ blockquote {
+ p {=
+ Complexity is a backdoor and can be misinterpreted as
+ sophistication.
+ }
+ }
+ figcaption {-asvln.com}
+ }
+ }
+
+ main {
+ h2 #value {-Values}
+ p {-
+ As covered in @a href="/blog/new-sh" {-my last post}, I’m working on
+ Andy, my personal shell. One of the pretty interesting features of Andy
+ I think is the way that @em{-values} are handled. In the conventional
+ shell, you can think of a value as a string. In @code{-echo foo}, both
+ ‘echo’ and ‘foo’ can be thought of as values. Values aren’t just
+ string-literals though, a Bash process-redirection (@code{-<(cmd)}) is
+ also a value; typically one that looks like ‘/dev/fd/N’.
+ }
+
+ p {-
+ In Andy this mostly holds, with one very important difference: values
+ are not strings — they’re lists of strings. While the string-literal
+ @code{-"foo"} might be a string list of length 1, the
+ process-redirection of @code{-<>{cmd\}} is a list of 2 strings — a path
+ to a file you can read from, and a path to a file you can write to.
+ }
+
+ p {-
+ This is an important distinction to make because of the fact that
+ value-concatenation goes from a simple string-concatenation to a
+ cartesian product of the left- and right values:
+ }
+
+ figure {
+ pre {= m4_fmt_code(cartesian.an.gsp) }
+ }
+
+ p {-
+ This is not just constrainted to literals of course, process
+ substitutions are also values, so appending each line of a processes
+ output with a closing-angle-bracket becomes trivial:
+ }
+
+ figure {
+ pre {= m4_fmt_code(angle-bracket.an.gsp) }
+ }
+
+ p {-
+ Of course you can also append the closing-angle-bracket using
+ @code{-printf} itself, but it’s just an example after all.
+ }
+
+ h2 #dynamic {-Dynamic Code}
+ p {-
+ What makes Andy different is not just the behavior of values, but where
+ you can use them. In most shells, various syntactic elements are not
+ expanded in the same way that regular values are. The following example
+ results in an error because the function name @code{-$foo} doesn’t get
+ expanded into @code{-bar}:
+ }
+
+ figure {
+ pre {= m4_fmt_code(posix-fail.sh.gsp) }
+ }
+
+ p {-
+ Andy doesn’t give a fuck though, it lets you do this if you really want
+ to:
+ }
+
+ figure {
+ pre {= m4_fmt_code(dynamic-func.an.gsp) }
+ }
+
+ p {-
+ Now you might think that this is really retarded — especially if you’re
+ a Rust developer — and you know what? I did too! But you know what the
+ beauty of recreational programming is? It doesn’t @code{-have} to be
+ good — and once you learn to ignore the low-value morons that will
+ see you experimenting with new ideas and call it garbage — you can start
+ to actually develop some pretty neat solutions to problems.
+ }
+
+ p {-
+ For example, Andy like all shells implements support for signal
+ handling. In the POSIX shell this is done via the ‘trap’ builtin
+ function:
+ }
+
+ figure {
+ pre {= m4_fmt_code(trap.sh.gsp) }
+ }
+
+ p {-
+ Now personally, I really don’t like @code{-trap}. Having to write your
+ signal handling code in string is just not very ergonomic. You
+ @em{-can} put your code in a function that you then call in your signal
+ handler, but I think Andy can do better. The way you handle a signal in
+ Andy is to simply define a function of the name ‘sigX’ where ‘X’ is the
+ name of the signal. If you want to write a handler for SIGINT, you
+ simply define the ‘sigint’ function!
+ }
+
+ p {-
+ What if we want to handle multiple signals though? In the above
+ example, we deleted some temporary files on SIGQUIT and also on the
+ special SIGEXIT (a fake signal that signifies that the process is
+ exiting). Well the naïve solution is to simply define a handler
+ function that you call from your handlers:
+ }
+
+ figure {
+ pre .sh {= m4_fmt_code(naïve.an.gsp) }
+ }
+
+ p {-
+ But wait… remember how we can dynamically define functions? What if we
+ just… dynamically define our signal handlers:
+ }
+
+ figure {
+ pre .sh {= m4_fmt_code(smart.an.gsp) }
+ }
+
+ p {-
+ Personally, I think that’s pretty neat, and I like it! Of course some
+ Haskell developer that’s never @em{-actually} written any working
+ software will probably be sending me an angry email right about now
+ about how this is unsafe code and blah blah, but I don’t care.
+ }
+
+ p {-
+ I suppose while this post is primarily about just showing off some of
+ Andy’s behavior, I also want to make the point that it’s always a good
+ idea to just try new ideas, no matter how contrary they are to ‘best
+ practices’ and Rust developers. Don’t waste your time worrying about
+ what other people think about what you make; I used to do that, and it’s
+ not great. Just make shit, even if it’s weird. You might just
+ accidentally add a cool new feature you actually kind of like.
+ }
+ }
+
+ hr{}
+
+ footer { m4_footer }
+ }
+}
diff --git a/src/blog/andy-val/naïve.an.gsp b/src/blog/andy-val/naïve.an.gsp
new file mode 100644
index 0000000..661af89
--- /dev/null
+++ b/src/blog/andy-val/naïve.an.gsp
@@ -0,0 +1,6 @@
+@span .kw {-func} handler {
+ @span .fn {-rm} -f (foo bar).tmp
+\}
+
+@span .kw {-func} sigquit { @span .fn {-handler} \}
+@span .kw {-func} sigexit { @span .fn {-handler} \}
diff --git a/src/blog/andy-val/posix-fail.sh.gsp b/src/blog/andy-val/posix-fail.sh.gsp
new file mode 100644
index 0000000..b66ce22
--- /dev/null
+++ b/src/blog/andy-val/posix-fail.sh.gsp
@@ -0,0 +1,3 @@
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}foo@span .op {-=}bar
+@span .p {-thomas} @span .pp {-~} @span .p {-〉}@span .var {-$foo}() { @span .fn {-:}@span .op {-;} \}
+bash: `$bar': not a valid identifier
diff --git a/src/blog/andy-val/smart.an.gsp b/src/blog/andy-val/smart.an.gsp
new file mode 100644
index 0000000..668f189
--- /dev/null
+++ b/src/blog/andy-val/smart.an.gsp
@@ -0,0 +1,7 @@
+@span .cmt {-# $_ represents the current iteration variable. You can give an explicit name}
+@span .cmt {-# with a for-in loop though.}
+@span .kw {-for} quit exit {
+ @span .kw {-func} sig$_ {
+ @span .fn {-rm} -f (foo bar).tmp
+ \}
+\}
diff --git a/src/blog/andy-val/trap.sh.gsp b/src/blog/andy-val/trap.sh.gsp
new file mode 100644
index 0000000..30a60ad
--- /dev/null
+++ b/src/blog/andy-val/trap.sh.gsp
@@ -0,0 +1 @@
+@span .fn {-trap} @span .str {-"rm -f foo.tmp bar.tmp"} QUIT EXIT
diff --git a/src/blog/index.gsp b/src/blog/index.gsp
index 7ad0296..aac12e0 100644
--- a/src/blog/index.gsp
+++ b/src/blog/index.gsp
@@ -28,6 +28,7 @@ html lang="en" {
p {-Posts:}
ul {
+ m4_article(andy-val, {-Values in Andy})
m4_article(new-sh, {-Making a New Shell})
m4_article(extend, {-Extensible Scripting})
m4_article(nvim-ts, {-Hacking with Tree-Sitter on Neovim})
diff --git a/src/style.css b/src/style.css
index 6581e9d..42b55e1 100644
--- a/src/style.css
+++ b/src/style.css
@@ -170,11 +170,12 @@ dl {
/* New classes */
.cmt { color: var(--lesser); font-style: italic; }
+.cnst { color: var(--blue); }
.fn { color: var(--accent); }
.kw { color: var(--green); }
-.str { color: var(--aqua); }
-.cnst { color: var(--blue); }
.op { color: var(--lesser); }
+.str { color: var(--aqua); }
+.var { color: var(--blue); font-style: italic; }
/* Terminal prompt */
.p { color: #24DFC4; font-weight: bold; }