Acme is a text editor/IDE developed by Rob Pike (Go, UTF-8, Sam, etc.) for the Plan9 operating system; the editor is available via e.g. Plan 9 from User Space on UNIX.
In comparison to other modern editors, it is characterized by a restricted features set. The editor is succinctly presented, followed by a quick presentation of some scripts aiming at improving acme(1)’ usability/programmability.
Introduction
If you’re new to the editor, you may want to see Russ Cox’s Tour of Acme (video, Sept. 2012), linked here:
Or head to the resources section at the end of this article. If you’re curious about the Plan9 ecosystem, here’s a very complete summary of the various Plan9 derivatives, the research papers for Plan9’s 4th edition and the system’s main documentation, its man pages.
To keep things short, acme(1) is well described as an Integrating Development Environment. Despite a few caveats (e.g. no easy way to programmatically move windows), it’s good enough, small, light, stable, intuitive to UNIX savvy people.
It’s a great example simple software.
Tools
The following tools, thereafter described, aim at reducing the amount of windows, and ease to some extent Acme’s scriptability, pushing lib/acme.rc a bit further. Likely, those tools will only makes sense to you if you’ve already been using the editor for a while.
Run
This is perhaps the most useful, at least to me. Most others tools were developed
mainly in order to create Run
. It aims at implementing a typical
“build/run” feature, more precisely, it:
- Puts (save) all opened files (see
XPutall
); - Opens (see
Open
)if necessary an output buffer/window (by default, it targets the+Buffer
window, described in the next subsection), and clearing its content (seeClear
) if necessary - Executes (see
Exec
,To
) the program related to the current buffer (there’s an ad-hoc long list ofif/else
inRun
to determine what to do); - Redirecting stderr/stdout to the output buffer along the way, eventually tweaking stderr’s output by piping it to a program (this for instance allows to rewrite some error message to be more acme(1)/plumber(4) compliant).
Of course, CLI arguments can be provided to the program to be executed,
for instance: Run -- -o foo -x bar baz
will feed the program
-o foo -x bar baz
as CLI arguments.
A convenient -m <target>
option will execute make <target>
in
the first directory containing a Makefile
, starting from the current
directory, and going up in the tree until it reaches /
. For instance, when:
- middle clicking
Run -m tests
on the tagline of a file/home/user/gits/project/dir/subdir/foo.go
; - assuming a
/home/user/gits/project/Makefile
exists; - will run
make tests
in/home/user/gits/project/
(of course, surrounded by all previous boilerplate: saving files, opening output buffer, etc.)
“+Buffer” window
In practice, I’ve found that having a single +Errors window, with automatic content flushing, is more suitable than spanning one +Errors window per directory, with no flushing.
Note: the default behavior is reasonable though: better be verbose, and let the user filter as needed.
By convention, this window is called the +Buffer window, being the only window whose name is suffixed by +Buffer. Its access is automatically managed via the Getids command, described thereafter.
That window’s tagline is also used for running global commands, such as the session-related ones, also described later on.
Getids
Getids is a key script, on which most other scripts are built upon. It allows to easily target:
- the +Buffer window (creating it when necessary);
- multiple windows (X//-like looping);
- current window (the default).
It outputs a list of window IDs, one per line, from either:
- a number (window ID);
- an awk(1) regular expression;
- -a for automatically targeting the +Buffer window;
- nothing (current window,
$winid
).
As an example, a script like Do that runs a command from a window’s tagline, thus allowing to run/chain regular acme(1) commands (e.g. Put, Putall, etc.), has an optional argument that is forwarded to Getids:
# Clean current window
(tagline)$ Do 'Edit ,d'
# Clean the content of all +Errors windows
(sh|tagline)$ Do 'Edit ,d' '\+Errors$'
# Write is used to store data in special buffer's files (9P),
# similar to lib/acme.rc's winwrite().
#
# The following writes and closes all windows whose name contain
# "/project42/", cleaning the +Buffer window's content thereafter,
# creating it if necessary.
(sh|tagline)$ Write ctl put '\/project42\/' && \
Write ctl delete '\/project42\/' && \
Do 'Edit ,d' -a
XDump, XLoad, Switch (sessions)
Again aiming at reducing windows proliferation, those three small scripts load/dump current windows’ states:
# Put all files and creates a dump file in
# $HOME/acme.dumps/project42.dump with current state
(sh|tagline)$ XPutall && XDump project42 # optional .dump extension
# Restore state from $HOME/acme.dumps/projects42.dump,
# closing all opened windows beforehand
(sh|tagline)$ XLoad project42.dump # optional .dump extension
# Dump current state to $HOME/acme.dumps/project42.dump and
# load session $HOME/acme.dumps/website.dump
(sh|tagline)$ Switch project42 website # optional .dump extension
More
Complete documentation of all the tools can be found on github.
Resources
- Acme: A User Interface for Programmers, by Rob Pike (original research paper);
- A Tour of Acme (video, Sept. 2012), by Russ Cox;
- acme.cat-v.org;
- acme(1) and acme(4);
- Curated list of resources;
- Various tips and resources.
- “Theming” acme from C;
- acmeeval, acmepipe, autoacme;
- acme LSP support;
- etc.
See also some “modern” rewrites attempts:
- Edward (Go), based on:
- Edwood (Go), based on:
Comments
By email, at mathieu.bivert chez: