Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: ztrftime %. for fractions of a second in prompts



I was trying to get some timings in prompts to better than a second ---
not particularly useful in a regular shell prompt, but very useful in
the prompts provided by e.g. the TCP functions.

I was shocked! shocked! to find this appears not to be possible.

I've used %. for this as it's definitely not POSIX and is very easy to
remember.  You can specify 1 to 6 digits between the '%' and the '.'.

This doesn't appear to be useful in non-prompt calls to ztrftime() since
the fractions of a second aren't available.

pws


diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index eab15d2..36f351b 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -185,6 +185,13 @@ sitem(tt(%K))(the hour of the day on the 24-hour clock)
 sitem(tt(%L))(the hour of the day on the 12-hour clock)
 endsitem()
 
+In addition, if the system supports the POSIX tt(gettimeofday) system
+call, tt(%.) provides decimal fractions of a second since the epoch with
+leading zeroes.  By default three decimal places are provided, but a
+number of digits up to 6 may be given following the tt(%); hence tt(%6.)
+outputs microseconds.  A typical example of this is the format
+`tt(%D{%H:%M:%S.%.})'.
+
 The GNU extension that a `tt(-)' between the tt(%) and the
 format character causes a leading zero or space to be stripped
 is handled directly by the shell for the format characters tt(d), tt(f),
diff --git a/Src/builtin.c b/Src/builtin.c
index 34a5296..a2a3ad7 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1731,7 +1731,7 @@ fclist(FILE *f, Options ops, zlong first, zlong last,
 	    if (tdfmt != NULL) {
 		struct tm *ltm;
 		ltm = localtime(&ent->stim);
-		if (ztrftime(timebuf, 256, tdfmt, ltm))
+		if (ztrftime(timebuf, 256, tdfmt, ltm, 0L))
 		    fprintf(f, "%s  ", timebuf);
 	    }
 	    /* display the time taken by the command, if required */
diff --git a/Src/prompt.c b/Src/prompt.c
index 95a7d49..c16d781 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -270,6 +270,8 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
     char *ss, *hostnam;
     int t0, arg, test, sep, j, numjobs;
     struct tm *tm;
+    struct timezone dummy_tz;
+    struct timeval tv;
     time_t timet;
     Nameddir nd;
 
@@ -636,8 +638,8 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
 			tmfmt = "%l:%M%p";
 			break;
 		    }
-		    timet = time(NULL);
-		    tm = localtime(&timet);
+		    gettimeofday(&tv, &dummy_tz);
+		    tm = localtime(&tv.tv_sec);
 		    /*
 		     * Hack because strftime won't say how
 		     * much space it actually needs.  Try to add it
@@ -647,7 +649,7 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
 		     */
 		    for(j = 0, t0 = strlen(tmfmt)*8; j < 3; j++, t0*=2) {
 			addbufspc(t0);
-			if (ztrftime(bv->bp, t0, tmfmt, tm) >= 0)
+			if (ztrftime(bv->bp, t0, tmfmt, tm, tv.tv_usec) >= 0)
 			    break;
 		    }
 		    /* There is enough room for this because addbufspc(t0)
diff --git a/Src/utils.c b/Src/utils.c
index cef2abe..aa978e6 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2710,7 +2710,7 @@ ztrftimebuf(int *bufsizeptr, int decr)
 
 /**/
 mod_export int
-ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
+ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec)
 {
     int hr12;
 #ifdef HAVE_STRFTIME
@@ -2729,6 +2729,7 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
     while (*fmt)
 	if (*fmt == '%') {
 	    int strip;
+	    int digs = 3;
 
 	    fmt++;
 	    if (*fmt == '-') {
@@ -2736,6 +2737,17 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
 		fmt++;
 	    } else
 		strip = 0;
+	    if (idigit(*fmt)) {
+		/* Digit --- only useful with . */
+		char *dstart = fmt;
+		char *dend = fmt+1;
+		while (idigit(*dend))
+		    dend++;
+		if (*dend == '.') {
+		    fmt = dend;
+		    digs = atoi(dstart);
+		}
+	    }
 	    /*
 	     * Assume this format will take up at least two
 	     * characters.  Not always true, but if that matters
@@ -2745,6 +2757,20 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
 	    if (ztrftimebuf(&bufsize, 2))
 		return -1;
 	    switch (*fmt++) {
+	    case '.':
+		if (ztrftimebuf(&bufsize, digs))
+		    return -1;
+		if (digs > 6)
+		    digs = 6;
+		if (digs < 6) {
+		    int trunc;
+		    for (trunc = 5 - digs; trunc; trunc--)
+			usec /= 10;
+		    usec  = (usec + 5) / 10;
+		}
+		sprintf(buf, "%0*ld", digs, usec);
+		buf += digs;
+		break;
 	    case 'd':
 		if (tm->tm_mday > 9 || !strip)
 		    *buf++ = '0' + tm->tm_mday / 10;
diff --git a/Src/watch.c b/Src/watch.c
index 5231579..8dea0b4 100644
--- a/Src/watch.c
+++ b/Src/watch.c
@@ -330,7 +330,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
 		    }
 		    timet = getlogtime(u, inout);
 		    tm = localtime(&timet);
-		    ztrftime(buf, 40, fm2, tm);
+		    ztrftime(buf, 40, fm2, tm, 0L);
 		    printf("%s", (*buf == ' ') ? buf + 1 : buf);
 		    break;
 		case '%':



Messages sorted by: Reverse Date, Date, Thread, Author