mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +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:
		| @@ -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)); | ||||
| } | ||||
|   | ||||
							
								
								
									
										64
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								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]; | ||||
| 	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,6 +188,9 @@ 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); | ||||
| 	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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm