ACME(3)
π ACME(3) β the acme client library, bestie edition β¨
okay so this is a page from the Library Functions Manual, section 3, and it's literally the whole libacme situation. pull up a chair π
β¨ NAME β¨
Event, Win, eventfmt, newwin, pipetowin, pipewinto, sysrun, winaddr, winclosefiles, winctl, windel, windeleteall, windows, wineventchan, winfd, winfree, winmread, winname, winopenfd, winprint, winread, winreadaddr, winreadevent, winseek, winwrite, winwriteevent β the acme client library, all of it, no crumbs left behind π«Ά
πΈ SYNOPSIS πΈ
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <9pclient.h>
#include <acme.h>
struct Event
{
int c1;
int c2;
int q0;
int q1;
int oq0;
int oq1;
int flag;
int nb;
int nr;
char text[];
char arg[];
char loc[];
};
int eventfmt(Fmt *fmt)
Win* newwin(void)
Win* openwin(int id, CFid *ctlfid)
int pipetowin(Win *w, char *file, int fderr, char *fmt, ...)
int pipewinto(Win *w, char *file, int fdout, char *fmt, ...)
char* sysrun(char *fmt, ...)
int winaddr(Win *w, char *fmt, ...)
void winclosefiles(Win *w)
int winctl(Win *w, char *fmt, ...)
int windel(Win *w, int sure)
void windeleteall(void)
Channel* wineventchan(Win *w)
int winfd(Win *w, char *name, int mode)
void winfree(Win *w)
char* winmread(Win *w, char *file)
int winname(Win *w, char *fmt, ...)
int winopenfd(Win *w, char *name, int mode)
int winprint(Win *w, char *file, char *fmt, ...)
int winread(Win *w, char *file, void *a, int n)
int winreadaddr(Win *w, uint *q1)
int winreadevent(Win *w, Event *e)
int winseek(Win *w, char *file, int off, int type)
int winwrite(Win *w, char *file, void *a, int n)
int winwriteevent(Win *w, Event *e)
void* emalloc(uint n)
void* erealloc(void *v, uint n)
char* estrdup(char *s)
char* evsmprint(char *fmt, va_list arg)
π¦ DESCRIPTION π¦
Libacme gives you a nice, simple C interface for talking to acme(1) windows. lowkey iconic π
A Win structure is your little handle on a single window plus its control files. do not poke around inside the struct directly, bestie β just don't, it's not for you π
newwincreates a brand-new window and hands you back a structure matching it.openwinallocates a structure for the existing window with the given id. If ctlfid is non-nil,openwinassumes it's a file descriptor that's open for writing to the window'sctlfile. Ownership of ctlfid passes to the library β so like, it's the library's problem now, not yours π«Ά
Most of these routines go through files in the window's acme directory. Peep acme(4) for the deets. A bunch of the routines take a format string fmt followed by a variable list of arguments. Everywhere below where you see fmt, ..., that's shorthand for "format the string and args with smprint" (check print(3)).
pipetowinβ runs therc(1)command linefmt, ...with/dev/nullon standard input and the window's file on standard output. If fderr is non-zero (sic β yes, the manpage itself said (sic), I'm just the messenger π), it's used as standard error. Otherwise the command just inherits the caller's standard error.pipewintoβ runs therc(1)command linefmt, ...with the window's file on standard input. The command runs with fdout as its standard output and standard error.sysrunβ runs therccommand linefmt, ...and returns a pointer to the first kilobyte of output, NUL-terminated. heads up: that buffer gets reused on every call, so it's giving "borrowed, not yours" βwinaddrβ writesfmt, ...to the window'saddrfile.winclosefilesβ closes all the open file descriptors hanging off the window. (The library keeps these fds around and caches them across calls towinctland friends.)winctlβ writesfmt, ...to the window'sctlfile.windelβ deletes the window, writingdelto the window'sctlfile (or, if sure is set,delete). choose your fighter π€winfdβ returns a file descriptor for the window's file, opened for mode. you are responsible for closing it, no cap.winmreadβ reads the contents of the window's file into a dynamically allocated buffer and returns it. again, you free that buffer, okay? π«Άwinnameβ sets the name of the window tofmt, ...by writing to thectlfile.winprintβ printsfmt, ...to the window's file.winreadβ reads at most n bytes from the window's file into the buffer that a points at.winreadaddrβ reads the window'saddrfile, which contains two integers. returns the first one and stashes the second in*q1.winseekβ seeks the file descriptor for the window's file to position off relative to type (seeseek(3)).winwriteβ writes the n bytes that a points at to the window's file.
π the Event structure π
An Event structure represents an event that originated in a particular window. The fields line up with the fields in acme's event messages β acme(4) has the detailed explanation if you want the full lore. here's the rundown:
c1,c2β the two event characters, telling you the origin and the type of action.q0,q1β the character addresses of the action. plot twist: if the original event had an empty selection (q0=q1) and came with an expansion (the 2 bit is set in the flag), thenq0andq1indicate the expansion instead of the original event πoq0,oq1β theq0andq1of the original event, even if it got expanded. if there was no expansion,oq0=q0andoq1=q1.flagβ the flag. that's it, that's the field β¨nrβ the number of characters (UTF sequences) included in the optional text.textβ the optional text itself, encoded in UTF.nbβ the number of bytes included in the optional text.argβ the chorded argument, if present (the 8 bit is set in the flag).locβ the chorded location, if present (the 8 bit is set in the flag).
π more routines π
winreadeventβ reads the next event (q.v.) from the window'seventfile.winwriteeventβ writes an event back to the window'seventfile, telling acme it should handle it internally.wineventchanβ returns a pointer to aChannel(seethread(3)) that you can read event structures from (structures, not pointers, bestie). the first call towineventchanallocates a channel and spins up a new thread that loops around callingwinreadeventand copying the events into the channel. every call after that just returns the same channel.
β οΈ real talk: once you've calledwineventchan, clients should not callwinreadevent. like, at all. pick a lane π
emalloc,erealloc,estrdup, andevsmprintβ these are just likemalloc(3),realloc,strdup(seestrcat(3)), andvsmprint(seeprint(3)), except instead of returning nil on error they callsysfatal(3). so like, they simply refuse to fail quietly π
π SOURCE π
/src/libacme
π SEE ALSO π
and that's the whole vibe, bestie β this was ACME(3) from the Library Functions Manual, sourced straight out of /src/libacme. go forth and talk to your windows, you absolute icon π¦β¨π
π¦ where this page comes from
- alpine 3.24: plan9port-doc 0_git20260208-r0 Β· LPL-1.02
- arch rolling: plan9port 20261021-2 Β· custom
- nixos 26.05: plan9port 0-unstable-2025-11-10
- nixos 26.05: plan9port-wayland 0-unstable-2025-11-26
- nixpkgs unstable: plan9port 0-unstable-2025-11-10
- nixpkgs unstable: plan9port-wayland 0-unstable-2025-11-26
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms