Add an option variation-selector-always-wide to instruct tmux not to

always interpret VS16 as a wide character and assume the terminal does
likewise. This is behaviour seen in a number of newer terminals' Unicode
14 support but not in older terminals; it seems to be a little
contentious and is currently difficult to detect.

Probably in the long run tmux should pick a behaviour, look at a (new)
terminfo(5) capability to tell it what the terminal will do, and emulate
as required, but at this point I'm not sure that is worth it for
something where support is mixed, seems to be in flux, and that mostly
only matters for emojis.

GitHub issues 3923 and 4475 and others before that.
This commit is contained in:
nicm
2025-05-01 07:12:00 +00:00
parent 1926c1b683
commit 6106a0f2c4
3 changed files with 32 additions and 17 deletions

View File

@ -406,7 +406,7 @@ const struct options_table_entry options_table[] = {
.choices = options_table_popup_border_lines_list,
.default_num = BOX_LINES_SINGLE,
.text = "Type of characters used to draw menu border lines. Some of "
"these are only supported on terminals with UTF-8 support."
"these are only supported on terminals with UTF-8 support."
},
{ .name = "message-limit",
@ -426,7 +426,7 @@ const struct options_table_entry options_table[] = {
.default_num = 0,
.unit = "milliseconds",
.text = "The timeout for the prefix key if no subsequent key is "
"pressed. Zero means disabled."
"pressed. Zero means disabled."
},
{ .name = "prompt-history-limit",
@ -463,7 +463,7 @@ const struct options_table_entry options_table[] = {
.flags = OPTIONS_TABLE_IS_ARRAY,
.default_str = "xterm*:clipboard:ccolour:cstyle:focus:title,"
"screen*:title,"
"rxvt*:ignorefkeys",
"rxvt*:ignorefkeys",
.separator = ",",
.text = "List of terminal features, used if they cannot be "
"automatically detected."
@ -480,6 +480,14 @@ const struct options_table_entry options_table[] = {
"'User0', 'User1' and so on."
},
{ .name = "variation-selector-always-wide",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_SERVER,
.default_num = 1,
.text = "If the Unicode VS16 codepoint should always be treated as a "
"wide character."
},
/* Session options. */
{ .name = "activity-action",
.type = OPTIONS_TABLE_CHOICE,
@ -612,8 +620,8 @@ const struct options_table_entry options_table[] = {
.default_num = 0,
.unit = "milliseconds",
.text = "Time to wait for a key binding to repeat the first time the "
"key is pressed, if it is bound with the '-r' flag. "
"Subsequent presses use the 'repeat-time' option."
"key is pressed, if it is bound with the '-r' flag. "
"Subsequent presses use the 'repeat-time' option."
},
{ .name = "key-table",
@ -1034,11 +1042,11 @@ const struct options_table_entry options_table[] = {
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "#[align=right]"
"#{t/p:top_line_time}#{?#{e|>:#{top_line_time},0}, ,}"
"[#{scroll_position}/#{history_size}]"
"#{?search_timed_out, (timed out),"
"#{?search_count, (#{search_count}"
"#{?search_count_partial,+,} results),}}",
"#{t/p:top_line_time}#{?#{e|>:#{top_line_time},0}, ,}"
"[#{scroll_position}/#{history_size}]"
"#{?search_timed_out, (timed out),"
"#{?search_count, (#{search_count}"
"#{?search_count_partial,+,} results),}}",
.text = "Format of the position indicator in copy mode."
},
@ -1235,7 +1243,7 @@ const struct options_table_entry options_table[] = {
.text = "Pane scrollbar position."
},
{ .name = "popup-style",
{ .name = "popup-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "default",
@ -1276,12 +1284,12 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "Pane is dead ("
"#{?#{!=:#{pane_dead_status},},"
"status #{pane_dead_status},}"
"status #{pane_dead_status},}"
"#{?#{!=:#{pane_dead_signal},},"
"signal #{pane_dead_signal},}, "
"signal #{pane_dead_signal},}, "
"#{t:pane_dead_time})",
.text = "Message shown after the program in a pane has exited, if "
"remain-on-exit is enabled."
"remain-on-exit is enabled."
},
{ .name = "scroll-on-clear",

View File

@ -2010,9 +2010,11 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
*/
if (utf8_is_zwj(ud))
zero_width = 1;
else if (utf8_is_vs(ud))
zero_width = force_wide = 1;
else if (ud->width == 0)
else if (utf8_is_vs(ud)) {
zero_width = 1;
if (options_get_number(global_options, "variation-selector-always-wide"))
force_wide = 1;
} else if (ud->width == 0)
zero_width = 1;
/* Cannot combine empty character or at left. */

5
tmux.1
View File

@ -4392,6 +4392,11 @@ For example:
set -s user-keys[0] "\ee[5;30012\[ti]"
bind User0 resize-pane -L 3
.Ed
.It Xo Ic variation-selector-always-wide
.Op Ic on | off
.Xc
Always treat Unicode variation selector 16 as marking a wide character.
This is a feature of some terminals as part of their Unicode 14 support.
.El
.Pp
Available session options are: