diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index 6be3d9575..f711b3b48 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -858,6 +858,8 @@ The user can change the settings of `fish` by changing the values of certain var
- `fish_emoji_width` controls the computed width of certain characters, in particular emoji, whose rendered width varies across terminal emulators. This should be set to 1 if your terminal emulator renders emoji single-width, or 2 if double-width. Set this only if you see graphical glitching when printing emoji.
+- `fish_ambiguous_width` controls the computed width of ambiguous East Asian characters. This should be set to 1 if your terminal emulator renders these characters as single-width (typical), or 2 if double-width.
+
- `fish_escape_delay_ms` overrides the default timeout of 300ms (default key bindings) or 10ms (vi key bindings) after seeing an escape character before giving up on matching a key binding. See the documentation for the bind builtin command. This delay facilitates using escape as a meta key.
- `fish_greeting`, the greeting message printed on startup.
diff --git a/src/env.cpp b/src/env.cpp
index 5b57f7a1a..77f65b7bc 100644
--- a/src/env.cpp
+++ b/src/env.cpp
@@ -788,6 +788,16 @@ static void handle_change_emoji_width(const wcstring &op, const wcstring &var_na
g_fish_emoji_width = std::max(0, new_width);
}
+static void handle_change_ambiguous_width(const wcstring &op, const wcstring &var_name) {
+ (void)op;
+ (void)var_name;
+ int new_width = 1;
+ if (auto width_str = env_get(L"fish_ambiguous_width")) {
+ new_width = fish_wcstol(width_str->as_string().c_str());
+ }
+ g_fish_ambiguous_width = std::max(0, new_width);
+}
+
static void handle_term_size_change(const wcstring &op, const wcstring &var_name) {
UNUSED(op);
UNUSED(var_name);
@@ -860,6 +870,7 @@ static void setup_var_dispatch_table() {
var_dispatch_table.emplace(L"fish_term24bit", handle_fish_term_change);
var_dispatch_table.emplace(L"fish_escape_delay_ms", handle_escape_delay_change);
var_dispatch_table.emplace(L"fish_emoji_width", handle_change_emoji_width);
+ var_dispatch_table.emplace(L"fish_ambiguous_width", handle_change_ambiguous_width);
var_dispatch_table.emplace(L"LINES", handle_term_size_change);
var_dispatch_table.emplace(L"COLUMNS", handle_term_size_change);
var_dispatch_table.emplace(L"fish_complete_path", handle_complete_path_change);
diff --git a/src/fallback.cpp b/src/fallback.cpp
index bfccb7941..42a9d62d2 100644
--- a/src/fallback.cpp
+++ b/src/fallback.cpp
@@ -249,6 +249,10 @@ int killpg(int pgr, int sig) {
}
#endif
+// Width of ambiguous characters. 1 is typical default.
+int g_fish_ambiguous_width = 1;
+
+// Width of emoji characters.
int g_fish_emoji_width = 0;
// 1 is the typical emoji width in Unicode 8.
@@ -289,8 +293,10 @@ int fish_wcwidth(wchar_t wc) {
// Fall back to system wcwidth in this case.
return wcwidth(wc);
case widechar_ambiguous:
+ return g_fish_ambiguous_width;
case widechar_private_use:
- return 1;
+ // TR11: "All private-use characters are by default classified as Ambiguous".
+ return g_fish_ambiguous_width;
case widechar_widened_in_9:
return fish_get_emoji_width(wc);
default:
diff --git a/src/fallback.h b/src/fallback.h
index 4647a6f67..44ddee398 100644
--- a/src/fallback.h
+++ b/src/fallback.h
@@ -16,6 +16,9 @@
// substitution if wchar.h is included after this header.
#include // IWYU pragma: keep
+/// The column width of ambiguous East Asian characters.
+extern int g_fish_ambiguous_width;
+
/// The column width of emoji characters. This must be configurable because the value changed
/// between Unicode 8 and Unicode 9, wcwidth() is emoji-ignorant, and terminal emulators do
/// different things. See issues like #4539 and https://github.com/neovim/neovim/issues/4976 for how