code: plan9front

Download patch

ref: 73e115aab038880a68c9f73b5c49d8fa12d0e5e2
parent: 827fdabbf912fa94b6472cf21cbdc5c82306af01
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Dec 14 15:52:04 EST 2022

vt: add OSC 7 support for plumbing of remote files without mount/bind magic

--- a/sys/src/cmd/vt/cons.h
+++ b/sys/src/cmd/vt/cons.h
@@ -10,7 +10,10 @@
 #define	INSET	2
 #define	BUFS	256
 #define	HISTSIZ	(64*1024)	/* number of history characters */
-#define BSIZE	(8*1024)
+#define	BSIZE	(8*1024)
+#define	WDIR	1024
+
+extern char osc7cwd[];
 
 #define	SCROLL	2
 #define NEWLINE	1
--- a/sys/src/cmd/vt/main.c
+++ b/sys/src/cmd/vt/main.c
@@ -1007,13 +1007,30 @@
 void
 plumbsel(void)
 {
-	char *s, wdir[1024];
+	char *s, *e, wdir[WDIR];
+	Plumbmsg msg;
 	int plumb;
 
 	s = selection();
 	if(s == nil || *s == 0)
 		return;
-	if(getwd(wdir, sizeof wdir) == nil){
+	memset(&msg, 0, sizeof(msg));
+	msg.src = "vt";
+	msg.type = "text";
+	msg.ndata = strlen(s);
+	msg.data = s;
+	msg.wdir = wdir;
+	if(*osc7cwd != 0){
+		strcpy(wdir, osc7cwd);
+		/* absolute path? adjust wdir and path */
+		if(*s == '/'){
+			if((e = strchr(wdir+3, '/')) != nil){
+				*e = 0;
+				msg.data++;
+				msg.ndata--;
+			}
+		}
+	}else if(getwd(wdir, sizeof wdir) == nil){
 		free(s);
 		return;
 	}
@@ -1021,7 +1038,7 @@
 		free(s);
 		return;
 	}
-	plumbsendtext(plumb, "vt", nil, wdir, s);
+	plumbsend(plumb, &msg);
 	close(plumb);
 	free(s);
 }
--- a/sys/src/cmd/vt/vt.c
+++ b/sys/src/cmd/vt/vt.c
@@ -32,6 +32,7 @@
 int	originrelative = 0;
 
 int	tabcol[200];
+char osc7cwd[WDIR];
 
 struct funckey ansifk[] = {
 	{ "up key",		"\033[A", },
@@ -952,6 +953,16 @@
 	}
 }
 
+static int
+hexnib(char c)
+{
+	if(c >= 'a')
+		return c - 'a' + 10;
+	if(c >= 'A')
+		return c - 'A' + 10;
+	return c - '0';
+}
+
 // handle ESC], Operating System Command
 static void
 osc(void)
@@ -958,6 +969,7 @@
 {
 	Rune ch, buf[BUFS+1];
 	int fd, osc, got, i;
+	char *o, *s;
 	osc = number(&ch, &got);
 
 	if(got) {
@@ -964,8 +976,7 @@
 		switch(osc) {
 		case 0:
 		case 1:
-		case 2:
-			// set title
+		case 2: /* set title */
 			i = 0;
 
 			while((ch = get_next_char()) != '\a') {
@@ -977,6 +988,33 @@
 			if((fd = open("/dev/label", OWRITE)) >= 0) {
 				fprint(fd, "%S", buf);
 				close(fd);
+			}
+			break;
+
+		case 7: /* set pwd */
+			i = 0;
+
+			while((ch = get_next_char()) != '\033'){
+				if(i < sizeof(osc7cwd)-UTFmax-1)
+					i += runetochar(osc7cwd+i, &ch);
+			}
+			get_next_char();
+			osc7cwd[i] = 0;
+
+			/* file://hostname/path → /n/hostname/path */
+			if(strncmp(osc7cwd, "file://", 7) == 0){
+				osc7cwd[0] = '/';
+				osc7cwd[1] = 'n';
+				o = osc7cwd+2;
+				s = osc7cwd+6;
+				while(*s){
+					if(*s == '%' && s[1] != 0 && s[2] != 0){
+						*o++ = hexnib(s[1])<<4 | hexnib(s[2]);
+						s += 3;
+					}else
+						*o++ = *s++;
+				}
+				*o = 0;
 			}
 			break;
 		}