zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: zsh-workers@sunsite.dk (Zsh hackers list)
Subject: PATCH: zcurses stuff
Date: Tue, 23 Oct 2007 21:45:55 +0100	[thread overview]
Message-ID: <9462.1193172355@pws-pc.ntlworld.com> (raw)

1. Wrong argument counts for attr and endwin
2. More verbose errors for wrong number of arguments
3. One cchar_t should be a wchar_t
4. Now we have a command table, it's neater to dispatch straight
   to subcommands.
5. attr didn't pass back the status from actually setting attributes.

Other things I've thought about, but not done:
1. I think I prefer "end" to "endwin".  As I said, curses naming
   is horrible and "endwin" to me suggests it applies to a single
   window (indeed, what else could it logically mean?)
2. I think I prefer "char" and "string" to "c" and "s", which are
   the names of the subcommands internally anyway.
3. I'm not sure we actually need both "attr" and "color"; we
   can easily discriminate between types and as far as the user is
   concerned it's natural to set them in a single command,
     zcurses attr +bold red/black
   Also, I think we could assume the "+" if not present; other
   bits of the shell do this.
4. I think we can be more verbose with errors in places, for
   example if colo[u]rs or attributes aren't found.  The fact that
   it messes up the screen is neither here nor there if the result
   didn't work anyway.

By the way, I've adapted the test function so that it always tidies up:


zmodload zsh/curses

{
  zcurses init
  zcurses addwin tw $(( LINES - 10 )) $(( COLUMNS - 20 )) 5 10
  zcurses border tw
  zcurses move tw 1 1
  zcurses c tw B
  zcurses c tw l
  zcurses c tw a
  zcurses c tw h
  zcurses refresh tw
  zcurses move tw 2 2
  zcurses s tw String
  zcurses move tw 3 3
  zcurses attr tw +bold +underline
  zcurses s tw BoLD
  zcurses move tw 4 4
  zcurses attr tw -bold -underline
  zcurses color tw green/black
  zcurses s tw Green
  zcurses refresh tw
  sleep 5
  zcurses delwin tw
} always {
  zcurses endwin
}


Index: Src/Modules/curses.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/curses.c,v
retrieving revision 1.16
diff -u -r1.16 curses.c
--- Src/Modules/curses.c	21 Oct 2007 21:16:07 -0000	1.16
+++ Src/Modules/curses.c	23 Oct 2007 20:43:51 -0000
@@ -60,8 +60,10 @@
 };
 typedef struct colorpairnode *Colorpairnode;
 
+typedef int (*zccmd_t)(const char *nam, char **args);
 struct zcurses_subcommand {
-    struct zcurses_namenumberpair nn;
+    const char *name;
+    zccmd_t cmd;
     int minargs;
     int maxargs;
 };
@@ -110,7 +112,7 @@
 }
 
 static LinkNode
-zcurses_getwindowbyname(char *name)
+zcurses_getwindowbyname(const char *name)
 {
     LinkNode node;
     ZCWin w;
@@ -198,7 +200,7 @@
 }
 
 static short
-zcurses_color(char *color)
+zcurses_color(const char *color)
 {
     struct zcurses_namenumberpair *zc;
 
@@ -275,332 +277,385 @@
     zfree(hn, sizeof(struct colorpairnode));
 }
 
-/**/
+
+/*************
+ * Subcommands
+ *************/
+
 static int
-bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
+zccmd_init(const char *nam, char **args)
 {
-    char **saargs;
-    struct zcurses_subcommand *zcsc;
-    int sc, num_args;
+    if (!win_zero) {
+	gettyinfo(&saved_tty_state);
+	win_zero = initscr();
+	if (start_color() != ERR) {
+	    if(!zc_color_phase)
+		zc_color_phase = 1;
+	    zcurses_colorpairs = newhashtable(8, "zc_colorpairs", NULL);
+
+	    zcurses_colorpairs->hash        = hasher;
+	    zcurses_colorpairs->emptytable  = emptyhashtable;
+	    zcurses_colorpairs->filltable   = NULL;
+	    zcurses_colorpairs->cmpnodes    = strcmp;
+	    zcurses_colorpairs->addnode     = addhashnode;
+	    zcurses_colorpairs->getnode     = gethashnode2;
+	    zcurses_colorpairs->getnode2    = gethashnode2;
+	    zcurses_colorpairs->removenode  = removehashnode;
+	    zcurses_colorpairs->disablenode = NULL;
+	    zcurses_colorpairs->enablenode  = NULL;
+	    zcurses_colorpairs->freenode    = freecolorpairnode;
+	    zcurses_colorpairs->printnode   = NULL;
+
+	}
+	gettyinfo(&curses_tty_state);
+    } else {
+	settyinfo(&curses_tty_state);
+    }
+    return 0;
+}
 
-    struct zcurses_subcommand scs[] = {
-	{{"init", ZCURSES_SC_INIT}, 0, 0},
-	{{"addwin", ZCURSES_SC_ADDWIN}, 5, 5},
-	{{"delwin", ZCURSES_SC_DELWIN}, 1, 1},
-	{{"refresh", ZCURSES_SC_REFRESH}, 0, 1},
-	{{"move", ZCURSES_SC_MOVE}, 3, 3},
-	{{"c", ZCURSES_SC_CHAR}, 2, 2},
-	{{"s", ZCURSES_SC_STRING}, 2, 2},
-	{{"border", ZCURSES_SC_BORDER}, 1, 5},
-	{{"endwin", ZCURSES_SC_ENDWIN}, 1, 1},
-	{{"attr", ZCURSES_SC_ATTR}, 2, 2},
-	{{"color", ZCURSES_SC_COLOR}, 2, 2},
-	{{NULL, -1}, 0, 0}
-    };
 
