mirror of
https://github.com/tmux/tmux.git
synced 2025-01-07 16:28:48 +00:00
Support UTF-8 with choose-buffer, from Kosuke ASAMI. Also make
buffer_sample bigger to let it trim at window right edge.
This commit is contained in:
parent
82f3e0e9e6
commit
252a7373d6
@ -49,6 +49,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
char *action, *action_data;
|
char *action, *action_data;
|
||||||
const char *template;
|
const char *template;
|
||||||
u_int idx;
|
u_int idx;
|
||||||
|
int utf8flag;
|
||||||
|
|
||||||
if ((c = cmd_current_client(cmdq)) == NULL) {
|
if ((c = cmd_current_client(cmdq)) == NULL) {
|
||||||
cmdq_error(cmdq, "no client available");
|
cmdq_error(cmdq, "no client available");
|
||||||
@ -60,6 +61,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
|
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
|
utf8flag = options_get_number(&wl->window->options, "utf8");
|
||||||
|
|
||||||
if (paste_get_top(&global_buffers) == NULL)
|
if (paste_get_top(&global_buffers) == NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@ -79,7 +81,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
cdata->ft_template = xstrdup(template);
|
cdata->ft_template = xstrdup(template);
|
||||||
format_add(cdata->ft, "line", "%u", idx - 1);
|
format_add(cdata->ft, "line", "%u", idx - 1);
|
||||||
format_paste_buffer(cdata->ft, pb);
|
format_paste_buffer(cdata->ft, pb, utf8flag);
|
||||||
|
|
||||||
xasprintf(&action_data, "%u", idx - 1);
|
xasprintf(&action_data, "%u", idx - 1);
|
||||||
cdata->command = cmd_template_replace(action, action_data, 1);
|
cdata->command = cmd_template_replace(action, action_data, 1);
|
||||||
|
@ -55,7 +55,7 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
|
|||||||
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
|
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
|
||||||
ft = format_create();
|
ft = format_create();
|
||||||
format_add(ft, "line", "%u", idx - 1);
|
format_add(ft, "line", "%u", idx - 1);
|
||||||
format_paste_buffer(ft, pb);
|
format_paste_buffer(ft, pb, 0);
|
||||||
|
|
||||||
line = format_expand(ft, template);
|
line = format_expand(ft, template);
|
||||||
cmdq_print(cmdq, "%s", line);
|
cmdq_print(cmdq, "%s", line);
|
||||||
|
10
format.c
10
format.c
@ -601,12 +601,14 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
|
|||||||
|
|
||||||
/* Set default format keys for paste buffer. */
|
/* Set default format keys for paste buffer. */
|
||||||
void
|
void
|
||||||
format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
|
format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
|
||||||
|
int utf8flag)
|
||||||
{
|
{
|
||||||
char *pb_print = paste_print(pb, 50);
|
char *s;
|
||||||
|
|
||||||
format_add(ft, "buffer_size", "%zu", pb->size);
|
format_add(ft, "buffer_size", "%zu", pb->size);
|
||||||
format_add(ft, "buffer_sample", "%s", pb_print);
|
|
||||||
|
|
||||||
free(pb_print);
|
s = paste_make_sample(pb, utf8flag);
|
||||||
|
format_add(ft, "buffer_sample", "%s", s);
|
||||||
|
free(s);
|
||||||
}
|
}
|
||||||
|
23
paste.c
23
paste.c
@ -148,25 +148,26 @@ paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert a buffer into a visible string. */
|
/* Convert start of buffer into a nice string. */
|
||||||
char *
|
char *
|
||||||
paste_print(struct paste_buffer *pb, size_t width)
|
paste_make_sample(struct paste_buffer *pb, int utf8flag)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t len, used;
|
size_t len, used;
|
||||||
|
const int flags = VIS_OCTAL|VIS_TAB|VIS_NL;
|
||||||
if (width < 3)
|
const size_t width = 200;
|
||||||
width = 3;
|
|
||||||
buf = xmalloc(width * 4 + 1);
|
|
||||||
|
|
||||||
len = pb->size;
|
len = pb->size;
|
||||||
if (len > width)
|
if (len > width)
|
||||||
len = width;
|
len = width;
|
||||||
|
buf = xmalloc(len * 4 + 4);
|
||||||
|
|
||||||
used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
|
if (utf8flag)
|
||||||
|
used = utf8_strvis(buf, pb->data, len, flags);
|
||||||
|
else
|
||||||
|
used = strvisx(buf, pb->data, len, flags);
|
||||||
if (pb->size > width || used > width)
|
if (pb->size > width || used > width)
|
||||||
strlcpy(buf + width - 3, "...", 4);
|
strlcpy(buf + width, "...", 4);
|
||||||
|
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
tmux.1
2
tmux.1
@ -3087,7 +3087,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "alternate_on" Ta "" Ta "If pane is in alternate screen"
|
.It Li "alternate_on" Ta "" Ta "If pane is in alternate screen"
|
||||||
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
|
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
|
||||||
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
|
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
|
||||||
.It Li "buffer_sample" Ta "" Ta "First 50 characters from buffer"
|
.It Li "buffer_sample" Ta "" Ta "Sample of start of buffer"
|
||||||
.It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
|
.It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
|
||||||
.It Li "client_activity" Ta "" Ta "Integer time client last had activity"
|
.It Li "client_activity" Ta "" Ta "Integer time client last had activity"
|
||||||
.It Li "client_activity_string" Ta "" Ta "String time client last had activity"
|
.It Li "client_activity_string" Ta "" Ta "String time client last had activity"
|
||||||
|
7
tmux.h
7
tmux.h
@ -85,7 +85,7 @@ extern char **environ;
|
|||||||
|
|
||||||
/* Default template for choose-buffer. */
|
/* Default template for choose-buffer. */
|
||||||
#define CHOOSE_BUFFER_TEMPLATE \
|
#define CHOOSE_BUFFER_TEMPLATE \
|
||||||
"#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
|
"#{line}: #{buffer_size} bytes: #{buffer_sample}"
|
||||||
|
|
||||||
/* Default template for choose-client. */
|
/* Default template for choose-client. */
|
||||||
#define CHOOSE_CLIENT_TEMPLATE \
|
#define CHOOSE_CLIENT_TEMPLATE \
|
||||||
@ -1544,7 +1544,7 @@ void format_winlink(struct format_tree *, struct session *,
|
|||||||
void format_window_pane(struct format_tree *,
|
void format_window_pane(struct format_tree *,
|
||||||
struct window_pane *);
|
struct window_pane *);
|
||||||
void format_paste_buffer(struct format_tree *,
|
void format_paste_buffer(struct format_tree *,
|
||||||
struct paste_buffer *);
|
struct paste_buffer *, int);
|
||||||
|
|
||||||
/* mode-key.c */
|
/* mode-key.c */
|
||||||
extern const struct mode_key_table mode_key_tables[];
|
extern const struct mode_key_table mode_key_tables[];
|
||||||
@ -1714,7 +1714,7 @@ int paste_free_top(struct paste_stack *);
|
|||||||
int paste_free_index(struct paste_stack *, u_int);
|
int paste_free_index(struct paste_stack *, u_int);
|
||||||
void paste_add(struct paste_stack *, char *, size_t, u_int);
|
void paste_add(struct paste_stack *, char *, size_t, u_int);
|
||||||
int paste_replace(struct paste_stack *, u_int, char *, size_t);
|
int paste_replace(struct paste_stack *, u_int, char *, size_t);
|
||||||
char *paste_print(struct paste_buffer *, size_t);
|
char *paste_make_sample(struct paste_buffer *, int);
|
||||||
void paste_send_pane(struct paste_buffer *, struct window_pane *,
|
void paste_send_pane(struct paste_buffer *, struct window_pane *,
|
||||||
const char *, int);
|
const char *, int);
|
||||||
|
|
||||||
@ -2326,6 +2326,7 @@ int utf8_open(struct utf8_data *, u_char);
|
|||||||
int utf8_append(struct utf8_data *, u_char);
|
int utf8_append(struct utf8_data *, u_char);
|
||||||
u_int utf8_combine(const struct utf8_data *);
|
u_int utf8_combine(const struct utf8_data *);
|
||||||
u_int utf8_split2(u_int, u_char *);
|
u_int utf8_split2(u_int, u_char *);
|
||||||
|
int utf8_strvis(char *, const char *, size_t, int);
|
||||||
|
|
||||||
/* procname.c */
|
/* procname.c */
|
||||||
char *get_proc_name(int, char *);
|
char *get_proc_name(int, char *);
|
||||||
|
43
utf8.c
43
utf8.c
@ -19,6 +19,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <vis.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@ -350,3 +351,45 @@ utf8_width(const struct utf8_data *utf8data)
|
|||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode len characters from src into dst, which is guaranteed to have four
|
||||||
|
* bytes available for each character from src (for \abc or UTF-8) plus space
|
||||||
|
* for \0.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
utf8_strvis(char *dst, const char *src, size_t len, int flag)
|
||||||
|
{
|
||||||
|
struct utf8_data utf8data;
|
||||||
|
const char *start, *end;
|
||||||
|
int more;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
start = dst;
|
||||||
|
end = src + len;
|
||||||
|
|
||||||
|
while (src < end) {
|
||||||
|
if (utf8_open(&utf8data, *src)) {
|
||||||
|
more = 1;
|
||||||
|
while (++src < end && more)
|
||||||
|
more = utf8_append(&utf8data, *src);
|
||||||
|
if (!more) {
|
||||||
|
/* UTF-8 character finished. */
|
||||||
|
for (i = 0; i < utf8data.size; i++)
|
||||||
|
*dst++ = utf8data.data[i];
|
||||||
|
continue;
|
||||||
|
} else if (utf8data.have > 0) {
|
||||||
|
/* Not a complete UTF-8 character. */
|
||||||
|
src -= utf8data.have;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (src < end - 1)
|
||||||
|
dst = vis(dst, src[0], flag, src[1]);
|
||||||
|
else if (src < end)
|
||||||
|
dst = vis(dst, src[0], flag, '\0');
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = '\0';
|
||||||
|
return (dst - start);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user