Customizing Acme With Plumber

Nov 26, 2019 06:59 · 585 words · 3 minute read Acme Tools Editors

I touched a bit on the plumber back in January. It’s a cool little program that essentially is a very clean and simple message bus/processor you can use for your system.

Plumber Usage

If you installed plan9port, you have Acme and the plumber programs installed on your system. You’ll want to launch plumber by itself without any parameter:

$ plumber

That’s all. Nothing else. If you get an error like the following, it just means the plumber was already running:

9pserve: announce unix!/tmp/ns.many.words.here:0/plumb: Address already in use 
plumber: post9pservice plumb: 9pserve failed

From that point on, you can send data to the plumber from the command line by doing plumb any-string-you-want. You can also echo some-other-string | plumb -i.

Now, unless those strings are matched by the plumber, nothing will happen. How do you figure out what strings are in the plumber? Glad you asked.

Configuring the Plumber

Running 9p read plumb/rules will output a set of rules on the standard output. The format is documented in the plumb(7) man page. Let’s take the man page plumb rule for example:

type	is	text
data	matches	'([a-zA-Z¡-0-9_\-./]+)\(([1-8])\)'
plumb	start	rc -c 'man '$2' '$1' >[2=1] | 
	nobs | 
	plumb -i 
	      -d edit 
	      -a ''action=showdata filename=/man/'$1'('$2')'''
# Newlines added for readability purposes.

It’s not really simple, I’ll grant you that much, but there’s fun to be had in there. The type is text is both the default value and also the only supported value as of right now, so you can more or less ignore that part. The data matches section is followed by a regular expression that essentially matches things of the form manpagename(n), where n is a number from 1 to 8.

The plumb start line essentially calls man, filters out the output, and feeds it back in to the plumber to the edit destination (that -d edit flag). Acme listens to the edit destination, so it grabs the data and shows it as a file named /man/manpagename(n).

Getting Cute With Plumbing and IETF RFCs

You can use that same concept to do fancy stuff. For instance, in my home setup I have mirrored a text-only archive of the IETF RFCs, and when I type rfc6749 and right click on it, anywhere in my editor (or just call plumb rfc6749 from a terminal), the core OAuth2 RFC plops open in a nice window directly in Acme. What’s more, I do a bit of post-processing on the RFCs so that mentions of other RFCs can be right-clicked right within Acme, and that opens another window with that RFC, and so on, and so forth. Quite a nice interface, if I do say so myself. How do you even? Glad you asked.

Step 1: RSync. Essentially, you just need to run rsync -avz --delete ftp.rfc-editor.org::rfcs-text-only destination/directory

Step 2: Add the new rule to the Plumber.

If you haven’t already tweaked your Plumber configuration, first run mkdir -p $HOME/lib; 9p read plumb/rules > $HOME/lib/plumbing.

Then, add the following to that file:

type	is	text
data	matches	'[rR][fF][cC]([0-9]+)'
arg		isfile	/fullpath-to-destination-directory/rfc$1.txt
plumb	start	rc -c 'sed ''s,RFC \([0-9]*\),rfc\1,g'' 
		  < /fullpath-to-destination-directory/rfc'$1'.txt | 
	tail -n +6 | 
	nobs | 
	plumb -i 
	      -d edit 
	      -a ''action=showdata filename=/rfc/'$1''''

# I'm super sorry about readability. 
# You'll want that on a single line I think.

IMPORTANT: THE PLUMBING FILE NEEDS TO END WITH A NEWLINE. WE ARE NOT SAVAGES HERE.

Step 3: Restart the Plumber.

That’s all. You can now plop RFCs around like there’s no tomorrow. It’s pretty practical. Well. For me, anyway.