ACME(3)

πŸ“¦ version 0_git20260208, in alpine 3.24, arch rolling, nixos 26.05, nixpkgs unstable

πŸ’… 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 πŸ™ˆ

  • newwin creates a brand-new window and hands you back a structure matching it.
  • openwin allocates a structure for the existing window with the given id. If ctlfid is non-nil, openwin assumes it's a file descriptor that's open for writing to the window's ctl file. 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 the rc(1) command line fmt, ... with /dev/null on 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 the rc(1) command line fmt, ... with the window's file on standard input. The command runs with fdout as its standard output and standard error.
  • sysrun β€” runs the rc command line fmt, ... 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 β€” writes fmt, ... to the window's addr file.
  • winclosefiles β€” closes all the open file descriptors hanging off the window. (The library keeps these fds around and caches them across calls to winctl and friends.)
  • winctl β€” writes fmt, ... to the window's ctl file.
  • windel β€” deletes the window, writing del to the window's ctl file (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 to fmt, ... by writing to the ctl file.
  • winprint β€” prints fmt, ... 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's addr file, 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 (see seek(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), then q0 and q1 indicate the expansion instead of the original event πŸ‘€
  • oq0, oq1 β€” the q0 and q1 of the original event, even if it got expanded. if there was no expansion, oq0=q0 and oq1=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's event file.
  • winwriteevent β€” writes an event back to the window's event file, telling acme it should handle it internally.
  • wineventchan β€” returns a pointer to a Channel (see thread(3)) that you can read event structures from (structures, not pointers, bestie). the first call to wineventchan allocates a channel and spins up a new thread that loops around calling winreadevent and copying the events into the channel. every call after that just returns the same channel.
⚠️ real talk: once you've called wineventchan, clients should not call winreadevent. like, at all. pick a lane πŸ’€
  • emalloc, erealloc, estrdup, and evsmprint β€” these are just like malloc(3), realloc, strdup (see strcat(3)), and vsmprint (see print(3)), except instead of returning nil on error they call sysfatal(3). so like, they simply refuse to fail quietly πŸ’…

πŸ“ SOURCE πŸ“

/src/libacme

πŸ‘‘ SEE ALSO πŸ‘‘

acme(1), acme(4)


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 πŸ¦‹βœ¨πŸŽ€