-    for(zcsc = scs; zcsc->nn.name; zcsc++) {
-	if(!strcmp(args[0], zcsc->nn.name))
-	    break;
+static int
+zccmd_addwin(const char *nam, char **args)
+{
+    int nlines, ncols, begin_y, begin_x;
+    ZCWin w;
+
+    if (zcurses_validate_window(args[0], ZCURSES_UNUSED) == NULL &&
+	zc_errno) {
+	zerrnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
     }
 
-    sc = zcsc->nn.number;
+    nlines = atoi(args[1]);
+    ncols = atoi(args[2]);
+    begin_y = atoi(args[3]);
+    begin_x = atoi(args[4]);
 
-    if (sc == -1) {
-	zwarnnam(nam, "unknown subcommand: %s", args[0], 0);
+    w = (ZCWin)zshcalloc(sizeof(struct zc_win));
+    if (!w)
 	return 1;
-    }
 
-    saargs = args;
-    while (*saargs++);
-    num_args = saargs - (args + 2);
+    w->name = ztrdup(args[0]);
+    w->win = newwin(nlines, ncols, begin_y, begin_x);
 
-    if (num_args < zcsc->minargs || num_args > zcsc->maxargs)
+    if (w->win == NULL) {
+	zsfree(w->name);
+	free(w);
 	return 1;
+    }
 
-    saargs = args + 1;
+    zinsertlinknode(zcurses_windows, lastnode(zcurses_windows), (void *)w);
 
-    /* Initialise curses */
-    if (sc == ZCURSES_SC_INIT) {
-	if (!win_zero) {
-	    gettyinfo(&saved_tty_state);
-	    win_zero = initscr();
-	    if (start_color() != ERR) {
-		if(!zc_color_phase)
-		    zc_color_phase = 1;
-		zcurses_colorpairs = newhashtable(8, "zc_colorpairs", NULL);
-
-		zcurses_colorpairs->hash        = hasher;
-		zcurses_colorpairs->emptytable  = emptyhashtable;
-		zcurses_colorpairs->filltable   = NULL;
-		zcurses_colorpairs->cmpnodes    = strcmp;
-		zcurses_colorpairs->addnode     = addhashnode;
-		zcurses_colorpairs->getnode     = gethashnode2;
-		zcurses_colorpairs->getnode2    = gethashnode2;
-		zcurses_colorpairs->removenode  = removehashnode;
-		zcurses_colorpairs->disablenode = NULL;
-		zcurses_colorpairs->enablenode  = NULL;
-		zcurses_colorpairs->freenode    = freecolorpairnode;
-		zcurses_colorpairs->printnode   = NULL;
+    return 0;
+}
 
-	    }
-	    gettyinfo(&curses_tty_state);
-	} else {
-	    settyinfo(&curses_tty_state);
-	}
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_ADDWIN) {
-	int nlines, ncols, begin_y, begin_x;
-	ZCWin w;
+static int
+zccmd_delwin(const char *nam, char **args)
+{
+    LinkNode node;
+    ZCWin w;
 
-	if (zcurses_validate_window(saargs[0], ZCURSES_UNUSED) == NULL && zc_errno) {
-	    zerrnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0], 0);
-	    return 1;
-	}
+    node = zcurses_validate_window(args[0], ZCURSES_USED);
+    if (node == NULL) {
+	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
+    }
 
-	nlines = atoi(saargs[1]);
-	ncols = atoi(saargs[2]);
-	begin_y = atoi(saargs[3]);
-	begin_x = atoi(saargs[4]);
+    w = (ZCWin)getdata(node);
 
-	w = (ZCWin)zshcalloc(sizeof(struct zc_win));
-	if (!w)
-	    return 1;
+    if (w == NULL) {
+	zwarnnam(nam, "record for window `%s' is corrupt", args[0], 0);
+	return 1;
+    }
+    if (delwin(w->win)!=OK)
+	return 1;
 
-	w->name = ztrdup(saargs[0]);
-	w->win = newwin(nlines, ncols, begin_y, begin_x);
+    if (w->name)
+	zsfree(w->name);
 
-	if (w->win == NULL) {
-	    zsfree(w->name);
-	    free(w);
-	    return 1;
-	}
+    zfree((ZCWin)remnode(zcurses_windows, node), sizeof(struct zc_win));
 
-	zinsertlinknode(zcurses_windows, lastnode(zcurses_windows), (void *)w);
+    return 0;
+}
 
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_DELWIN) {
+static int
+zccmd_refresh(const char *nam, char **args)
+{
+    if (args[0]) {
 	LinkNode node;
 	ZCWin w;
 
-	node = zcurses_validate_window(saargs[0], ZCURSES_USED);
+	node = zcurses_validate_window(args[0], ZCURSES_USED);
 	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0], 0);
+	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0],
+		     0);
 	    return 1;
 	}
 
 	w = (ZCWin)getdata(node);
 
-	if (w == NULL) {
-	    zwarnnam(nam, "record for window `%s' is corrupt", saargs[0], 0);
-	    return 1;
-	}
-	if (delwin(w->win)!=OK)
-	    return 1;
-
-	if (w->name)
-	    zsfree(w->name);
+	return (wrefresh(w->win)!=OK) ? 1 : 0;
+    }
+    else
+    {
+	return (refresh() != OK) ? 1 : 0;
+    }
+}
 
