Thorsten Glaser <[email protected]> wrote:
 |>  - jobs names hard cut to ridiculous size (should at least be START..END, \
 |  not
 |>    STARTUNTILCUT, for, e.g., playing music or having multiple jobs which \
 |  read
 |>    RFCs)
 |
 |It’s pretty hard to do this well. Additionally, there are some
 |memory constraints *and* terminal sizes come into play… but your
 |improvement idea is noted and gives me some ideas; I know where
 |and what to change, for this.

Just in case you're interested in this, here is a patch that tries
to focus display on the executable name.  E.g., without the patch:

  ?0[steffen@sherwood steffen]$ ls -Fastr /usr/share/calendar/calendar.music &
  [1] + Done                 ls -Fastr /usr/share/calendar/calen

And with it:

  ?0[steffen@nhead src]$ ls -Fastr /usr/share/calendar/calendar.music &
  [1] + Done                 ls -Fastr /...lendar/calendar.music

It's pretty fresh, but all tests pass and i think it's just fine
now.  Hope you like it!

--steffen
Date:   2013-02-23 18:16:08 +0100

    Try to display executables of jobnames
---
 tree.c |  124 +++++++++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 92 insertions(+), 32 deletions(-)

diff --git a/tree.c b/tree.c
index 8015a8d..539b57d 100644
--- a/tree.c
+++ b/tree.c
@@ -736,48 +736,108 @@ fpFUNCTf(struct shf *shf, int i, bool isksh, const char *k, struct op *v)
 		fptreef(shf, i, "%s() %T", k, v);
 }
 
-
 /* for jobs.c */
 void
 vistree(char *dst, size_t sz, struct op *t)
 {
 	unsigned int c;
-	char *cp, *buf;
+	bool is_com;
+	char *cp, *buf, *dp, *dbuf;
+	unsigned char *sp, *steps;
 	size_t n;
 
-	buf = alloc(sz + 8, ATEMP);
-	snptreef(buf, sz + 8, "%T", t);
-	cp = buf;
- vist_loop:
-	if (UTFMODE && (n = utf_mbtowc(&c, cp)) != (size_t)-1) {
-		if (c == 0 || n >= sz)
-			/* NUL or not enough free space */
-			goto vist_out;
-		/* copy multibyte char */
-		sz -= n;
-		while (n--)
-			*dst++ = *cp++;
-		goto vist_loop;
+	/*
+	 * When the job is a simple command then try to display as much of the
+	 * executable as possible, otherwise hard cut after sz bytes.
+	 */
+	if (t->type == TCOM) {
+		is_com = true;
+		buf = NULL;
+	} else {
+		is_com = false;
+		buf = alloc(sz + 8, ATEMP);
 	}
-	if (--sz == 0 || (c = (unsigned char)(*cp++)) == 0)
-		/* NUL or not enough free space */
-		goto vist_out;
-	if ((c & 0x60) == 0 || (c & 0x7F) == 0x7F) {
-		/* C0 or C1 control character or DEL */
-		if (--sz == 0)
-			/* not enough free space for two chars */
-			goto vist_out;
-		*dst++ = (c & 0x80) ? '$' : '^';
-		c = (c & 0x7F) ^ 0x40;
-	} else if (UTFMODE && c > 0x7F) {
-		/* better not try to display broken multibyte chars */
-		c = '?';
+
+	cp = buf = snptreef(buf, sz + 8, "%T", t);
+
+	/* Temporary, sufficiently spaced output buffer and MB step info */
+	n = strlen(cp);
+	if (! is_com)
+		n = ksh_min(n, sz);
+	dp = dbuf = alloc(n * 2 + 6 /* MB_LEN_MAX */ + 1, ATEMP);
+	sp = steps = alloc(n, ATEMP);
+
+	for (;;) {
+		if (UTFMODE && (n = utf_mbtowc(&c, cp)) != (size_t)-1) {
+			if (c == (unsigned char)'\0')
+				break;
+			/* Copy over MB */
+			*sp = (unsigned char)n;
+			while (n--)
+				*dp++ = *cp++;
+		} else {
+			if ((c = (unsigned char)*cp++) == (unsigned char)'\0')
+				break;
+			if ((c & 0x60) == 0 || (c & 0x7F) == 0x7F) {
+				/* C0 or C1 control character or DEL */
+				dp[0] = (c & 0x80) ? '$' : '^';
+				dp[1] = (c & 0x7F) ^ 0x40;
+				dp += 2;
+				*sp = 2;
+			} else {
+				if (UTFMODE && c > 0x7F)
+					/* Replace broken MB chars */
+					c = (unsigned char)'?';
+				*dp++ = (char)c;
+				*sp = 1;
+			}
+		}
+		++sp;
+		if (! is_com && sz < (size_t)(dp - dbuf))
+			break;
+	}
+
+	/* If the last character was SP, remove that (see ptree()) */
+	if (dp > dbuf && dp[-1] == ' ')
+		--dp;
+	*dp = '\0';
+
+	/* Copy over to real destination */
+	n = (size_t)(dp - dbuf);
+	cp = dst;
+	dp = dbuf;
+	sp = steps;
+
+	if (n < sz) {
+		memcpy(cp, dbuf, n);
+		cp += n;
+	} else if (! is_com) {
+		while (sz > (n = *sp++)) {
+			sz -= n;
+			while (n--)
+				*cp++ = *dp++;
+		}
+	} else {
+		char *topstart = dbuf + n - 1 - (sz - 4 - sz / 3);
+
+		sz /= 3;
+		while (sz > (n = *sp++)) {
+			sz -= n;
+			while (n--)
+				*cp++ = *dp++;
+		}
+		dp += n;
+		cp[0] = '.'; cp[1] = '.'; cp[2] = '.';
+		cp += 3;
+		while (dp < topstart)
+			dp += *sp++;
+		while (*dp != '\0')
+			*cp++ = *dp++;
 	}
-	*dst++ = c;
-	goto vist_loop;
+	*cp = '\0';
 
- vist_out:
-	*dst = '\0';
+	afree(steps, ATEMP);
+	afree(dbuf, ATEMP);
 	afree(buf, ATEMP);
 }
 

Reply via email to