dvtm

dynamic virtual terminal manager - with my changes
git clone https://pi.duncano.de/git/dvtm.git
Log | Files | Refs | README | LICENSE

commit 5d9ab4e52899833be375ac1c26e5c06f08a73437
parent 954dc438a362ca9d5134bd4752407763ed8daa99
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Mon, 28 Sep 2015 12:15:20 +0200

Try to preserve coloring in copymode

This only works if the viewer/filter program used for the copymode
understands color related terminal escape sequences. It is currently
only enabled for less. Use it as follows:

 $ DVTM_EDITOR=less dvtm

Diffstat:
config.def.h | 15++++++++-------
dvtm.c | 5++++-
vt.c | 42++++++++++++++++++++++++++++++++++++++----
vt.h | 2+-
4 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -204,13 +204,14 @@ static char const * const keytable[] = { * set the first entry is chosen. Otherwise the array is consulted for supported * options. A %d in argv is replaced by the line number at which the file should * be opened. If filter is true the editor is expected to work even if stdout is - * redirected (i.e. not a terminal). + * redirected (i.e. not a terminal). If color is true then color escape sequences + * are generated in the output. */ static Editor editors[] = { - { .name = "vis", .argv = { "vis", "+%d", "-", NULL }, .filter = true }, - { .name = "sandy", .argv = { "sandy", "-d", "-", NULL }, .filter = true }, - { .name = "dvtm-editor", .argv = { "dvtm-editor", "-", NULL }, .filter = true }, - { .name = "vim", .argv = { "vim", "+%d", "-", NULL }, .filter = false }, - { .name = "less", .argv = { "less", "+%d", NULL }, .filter = false }, - { .name = "more", .argv = { "more", "+%d", NULL }, .filter = false }, + { .name = "vis", .argv = { "vis", "+%d", "-", NULL }, .filter = true, .color = false }, + { .name = "sandy", .argv = { "sandy", "-d", "-", NULL }, .filter = true, .color = false }, + { .name = "dvtm-editor", .argv = { "dvtm-editor", "-", NULL }, .filter = true, .color = false }, + { .name = "vim", .argv = { "vim", "+%d", "-", NULL }, .filter = false, .color = false }, + { .name = "less", .argv = { "less", "-R", "+%d", NULL }, .filter = false, .color = true }, + { .name = "more", .argv = { "more", "+%d", NULL }, .filter = false, .color = false }, }; diff --git a/dvtm.c b/dvtm.c @@ -161,6 +161,7 @@ typedef struct { char *name; const char *argv[4]; bool filter; + bool color; } Editor; #define LENGTH(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -1056,6 +1057,7 @@ copymode(const char *args[]) { const char **argv = (const char*[]){ ed, "-", NULL, NULL }; char argline[32]; + bool colored = false; for (unsigned int i = 0; i < LENGTH(editors); i++) { if (!strcmp(editors[i].name, ed)) { @@ -1070,6 +1072,7 @@ copymode(const char *args[]) { } if (editors[i].filter) from = &sel->editor_fds[1]; + colored = editors[i].color; break; } } @@ -1084,7 +1087,7 @@ copymode(const char *args[]) { if (sel->editor_fds[0] != -1) { char *buf = NULL; - size_t len = vt_content_get(sel->app, &buf); + size_t len = vt_content_get(sel->app, &buf, colored); char *cur = buf; while (len > 0) { ssize_t res = write(sel->editor_fds[0], cur, len); diff --git a/vt.c b/vt.c @@ -1884,11 +1884,11 @@ pid_t vt_pid_get(Vt *t) return t->pid; } -size_t vt_content_get(Vt *t, char **buf) +size_t vt_content_get(Vt *t, char **buf, bool colored) { Buffer *b = t->buffer; int lines = b->scroll_above + b->scroll_below + b->rows + 1; - size_t size = lines * (b->cols * MB_CUR_MAX + 1); + size_t size = lines * ((b->cols + 1) * ((colored ? 64 : 0) + MB_CUR_MAX)); mbstate_t ps; memset(&ps, 0, sizeof(ps)); @@ -1896,13 +1896,47 @@ size_t vt_content_get(Vt *t, char **buf) return 0; char *s = *buf; + Cell *prev_cell = NULL; for (Row *row = buffer_row_first(b); row; row = buffer_row_next(b, row)) { size_t len = 0; char *last_non_space = s; for (int col = 0; col < b->cols; col++) { - if (row->cells[col].text) { - len = wcrtomb(s, row->cells[col].text, &ps); + Cell *cell = row->cells + col; + if (cell->text) { + if (colored) { + int esclen = 0; + if (!prev_cell || cell->attr != prev_cell->attr) { + attr_t attr = cell->attr << NCURSES_ATTR_SHIFT; + esclen = sprintf(s, "\033[0%s%s%s%s%s%sm", + attr & A_BOLD ? ";1" : "", + attr & A_DIM ? ";2" : "", + attr & A_UNDERLINE ? ";4" : "", + attr & A_BLINK ? ";5" : "", + attr & A_REVERSE ? ";7" : "", + attr & A_INVIS ? ";8" : ""); + if (esclen > 0) + s += esclen; + } + if (!prev_cell || cell->fg != prev_cell->fg || cell->attr != prev_cell->attr) { + if (cell->fg == -1) + esclen = sprintf(s, "\033[39m"); + else + esclen = sprintf(s, "\033[38;5;%dm", cell->fg); + if (esclen > 0) + s += esclen; + } + if (!prev_cell || cell->bg != prev_cell->bg || cell->attr != prev_cell->attr) { + if (cell->bg == -1) + esclen = sprintf(s, "\033[49m"); + else + esclen = sprintf(s, "\033[48;5;%dm", cell->bg); + if (esclen > 0) + s += esclen; + } + prev_cell = cell; + } + len = wcrtomb(s, cell->text, &ps); if (len > 0) s += len; last_non_space = s; diff --git a/vt.h b/vt.h @@ -60,7 +60,7 @@ void vt_scroll(Vt*, int rows); void vt_noscroll(Vt*); pid_t vt_pid_get(Vt*); -size_t vt_content_get(Vt*, char **s); +size_t vt_content_get(Vt*, char **s, bool colored); int vt_content_start(Vt*); #endif /* VT_H */