mirror of
https://github.com/tmux/tmux.git
synced 2024-11-17 18:08:51 +00:00
Support hyperlinks with capture-pane -e and add a mouse_hyperlink
format, GitHub issue 3247 from Jeff Chiang.
This commit is contained in:
parent
9360e0ef32
commit
d0d2c39dec
@ -177,7 +177,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
buf = NULL;
|
||||
for (i = top; i <= bottom; i++) {
|
||||
line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
|
||||
escape_c0, !join_lines && !no_trim);
|
||||
escape_c0, !join_lines && !no_trim, wp->screen);
|
||||
linelen = strlen(line);
|
||||
|
||||
buf = cmd_capture_pane_append(buf, len, line, linelen);
|
||||
|
39
format.c
39
format.c
@ -1145,6 +1145,25 @@ format_cb_mouse_word(struct format_tree *ft)
|
||||
return (format_grid_word(gd, x, gd->hsize + y));
|
||||
}
|
||||
|
||||
/* Callback for mouse_hyperlink. */
|
||||
static void *
|
||||
format_cb_mouse_hyperlink(struct format_tree *ft)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
struct grid *gd;
|
||||
u_int x, y;
|
||||
|
||||
if (!ft->m.valid)
|
||||
return (NULL);
|
||||
wp = cmd_mouse_pane(&ft->m, NULL, NULL);
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
|
||||
return (NULL);
|
||||
gd = wp->base.grid;
|
||||
return (format_grid_hyperlink(gd, x, gd->hsize + y, wp->screen));
|
||||
}
|
||||
|
||||
/* Callback for mouse_line. */
|
||||
static void *
|
||||
format_cb_mouse_line(struct format_tree *ft)
|
||||
@ -2789,6 +2808,9 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "mouse_button_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_button_flag
|
||||
},
|
||||
{ "mouse_hyperlink", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_hyperlink
|
||||
},
|
||||
{ "mouse_line", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_line
|
||||
},
|
||||
@ -5064,3 +5086,20 @@ format_grid_line(struct grid *gd, u_int y)
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Return hyperlink at given coordinates. Caller frees. */
|
||||
char *
|
||||
format_grid_hyperlink(struct grid *gd, u_int x, u_int y, struct screen* s)
|
||||
{
|
||||
const char *uri;
|
||||
struct grid_cell gc;
|
||||
|
||||
grid_get_cell(gd, x, y, &gc);
|
||||
if (gc.flags & GRID_FLAG_PADDING)
|
||||
return (NULL);
|
||||
if (s->hyperlinks == NULL || gc.link == 0)
|
||||
return (NULL);
|
||||
if (!hyperlinks_get(s->hyperlinks, gc.link, &uri, NULL, NULL))
|
||||
return (NULL);
|
||||
return (xstrdup(uri));
|
||||
}
|
||||
|
@ -231,5 +231,5 @@ grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
|
||||
px = grid_view_x(gd, px);
|
||||
py = grid_view_y(gd, py);
|
||||
|
||||
return (grid_string_cells(gd, px, py, nx, NULL, 0, 0, 0));
|
||||
return (grid_string_cells(gd, px, py, nx, NULL, 0, 0, 0, NULL));
|
||||
}
|
||||
|
72
grid.c
72
grid.c
@ -885,18 +885,47 @@ grid_string_cells_add_code(char *buf, size_t len, u_int n, int *s, int *newc,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
|
||||
const char *uri, int escape_c0)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (strlen(uri) + strlen(id) + 17 >= len)
|
||||
return (0);
|
||||
|
||||
if (escape_c0)
|
||||
strlcat(buf, "\\033]8;", len);
|
||||
else
|
||||
strlcat(buf, "\033]8;", len);
|
||||
if (*id != '\0') {
|
||||
xasprintf(&tmp, "id=%s;", id);
|
||||
strlcat(buf, tmp, len);
|
||||
free(tmp);
|
||||
} else
|
||||
strlcat(buf, ";", len);
|
||||
strlcat(buf, uri, len);
|
||||
if (escape_c0)
|
||||
strlcat(buf, "\\033\\\\", len);
|
||||
else
|
||||
strlcat(buf, "\033\\", len);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns ANSI code to set particular attributes (colour, bold and so on)
|
||||
* given a current state.
|
||||
*/
|
||||
static void
|
||||
grid_string_cells_code(const struct grid_cell *lastgc,
|
||||
const struct grid_cell *gc, char *buf, size_t len, int escape_c0)
|
||||
const struct grid_cell *gc, char *buf, size_t len, int escape_c0,
|
||||
struct screen *sc, int *has_link)
|
||||
{
|
||||
int oldc[64], newc[64], s[128];
|
||||
size_t noldc, nnewc, n, i;
|
||||
u_int attr = gc->attr, lastattr = lastgc->attr;
|
||||
char tmp[64];
|
||||
int oldc[64], newc[64], s[128];
|
||||
size_t noldc, nnewc, n, i;
|
||||
u_int attr = gc->attr, lastattr = lastgc->attr;
|
||||
char tmp[64];
|
||||
const char *uri, *id;
|
||||
|
||||
struct {
|
||||
u_int mask;
|
||||
@ -986,19 +1015,32 @@ grid_string_cells_code(const struct grid_cell *lastgc,
|
||||
else
|
||||
strlcat(buf, "\017", len); /* SI */
|
||||
}
|
||||
|
||||
/* Add hyperlink if changed. */
|
||||
if (sc != NULL && sc->hyperlinks != NULL && lastgc->link != gc->link) {
|
||||
if (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) {
|
||||
*has_link = grid_string_cells_add_hyperlink(buf, len,
|
||||
id, uri, escape_c0);
|
||||
} else if (*has_link) {
|
||||
grid_string_cells_add_hyperlink(buf, len, "", "",
|
||||
escape_c0);
|
||||
*has_link = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert cells into a string. */
|
||||
char *
|
||||
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
|
||||
struct grid_cell **lastgc, int with_codes, int escape_c0, int trim)
|
||||
struct grid_cell **lastgc, int with_codes, int escape_c0, int trim,
|
||||
struct screen *s)
|
||||
{
|
||||
struct grid_cell gc;
|
||||
static struct grid_cell lastgc1;
|
||||
const char *data;
|
||||
char *buf, code[128];
|
||||
char *buf, code[8192];
|
||||
size_t len, off, size, codelen;
|
||||
u_int xx;
|
||||
u_int xx, has_link = 0;
|
||||
const struct grid_line *gl;
|
||||
|
||||
if (lastgc != NULL && *lastgc == NULL) {
|
||||
@ -1020,7 +1062,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
|
||||
|
||||
if (with_codes) {
|
||||
grid_string_cells_code(*lastgc, &gc, code, sizeof code,
|
||||
escape_c0);
|
||||
escape_c0, s, &has_link);
|
||||
codelen = strlen(code);
|
||||
memcpy(*lastgc, &gc, sizeof **lastgc);
|
||||
} else
|
||||
@ -1046,6 +1088,18 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
|
||||
off += size;
|
||||
}
|
||||
|
||||
if (has_link) {
|
||||
grid_string_cells_add_hyperlink(code, sizeof code, "", "",
|
||||
escape_c0);
|
||||
codelen = strlen(code);
|
||||
while (len < off + size + codelen + 1) {
|
||||
buf = xreallocarray(buf, 2, len);
|
||||
len *= 2;
|
||||
}
|
||||
memcpy(buf + off, code, codelen);
|
||||
off += codelen;
|
||||
}
|
||||
|
||||
if (trim) {
|
||||
while (off > 0 && buf[off - 1] == ' ')
|
||||
off--;
|
||||
|
@ -179,7 +179,7 @@ hyperlinks_put(struct hyperlinks *hl, const char *uri_in,
|
||||
/* Get hyperlink by inner number. */
|
||||
int
|
||||
hyperlinks_get(struct hyperlinks *hl, u_int inner, const char **uri_out,
|
||||
const char **external_id_out)
|
||||
const char **internal_id_out, const char **external_id_out)
|
||||
{
|
||||
struct hyperlinks_uri find, *hlu;
|
||||
|
||||
@ -188,7 +188,10 @@ hyperlinks_get(struct hyperlinks *hl, u_int inner, const char **uri_out,
|
||||
hlu = RB_FIND(hyperlinks_by_inner_tree, &hl->by_inner, &find);
|
||||
if (hlu == NULL)
|
||||
return (0);
|
||||
*external_id_out = hlu->external_id;
|
||||
if (internal_id_out != NULL)
|
||||
*internal_id_out = hlu->internal_id;
|
||||
if (external_id_out != NULL)
|
||||
*external_id_out = hlu->external_id;
|
||||
*uri_out = hlu->uri;
|
||||
return (1);
|
||||
}
|
||||
|
@ -54,6 +54,9 @@
|
||||
" '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {copy-mode -q; set-buffer -- \"#{q:mouse_word}\"}" \
|
||||
" '#{?mouse_line,Copy Line,}' 'l' {copy-mode -q; set-buffer -- \"#{q:mouse_line}\"}" \
|
||||
" ''" \
|
||||
" '#{?mouse_hyperlink,Type #[underscore]#{=/9/...:mouse_hyperlink},}' 'C-h' {copy-mode -q; send-keys -l -- \"#{q:mouse_hyperlink}\"}" \
|
||||
" '#{?mouse_hyperlink,Copy #[underscore]#{=/9/...:mouse_hyperlink},}' 'h' {copy-mode -q; set-buffer -- \"#{q:mouse_hyperlink}\"}" \
|
||||
" ''" \
|
||||
" 'Horizontal Split' 'h' {split-window -h}" \
|
||||
" 'Vertical Split' 'v' {split-window -v}" \
|
||||
" ''" \
|
||||
|
1
tmux.1
1
tmux.1
@ -5160,6 +5160,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
|
||||
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
|
||||
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
|
||||
.It Li "mouse_hyperlink" Ta "" Ta "Hyperlink under mouse, if any"
|
||||
.It Li "mouse_line" Ta "" Ta "Line under mouse, if any"
|
||||
.It Li "mouse_sgr_flag" Ta "" Ta "Pane mouse SGR flag"
|
||||
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
|
||||
|
6
tmux.h
6
tmux.h
@ -2126,6 +2126,8 @@ void format_defaults_paste_buffer(struct format_tree *,
|
||||
struct paste_buffer *);
|
||||
void format_lost_client(struct client *);
|
||||
char *format_grid_word(struct grid *, u_int, u_int);
|
||||
char *format_grid_hyperlink(struct grid *, u_int, u_int,
|
||||
struct screen *);
|
||||
char *format_grid_line(struct grid *, u_int);
|
||||
|
||||
/* format-draw.c */
|
||||
@ -2772,7 +2774,7 @@ void grid_clear_lines(struct grid *, u_int, u_int, u_int);
|
||||
void grid_move_lines(struct grid *, u_int, u_int, u_int, u_int);
|
||||
void grid_move_cells(struct grid *, u_int, u_int, u_int, u_int, u_int);
|
||||
char *grid_string_cells(struct grid *, u_int, u_int, u_int,
|
||||
struct grid_cell **, int, int, int);
|
||||
struct grid_cell **, int, int, int, struct screen *);
|
||||
void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
|
||||
u_int);
|
||||
void grid_reflow(struct grid *, u_int);
|
||||
@ -3312,7 +3314,7 @@ uid_t server_acl_get_uid(struct server_acl_user *);
|
||||
u_int hyperlinks_put(struct hyperlinks *, const char *,
|
||||
const char *);
|
||||
int hyperlinks_get(struct hyperlinks *, u_int,
|
||||
const char **, const char **);
|
||||
const char **, const char **, const char **);
|
||||
struct hyperlinks *hyperlinks_init(void);
|
||||
void hyperlinks_reset(struct hyperlinks *);
|
||||
void hyperlinks_free(struct hyperlinks *);
|
||||
|
2
tty.c
2
tty.c
@ -2501,7 +2501,7 @@ tty_hyperlink(struct tty *tty, const struct grid_cell *gc,
|
||||
if (hl == NULL)
|
||||
return;
|
||||
|
||||
if (gc->link == 0 || !hyperlinks_get(hl, gc->link, &uri, &id))
|
||||
if (gc->link == 0 || !hyperlinks_get(hl, gc->link, &uri, NULL, &id))
|
||||
tty_putcode_ptr2(tty, TTYC_HLS, "", "");
|
||||
else
|
||||
tty_putcode_ptr2(tty, TTYC_HLS, id, uri);
|
||||
|
Loading…
Reference in New Issue
Block a user