Hi, Yes, this looks perfectly fine to me, Nicholas. The only thing I've noticed (and I'm not sure how much it matters---hence why I've not fixed it) is the following doesn't expand:
% tmux display -pF '#{?session_attached, #{]#{session_name},(no session)}' Produces: {?session_attached, Because when we try and expand #{} we get nothing, and the expansion breaks from any further processing. I'm sure it's not a big problem though. As for the automatic-rename stuff, that's fine. -- Thomas Adam On 3 August 2013 21:28, Nicholas Marriott <nicholas.marri...@gmail.com> wrote: > Here's it updated to fix some warnings, to apply to top of latest git > and also with the changes to add automatic-rename-format which you might > like to look at. > > diff --git a/format.c b/format.c > index ee3339d..da939f0 100644 > --- a/format.c > +++ b/format.c > @@ -34,9 +34,10 @@ > * string. > */ > > -int format_replace(struct format_tree *, const char *, size_t, char **, > - size_t *, size_t *); > -void format_window_pane_tabs(struct format_tree *, struct window_pane *); > +int format_replace(struct format_tree *, const char *, size_t, char **, > + size_t *, size_t *); > +char *format_get_command(struct window_pane *); > +void format_window_pane_tabs(struct format_tree *, struct window_pane *); > > /* Format key-value replacement entry. */ > RB_GENERATE(format_tree, format_entry, entry, format_cmp); > @@ -193,7 +194,7 @@ int > format_replace(struct format_tree *ft, const char *key, size_t keylen, > char **buf, size_t *len, size_t *off) > { > - char *copy, *copy0, *endptr, *ptr; > + char *copy, *copy0, *endptr, *ptr, *saved; > const char *value; > size_t valuelen; > u_long limit = ULONG_MAX; > @@ -247,10 +248,13 @@ format_replace(struct format_tree *ft, const char *key, > size_t keylen, > goto fail; > value = ptr + 1; > } > + saved = format_expand(ft, value); > + value = saved; > } else { > value = format_find(ft, copy); > if (value == NULL) > value = ""; > + saved = NULL; > } > valuelen = strlen(value); > > @@ -266,6 +270,7 @@ format_replace(struct format_tree *ft, const char *key, > size_t keylen, > memcpy(*buf + *off, value, valuelen); > *off += valuelen; > > + free(saved); > free(copy0); > return (0); > > @@ -278,10 +283,10 @@ fail: > char * > format_expand(struct format_tree *ft, const char *fmt) > { > - char *buf, *ptr; > - const char *s; > + char *buf; > + const char *ptr, *s; > size_t off, len, n; > - int ch; > + int ch, brackets; > > len = 64; > buf = xmalloc(len); > @@ -299,11 +304,16 @@ format_expand(struct format_tree *ft, const char *fmt) > fmt++; > > ch = (u_char) *fmt++; > - > switch (ch) { > case '{': > - ptr = strchr(fmt, '}'); > - if (ptr == NULL) > + brackets = 1; > + for (ptr = fmt; *ptr != '\0'; ptr++) { > + if (*ptr == '{') > + brackets++; > + if (*ptr == '}' && --brackets == 0) > + break; > + } > + if (*ptr != '}' || brackets != 0) > break; > n = ptr - fmt; > > @@ -339,6 +349,21 @@ format_expand(struct format_tree *ft, const char *fmt) > return (buf); > } > > +/* Get command name for format. */ > +char * > +format_get_command(struct window_pane *wp) > +{ > + char *cmd; > + > + cmd = osdep_get_name(wp->fd, wp->tty); > + if (cmd == NULL || *cmd == '\0') { > + cmd = wp->cmd; > + if (cmd == NULL || *cmd == '\0') > + cmd = wp->shell; > + } > + return (parse_window_name(cmd)); > +} > + > /* Set default format keys for a session. */ > void > format_session(struct format_tree *ft, struct session *s) > @@ -418,26 +443,39 @@ format_client(struct format_tree *ft, struct client *c) > format_add(ft, "client_last_session", "%s", s->name); > } > > -/* Set default format keys for a winlink. */ > +/* Set default format keys for a window. */ > void > -format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl) > +format_window(struct format_tree *ft, struct window *w) > { > - struct window *w = wl->window; > - char *layout, *flags; > + char *layout; > > layout = layout_dump(w); > - flags = window_printable_flags(s, wl); > > format_add(ft, "window_id", "@%u", w->id); > - format_add(ft, "window_index", "%d", wl->idx); > format_add(ft, "window_name", "%s", w->name); > format_add(ft, "window_width", "%u", w->sx); > format_add(ft, "window_height", "%u", w->sy); > - format_add(ft, "window_flags", "%s", flags); > format_add(ft, "window_layout", "%s", layout); > - format_add(ft, "window_active", "%d", wl == s->curw); > format_add(ft, "window_panes", "%u", window_count_panes(w)); > > + free(layout); > +} > + > +/* Set default format keys for a winlink. */ > +void > +format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl) > +{ > + struct window *w = wl->window; > + char *flags; > + > + flags = window_printable_flags(s, wl); > + > + format_window(ft, w); > + > + format_add(ft, "window_index", "%d", wl->idx); > + format_add(ft, "window_flags", "%s", flags); > + format_add(ft, "window_active", "%d", wl == s->curw); > + > format_add(ft, "window_bell_flag", "%u", > !!(wl->flags & WINLINK_BELL)); > format_add(ft, "window_content_flag", "%u", > @@ -447,8 +485,8 @@ format_winlink(struct format_tree *ft, struct session *s, > struct winlink *wl) > format_add(ft, "window_silence_flag", "%u", > !!(wl->flags & WINLINK_SILENCE)); > > + > free(flags); > - free(layout); > } > > /* Add window pane tabs. */ > @@ -518,7 +556,7 @@ format_window_pane(struct format_tree *ft, struct > window_pane *wp) > format_add(ft, "pane_start_path", "%s", wp->cwd); > if ((cwd = osdep_get_cwd(wp->fd)) != NULL) > format_add(ft, "pane_current_path", "%s", cwd); > - if ((cmd = osdep_get_name(wp->fd, wp->tty)) != NULL) { > + if ((cmd = format_get_command(wp)) != NULL) { > format_add(ft, "pane_current_command", "%s", cmd); > free(cmd); > } > diff --git a/names.c b/names.c > index f536d2f..7c02961 100644 > --- a/names.c > +++ b/names.c > @@ -22,12 +22,10 @@ > #include <libgen.h> > #include <stdlib.h> > #include <string.h> > -#include <unistd.h> > > #include "tmux.h" > > void window_name_callback(unused int, unused short, void *); > -char *parse_window_name(const char *); > > void > queue_window_name(struct window *w) > @@ -47,7 +45,7 @@ void > window_name_callback(unused int fd, unused short events, void *data) > { > struct window *w = data; > - char *name, *wname; > + char *name; > > if (w->active == NULL) > return; > @@ -59,50 +57,40 @@ window_name_callback(unused int fd, unused short events, > void *data) > } > queue_window_name(w); > > - if (w->active->screen != &w->active->base) > - name = NULL; > - else > - name = osdep_get_name(w->active->fd, w->active->tty); > - if (name == NULL) > - wname = default_window_name(w); > - else { > - /* > - * If tmux is using the default command, it will be a login > - * shell and argv[0] may have a - prefix. Remove this if it is > - * present. Ick. > - */ > - if (w->active->cmd != NULL && *w->active->cmd == '\0' && > - name != NULL && name[0] == '-' && name[1] != '\0') > - wname = parse_window_name(name + 1); > - else > - wname = parse_window_name(name); > - free(name); > - } > - > - if (w->active->fd == -1) { > - xasprintf(&name, "%s[dead]", wname); > - free(wname); > - wname = name; > - } > - > - if (strcmp(wname, w->name)) { > - window_set_name(w, wname); > + name = format_window_name(w); > + if (strcmp(name, w->name) != 0) { > + window_set_name(w, name); > server_status_window(w); > } > - free(wname); > + free(name); > } > > char * > default_window_name(struct window *w) > { > - if (w->active->screen != &w->active->base) > - return (xstrdup("[tmux]")); > if (w->active->cmd != NULL && *w->active->cmd != '\0') > return (parse_window_name(w->active->cmd)); > return (parse_window_name(w->active->shell)); > } > > char * > +format_window_name(struct window *w) > +{ > + struct format_tree *ft; > + char *fmt, *name; > + > + ft = format_create(); > + format_window(ft, w); > + format_window_pane(ft, w->active); > + > + fmt = options_get_string(&w->options, "automatic-rename-format"); > + name = format_expand(ft, fmt); > + > + format_free(ft); > + return (name); > +} > + > +char * > parse_window_name(const char *in) > { > char *copy, *name, *ptr; > @@ -111,7 +99,7 @@ parse_window_name(const char *in) > if (strncmp(name, "exec ", (sizeof "exec ") - 1) == 0) > name = name + (sizeof "exec ") - 1; > > - while (*name == ' ') > + while (*name == ' ' || *name == '-') > name++; > if ((ptr = strchr(name, ' ')) != NULL) > *ptr = '\0'; > diff --git a/options-table.c b/options-table.c > index 0b86ef7..f6a1547 100644 > --- a/options-table.c > +++ b/options-table.c > @@ -481,6 +481,11 @@ const struct options_table_entry window_options_table[] > = { > .default_num = 1 > }, > > + { .name = "automatic-rename-format", > + .type = OPTIONS_TABLE_STRING, > + .default_str = > "#{?pane_in_mode,[tmux],#{pane_current_command}}#{?pane_dead,[dead],}" > + }, > + > { .name = "c0-change-trigger", > .type = OPTIONS_TABLE_NUMBER, > .default_num = 250, > diff --git a/tmux.1 b/tmux.1 > index 19ae4a9..c93f4d9 100644 > --- a/tmux.1 > +++ b/tmux.1 > @@ -2710,8 +2710,8 @@ The default is on. > Control automatic window renaming. > When this setting is enabled, > .Nm > -will attempt - on supported platforms - to rename the window to reflect the > -command currently running in it. > +will rename the window automatically using the format specified by > +.Ic automatic-rename-format . > This flag is automatically disabled for an individual window when a name > is specified at creation with > .Ic new-window > @@ -2725,6 +2725,13 @@ It may be switched off globally with: > set-window-option -g automatic-rename off > .Ed > .Pp > +.It Ic automatic-rename-format Ar format > +The format (see > +.Sx FORMATS ) > +used when the > +.Ic automatic-rename > +option is enabled. > +.Pp > .It Ic c0-change-interval Ar interval > .It Ic c0-change-trigger Ar trigger > These two options configure a simple form of rate limiting for a pane. > diff --git a/tmux.h b/tmux.h > index 1cb5cd8..6ab9861 100644 > --- a/tmux.h > +++ b/tmux.h > @@ -1549,16 +1549,19 @@ int format_cmp(struct format_entry *, > struct format_entry *); > RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp); > struct format_tree *format_create(void); > void format_free(struct format_tree *); > -void printflike3 format_add( > - struct format_tree *, const char *, const char *, ...); > +void printflike3 format_add(struct format_tree *, const char *, const char *, > + ...); > const char *format_find(struct format_tree *, const char *); > char *format_expand(struct format_tree *, const char *); > void format_session(struct format_tree *, struct session *); > void format_client(struct format_tree *, struct client *); > -void format_winlink( > - struct format_tree *, struct session *, struct winlink > *); > -void format_window_pane(struct format_tree *, struct window_pane > *); > -void format_paste_buffer(struct format_tree *, struct > paste_buffer *); > +void format_window(struct format_tree *, struct window *); > +void format_winlink(struct format_tree *, struct session *, > + struct winlink *); > +void format_window_pane(struct format_tree *, > + struct window_pane *); > +void format_paste_buffer(struct format_tree *, > + struct paste_buffer *); > > /* mode-key.c */ > extern const struct mode_key_table mode_key_tables[]; > @@ -2272,8 +2275,10 @@ void window_choose_collapse_all(struct window_pane > *); > void window_choose_set_current(struct window_pane *, u_int); > > /* names.c */ > -void queue_window_name(struct window *); > -char *default_window_name(struct window *); > +void queue_window_name(struct window *); > +char *default_window_name(struct window *); > +char *format_window_name(struct window *); > +char *parse_window_name(const char *); > > /* signal.c */ > void set_signals(void(*)(int, short, void *)); > > > > On Fri, Aug 02, 2013 at 02:11:10PM +0100, Nicholas Marriott wrote: >> How about this? >> >> >> diff --git a/format.c b/format.c >> index 0845df6..9a3ed07 100644 >> --- a/format.c >> +++ b/format.c >> @@ -191,7 +191,7 @@ int >> format_replace(struct format_tree *ft, >> const char *key, size_t keylen, char **buf, size_t *len, size_t *off) >> { >> - char *copy, *ptr; >> + char *copy, *ptr, *saved; >> const char *value; >> size_t valuelen; >> >> @@ -223,10 +223,15 @@ format_replace(struct format_tree *ft, >> goto fail; >> value = ptr + 1; >> } >> + value = format_expand(ft, value); >> + >> + saved = value; >> } else { >> value = format_find(ft, copy); >> if (value == NULL) >> value = ""; >> + >> + saved = NULL; >> } >> valuelen = strlen(value); >> >> @@ -238,6 +243,7 @@ format_replace(struct format_tree *ft, >> memcpy(*buf + *off, value, valuelen); >> *off += valuelen; >> >> + free(saved); >> free(copy); >> return (0); >> >> @@ -253,7 +259,7 @@ format_expand(struct format_tree *ft, const char *fmt) >> char *buf, *ptr; >> const char *s; >> size_t off, len, n; >> - int ch; >> + int ch, brackets; >> >> len = 64; >> buf = xmalloc(len); >> @@ -271,11 +277,16 @@ format_expand(struct format_tree *ft, const char *fmt) >> fmt++; >> >> ch = (u_char) *fmt++; >> - >> switch (ch) { >> case '{': >> - ptr = strchr(fmt, '}'); >> - if (ptr == NULL) >> + brackets = 1; >> + for (ptr = fmt; *ptr != '\0'; ptr++) { >> + if (*ptr == '{') >> + brackets++; >> + if (*ptr == '}' && --brackets == 0) >> + break; >> + } >> + if (*ptr != '}' || brackets != 0) >> break; >> n = ptr - fmt; >> >> >> >> >> >> On Wed, May 15, 2013 at 05:01:53PM +0100, Nicholas Marriott wrote: >> > This still doesn't seem right. >> > >> > If I have "#{?foo,bar,#{baz}} #{zoink}". >> > >> > Then in format_expand it'll decide the first { is: "?foo,bar,#{baz}} >> > #{zoink". >> > >> > Then if foo is true I'll get bar (which is fine) >> > >> > But if it's false I'll get "#{baz}} #{zoink" which is wrong. >> > >> > You need to replace the strchr with a loop like: >> > >> > depth = 1; >> > ptr = fmt; >> > while (*ptr != '\0') { >> > if (*ptr == '{') >> > depth++; >> > if (*ptr == '}') { >> > if (--depth == 0) >> > break; >> > } >> > } >> > >> > Which means format_replace will be passed exactly "?foo,bar,#{baz}". >> > >> > >> > On Sun, Apr 28, 2013 at 01:54:44PM +0100, Thomas Adam wrote: >> > > Hi, >> > > >> > > On Thu, Apr 25, 2013 at 10:55:56PM +0100, Nicholas Marriott wrote: >> > > > Ok. I think you have the right idea about recursing through >> > > > format_expand you are just going to need to pull out the affected >> > > > format >> > > > differently (ditch strchr and use a custom loop which counts {s and >> > > > }s). >> > > >> > > Yeah, that's one way. But actually, strchr/strchrr would both be doing >> > > the >> > > same thing as this manual loop you refer to, it's just that their use >> > > would >> > > vary depending on whether we're expanding a terniary-form of a format >> > > replacement or just a single element. >> > > >> > > So I think something along the lines of the patch attached might be an >> > > idea. >> > > It's certainly the path of least resistance (i.e., not much code changed) >> > > but that doesn't mean I particularly like it. ;P >> > > >> > > -- Thomas Adam >> > >> > > diff --git a/format.c b/format.c >> > > index 7de819a..178f201 100644 >> > > --- a/format.c >> > > +++ b/format.c >> > > @@ -150,8 +150,8 @@ int >> > > format_replace(struct format_tree *ft, >> > > const char *key, size_t keylen, char **buf, size_t *len, size_t >> > > *off) >> > > { >> > > - char *copy, *ptr; >> > > const char *value; >> > > + char *copy, *ptr; >> > > size_t valuelen; >> > > >> > > /* Make a copy of the key. */ >> > > @@ -182,6 +182,7 @@ format_replace(struct format_tree *ft, >> > > goto fail; >> > > value = ptr + 1; >> > > } >> > > + value = format_expand(ft, value); >> > > } else { >> > > value = format_find(ft, copy); >> > > if (value == NULL) >> > > @@ -232,7 +233,11 @@ format_expand(struct format_tree *ft, const char >> > > *fmt) >> > > ch = (u_char) *fmt++; >> > > switch (ch) { >> > > case '{': >> > > - ptr = strchr(fmt, '}'); >> > > + if (*fmt++ == '?') >> > > + ptr = strrchr(--fmt, '}'); >> > > + else >> > > + ptr = strchr(--fmt, '}'); >> > >> > There is no need to do fmt++ if you then do --fmt in both branches of >> > the if. >> > >> > > + >> > > if (ptr == NULL) >> > > break; >> > > n = ptr - fmt; >> > > -- >> > > 1.7.11.4 >> > > >> > > > ------------------------------------------------------------------------------ > Get your SQL database under version control now! > Version control is standard for application code, but databases havent > caught up. So what steps can you take to put your SQL databases under > version control? Why should you start doing it? Read more to find out. > http://pubads.g.doubleclick.net/gampad/clk?id=49501711&iu=/4140/ostg.clktrk > _______________________________________________ > tmux-users mailing list > tmux-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tmux-users ------------------------------------------------------------------------------ Get 100% visibility into Java/.NET code with AppDynamics Lite! It's a free troubleshooting tool designed for production. Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users