Hi I like the other diff a bit more than yours so I think I will go with it, does it meet your needs too, or any comments?
On Mon, Apr 20, 2015 at 09:02:52AM -0400, John O'Meara wrote: > Hi list, > > I had made a patch for myself to add a per-pane status bar a few weeks > ago, and saw yesterday that there was a ticket open for a similar feature. > Nicholas pointed out that he had already done work on this, but suggested > I post my patch anyway. > > Firstly, sorry for duplicating effort. I hope this patch is helpful but I > understand if it isn't. > > Secondly, the ticket does request top-of-pane title, where my patch > currently only does bottom-of-pane, but it uses the expansion system that > the regular status line uses, so the pane title and whatever else might be > wanted can go there (I use pane-tty and pane-title, for example). If it is > desired for this patch to move forward, I will work on adding a > pane-status-position option to allow it to be placed top-of-pane (as well > as other suggestions I receive) > > The patch works by decreasing the pane height by 1 when pane-status is > enabled, and drawing the pane status line in the opened up space. > Adjustments are made for border drawing, window selection, and mouse > movements to work properly with the adjusted pane size. Redrawing is > handled similar to the regular status line, in that the statuses are > pre-rendered in memory and only sent to the screen if they differ from the > last render. Rendering is per-client to allow things like client-tty > expansions to work correctly. > > Usage is documented in the man page, and the default options move the > pane-title from status-right to pane-status-format (leaving only the time > in status-right), allowing for a quick example when run with default > settings. > > Thanks, > > -- John O'Meara > diff --git a/layout.c b/layout.c > index b91b86c..c66ca00 100644 > --- a/layout.c > +++ b/layout.c > @@ -170,6 +170,9 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy) > struct window_pane *wp; > struct layout_cell *lc; > u_int sx, sy; > + int has_pane_status; > + > + has_pane_status = options_get_number(&w->options, "pane-status"); > > TAILQ_FOREACH(wp, &w->panes, entry) { > if ((lc = wp->layout_cell) == NULL) > @@ -207,9 +210,9 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy) > * is two because scroll regions cannot be one line. > */ > if (lc->yoff >= wsy || lc->yoff + lc->sy < wsy) > - sy = lc->sy; > + sy = lc->sy - has_pane_status; > else { > - sy = wsy - lc->yoff; > + sy = wsy - lc->yoff - has_pane_status; > if (sy < 2) > sy = lc->sy; > } > @@ -527,9 +530,12 @@ layout_resize_pane_mouse(struct client *c) > struct window_pane *wp; > struct mouse_event *m = &c->tty.mouse; > int pane_border; > + int has_pane_status; > > w = c->session->curw->window; > > + has_pane_status = options_get_number(&w->options, "pane-status"); > + > pane_border = 0; > if (m->event & MOUSE_EVENT_DRAG && m->flags & MOUSE_RESIZE_PANE) { > TAILQ_FOREACH(wp, &w->panes, entry) { > @@ -538,12 +544,12 @@ layout_resize_pane_mouse(struct client *c) > > if (wp->xoff + wp->sx == m->lx && > wp->yoff <= 1 + m->ly && > - wp->yoff + wp->sy >= m->ly) { > + wp->yoff + wp->sy + has_pane_status >= m->ly) { > layout_resize_pane(wp, LAYOUT_LEFTRIGHT, > m->x - m->lx); > pane_border = 1; > } > - if (wp->yoff + wp->sy == m->ly && > + if (wp->yoff + wp->sy + has_pane_status == m->ly && > wp->xoff <= 1 + m->lx && > wp->xoff + wp->sx >= m->lx) { > layout_resize_pane(wp, LAYOUT_TOPBOTTOM, > @@ -557,8 +563,8 @@ layout_resize_pane_mouse(struct client *c) > TAILQ_FOREACH(wp, &w->panes, entry) { > if ((wp->xoff + wp->sx == m->x && > wp->yoff <= 1 + m->y && > - wp->yoff + wp->sy >= m->y) || > - (wp->yoff + wp->sy == m->y && > + wp->yoff + wp->sy + has_pane_status >= m->y) || > + (wp->yoff + wp->sy + has_pane_status == m->y && > wp->xoff <= 1 + m->x && > wp->xoff + wp->sx >= m->x)) { > pane_border = 1; > diff --git a/options-table.c b/options-table.c > index 2bcf29b..be9af3f 100644 > --- a/options-table.c > +++ b/options-table.c > @@ -396,7 +396,7 @@ const struct options_table_entry session_options_table[] > = { > > { .name = "status-right", > .type = OPTIONS_TABLE_STRING, > - .default_str = " \"#{=21:pane_title}\" %H:%M %d-%b-%y" > + .default_str = "%H:%M %d-%b-%y" > }, > > { .name = "status-right-attr", > @@ -652,6 +652,39 @@ const struct options_table_entry window_options_table[] > = { > .default_str = "default" > }, > > + { .name = "pane-status", > + .type = OPTIONS_TABLE_FLAG, > + .default_num = 1 > + }, > + > + { .name = "pane-status-attr", > + .type = OPTIONS_TABLE_ATTRIBUTES, > + .default_num = 0, > + .style = "pane-status-style" > + }, > + > + { .name = "pane-status-bg", > + .type = OPTIONS_TABLE_COLOUR, > + .default_num = 2, > + .style = "pane-status-style" > + }, > + > + { .name = "pane-status-fg", > + .type = OPTIONS_TABLE_COLOUR, > + .default_num = 0, > + .style = "pane-status-style" > + }, > + > + { .name = "pane-status-format", > + .type = OPTIONS_TABLE_STRING, > + .default_str = "[#T]" > + }, > + > + { .name = "pane-status-style", > + .type = OPTIONS_TABLE_STYLE, > + .default_str = "default" > + }, > + > { .name = "remain-on-exit", > .type = OPTIONS_TABLE_FLAG, > .default_num = 0 > diff --git a/resize.c b/resize.c > index 9ad73c8..edf44d5 100644 > --- a/resize.c > +++ b/resize.c > @@ -128,8 +128,16 @@ recalculate_sizes(void) > forced |= WINDOW_FORCEHEIGHT; > } > > +#if 0 /* This optimization to not resize panes if the window size doesn't > + change fails to handle the case where pane sizes may have changed > + due to options like 'pane-status' changing. Unfortunately, we > + can't at this point know if this function was called because of an > + option change, let alone specific option changes. For now, we'll > + just skip the optimization and take the computational hit rather > + than have a stale display. */ > if (w->sx == ssx && w->sy == ssy) > continue; > +#endif > log_debug("window size %u,%u (was %u,%u)", ssx, ssy, w->sx, > w->sy); > > diff --git a/screen-redraw.c b/screen-redraw.c > index c2b2ece..a36a2fe 100644 > --- a/screen-redraw.c > +++ b/screen-redraw.c > @@ -54,13 +54,17 @@ void screen_redraw_draw_number(struct client *, > struct window_pane *); > int > screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py) > { > + int has_pane_status; > + > + has_pane_status = options_get_number(&wp->window->options, > "pane-status"); > + > /* Inside pane. */ > if (px >= wp->xoff && px < wp->xoff + wp->sx && > - py >= wp->yoff && py < wp->yoff + wp->sy) > + py >= wp->yoff && py < wp->yoff + wp->sy + has_pane_status) > return (0); > > /* Left/right borders. */ > - if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= wp->yoff + wp->sy) { > + if ((wp->yoff == 0 || py >= wp->yoff - 1 + has_pane_status) && py <= > wp->yoff + wp->sy + has_pane_status) { > if (wp->xoff != 0 && px == wp->xoff - 1) > return (1); > if (px == wp->xoff + wp->sx) > @@ -71,7 +75,7 @@ screen_redraw_cell_border1(struct window_pane *wp, u_int > px, u_int py) > if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= wp->xoff + wp->sx) { > if (wp->yoff != 0 && py == wp->yoff - 1) > return (1); > - if (py == wp->yoff + wp->sy) > + if (py == wp->yoff + wp->sy + has_pane_status) > return (1); > } > > @@ -106,6 +110,9 @@ screen_redraw_check_cell(struct client *c, u_int px, > u_int py, > struct window *w = c->session->curw->window; > struct window_pane *wp; > int borders; > + int has_pane_status; > + > + has_pane_status = options_get_number(&w->options, "pane-status"); > > if (px > w->sx || py > w->sy) > return (CELL_OUTSIDE); > @@ -119,7 +126,7 @@ screen_redraw_check_cell(struct client *c, u_int px, > u_int py, > if ((wp->xoff != 0 && px < wp->xoff - 1) || > px > wp->xoff + wp->sx || > (wp->yoff != 0 && py < wp->yoff - 1) || > - py > wp->yoff + wp->sy) > + py > wp->yoff + wp->sy + has_pane_status) > continue; > > /* If definitely inside, return so. */ > @@ -180,6 +187,10 @@ int > screen_redraw_check_active(u_int px, u_int py, int type, struct window *w, > struct window_pane *wp) > { > + int has_pane_status; > + > + has_pane_status = options_get_number(&wp->window->options, > "pane-status"); > + > /* Is this off the active pane border? */ > if (screen_redraw_cell_border1(w->active, px, py) != 1) > return (0); > @@ -204,7 +215,7 @@ screen_redraw_check_active(u_int px, u_int py, int type, > struct window *w, > } > > /* Check if the pane covers the whole height. */ > - if (wp->yoff == 0 && wp->sy == w->sy) { > + if (wp->yoff == 0 && wp->sy + has_pane_status == w->sy) { > /* This can either be the left pane or the right pane. */ > if (wp->xoff == 0) { /* left pane */ > if (wp == w->active) > @@ -217,6 +228,24 @@ screen_redraw_check_active(u_int px, u_int py, int type, > struct window *w, > return (type); > } > > +void > +screen_redraw_draw_pane_status(struct client *c, u_int top) > +{ > + struct window *w = c->session->curw->window; > + struct window_pane *wp; > + struct pane_status *ps = TAILQ_FIRST(&c->pane_statuses); > + > + TAILQ_FOREACH(wp, &w->panes, entry) { > + if (!window_pane_visible(wp)) > + continue; > + if (!ps) { > + fatalx("pane status not found"); > + } > + tty_draw_line(&c->tty, &ps->status, 0, wp->xoff, top + wp->yoff > + wp->sy); > + ps = TAILQ_NEXT(ps, entry); > + } > +} > + > /* Redraw entire screen. */ > void > screen_redraw_screen(struct client *c, int draw_panes, int draw_status, > @@ -226,6 +255,7 @@ screen_redraw_screen(struct client *c, int draw_panes, > int draw_status, > struct tty *tty = &c->tty; > u_int top; > int status, spos; > + int draw_pane_status; > > /* Suspended clients should not be updated. */ > if (c->flags & CLIENT_SUSPENDED) > @@ -238,6 +268,10 @@ screen_redraw_screen(struct client *c, int draw_panes, > int draw_status, > else > status = options_get_number(oo, "status"); > top = 0; > + if (draw_status && > options_get_number(&c->session->curw->window->options, "pane-status")) > + draw_pane_status = 1; > + else > + draw_pane_status = 0; > if (status && spos == 0) > top = 1; > if (!status) > @@ -249,6 +283,9 @@ screen_redraw_screen(struct client *c, int draw_panes, > int draw_status, > screen_redraw_draw_panes(c, top); > if (draw_status) > screen_redraw_draw_status(c, top); > + if (draw_pane_status){ > + screen_redraw_draw_pane_status(c, top); > + } > tty_reset(tty); > } > > diff --git a/server-client.c b/server-client.c > index f7ce35c..fa278af 100644 > --- a/server-client.c > +++ b/server-client.c > @@ -749,6 +749,7 @@ server_client_check_redraw(struct client *c) > redraw = status_prompt_redraw(c); > else > redraw = status_redraw(c); > + redraw |= pane_status_redraw(c); > if (!redraw) > c->flags &= ~CLIENT_STATUS; > } > diff --git a/status.c b/status.c > index 5f8895f..b7546bb 100644 > --- a/status.c > +++ b/status.c > @@ -38,7 +38,7 @@ void status_job_free(void *); > void status_job_callback(struct job *); > char *status_print(struct client *, struct winlink *, time_t, > struct grid_cell *); > -char *status_replace(struct client *, struct winlink *, const char *, > time_t); > +char *status_replace(struct client *, struct winlink *, struct window_pane > *wp, const char *, time_t); > void status_replace1(struct client *, char **, char **, char *, size_t); > void status_message_callback(int, short, void *); > > @@ -87,7 +87,7 @@ status_redraw_get_left(struct client *c, time_t t, int > utf8flag, > style_apply_update(gc, &s->options, "status-left-style"); > > template = options_get_string(&s->options, "status-left"); > - left = status_replace(c, NULL, template, t); > + left = status_replace(c, NULL, NULL, template, t); > > *size = options_get_number(&s->options, "status-left-length"); > leftlen = screen_write_cstrlen(utf8flag, "%s", left); > @@ -109,7 +109,7 @@ status_redraw_get_right(struct client *c, time_t t, int > utf8flag, > style_apply_update(gc, &s->options, "status-right-style"); > > template = options_get_string(&s->options, "status-right"); > - right = status_replace(c, NULL, template, t); > + right = status_replace(c, NULL, NULL, template, t); > > *size = options_get_number(&s->options, "status-right-length"); > rightlen = screen_write_cstrlen(utf8flag, "%s", right); > @@ -362,6 +362,86 @@ out: > return (1); > } > > +/* Draw status for panes */ > +int > +pane_status_redraw(struct client *c) > +{ > + struct screen_write_ctx ctx; > + int utf8flag; > + struct grid_cell stdgc; > + char *msg; > + struct window *w = c->session->curw->window; > + struct window_pane *wp; > + struct pane_statuses old_pane_statuses; > + struct pane_status *pane_status; > + struct pane_status *t; > + int diff = 0; > + unsigned int len; > + > + if (options_get_number(&w->options, "pane-status") == 0) { > + return 0; > + } > + > + memcpy(&old_pane_statuses, &c->pane_statuses, sizeof old_pane_statuses); > + TAILQ_INIT(&c->pane_statuses); > + > + utf8flag = options_get_number(&c->session->options, "status-utf8"); > + > + /* Create set of statuses for each pane */ > + TAILQ_FOREACH(wp, &w->panes, entry) { > + if (!window_pane_visible(wp)) > + continue; > + pane_status = malloc(sizeof *pane_status); > + if (!pane_status) { > + continue; > + } > + memcpy(&stdgc, &grid_default_cell, sizeof stdgc); > + colour_set_fg(&stdgc, options_get_number(&wp->window->options, > "pane-status-fg")); > + colour_set_bg(&stdgc, options_get_number(&wp->window->options, > "pane-status-bg")); > + stdgc.attr |= options_get_number(&wp->window->options, > "pane-status-attr"); > + screen_init(&pane_status->status, wp->sx, 1, 0); > + msg = status_replace(c, NULL, wp, > options_get_string(&wp->window->options, "pane-status-format"), time(NULL)); > + len = screen_write_strlen(utf8flag, "%s", msg); > + if (len > wp->sx) { > + len = wp->sx; > + } > + screen_write_start(&ctx, NULL, &pane_status->status); > + screen_write_cursormove(&ctx, 0, 0); > + screen_write_cnputs(&ctx, len, &stdgc, utf8flag, "%s", msg); > + screen_write_stop(&ctx); > + free(msg); > + TAILQ_INSERT_TAIL(&c->pane_statuses, pane_status, entry); > + } > + > + /* Check if any of the status lines have changed, or if the number > + * of status lines have changed. */ > + { > + struct pane_status *old; > + struct pane_status *new; > + old = TAILQ_FIRST(&old_pane_statuses); > + new = TAILQ_FIRST(&c->pane_statuses); > + while (old != TAILQ_END(&old_pane_statuses) && new != > TAILQ_END(&c->pane_statuses)) { > + if (grid_compare(old->status.grid, new->status.grid) != > 0) { > + //screen_free(&old_status); > + diff = 1; > + } > + //screen_free(&old_status); > + old = TAILQ_NEXT(old, entry); > + new = TAILQ_NEXT(new, entry); > + } > + if (old != TAILQ_END(&old_pane_statuses) || new != > TAILQ_END(&c->pane_statuses)) { > + diff = 1; > + } > + } > + /* discard old */ > + TAILQ_FOREACH_SAFE(pane_status, &old_pane_statuses, entry, t) { > + screen_free(&pane_status->status); > + free(pane_status); > + } > + return diff; > +} > + > + > /* Replace a single special sequence (prefixed by #). */ > void > status_replace1(struct client *c, char **iptr, char **optr, char *out, > @@ -431,7 +511,7 @@ skip_to: > > /* Replace special sequences in fmt. */ > char * > -status_replace(struct client *c, struct winlink *wl, const char *fmt, time_t > t) > +status_replace(struct client *c, struct winlink *wl, struct window_pane *wp, > const char *fmt, time_t t) > { > static char out[BUFSIZ]; > char in[BUFSIZ], ch, *iptr, *optr, *expanded; > @@ -461,7 +541,7 @@ status_replace(struct client *c, struct winlink *wl, > const char *fmt, time_t t) > *optr = '\0'; > > ft = format_create(); > - format_defaults(ft, c, NULL, wl, NULL); > + format_defaults(ft, c, NULL, wl, wp); > expanded = format_expand(ft, out); > format_free(ft); > return (expanded); > @@ -626,7 +706,7 @@ status_print(struct client *c, struct winlink *wl, time_t > t, > else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE)) > style_apply_update(gc, oo, "window-status-activity-style"); > > - text = status_replace(c, wl, fmt, t); > + text = status_replace(c, wl, NULL, fmt, t); > return (text); > } > > diff --git a/tmux.1 b/tmux.1 > index 8a0879b..b277376 100644 > --- a/tmux.1 > +++ b/tmux.1 > @@ -2617,7 +2617,7 @@ Set the position of the status line. > Display > .Ar string > to the right of the status bar. > -By default, the current window title in double quotes, the date and the time > +By default, the date and the time > are shown. > As with > .Ic status-left , > @@ -2918,6 +2918,33 @@ see the > option. > Attributes are ignored. > .Pp > +.It Xo Ic pane-status > +.Op Ic on | off > +.Xc > +Show or hide a status line at the bottom of each pane. > +.Pp > +.It Ic pane-status-format Ar string > +Display > +.Ar string > +in the status bar of each pane in the window. > +By default, the pane title is shown in brackets. > +As with > +.Ic status-left , > +.Ar string > +will be passed to > +.Xr strftime 3 , > +character pairs are replaced, and UTF-8 is dependent on the > +.Ic status-utf8 > +option. > +.Pp > +.It Ic pane-status-style Ar style > +Set the pane status line style. > +For how to specify > +.Ar style , > +see the > +.Ic message-command-style > +opption. > +.Pp > .It Xo Ic remain-on-exit > .Op Ic on | off > .Xc > diff --git a/tmux.h b/tmux.h > index e296ac7..bc1e659 100644 > --- a/tmux.h > +++ b/tmux.h > @@ -923,6 +923,12 @@ TAILQ_HEAD(window_panes, window_pane); > RB_HEAD(window_pane_tree, window_pane); > ARRAY_DECL(window_pane_list, struct window_pane *); > > +struct pane_status { > + struct screen status; > + TAILQ_ENTRY(pane_status) entry; > +}; > +TAILQ_HEAD(pane_statuses, pane_status); > + > /* Window structure. */ > struct window { > u_int id; > @@ -1283,6 +1289,7 @@ struct client { > struct status_out_tree status_new; > struct timeval status_timer; > struct screen status; > + struct pane_statuses pane_statuses; > > #define CLIENT_TERMINAL 0x1 > #define CLIENT_PREFIX 0x2 > @@ -1923,6 +1930,7 @@ void status_free_jobs(struct status_out_tree *); > void status_update_jobs(struct client *); > void status_set_window_at(struct client *, u_int); > int status_redraw(struct client *); > +int pane_status_redraw(struct client *c); > void printflike(2, 3) status_message_set(struct client *, const char *, ...); > void status_message_clear(struct client *); > int status_message_redraw(struct client *); > @@ -2058,6 +2066,7 @@ void screen_write_setselection(struct > screen_write_ctx *, u_char *, u_int); > void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); > > /* screen-redraw.c */ > +void screen_redraw_draw_pane_status(struct client *c, u_int top); > void screen_redraw_screen(struct client *, int, int, int); > void screen_redraw_pane(struct client *, struct window_pane *); > > diff --git a/window.c b/window.c > index fff2cfc..b7e6f53 100644 > --- a/window.c > +++ b/window.c > @@ -1180,6 +1180,9 @@ window_pane_find_up(struct window_pane *wp) > u_int edge, left, right, end; > struct window_pane_list list; > int found; > + int has_pane_status; > + > + has_pane_status = options_get_number(&wp->window->options, > "pane-status"); > > if (wp == NULL || !window_pane_visible(wp)) > return (NULL); > @@ -1195,7 +1198,7 @@ window_pane_find_up(struct window_pane *wp) > TAILQ_FOREACH(next, &wp->window->panes, entry) { > if (next == wp || !window_pane_visible(next)) > continue; > - if (next->yoff + next->sy + 1 != edge) > + if (next->yoff + next->sy + 1 + has_pane_status != edge) > continue; > end = next->xoff + next->sx - 1; > > @@ -1223,12 +1226,15 @@ window_pane_find_down(struct window_pane *wp) > u_int edge, left, right, end; > struct window_pane_list list; > int found; > + int has_pane_status; > + > + has_pane_status = options_get_number(&wp->window->options, > "pane-status"); > > if (wp == NULL || !window_pane_visible(wp)) > return (NULL); > ARRAY_INIT(&list); > > - edge = wp->yoff + wp->sy + 1; > + edge = wp->yoff + wp->sy + 1 + has_pane_status; > if (edge >= wp->window->sy) > edge = 0; > > ------------------------------------------------------------------------------ > BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT > Develop your own process in accordance with the BPMN 2 standard > Learn Process modeling best practices with Bonita BPM through live exercises > http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_ > source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF > _______________________________________________ > tmux-users mailing list > tmux-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tmux-users ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users