plum v0.0.22
Plum is a small, statically typed, compiled language.
Process identity — argv, the working directory, stdin and stderr — plus
two language-server fixes for macOS and Windows.
0.0.21 was never published. Its release job failed while uploading
one platform's artifact, and the commit it tagged still had the Windows
bug below. If you are on 0.0.20, this is the upgrade.
The language server, on macOS and Windows
Both bugs arrived in 0.0.20 and both were invisible on Linux.
On macOS, an error in one file of a project was attributed to a
temporary file rather than the file it is in — so the editor underlined
nothing and pointed somewhere you have never opened. The server checks
an unsaved buffer by copying the project to a scratch directory, and it
recognises a diagnostic from that copy by matching the directory as a
prefix. One side of that comparison had been normalized and the other
had not. It only showed where the temporary directory needed
normalizing, which is why macOS saw it and Linux did not: macOS sets
TMPDIR with a trailing slash.
On Windows, hover, completion, go-to-definition and cross-file
diagnostics all failed together. A file: URI always uses /, while
every path the compiler reports uses the platform separator — and the
two met without being reconciled, so the server handed a child process a
project directory spelled one way and a file path spelled the other.
Nothing matched. Both conventions are now converted at the boundary
where they meet.
bootstrap/lsp-smoke sets TMPDIR with a trailing slash itself now, on
every platform, so the shape that hid the first bug is exercised
everywhere rather than only where it happens to occur.
Process identity
use Os;
Os.cwd() // Result[String, String]
Os.chdir(path)
Os.home_dir() // Option[String] — $HOME, or %USERPROFILE%
Os.read_stdin_line() // Result[Option[String], String]
Os.read_stdin(4096) // Result[Bytes, String]
Os.write_stderr("...")
None from read_stdin_line is end of stream and Some("") is a blank
line, and keeping those apart is the point. The shims the language
server has always used answer "" to both, so a filter reading until
end of input stopped at the first blank line — wrong in a way that only
shows up on real data. A final line with no trailing newline is an
ordinary line rather than something to drop.
Os.read_stdin hands back Bytes, because standard input carries
whatever was piped into it. An empty result is end of stream; a short
one is data, since a pipe gives you what it has.
Os.write_stderr is not println, which is stdout. A diagnostic in the
same stream as the program's output cannot be separated from it by
whoever is reading.
Os.home_dir() reads the environment and returns None when it is
unset, rather than guessing a path from a username — a guess that is
usually right is the worst kind of wrong for a directory a program is
about to write to.
args() is documented
It has existed since the beginning, is used by this compiler and by the
test corpus, and appeared in STDLIB.md nowhere — under a heading
promising that every function is listed by construction.
It was not alone: chars_of and panic_raw were missing for the same
reason. The reference is generated by reading declarations, and these
three are implemented by the compiler rather than declared anywhere it
could see. All three are listed now, and a check fails the build if
another one is added without being.
Upgrading
Nothing that compiled under 0.0.20 fails under 0.0.22.
Os.cwd, chdir, home_dir, read_stdin_line, read_stdin and
write_stderr are new names in Os. If you were reaching into
native_stdlib with your own extern "C" block to read standard input,
that still works and is no longer necessary.