9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Stuart Morrow <morrow.stuart@gmail.com>
To: 9front@9front.org
Subject: Re: [9front] g
Date: Sat, 14 Aug 2021 21:38:19 +0000	[thread overview]
Message-ID: <CABB-WO9_BYdBfJeB1sDijoAJ3YPK2X_GGs=d=8XYLwukOE12XA@mail.gmail.com> (raw)
In-Reply-To: <9537C8A9A3C1A643998908E9CDDF9FE4@musolino.id.au>

[-- Attachment #1: Type: text/plain, Size: 535 bytes --]

> You don't need to create a new program.  Just specify the awk field
> separator regex correctly, i.e. -F ': *'.

For scripting you do - Plan 9 permits tarded filenames.

Bprint thing is attached. Nfile is in there too, for anyone that has
nfile (anticipating the dream of elastic tabstops?).

I also patched g to do a grep dry-run before walk. So we don't have to
wait on the disk or network to find out if we need to obtain a special
typing wand.

ls.c and ascii.c need a certain fix (hint: look at their 'Binit' line).

Good night

[-- Attachment #2: diffs --]
[-- Type: application/octet-stream, Size: 15789 bytes --]

--- //.git/fs/object/2af46e406bbd443ae10025777247798a685afc3c/tree/sys/man/2/bio
+++ sys/man/2/bio
@@ -12,7 +12,7 @@
 .ft L
 .nf
 .ta \w'    'u +\w'    'u +\w'    'u +\w'    'u +\w'    'u
-typedef struct Biobufhdr	Biobufhdr;
+typedef struct Biobufhdr Biobufhdr;
 struct Biobufhdr {
 	void	*aux;		/* user data */
 	...			/* internals */
--- //.git/fs/object/2af46e406bbd443ae10025777247798a685afc3c/tree/sys/man/2/complete
+++ sys/man/2/complete
@@ -11,7 +11,7 @@
 .ft L
 .nf
 .ta \w'    'u +\w'    'u +\w'    'u +\w'    'u +\w'    'u
-typedef struct Completion	Completion;
+typedef struct Completion Completion;
 struct Completion{
 	uchar advance;		/* whether forward progress has been made */
 	uchar complete;	/* whether the completion now represents a file or directory */

--- //.git/fs/object/2af46e406bbd443ae10025777247798a685afc3c/tree/rc/bin/g
+++ rc/bin/g
@@ -17,6 +17,7 @@
 
 suffixes='\.([bcChlmsy]|asm|awk|cc|cgi|cpp|cs|go|goc|hs|java|lua|lx|mk|ml|mli|ms|myr|pl|py|rc|sh|tex|xy)$'
 fullnames='(^|/)mkfile$'
+fn check { grep $pattern </dev/null || ~ $status *syntax* && exit $status }
 switch($#*){
 case 0
 	echo 'usage: g [flags] pattern [files]' >[1=2]
@@ -23,9 +24,11 @@
 	exit usage
 case 1
 	pattern=$1
+	check
 	files=`$nl{walk -f $recurse | grep -e $fullnames -e $suffixes >[2]/dev/null}
 case *
 	pattern=$1
+	check
 	shift
 	for(f in $*){
 		if(test -d $f)

--- //.git/fs/object/2af46e406bbd443ae10025777247798a685afc3c/tree/sys/src/cmd/file.c
+++ sys/src/cmd/file.c
@@ -9,6 +9,7 @@
  */
 #define	LENDIAN(p)	((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
 
+Biobuf	bout;
 uchar	buf[6001];
 short	cfreq[140];
 short	wfreq[50];
@@ -233,6 +234,8 @@
 		exits("usage");
 	}ARGEND;
 
+	Binit(&bout, 1, OWRITE);
+
 	maxlen = 0;
 	if(mime == 0 || argc > 1){
 		for(i = 0; i < argc; i++) {
@@ -244,7 +247,7 @@
 	}
 	if (argc <= 0) {
 		if(!mime)
-			print ("stdin: ");
+			Bprint(&bout, "stdin: ");
 		filetype(0);
 	}
 	else {
@@ -251,6 +254,7 @@
 		for(i = 0; i < argc; i++)
 			type(argv[i], maxlen);
 	}
+	Bterm(&bout);
 	exits(0);
 }
 
@@ -268,10 +272,11 @@
 				slash = p;
 			p += chartorune(&r, p);		/* count runes */
 		}
-		print("%s:%*s",file, nlen-i+1, "");
+		Bprint(&bout, "%s:%*s",file, nlen-i+1, "");
 	}
 	fname = file;
 	if ((fd = open(file, OREAD)) < 0) {
+		Bflush(&bout);
 		fprint(2, "cannot open: %r\n");
 		return;
 	}
@@ -292,12 +297,12 @@
 
 	if(memcmp(buf, "\x00\x00\xFE\xFF", 4) == 0){
 		if(!mime)
-			print("utf-32be ");
+			Bprint(&bout, "utf-32be ");
 		return;
 	} else
 	if(memcmp(buf, "\xFE\xFF\x00\x00", 4) == 0){
 		if(!mime)
-			print("utf-32le ");
+			Bprint(&bout, "utf-32le ");
 		return;
 	} else
 	if(memcmp(buf, "\xEF\xBB\xBF", 3) == 0){
@@ -307,7 +312,7 @@
 	} else
 	if(memcmp(buf, "\xFE\xFF", 2) == 0){
 		if(!mime)
-			print("utf-16be ");
+			Bprint(&bout, "utf-16be ");
 
 		nbuf -= 2;
 		rb = malloc(nbuf+1);
@@ -324,7 +329,7 @@
 	} else
 	if(memcmp(buf, "\xFF\xFE", 2) == 0){
 		if(!mime)
-			print("utf-16le ");
+			Bprint(&bout, "utf-16le ");
 
 		nbuf -= 2;
 		rb = malloc(nbuf+1);
@@ -351,28 +356,30 @@
 	free(mbuf);
 	mbuf = dirfstat(fd);
 	if(mbuf == nil){
+		Bflush(&bout);
 		fprint(2, "cannot stat: %r\n");
 		return;
 	}
 	if(mbuf->mode & DMDIR) {
-		print("%s\n", mime ? OCTET : "directory");
+		Bprint(&bout, "%s\n", mime ? OCTET : "directory");
 		return;
 	}
 	if(mbuf->type != 'M' && mbuf->type != '|') {
 		if(mime)
-			print("%s\n", OCTET);
+			Bprint(&bout, "%s\n", OCTET);
 		else
-			print("special file #%C/%s\n", mbuf->type, mbuf->name);
+			Bprint(&bout, "special file #%C/%s\n", mbuf->type, mbuf->name);
 		return;
 	}
 	/* may be reading a pipe on standard input */
 	nbuf = readn(fd, buf, sizeof(buf)-1);
 	if(nbuf < 0) {
+		Bflush(&bout);
 		fprint(2, "cannot read: %r\n");
 		return;
 	}
 	if(nbuf == 0) {
-		print("%s\n", mime ? PLAIN : "empty file");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "empty file");
 		return;
 	}
 	buf[nbuf] = 0;
@@ -442,16 +449,16 @@
 	 * print out gross classification
 	 */
 	if (nbuf < 100 && !mime)
-		print(mime ? PLAIN : "short ");
+		Bprint(&bout, mime ? PLAIN : "short ");
 	if (guess == Fascii)
-		print("%s\n", mime ? PLAIN : "Ascii");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "Ascii");
 	else if (guess == Feascii)
-		print("%s\n", mime ? PLAIN : "extended ascii");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "extended ascii");
 	else if (guess == Flatin)
-		print("%s\n", mime ? PLAIN : "latin ascii");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "latin ascii");
 	else if (guess == Futf && utf_count() < 4)
 		print_utf();
-	else print("%s\n", mime ? OCTET : "binary");
+	else Bprint(&bout, "%s\n", mime ? OCTET : "binary");
 }
 
 void
@@ -522,12 +529,12 @@
 	int i, printed, j;
 
 	if(mime){
-		print("%s\n", PLAIN);
+		Bprint(&bout, "%s\n", PLAIN);
 		return;
 	}
 	if (chkascii()) {
 		printed = 1;
-		print("Ascii");
+		Bprint(&bout, "Ascii");
 	} else
 		printed = 0;
 	for (i = 0; language[i].name; i++)
@@ -543,7 +550,7 @@
 			case Normal:
 			case First:
 				if (printed)
-					print(" & ");
+					Bprint(&bout, " & ");
 				else printed = 1;
 				print("%s", language[i].name);
 				break;
@@ -553,8 +560,8 @@
 			}
 		}
 	if(!printed)
-		print("UTF");
-	print(" text\n");
+		Bprint(&bout, "UTF");
+	Bprint(&bout, " text\n");
 }
 
 void
@@ -648,7 +655,7 @@
 
 	for(i=0; i<ntab; i++)
 		if((x&tab[i].mask) == tab[i].x){
-			print("%s\n", mime ? tab[i].mime : tab[i].desc);
+			Bprint(&bout, "%s\n", mime ? tab[i].mime : tab[i].desc);
 			return 1;
 		}
 	return 0;
@@ -698,7 +705,7 @@
 			continue;
 		x = LENDIAN(buf);
 		if((x&tp->mask) == tp->x){
-			print("%s\n", mime ? tp->mime : tp->desc);
+			Bprint(&bout, "%s\n", mime ? tp->mime : tp->desc);
 			return 1;
 		}
 	}
@@ -718,7 +725,7 @@
 
 	seek(fd, 0, 0);		/* reposition to start of file */
 	if(crackhdr(fd, &f)) {
-		print("%s\n", mime ? OCTET : f.name);
+		Bprint(&bout, "%s\n", mime ? OCTET : f.name);
 		return 1;
 	}
 	return 0;
@@ -744,19 +751,19 @@
 		p = tmp;
 
 	if (strcmp("rc", p) == 0)
-		print("%s\n", mime ? PLAIN : "rc executable file");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "rc executable file");
 	else if (strcmp("sh", p) == 0)
-		print("%s\n", mime ? "application/x-sh" : "sh executable file");
+		Bprint(&bout, "%s\n", mime ? "application/x-sh" : "sh executable file");
 	else if (strcmp("bash", p) == 0)
-		print("%s\n", mime ? "application/x-sh" : "bash executable file");
+		Bprint(&bout, "%s\n", mime ? "application/x-sh" : "bash executable file");
 	else if (strcmp("awk", p) == 0)
-		print("%s\n", mime ? PLAIN : "awk executable file");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "awk executable file");
 	else if (strcmp("sed", p) == 0)
-		print("%s\n", mime ? PLAIN : "sed executable file");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "sed executable file");
 	else if (strcmp("perl", p) == 0)
-		print("%s\n", mime ? PLAIN : "perl executable file");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "perl executable file");
 	else
-		print("%s\n", mime ? PLAIN : "unknown executable file");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "unknown executable file");
 	return 1;
 }
 
@@ -817,9 +824,9 @@
 	chksum = strtol(hdr->chksum, 0, 8);
 	if (hdr->name[0] != '\0' && checksum(hp) == chksum) {
 		if (strcmp(hdr->magic, "ustar") == 0)
-			print(mime? "application/x-ustar\n": "posix tar archive\n");
+			Bprint(&bout, mime? "application/x-ustar\n": "posix tar archive\n");
 		else
-			print(mime? "application/x-tar\n": "tar archive\n");
+			Bprint(&bout, mime? "application/x-tar\n": "tar archive\n");
 		return 1;
 	}
 	return 0;
@@ -935,7 +942,7 @@
 		if(l == -1)
 			l = strlen(p->key);
 		if(nbuf >= l && memcmp(buf, p->key, l) == 0) {
-			print("%s\n", mime ? p->mime : p->filetype);
+			Bprint(&bout, "%s\n", mime ? p->mime : p->filetype);
 			return 1;
 		}
 	}
@@ -944,9 +951,9 @@
 			if(buf[i] == '\n')
 				break;
 		if(mime)
-			print("%s\n", OCTET);
+			Bprint(&bout, "%s\n", OCTET);
 		else
-			print("%.*s picture\n", utfnlen((char*)buf+5, i-5), (char*)buf+5);
+			Bprint(&bout, "%.*s picture\n", utfnlen((char*)buf+5, i-5), (char*)buf+5);
 		return 1;
 	}
 	return 0;
@@ -977,7 +984,7 @@
 		if (readn(fd, buf, n) != n)
 			continue;
 		if(memcmp(buf, p->key, n) == 0) {
-			print("%s\n", mime ? p->mime : p->filetype);
+			Bprint(&bout, "%s\n", mime ? p->mime : p->filetype);
 			return 1;
 		}
 	}
@@ -989,18 +996,18 @@
 {
 	if (strncmp((char*)buf, "FORM", 4) == 0 &&
 	    strncmp((char*)buf+8, "AIFF", 4) == 0) {
-		print("%s\n", mime? "audio/x-aiff": "aiff audio");
+		Bprint(&bout, "%s\n", mime? "audio/x-aiff": "aiff audio");
 		return 1;
 	}
 	if (strncmp((char*)buf, "RIFF", 4) == 0) {
 		if (strncmp((char*)buf+8, "WAVE", 4) == 0)
-			print("%s\n", mime? "audio/wave": "wave audio");
+			Bprint(&bout, "%s\n", mime? "audio/wave": "wave audio");
 		else if (strncmp((char*)buf+8, "AVI ", 4) == 0)
-			print("%s\n", mime? "video/avi": "avi video");
+			Bprint(&bout, "%s\n", mime? "video/avi": "avi video");
 		else if (strncmp((char*)buf+8, "WEBP", 4) == 0)
-			print("%s\n", mime? "image/webp": "webp image");
+			Bprint(&bout, "%s\n", mime? "image/webp": "webp image");
 		else
-			print("%s\n", mime? OCTET : "riff file");
+			Bprint(&bout, "%s\n", mime? OCTET : "riff file");
 		return 1;
 	}
 	return 0;
@@ -1036,7 +1043,7 @@
 	if(strncmp(++p, "+++ ", 4) == 0)
 	if((p = strchr(p, '\n')) != nil)
 	if(strncmp(++p, "@@ ", 3) == 0){
-		print("%s\n", mime ? "text/plain" : "unified diff output");
+		Bprint(&bout, "%s\n", mime ? "text/plain" : "unified diff output");
 		return 1;
 	}
 	return 0;
@@ -1068,7 +1075,7 @@
 				p += n;
 				if(p < buf+nbuf && strchr("\t\r\n />", *p)){
 					if(++count > 2) {
-						print("%s\n", mime ? "text/html" : "HTML file");
+						Bprint(&bout, "%s\n", mime ? "text/html" : "HTML file");
 						return 1;
 					}
 				}
@@ -1126,7 +1133,7 @@
 		p = q+1;
 	}
 	if(count >= 3){
-		print("%s\n", mime ? "message/rfc822" : "email file");
+		Bprint(&bout, "%s\n", mime ? "message/rfc822" : "email file");
 		return 1;
 	}
 	return 0;
@@ -1143,7 +1150,7 @@
 		return 0;
 	*q = 0;
 	if(strncmp(p, "From ", 5) == 0 && strstr(p, " remote from ") == nil){
-		print("%s\n", mime ? "application/mbox" : "mail box");
+		Bprint(&bout, "%s\n", mime ? "application/mbox" : "mail box");
 		return 1;
 	}
 	*q = '\n';
@@ -1164,9 +1171,9 @@
 	if(type < 0)
 		return 0;
 	if(mime)
-		print("%s\n", OCTET);
+		Bprint(&bout, "%s\n", OCTET);
 	else
-		print("%s intermediate\n", name);
+		Bprint(&bout, "%s intermediate\n", name);
 	return 1;
 }
 
@@ -1197,13 +1204,13 @@
 
 yes:
 	if(mime){
-		print("%s\n", PLAIN);
+		Bprint(&bout, "%s\n", PLAIN);
 		return 1;
 	}
 	if(wfreq[Alword] > 0)
-		print("alef program\n");
+		Bprint(&bout, "alef program\n");
 	else
-		print("c program\n");
+		Bprint(&bout, "c program\n");
 	return 1;
 }
 
@@ -1215,7 +1222,7 @@
 	 */
 	if(wfreq[Lword] < 4)
 		return 0;
-	print("%s\n", mime ? PLAIN : "limbo program");
+	Bprint(&bout, "%s\n", mime ? PLAIN : "limbo program");
 	return 1;
 }
 
@@ -1227,7 +1234,7 @@
 	 */
 	if(wfreq[Aword] < 2)
 		return 0;
-	print("%s\n", mime ? PLAIN : "as program");
+	Bprint(&bout, "%s\n", mime ? PLAIN : "as program");
 	return 1;
 }
 
@@ -1260,7 +1267,7 @@
 			return 0;
 	} else
 		return 0;
-	print("%s\n", mime ? "image/tga" : "targa image");
+	Bprint(&bout, "%s\n", mime ? "image/tga" : "targa image");
 	return 1;
 }
 
@@ -1273,7 +1280,7 @@
 	e = p + nbuf-1;
 	while((p < e) && (p = memchr(p, 0xFF, e - p))){
 		if((p[1] & 0xFE) == 0xFA){
-			print("%s\n", mime ? "audio/mpeg" : "mp3 audio");
+			Bprint(&bout, "%s\n", mime ? "audio/mpeg" : "mp3 audio");
 			return 1;
 		}
 		p++;
@@ -1289,11 +1296,11 @@
 	if(memcmp(&buf[4], "ftyp", 4) != 0)
 		return 0;
 	if(memcmp(&buf[8], "isom", 4) == 0 || memcmp(&buf[8], "mp4", 3) == 0){
-		print("%s\n", mime ? "video/mp4" : "mp4 video");
+		Bprint(&bout, "%s\n", mime ? "video/mp4" : "mp4 video");
 		return 1;
 	}
 	if(memcmp(&buf[8], "M4A ", 4) == 0){
-		print("%s\n", mime ? "audio/m4a" : "m4a audio");
+		Bprint(&bout, "%s\n", mime ? "audio/m4a" : "m4a audio");
 		return 1;
 	}
 	return 0;
@@ -1320,18 +1327,18 @@
 	cs /= 8.;
 	if(cs <= 24.322) {
 		if(buf[0]==0x1f && buf[1]==0x9d)
-			print("%s\n", mime ? "application/x-compress" : "compressed");
+			Bprint(&bout, "%s\n", mime ? "application/x-compress" : "compressed");
 		else
 		if(buf[0]==0x1f && buf[1]==0x8b)
-			print("%s\n", mime ? "application/x-gzip" : "gzip compressed");
+			Bprint(&bout, "%s\n", mime ? "application/x-gzip" : "gzip compressed");
 		else
 		if(buf[0]=='B' && buf[1]=='Z' && buf[2]=='h')
-			print("%s\n", mime ? "application/x-bzip2" : "bzip2 compressed");
+			Bprint(&bout, "%s\n", mime ? "application/x-bzip2" : "bzip2 compressed");
 		else
 		if(buf[0]==0x78 && buf[1]==0x9c)
-			print("%s\n", mime ? "application/x-deflate" : "zlib compressed");
+			Bprint(&bout, "%s\n", mime ? "application/x-deflate" : "zlib compressed");
 		else
-			print("%s\n", mime ? OCTET : "encrypted");
+			Bprint(&bout, "%s\n", mime ? OCTET : "encrypted");
 		return 1;
 	}
 	return 0;
@@ -1386,7 +1393,7 @@
 		rare += cfreq[tolower(*p)];
 	}
 	if(vow*5 >= nbuf-cfreq[' '] && comm >= 10*rare) {
-		print("%s\n", mime ? PLAIN : "English text");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "English text");
 		return 1;
 	}
 	return 0;
@@ -1493,7 +1500,7 @@
 	 * for subfont, the subfont header should follow immediately.
 	 */
 	if (cmpr) {
-		print(mime ? "image/p9bit\n" : "Compressed %splan 9 image or subfont, depth %d, size %dx%d\n",
+		Bprint(&bout, mime ? "image/p9bit\n" : "Compressed %splan 9 image or subfont, depth %d, size %dx%d\n",
 			newlabel, dep, hix, hiy);
 		return 1;
 	}
@@ -1503,12 +1510,12 @@
 	 */
 	if (len != 0 && (mbuf->length == 0 || mbuf->length == len ||
 	    mbuf->length > len && mbuf->length < len+P9BITLEN)) {
-		print(mime ? "image/p9bit\n" : "%splan 9 image, depth %d, size %dx%d\n",
+		Bprint(&bout, mime ? "image/p9bit\n" : "%splan 9 image, depth %d, size %dx%d\n",
 			newlabel, dep, hix, hiy);
 		return 1;
 	}
 	if (p9subfont(buf+len)) {
-		print(mime ? "image/p9bit\n" : "%ssubfont file, depth %d, size %dx%d\n",
+		Bprint(&bout, mime ? "image/p9bit\n" : "%ssubfont file, depth %d, size %dx%d\n",
 			newlabel, dep, hix, hiy);
 		return 1;
 	}
@@ -1579,7 +1586,7 @@
 		}
 	}
 	if (i) {
-		print("%s\n", mime ? PLAIN : "font file");
+		Bprint(&bout, "%s\n", mime ? PLAIN : "font file");
 		return 1;
 	}
 	return 0;
@@ -1604,7 +1611,7 @@
 isrtf(void)
 {
 	if(strstr((char *)buf, "\\rtf1")){
-		print(mime ? "application/rtf\n" : "rich text format\n");
+		Bprint(&bout, mime ? "application/rtf\n" : "rich text format\n");
 		return 1;
 	}
 	return 0;
@@ -1614,7 +1621,7 @@
 ismsdos(void)
 {
 	if (buf[0] == 0x4d && buf[1] == 0x5a){
-		print(mime ? "application/x-msdownload\n" : "MSDOS executable\n");
+		Bprint(&bout, mime ? "application/x-msdownload\n" : "MSDOS executable\n");
 		return 1;
 	}
 	return 0;
@@ -1629,10 +1636,10 @@
 		return 0;
 	switch(buf[2]){
 	case 1:
-		print(mime ? "image/x-icon\n" : "Microsoft icon file\n");
+		Bprint(&bout, mime ? "image/x-icon\n" : "Microsoft icon file\n");
 		return 1;
 	case 2:
-		print(mime ? "image/x-icon\n" : "Microsoft cursor file\n");
+		Bprint(&bout, mime ? "image/x-icon\n" : "Microsoft cursor file\n");
 		return 1;
 	}
 	return 0;
@@ -1694,10 +1701,10 @@
 
 			if(n>0 && n < nelem(type) && type[n])
 				t = type[n];
-			print("%s ELF %s\n", p, t);
+			Bprint(&bout, "%s ELF %s\n", p, t);
 		}
 		else
-			print("application/x-elf-executable\n");
+			Bprint(&bout, "application/x-elf-executable\n");
 		return 1;
 	}
 
@@ -1736,8 +1743,8 @@
 	}
 
 	if(mime)
-		print("application/x-face\n");
+		Bprint(&bout, "application/x-face\n");
 	else
-		print("face image depth %d\n", ldepth);
+		Bprint(&bout, "face image depth %d\n", ldepth);
 	return 1;
 }

  reply	other threads:[~2021-08-15  4:11 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-10 18:03 Stuart Morrow
2021-08-11  1:13 ` ori
2021-08-11 20:15   ` Stuart Morrow
2021-08-11 20:32     ` Stuart Morrow
2021-08-12  5:38       ` Alex Musolino
2021-08-13  2:43     ` Alex Musolino
2021-08-14 21:38       ` Stuart Morrow [this message]
2021-08-14 21:45         ` Stuart Morrow
2021-08-15  2:42         ` Alex Musolino

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CABB-WO9_BYdBfJeB1sDijoAJ3YPK2X_GGs=d=8XYLwukOE12XA@mail.gmail.com' \
    --to=morrow.stuart@gmail.com \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).