-	zfree((ZCWin)remnode(zcurses_windows, node), sizeof(struct zc_win));
 
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_REFRESH) {
-	if (saargs[0]) {
-	    LinkNode node;
-	    ZCWin w;
-
-	    node = zcurses_validate_window(saargs[0], ZCURSES_USED);
-	    if (node == NULL) {
-		zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0],
-			0);
-		return 1;
-	    }
+static int
+zccmd_move(const char *nam, char **args)
+{
+    int y, x;
+    LinkNode node;
+    ZCWin w;
 
-	    w = (ZCWin)getdata(node);
+    node = zcurses_validate_window(args[0], ZCURSES_USED);
+    if (node == NULL) {
+	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
+    }
 
-	    return (wrefresh(w->win)!=OK) ? 1 : 0;
-	}
-	else
-	{
-	    return (refresh() != OK) ? 1 : 0;
-	}
-    } else
-    if (sc == ZCURSES_SC_MOVE) {
-	int y, x;
-	LinkNode node;
-	ZCWin w;
+    y = atoi(args[1]);
+    x = atoi(args[2]);
 
-	node = zcurses_validate_window(saargs[0], ZCURSES_USED);
-	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0], 0);
-	    return 1;
-	}
+    w = (ZCWin)getdata(node);
 
-	y = atoi(saargs[1]);
-	x = atoi(saargs[2]);
+    if (wmove(w->win, y, x)!=OK)
+	return 1;
 
-	w = (ZCWin)getdata(node);
+    return 0;
+}
 
-	if (wmove(w->win, y, x)!=OK)
-	    return 1;
 
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_CHAR) {
-	LinkNode node;
-	ZCWin w;
+static int
+zccmd_char(const char *nam, char **args)
+{
+    LinkNode node;
+    ZCWin w;
 #ifdef HAVE_SETCCHAR
-	wchar_t c;
-	cchar_t cc;
+    wchar_t c;
+    cchar_t cc;
 #endif
 
-	node = zcurses_validate_window(saargs[0], ZCURSES_USED);
-	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0], 0);
-	    return 1;
-	}
+    node = zcurses_validate_window(args[0], ZCURSES_USED);
+    if (node == NULL) {
+	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
+    }
 
-	w = (ZCWin)getdata(node);
+    w = (ZCWin)getdata(node);
 
 #ifdef HAVE_SETCCHAR
-	if (mbrtowc(&c, saargs[1], MB_CUR_MAX, NULL) < 1)
-	    return 1;
+    if (mbrtowc(&c, args[1], MB_CUR_MAX, NULL) < 1)
+	return 1;
 
-	if (setcchar(&cc, &c, A_NORMAL, 0, NULL)==ERR)
-	    return 1;
+    if (setcchar(&cc, &c, A_NORMAL, 0, NULL)==ERR)
+	return 1;
 
-	if (wadd_wch(w->win, &cc)!=OK)
-	    return 1;
+    if (wadd_wch(w->win, &cc)!=OK)
+	return 1;
 #else
-	if (waddch(w->win, (chtype)saargs[1][0])!=OK)
-	    return 1;
+    if (waddch(w->win, (chtype)args[1][0])!=OK)
+	return 1;
 #endif
 
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_STRING) {
-	LinkNode node;
-	ZCWin w;
+    return 0;
+}
+
+
+static int
+zccmd_string(const char *nam, char **args)
+{
+    LinkNode node;
+    ZCWin w;
 
 #ifdef HAVE_WADDWSTR
-	int clen;
-	wint_t wc;
-	wchar_t *wstr, *wptr;
-	char *str = saargs[1];
+    int clen;
+    wint_t wc;
+    wchar_t *wstr, *wptr;
+    char *str = args[1];
 #endif
 
-	node = zcurses_validate_window(saargs[0], ZCURSES_USED);
-	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
-	    return 1;
-	}
+    node = zcurses_validate_window(args[0], ZCURSES_USED);
+    if (node == NULL) {
+	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
+    }
 
-	w = (ZCWin)getdata(node);
+    w = (ZCWin)getdata(node);
 
 #ifdef HAVE_WADDWSTR
-	mb_metacharinit();
-	wptr = wstr = zhalloc((strlen(str)+1) * sizeof(cchar_t));
+    mb_metacharinit();
+    wptr = wstr = zhalloc((strlen(str)+1) * sizeof(wchar_t));
 
-	while (*str && (clen = mb_metacharlenconv(str, &wc))) {
-	    str += clen;
-	    if (wc == WEOF) /* TODO: replace with space? nicen? */
-		continue;
-	    *wptr++ = wc;
-	}
-	*wptr++ = L'\0';
-	if (waddwstr(w->win, wstr)!=OK) {
-	    return 1;
-	}
+    while (*str && (clen = mb_metacharlenconv(str, &wc))) {
+	str += clen;
+	if (wc == WEOF) /* TODO: replace with space? nicen? */
+	    continue;
+	*wptr++ = wc;
+    }
+    *wptr++ = L'\0';
+    if (waddwstr(w->win, wstr)!=OK) {
+	return 1;
+    }
 #else
-	if (waddstr(w->win, saargs[1])!=OK)
-	    return 1;
+    if (waddstr(w->win, args[1])!=OK)
+	return 1;
 #endif
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_BORDER) {
-	LinkNode node;
-	ZCWin w;
+    return 0;
+}
 
-	node = zcurses_validate_window(saargs[0], ZCURSES_USED);
-	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0], 0);
-	    return 1;
-	}
 
-	w = (ZCWin)getdata(node);
+static int
+zccmd_border(const char *nam, char **args)
+{
+    LinkNode node;
+    ZCWin w;
 
-	if (wborder(w->win, 0, 0, 0, 0, 0, 0, 0, 0)!=OK)
-	    return 1;
+    node = zcurses_validate_window(args[0], ZCURSES_USED);
+    if (node == NULL) {
+	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
+    }
 
-	return 0;
-    } else
-    /* Finish using curses */
-    if (sc == ZCURSES_SC_ENDWIN) {
-	if (win_zero) {
-	    endwin();
-	    /* Restore TTY as it was before zcurses -i */
-	    settyinfo(&saved_tty_state);
-	    /*
-	     * TODO: should I need the following?  Without it
-	     * the screen stays messed up.  Presumably we are
-	     * doing stuff with shttyinfo when we shouldn't really be.
-	     */
-	    gettyinfo(&shttyinfo);
-	}
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_ATTR) {
-	LinkNode node;
-	ZCWin w;
-	char **attrs;
+    w = (ZCWin)getdata(node);
 
-	if (!saargs[0])
-	    return 1;
+    if (wborder(w->win, 0, 0, 0, 0, 0, 0, 0, 0)!=OK)
+	return 1;
 
-	node = zcurses_validate_window(saargs[0], ZCURSES_USED);
-	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0], 0);
-	    return 1;
-	}
+    return 0;
+}
 
-	w = (ZCWin)getdata(node);
 
-	for(attrs = saargs+1; *attrs; attrs++) {
-	    switch(*attrs[0]) {
-		case '-':
-		    zcurses_attribute(w->win, (*attrs)+1, ZCURSES_ATTROFF);
-		    break;
-		case '+':
-		    zcurses_attribute(w->win, (*attrs)+1, ZCURSES_ATTRON);
-		    break;
-		default:
-		    /* maybe a bad idea to spew warnings here */
-		    break;
-	    }
-	}
-	return 0;
-    } else
-    if (sc == ZCURSES_SC_COLOR) {
-	LinkNode node;
-	ZCWin w;
+static int
+zccmd_endwin(const char *nam, char **args)
+{
+    if (win_zero) {
+	endwin();
+	/* Restore TTY as it was before zcurses -i */
+	settyinfo(&saved_tty_state);
+	/*
+	 * TODO: should I need the following?  Without it
+	 * the screen stays messed up.  Presumably we are
+	 * doing stuff with shttyinfo when we shouldn't really be.
+	 */
+	gettyinfo(&shttyinfo);
+    }
+    return 0;
+}
 
-	if (!saargs[0] || !saargs[1] || !zc_color_phase)
-	    return 1;
 
-	node = zcurses_validate_window(saargs[0], ZCURSES_USED);
-	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), saargs[0], 0);
-	    return 1;
+static int
+zccmd_attr(const char *nam, char **args)
+{
+    LinkNode node;
+    ZCWin w;
+    char **attrs;
+    int ret = 0;
+
+    if (!args[0])
+	return 1;
+
+    node = zcurses_validate_window(args[0], ZCURSES_USED);
+    if (node == NULL) {
+	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
+    }
+
+    w = (ZCWin)getdata(node);
+
+    for(attrs = args+1; *attrs; attrs++) {
+	switch(*attrs[0]) {
+	case '-':
+	    if (zcurses_attribute(w->win, (*attrs)+1, ZCURSES_ATTROFF))
+		ret = 1;
+	    break;
+	case '+':
+	    if (zcurses_attribute(w->win, (*attrs)+1, ZCURSES_ATTRON))
+		ret = 1;
+	    break;
+	default:
+	    /* maybe a bad idea to spew warnings here */
+	    break;
 	}
+    }
+    return ret;
+}
 
