groff 1.23.0 added .MR to its -man macro package. The NEWS file states
that the inclusion of the macro "was prompted by its introduction to
Plan 9 from User Space's troff in August 2020." From d32deab it seems
that the name for Plan 9 from User Space's implementation was suggested
by groff maintainer G. Brandon Robinson.
Not sure if the intention was to make these definitions compatible, but
it would be nice if they were.
Currently, Plan 9 from User Space's .MR expects its second argument to
be parenthesized. groff's .MR does not. This results in extra
parentheses appearing in manual references when viewing Plan 9 from User
Space's manual pages on a system using groff.
390 lines
6.5 KiB
Groff
390 lines
6.5 KiB
Groff
.TH ACMEEVENT 1
|
|
.SH NAME
|
|
acmeevent, acme.rc \- shell script support for acme clients
|
|
.SH SYNOPSIS
|
|
.B 9p
|
|
.B read
|
|
.B acme/acme/$winid/event | acmeevent
|
|
.PP
|
|
.B
|
|
\&. \*9/lib/acme.rc
|
|
.PP
|
|
.B newwindow
|
|
.PP
|
|
.B winread
|
|
.I file
|
|
.PP
|
|
.B winwrite
|
|
.I file
|
|
.PP
|
|
.B winctl
|
|
.I cmd
|
|
.PP
|
|
.B windump
|
|
[
|
|
.I dumpdir
|
|
|
|
|
.B -
|
|
]
|
|
[
|
|
.I dumpcmd
|
|
|
|
|
.B -
|
|
]
|
|
.PP
|
|
.B winname
|
|
.I name
|
|
.PP
|
|
.B windel
|
|
[
|
|
.B sure
|
|
]
|
|
.PP
|
|
.B winwriteevent
|
|
.I c1
|
|
.I c2
|
|
.I q0
|
|
.I q1
|
|
[
|
|
.I eq0
|
|
.I eq1
|
|
.I flag
|
|
.I textlen
|
|
.I text
|
|
.I chordarg
|
|
.I chordaddr
|
|
]
|
|
.PP
|
|
.B wineventloop
|
|
.SH DESCRIPTION
|
|
.I Acmeevent
|
|
and
|
|
.I acme.rc
|
|
make it easy to write simple
|
|
.MR acme 1
|
|
client programs as shell scripts.
|
|
.PP
|
|
.I Acme
|
|
clients read the
|
|
.B event
|
|
files
|
|
(see
|
|
.MR acme 4 )
|
|
for the windows they control, reacting to the events.
|
|
The events are presented in a format that is easy to read with C programs
|
|
but hard to read with shell scripts.
|
|
.PP
|
|
.I Acmeevent
|
|
reads an
|
|
.MR acme 4
|
|
event stream from standard input, printing a shell-friendly
|
|
version of the events, one per line, on standard output.
|
|
Each output line from
|
|
.I acmeevent
|
|
has the form:
|
|
.IP
|
|
.B event
|
|
.I c1
|
|
.I c2
|
|
.I q0
|
|
.I q1
|
|
.I eq0
|
|
.I eq1
|
|
.I flag
|
|
.I textlen
|
|
.I text
|
|
.I chordarg
|
|
.I chordaddr
|
|
.PP
|
|
The fields are:
|
|
.TP
|
|
.I c1
|
|
A character indicating the origin or cause of the action.
|
|
The possible causes are:
|
|
a write to the body or tag file
|
|
.RB ( E ),
|
|
a write to the window's other files
|
|
.RB ( F ),
|
|
input via the keyboard
|
|
.RB ( K ),
|
|
and
|
|
input via the mouse
|
|
.RB ( M ).
|
|
.TP
|
|
.I c2
|
|
A character indicating the type of action.
|
|
The possible types are:
|
|
text deleted from the body
|
|
.RB ( D ),
|
|
text deleted from the tag
|
|
.RB ( d ),
|
|
text inserted in the body
|
|
.RB ( I ),
|
|
text inserted in the tag
|
|
.RB ( i ),
|
|
a button 3 action in the body
|
|
.RB ( L ),
|
|
a button 3 action in the tag
|
|
.RB ( l ),
|
|
a button 2 action in the body
|
|
.RB ( X ),
|
|
and
|
|
a button 2 action in the tag
|
|
.RB ( x ).
|
|
.TP
|
|
.I q0\fR, \fPq1
|
|
The character addresses of the action.
|
|
.TP
|
|
.I eq0\fR, \fPq1
|
|
The expanded character addresses of the action.
|
|
If the text indicated by
|
|
.IR q0 ,
|
|
.I q1
|
|
is a null string that has a non-null expansion,
|
|
.IR eq0 ,
|
|
.I eq1
|
|
are the addresses of the expansion.
|
|
Otherwise they are the same as
|
|
.IR q0 ,
|
|
.IR q1 .
|
|
.TP
|
|
.I flag
|
|
.I Flag
|
|
is a bitwise OR (reported decimally) of the following:
|
|
1 if the text indicated is recognized as an
|
|
.I acme
|
|
built-in command;
|
|
2 if the text indicated is a null string that has a non-null expansion
|
|
(see
|
|
.IR eq0 ,
|
|
.I eq1
|
|
above);
|
|
8 if the command has an extra (chorded) argument
|
|
(see
|
|
.I chordarg
|
|
below).
|
|
.I Flag
|
|
remains from the
|
|
.MR acme 4
|
|
event format.
|
|
Because
|
|
.IR eq0 ,
|
|
.IR eq1 ,
|
|
and
|
|
.I chordarg
|
|
are explicit in each event
|
|
(unlike in
|
|
.MR acme 4
|
|
events),
|
|
.I flag
|
|
can usually be ignored.
|
|
.TP
|
|
.I textlen
|
|
The length of the action text (or its expansion) for button 2 and button 3 events in characters.
|
|
.TP
|
|
.I text
|
|
If
|
|
.I textlen
|
|
is less than 256 chracters,
|
|
.I text
|
|
is the action text itself.
|
|
Otherwise it is an empty string and must be read from the
|
|
.B data
|
|
file.
|
|
.TP
|
|
.I chordarg
|
|
The chorded argument for an action.
|
|
.TP
|
|
.I chordorigin
|
|
If the chord argument is in the body of a named window,
|
|
.I chordorigin
|
|
specifies the full address of the argument,
|
|
as in
|
|
.BR /etc/group:#123,#234 .
|
|
.PD
|
|
.PP
|
|
To experiment with
|
|
.IR acmeevent ,
|
|
create an empty window in
|
|
.I acme
|
|
(using
|
|
.IR New ), type
|
|
.IP
|
|
.EX
|
|
9p read acme/$winid/event | acmeevent
|
|
.EE
|
|
.LP
|
|
inside it, and execute it.
|
|
Actions performed on the window will be printed as events in the
|
|
.B +Errors
|
|
window.
|
|
.PP
|
|
.I Acme.rc
|
|
is a library of
|
|
.MR rc 1
|
|
shell functions useful for writing acme clients.
|
|
.PP
|
|
.I Newwindow
|
|
creates a new acme window and sets
|
|
.B $winid
|
|
to the new window's id.
|
|
The other commands all use
|
|
.B $winid
|
|
to determine which window to operate on.
|
|
.PP
|
|
.I Winread
|
|
prints the current window's
|
|
.I file
|
|
to standard output.
|
|
It is equivalent to
|
|
.B cat
|
|
.BI /mnt/acme/acme/$winid/ file
|
|
on Plan 9.
|
|
Similarly,
|
|
.I winwrite
|
|
writes standard input to the current window's
|
|
.IR file .
|
|
.I Winread
|
|
and
|
|
.I winwrite
|
|
are useful mainly in building more complex functions.
|
|
.PP
|
|
.I Winctl
|
|
writes
|
|
.I cmd
|
|
to the window's
|
|
.B ctl
|
|
file.
|
|
The most commonly-used command is
|
|
.BR clean ,
|
|
which marks the window as clean.
|
|
See
|
|
.MR acme 4
|
|
for a full list of commands.
|
|
.PP
|
|
.I Windump
|
|
sets the window's dump directory
|
|
and dump command
|
|
(see
|
|
.MR acme 4 ).
|
|
If either argument is omitted or is
|
|
.BR - ,
|
|
that argument is not set.
|
|
.PP
|
|
.I Winname
|
|
sets the name displayed in the window's tag.
|
|
.PP
|
|
.I Windel
|
|
simulates the
|
|
.B Del
|
|
command. If the argument
|
|
.B sure
|
|
is given, it simulates the
|
|
.B Delete
|
|
command.
|
|
.PP
|
|
.I Winwriteevent
|
|
writes an event to the window's event file.
|
|
The event is in the format produced by
|
|
.IR acmeevent .
|
|
Only the first four arguments are necessary:
|
|
the rest are ignored.
|
|
Event handlers should call
|
|
.I winwriteevent
|
|
to pass unhandled button 2 or button 3 events
|
|
back to
|
|
.I acme
|
|
for processing.
|
|
.PP
|
|
.I Wineventloop
|
|
executes the current window's event file, as output by
|
|
.IR acmeevent .
|
|
It returns when the window has been deleted.
|
|
Before running
|
|
.I wineventloop ,
|
|
clients must define a shell function named
|
|
.BR event ,
|
|
which will be run for each incoming event,
|
|
as
|
|
.I rc
|
|
executes the output of
|
|
.IR acmeevent .
|
|
A typical event function need only worry about button 2 and button 3 events.
|
|
Those events not handled should be sent back to
|
|
.I acme
|
|
with
|
|
.IR winwriteevent .
|
|
.SH EXAMPLE
|
|
.IR Adict ,
|
|
a dictionary browser,
|
|
is implemented using
|
|
.I acmeevent
|
|
and
|
|
.IR acme.rc .
|
|
The
|
|
.I event
|
|
handler is:
|
|
.IP
|
|
.EX
|
|
.ta +4n +4n +4n +4n +4n +4n
|
|
fn event {
|
|
switch($1$2){
|
|
case Mx MX # button 2 - pass back to acme
|
|
winwriteevent $*
|
|
case Ml ML # button 3 - open new window on dictionary or entry
|
|
{
|
|
if(~ $dict NONE)
|
|
dictwin /adict/$7/ $7
|
|
if not
|
|
dictwin /adict/$dict/$7 $dict $7
|
|
} &
|
|
}
|
|
}
|
|
.EE
|
|
.LP
|
|
Note that the button 3 handler starts a subshell in which to run
|
|
.IR dictwin .
|
|
That subshell will create a new window, set its name,
|
|
possibly fill the window with a dictionary list or dictionary entry,
|
|
mark the window as clean, and run the event loop:
|
|
.IP
|
|
.EX
|
|
fn dictwin {
|
|
newwindow
|
|
winname $1
|
|
dict=$2
|
|
if(~ $dict NONE)
|
|
dict -d '?' >[2=1] | sed 1d | winwrite body
|
|
if(~ $#* 3)
|
|
dict -d $dict $3 >[2=1] | winwrite body
|
|
winctl clean
|
|
wineventloop
|
|
}
|
|
.EE
|
|
.LP
|
|
The script starts with an initial window:
|
|
.IP
|
|
.EX
|
|
dictwin /adict/ NONE
|
|
.EE
|
|
.LP
|
|
Button 3 clicking on a dictionary name in the initial window
|
|
will create a new empty window for that dictionary.
|
|
Typing and button 3 clicking on a word in that window
|
|
will create a new window with the dictionary's entry for that word.
|
|
.PP
|
|
See
|
|
.B \*9/bin/adict
|
|
for the full implementation.
|
|
.SH SOURCE
|
|
.B \*9/src/cmd/acmeevent.c
|
|
.br
|
|
.B \*9/lib/acme.rc
|
|
.SH SEE ALSO
|
|
.MR acme 1 ,
|
|
.MR acme 4 ,
|
|
.MR rc 1
|
|
.SH BUGS
|
|
There is more that could be done to ease the writing
|
|
of complicated clients.
|