ref: 4dcc894ba6700ac9ade6a46b64334a1a59784229
author: B. Wilson <x@wilsonb.com>
date: Tue Jul 15 08:08:00 EDT 2025
Initial proof-of-concept
--- /dev/null
+++ b/aplenty.c
@@ -1,0 +1,227 @@
+#include <u.h>
+#include <libc.h>
+#include <stdio.h>
+#include <bio.h>
+#include <json.h>
+#include <regexp.h>
+
+int debug;
+vlong caddr;
+
+void
+handlerideevents(int in, int out, int text){+ Biobuf *bin;
+ char *b, k; /* event buffer, kind */
+ long t, n, o; /* type, length, offset */
+
+ bin = Bfdopen(in, OREAD);
+ while(b = Brdline(bin, '\n')){+ Bseek(bin, Blinelen(bin), 1);
+ k = b[0]; b++;
+ t = atol(strtok(b, " \n"));
+ n = atol(strtok(nil, " \n"));
+ o = atol(strtok(nil, " \n"));
+ b = malloc(n);
+ seek(text, o, 0);
+ readn(text, b, n);
+ if(debug > 1)
+ fprintf(stderr, "ride: %c %ld %ld %ld\n", k, t, n, o);
+
+ if(strchr("po", k))+ write(out, b, n);
+
+ free(b);
+ }
+}
+
+void
+handlerootevents(int wid, int in, int out){+ Biobuf *bin, *bxdata, *btag;
+ int fdctl, fdevent, fdaddr, fdbody;
+ char o, t; /* event origin, type */
+ long n, m, f, l; /* addr n, addr m, flag, len */
+ Rune *r; /* runes */
+ long c;
+ char *ln, s[256];
+ int i;
+
+ /* setup files */
+ snprintf(s, sizeof(s), "/mnt/acme/%i", wid);
+ chdir(s);
+ fdctl = open("ctl", OWRITE);+ fdevent = open("event", OWRITE);+ fdaddr = open("addr", ORDWR);+ fdbody = open("body", OWRITE);+ bin = Bfdopen(in, OREAD);
+ rerrstr(s, sizeof(s));
+ if(s[0] != 0)
+ exits(s);
+
+ /* initial prompt not setup by ride */
+ write(fdbody, " ", 6);
+ write(fdaddr, "$", 1);
+ fprint(fdctl, "dot=addr");
+
+ /* event handle loop: cf acme(4):/event */
+ r = malloc((2+4*12 + 256)*sizeof(*r));
+ while((o = Bgetc(bin)) != EOF){+ t = Bgetc(bin);
+ n = atol(Brdline(bin, ' '));
+ m = atol(Brdline(bin, ' '));
+ f = atol(Brdline(bin, ' '));
+ l = atol(Brdline(bin, ' '));
+ for(i = 0; i < l+1; i++) /* trailing LF not counted by l */
+ Bgetrune(bin);
+ if(debug > 1)
+ fprintf(stderr, "acme: %c%c%ld %ld %ld %ld\n", o, t, n , m, f, l);
+
+ /* Ride-triggered edits */
+ if(o == 'E'){+ seek(fdaddr, 0, 0);
+ write(fdaddr, "$", 1);
+ read(fdaddr, s, 12);
+ n = atol(strtok(s, " "));
+ caddr = n;
+ continue;
+ }
+
+ /* trailing text may be elided; read canonical source */
+ if(!strchr("Dd", t)){+ fprint(fdaddr, "#%ld,#%ld", n, m);
+ if(strchr("ILX", t)){+ bxdata = Bopen("xdata", OREAD);+ for(i = 0, c = Bgetrune(bxdata); c >= 0; i++, c = Bgetrune(bxdata))
+ r[i] = c;
+ Bterm(bxdata);
+ } else if(strchr("ilx", t)) {+ btag = Bopen("tag", OREAD);+ for(i = 0, c = Bgetrune(btag); c >= 0; i++, c = Bgetrune(btag))
+ r[i] = c;
+ Bterm(btag);
+ }
+ r[i] = t == 'X' ? '\n' : 0;
+
+ /* XXX: Only execute first line if multiline input */
+ if(t == 'I' && n >= caddr || t == 'X'){+ fprint(fdaddr, "#%lld,$", caddr);
+ bxdata = Bopen("xdata", OREAD);+ ln = Brdline(bxdata, '\n');
+ if(ln) write(out, ln, Blinelen(bxdata));
+ Bterm(bxdata);
+ }
+ }
+
+ if(strchr("ID", t))+ if((t == 'D') + m < caddr)
+ caddr += t == 'D' ? n-m : m-n;
+
+ if(f%2 == 0 && strchr("Lidlx", t))+ fprint(fdevent, "%c%c%ld %ld\n", o, t, n, m);
+ }
+}
+
+char*
+errmsg(char *err){+ if(err == nil){+ err = malloc(ERRMAX);
+ rerrstr(err, ERRMAX);
+ }
+ fprintf(stderr, "%s\n", err);
+ return err;
+}
+
+void
+usage(void){+ fprintf(stderr, "Usage: %s [-d] addr\n", argv0);
+}
+
+void
+main(int argc, char **argv){+ char *err, *addr, b[256], p[256];
+ int rid, rctl, rin, rout, rtext; /* ride */
+ int wid, wctl, win, wout; /* root window */
+
+ if(argc < 1){+ usage();
+ exits("requires address argument");+ }
+
+ ARGBEGIN{+ case 'd': debug++; break;
+ case 'h': usage(); exits(nil);
+ }ARGEND
+
+ if(argc == 0)
+ addr = getenv("rideaddr");+ else
+ addr = argv[0];
+ if(addr == nil){+ usage();
+ exits(errmsg("no ride address"));+ }
+
+ err = nil;
+
+ /* new ride connection */
+ if((rctl = open("/mnt/ride/clone", ORDWR)) < 0)+ exits(errmsg(err));
+ sprintf(b, "connect %s\n", addr);
+ write(rctl, b, strlen(b));
+
+ /* connection id */
+ seek(rctl, 0, 0);
+ read(rctl, b, sizeof(b));
+ sprintf(p, "\n");
+ rid = atoi(strtok(b, p));
+
+ /* establish connection */
+ snprintf(p, sizeof(p), "/mnt/ride/%i/text", rid);
+ if((rout = open(p, OWRITE)) < 0)
+ exits(errmsg(err));
+ if((rtext = open(p, OREAD)) < 0)
+ exits(errmsg(err));
+
+ /* ride i/o files */
+ snprintf(p, sizeof(p), "/mnt/ride/%i/event", rid);
+ if((rin = open(p, OREAD)) < 0)
+ exits(errmsg(err));
+
+ /* new acme window */
+ if((wctl = open("/mnt/acme/new/ctl", OREAD)) < 0)+ exits(errmsg(err));
+ readn(wctl, b, 12);
+ wid = atoi(strtok(b, " "));
+
+ /* window i/o files */
+ snprintf(p, sizeof(p), "/mnt/acme/%i/event", wid);
+ if((win = open(p, OREAD)) < 0)
+ exits(errmsg(err));
+ snprintf(p, sizeof(p), "/mnt/acme/%i/body", wid);
+ if((wout = open(p, OWRITE)) < 0)
+ exits(errmsg(err));
+
+ JSONfmtinstall();
+
+ rfork(RFNOTEG);
+
+ switch(rfork(RFPROC|RFMEM)){+ case -1: err = "unable to start ride message handler"; break;
+ case 0:
+ handlerideevents(rin, wout, rtext);
+ exits(nil);
+ default: break;
+ }
+
+ switch(rfork(RFPROC|RFMEM)){+ case -1: err = "unable to start root window event handler"; break;
+ case 0:
+ handlerootevents(wid, win, rout);
+ exits(nil);
+ default: break;
+ }
+
+ wait();
+ postnote(PNGROUP, getpid(), "exit");
+
+ exits(errmsg(err));
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+BIN=/$objtype/bin
+TARG=aplenty
+OFILES=aplenty.$O
+
+</sys/src/cmd/mkone
\ No newline at end of file
--
⑨