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 <[email protected]> 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
> [email protected]
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-users