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

Reply via email to