-	w = (ZCWin)getdata(node);
 
-	return zcurses_colorset(w->win, saargs[1]);
+static int
+zccmd_color(const char *nam, char **args)
+{
+    LinkNode node;
+    ZCWin w;
+
+    if (!args[0] || !args[1] || !zc_color_phase)
+	return 1;
+
+    node = zcurses_validate_window(args[0], ZCURSES_USED);
+    if (node == NULL) {
+	zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+	return 1;
     }
 
-    return 0;
+    w = (ZCWin)getdata(node);
+
+    return zcurses_colorset(w->win, args[1]);
+}
+
+
+/*********************
+  Main builtin handler
+ *********************/
+
+/**/
+static int
+bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
+{
+    char **saargs;
+    struct zcurses_subcommand *zcsc;
+    int num_args;
+
+    struct zcurses_subcommand scs[] = {
+	{"init", zccmd_init, 0, 0},
+	{"addwin", zccmd_addwin, 5, 5},
+	{"delwin", zccmd_delwin, 1, 1},
+	{"refresh", zccmd_refresh, 0, 1},
+	{"move", zccmd_move, 3, 3},
+	{"c", zccmd_char, 2, 2},
+	{"s", zccmd_string, 2, 2},
+	{"border", zccmd_border, 1, 5},
+	{"endwin", zccmd_endwin, 0, 0},
+	{"attr", zccmd_attr, 2, -1},
+	{"color", zccmd_color, 2, 2},
+	{NULL, (zccmd_t)0, 0, 0}
+    };
+
+    for(zcsc = scs; zcsc->name; zcsc++) {
+	if(!strcmp(args[0], zcsc->name))
+	    break;
+    }
+
+    if (zcsc->name == NULL) {
+	zwarnnam(nam, "unknown subcommand: %s", args[0]);
+	return 1;
+    }
+
+    saargs = args;
+    while (*saargs++);
+    num_args = saargs - (args + 2);
+
+    if (num_args < zcsc->minargs) {
+	zwarnnam(nam, "too few arguments for subcommand: %s", args[0]);
+	return 1;
+    } else if (zcsc->maxargs >= 0 && num_args > zcsc->maxargs) {
+	zwarnnam(nam, "too may arguments for subcommand: %s", args[0]);
+	return 1;
+    }
+
+    return zcsc->cmd(nam, args+1);
 }
 
 /*


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


             reply	other threads:[~2007-10-23 20:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-23 20:45 Peter Stephenson [this message]
2007-10-23 21:12 ` Clint Adams
2007-10-24  8:45   ` Peter Stephenson
2007-10-24  0:52 ` Bart Schaefer
2007-10-24  1:06   ` Matthew Wozniski
2007-10-24  5:18     ` Bart Schaefer

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=9462.1193172355@pws-pc.ntlworld.com \
    --to=p.w.stephenson@ntlworld.com \
    --cc=zsh-workers@sunsite.dk \
    /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.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

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).