Instead of everyone overriding save_to() and set_property() and doing
a pretty asymmetric job of implementing the various properties, let's
add a bit of structure here.
Object properties are now represented by a Core::Property. Properties
are registered with a getter and setter (optional) in constructors.
I've added some convenience macros for creating and registering
properties, but this does still feel a bit bulky. We'll have to
iterate on this and see where it goes.
This commit adds an equivalent to the sh 'case' construct, except it's
much more pleasing to look at and write:
```sh
match "$something" {
p1 { echo "p1!" }
p2 { echo "p2!" }
* { echo "string catch-all!" }
}
```
is the equivalent of:
```sh
case $something in
p1)
echo "p1!"
;;
p2)
echo "p2!"
;;
*)
echo "catch-all!"
;;
esac
```
Since our shell does not treat lists as strings, matching lists is also
possible:
```sh
match (1foo 2foo foo3) {
(?foo 2* *) { echo wowzers! }
(* * *) { echo 3-element list catch-all }
}
```
OutputMemoryStream was originally a proxy for DuplexMemoryStream that
did not expose any reading API.
Now I need to add another class that is like OutputMemoryStream but only
for static buffers. My first idea was to make OutputMemoryStream do that
too, but I think it's much better to have a distinct class for that.
I originally wanted to call that class FixedOutputMemoryStream but that
name is really cumbersome and it's a bit unintuitive because
InputMemoryStream is already reading from a fixed buffer.
So let's just use DuplexMemoryStream instead of OutputMemoryStream for
any dynamic stuff and create a new OutputMemoryStream for static
buffers.
This fixes a duplicate message when running `jobs` for the first time
after a job has been moved to the background.
Also actually announces background exits now :^)
This patchset makes the shell capable of lazily resolving and executing
sequences of commands, to allow for putting logical sequences in the
background.
In particular, it enables And/Or/Sequence nodes to be run in the background,
and consequently unmarks them as `would_execute`.
Doing so also fixes job control to an extent, as jobs are now capable of
having 'tails', so sequences can be put in the background while
preserving their following sequences.
Makes C-c print "^C" and continue prompting on a new line.
Also fixes a problem where an interrupted get_line() would need more
read()'s than required to update the display.