Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

oh my posh theme lambdageneration.omp.json draws wrongly in Chinese codepage 936 (Simplified Chinese) #406

Closed
andywowws opened this issue Jan 16, 2023 · 38 comments
Labels
bug Something isn't working

Comments

@andywowws
Copy link

After Update Clink to the latest version,it doesn't work well with oh-my-posh
Snipaste_2023-01-16_10-29-47

@andywowws
Copy link
Author

Also,Oh-my-posh works currently in powershell7
Snipaste_2023-01-16_10-35-32

@andywowws
Copy link
Author

i write
load(io.popen('oh-my-posh init cmd --config C:/Users/andyw/AppData/Local/Programs/oh-my-posh/themes/lambdageneration.omp.json'):read("*a"))()
in the oh-my-posh.lua

@chrisant996
Copy link
Owner

What is the output from chcp?

What is the full output from clink set?

@andywowws
Copy link
Author

clink set

autosuggest.async                 True
autosuggest.enable                True
autosuggest.original_case         True
autosuggest.strategy              match_prev_cmd history completion
clink.autostart
clink.autoupdate                  True
clink.colorize_input              True
clink.default_bindings            windows
clink.logo                        full
clink.max_input_rows              0
clink.paste_crlf                  crlf
clink.path
clink.promptfilter                True
clink.update_interval             5
cmd.admin_title_prefix
cmd.altf4_exits                   True
cmd.auto_answer                   off
cmd.ctrld_exits                   False
cmd.get_errorlevel                True
color.arg                         bold
color.arginfo                     sgr 38;5;172
color.argmatcher                  sgr 1;38;5;40
color.cmd                         sgr 1;38;5;231
color.cmdredir                    sgr 38;5;172
color.cmdsep                      sgr 38;5;214
color.comment_row                 sgr 38;5;87;48;5;18
color.description                 sgr 38;5;39
color.doskey                      sgr 1;38;5;75
color.executable                  sgr 1;38;5;33
color.filtered                    sgr 38;5;231
color.flag                        sgr 38;5;117
color.hidden                      sgr 38;5;160
color.histexpand                  sgr 97;48;5;55
color.horizscroll                 sgr 38;5;16;48;5;30
color.input                       sgr 38;5;222
color.interact                    bold
color.message                     default
color.modmark
color.popup
color.popup_desc
color.prompt
color.readonly                    sgr 38;5;28
color.selected_completion         sgr 38;5;16;48;5;254
color.selection                   sgr 38;5;16;48;5;179
color.suggestion                  sgr 38;5;239
color.unexpected                  default
color.unrecognized                sgr 38;5;203
debug.log_terminal                False
directories.dupe_mode             add
doskey.enhanced                   True
exec.aliases                      True
exec.commands                     True
exec.cwd                          True
exec.dirs                         True
exec.enable                       True
exec.files                        False
exec.path                         True
exec.space_prefix                 True
files.hidden                      True
files.system                      False
history.auto_expand               True
history.dont_add_to_history_cmds  exit history
history.dupe_mode                 erase_prev
history.expand_mode               not_quoted
history.ignore_space              True
history.max_lines                 25000
history.save                      True
history.shared                    False
history.sticky_search             False
history.time_format               %F %T
history.time_stamp                show
lua.break_on_error                False
lua.break_on_traceback            False
lua.debug                         False
lua.path
lua.reload_scripts                False
lua.strict                        True
lua.traceback_on_error            False
match.expand_abbrev               True
match.expand_envvars              True
match.fit_columns                 True
match.ignore_accent               True
match.ignore_case                 relaxed
match.max_fitted_matches          0
match.max_rows                    0
match.preview_rows                5
match.sort_dirs                   with
match.substring                   True
match.translate_slashes           system
match.wild                        True
prompt.async                      True
prompt.transient                  off
readline.hide_stderr              False
terminal.adjust_cursor_style      True
terminal.color_emoji              auto
terminal.differentiate_keys       False
terminal.east_asian_ambiguous     auto
terminal.emulation                auto
terminal.mouse_input              auto
terminal.mouse_modifier
terminal.raw_esc                  False
terminal.use_altgr_substitute     False

@andywowws
Copy link
Author

chcp 936

@andywowws
Copy link
Author

if I use clink below 1.4.9,this problem won't appear.
Maybe it's because clink 1.4.9 fixed the problem East Asian ambiguous width characters?

@chrisant996
Copy link
Owner

What font are you using? Is there a link where I can download it?

This has to be due to the East Asian ambiguous character width fix. I want to test with the same font you're using, to see if it's a font issue, or terminal issue, or OS issue, or Clink issue. And hopefully I can find an automatic workaround.

In the meantime, you can probably get it working by changing the terminal.east_asian_ambiguous setting.

And I just noticed the online documentation refers to inaccurate names for the available modes, so refer to clink set terminal.east_asian_ambiguous to see the correct names (I'll fix the documentation).

@chrisant996
Copy link
Owner

chrisant996 commented Jan 16, 2023

The fancy line drawing characters are in the range of East Asian ambiguous width characters.

Different terminals will draw and measure them differently, and may or may not match how the OS measures them in the hidden "real" console window that contains the underlying text and layout which terminal programs then draw into a visible window.

  • If you use the basic conhost terminal host, then they get drawn strangely: some of them are drawn as 2 character cells wide, but only move the cursor by 1 character cell, causing some of the characters to overlap strangely.
  • But Windows Terminal both draws and measures them as 1 character cell wide, at least in the three fonts that I tried.

So it's indeed the classic problem caused by the East Asian ambiguous width characters.

In recent versions of Clink, when you press Ctrl-X,Ctrl-Z it will analyze the prompt text, report characters that may be problematic, and offer suggestions for how to resolve problems that might occur. And in CJK codepages (including 936) it reports several ambiguous width characters in the prompt text when using the lambdageneration.omp.json theme.

You'll need to either use chcp 65001 to use the UTF8 codepage instead of a CJK codepage, or use clink set terminal.east_asian_ambiguous one to tell Clink to interpret the ambiguous width characters as 1 cell wide. (Theoretically, some fonts might solve the problem, but I don't know which fonts).

P.S. The reason that the default auto mode for terminal.east_asian_ambiguous isn't automatically solving the problem is because, at least for the Consolas font, the OS is reporting 0 as the console font character width. Which is another part of the problem -- the hidden "real" console window in the OS is using the "Consolas" font, but Windows Terminal or ConEmu or etc use a different font to actually draw the text in the terminal. The mismatch between fonts can cause problems. But even if the fonts were the same, some fonts report 0 as the console font character width.

@chrisant996
Copy link
Owner

... but also, the lambdageneration.omp.json theme is actually printing Unicode codepoint 0xFB26 which is the Hebrew letter Wide Final Mem , but somehow Windows Terminal ends up drawing it as though it were 0x03BB which would be the Greek small letter Lambda λ. That's very surprising behavior! ...

@chrisant996
Copy link
Owner

@andywowws I think I found a solution that will make it work automatically again, at least in most cases.

I'll finish testing it today and probably publish a new version later today.

@andywowws
Copy link
Author

I'm using Anonymice nerd font

@chrisant996
Copy link
Owner

I'm using Anonymice nerd font

Have you upgraded to v1.4.11 yet?
v1.4.11 should fix the problem.

@andywowws
Copy link
Author

yes,and it fixed!

@andywowws
Copy link
Author

But it only works in code page 65001

@chrisant996
Copy link
Owner

chrisant996 commented Jan 17, 2023

But it only works in code page 65001

@andywowws Ok, but then no, you're saying the CJK ambiguous width problems aren't fixed at all, then, for you. Codepage 65001 is not a CJK codepage, it is UTF8.

I was able to reproduce the CJK issue using the steps you provided.

I tracked it down and fixed it, and verified it no longer occurs in v1.4.11 with any of the four CJK codepages.

v1.4.11 also includes new logging about the East Asian ambiguous width character measurements.

Can you please:

  1. Reproduce the problem and then attach the clink.log file here?
  2. Share a new screen shot and description of what's happening in v1.4.11?
  3. If any of the configuration or steps have changed since the original report, can you please share the new information?

@chrisant996 chrisant996 reopened this Jan 17, 2023
@andywowws
Copy link
Author

andywowws commented Jan 17, 2023

ok
clink.log

4f58 inject                    610 ---- 2023/01/17 15:49:04.327 -------------------------------------------------
4f58 inject                    611 Injecting Clink...
4f58 inject_dll                269 Version: 1.4.11.088f68
4f58 inject_dll                270 Arch: x64
4f58 inject_dll                271 DLL: C:\Users\andyw\AppData\Local\Temp\clink\dll_cache\1.4.11.088f68_b3fc4c8f\clink_dll_x64.dll
4f58 inject_dll                273 Parent pid: 25092
4f58 check_dll_version         168 DLL version: 00010004 000b0000
4f58 inject_dll                341 Host is not interactive; cancelling inject.

clink set

autosuggest.async                 True
autosuggest.enable                True
autosuggest.original_case         True
autosuggest.strategy              match_prev_cmd history completion
clink.autostart
clink.autoupdate                  True
clink.colorize_input              True
clink.default_bindings            windows
clink.logo                        full
clink.max_input_rows              0
clink.paste_crlf                  crlf
clink.path
clink.promptfilter                True
clink.update_interval             5
cmd.admin_title_prefix
cmd.altf4_exits                   True
cmd.auto_answer                   off
cmd.ctrld_exits                   False
cmd.get_errorlevel                True
color.arg                         bold
color.arginfo                     sgr 38;5;172
color.argmatcher                  sgr 1;38;5;40
color.cmd                         sgr 1;38;5;231
color.cmdredir                    sgr 38;5;172
color.cmdsep                      sgr 38;5;214
color.comment_row                 sgr 38;5;87;48;5;18
color.description                 sgr 38;5;39
color.doskey                      sgr 1;38;5;75
color.executable                  sgr 1;38;5;33
color.filtered                    sgr 38;5;231
color.flag                        sgr 38;5;117
color.hidden                      sgr 38;5;160
color.histexpand                  sgr 97;48;5;55
color.horizscroll                 sgr 38;5;16;48;5;30
color.input                       sgr 38;5;222
color.interact                    bold
color.message                     default
color.modmark
color.popup
color.popup_desc
color.prompt
color.readonly                    sgr 38;5;28
color.selected_completion         sgr 38;5;16;48;5;254
color.selection                   sgr 38;5;16;48;5;179
color.suggestion                  sgr 38;5;239
color.unexpected                  default
color.unrecognized                sgr 38;5;203
debug.log_terminal                False
directories.dupe_mode             add
doskey.enhanced                   True
exec.aliases                      True
exec.commands                     True
exec.cwd                          True
exec.dirs                         True
exec.enable                       True
exec.files                        False
exec.path                         True
exec.space_prefix                 True
files.hidden                      True
files.system                      False
history.auto_expand               True
history.dont_add_to_history_cmds  exit history
history.dupe_mode                 erase_prev
history.expand_mode               not_quoted
history.ignore_space              True
history.max_lines                 25000
history.save                      True
history.shared                    False
history.sticky_search             False
history.time_format               %F %T
history.time_stamp                show
lua.break_on_error                False
lua.break_on_traceback            False
lua.debug                         False
lua.path
lua.reload_scripts                False
lua.strict                        True
lua.traceback_on_error            False
match.expand_abbrev               True
match.expand_envvars              True
match.fit_columns                 True
match.ignore_accent               True
match.ignore_case                 relaxed
match.max_fitted_matches          0
match.max_rows                    0
match.preview_rows                5
match.sort_dirs                   with
match.substring                   True
match.translate_slashes           system
match.wild                        True
prompt.async                      True
prompt.transient                  off
readline.hide_stderr              False
terminal.adjust_cursor_style      True
terminal.color_emoji              auto
terminal.differentiate_keys       False
terminal.east_asian_ambiguous     auto
terminal.emulation                auto
terminal.mouse_input              auto
terminal.mouse_modifier
terminal.raw_esc                  False
terminal.use_altgr_substitute     False

chcp 936
image
all the settings are still the default settings

@chrisant996
Copy link
Owner

chrisant996 commented Jan 17, 2023

@andywowws Unfortunately, that clink.log file is essentially empty, and is from a different session. It looks like you've got AutoRun enabled, and so running oh-my-posh also runs another CMD, which tries to AutoRun-inject Clink, which resets the log file.

Try the following, to capture the needed log info:

  1. Start a CMD session as usual
  2. Run set clink_noautorun=1
  3. Press Ctrl-X Ctrl-R
  4. Press Enter and confirm the problem still happens
  5. Attach the clink.log file.

In the meantime, I'll see if I can come up with a way for AutoRun during prompt filtering to not zap log files.

Depending on what the log file reveals, I also might need to add more logging.

@andywowws
Copy link
Author

andywowws commented Jan 17, 2023

I confirm that the bug still happens
clink.log

7c24 inject                    610 ---- 2023/01/17 19:09:00.604 -------------------------------------------------
7c24 inject                    611 Injecting Clink...
7c24 inject_dll                269 Version: 1.4.11.088f68
7c24 inject_dll                270 Arch: x64
7c24 inject_dll                271 DLL: C:\Users\andyw\AppData\Local\Temp\clink\dll_cache\1.4.11.088f68_b3fc4c8f\clink_dll_x64.dll
7c24 inject_dll                273 Parent pid: 24976
7c24 check_dll_version         168 DLL version: 00010004 000b0000
7c24 inject_dll                341 Host is not interactive; cancelling inject.
172c reset_handle              144 resetting mismatched stdout handle
172c reset_handle              144 resetting mismatched stderr handle
172c history_db::compact      1526 History:  41 active, 120 deleted
172c host_lua::load_scripts    158 Loaded 1 Lua scripts in 122 ms
172c reset_handle              144 resetting mismatched stdout handle
172c reset_handle              144 resetting mismatched stderr handle
172c history_db::compact      1526 History:  41 active, 120 deleted
172c reset_handle              144 resetting mismatched stdout handle
172c reset_handle              144 resetting mismatched stderr handle
172c history_db::compact      1526 History:  41 active, 120 deleted

@andywowws
Copy link
Author

Wait a minute

@andywowws
Copy link
Author

i found that east_asian_ambiguous can't automatically solve this problem but if I set east_asian_ambiguous to one the bug will be fixed

@andywowws
Copy link
Author

i've run set clink_noautorun=1

@chrisant996
Copy link
Owner

@andywowws the log file is still missing the needed info.

Are you willing to install a pre-release version of Clink with extra logging and extra logic?

If so, that would make it easy to get the needed info.

(It will even automatically upgrade to the next official release.)

@andywowws
Copy link
Author

ok

@andywowws
Copy link
Author

Unfortunatelly the log is still too short
i'm using Clink v1.1.47.c54850 now

@chrisant996
Copy link
Owner

Unfortunatelly the log is still too short i'm using Clink v1.1.47.c54850 now

"pre-release" didn't mean an old released version.

I meant would you be willing to run a new and unreleased version that I haven't released yet, where the logging has been changed to produce more information.

Here is the new pre-release version: clink.1.4.12.802320.zip

@andywowws
Copy link
Author

okay

@andywowws
Copy link
Author

i'll try it soon

@andywowws
Copy link
Author

clink.log

2848 start_logger              160 ---- 2023/01/18 13:33:00.117 -------------------------------------------------
2848 start_logger              166 Host process is 'cmd.exe' (pid 10312)
2848 start_logger              170 DLL path is 'D:\Clink'
2848 start_logger              185 Windows version 10.0.22621 (x64)
2848 start_logger              187 Clink version 1.4.12.802320 (x64)
2848 hook_setter::hook_setter  159 >>> Started hook transaction.
2848 hook_setter::attach_iat   316 Attempting to hook SetEnvironmentVariableW in IAT for module 00007FF63CBE0000.
2848 pe_info::iterate_imports  159 Found import in 'api-ms-win-core-processenvironment-l1-1-0.dll'
2848 find_iat                  124 Found import at 00007FF63CC16E98 (value is 00007FFC3C7AE5C0).
2848 hook_setter::attach_iat   316 Attempting to hook WriteConsoleW in IAT for module 00007FF63CBE0000.
2848 pe_info::iterate_imports  159 Found import in 'api-ms-win-core-console-l1-1-0.dll'
2848 find_iat                  124 Found import at 00007FF63CC16AF0 (value is 00007FFC3C772F70).
2848 hook_setter::attach_iat   316 Attempting to hook GetEnvironmentVariableW in IAT for module 00007FF63CBE0000.
2848 pe_info::iterate_imports  159 Found import in 'api-ms-win-core-processenvironment-l1-1-0.dll'
2848 find_iat                  124 Found import at 00007FF63CC16E68 (value is 00007FFC3C75BC30).
2848 hook_setter::commit       207 <<< Hook transaction committed.
2848 hook_setter::hook_setter  159 >>> Started hook transaction.
2848 hook_setter::detach_iat   359 Attempting to unhook 00007FFBB5669850 from GetEnvironmentVariableW in IAT for module 00007FF63CBE0000.
2848 pe_info::iterate_imports  159 Found import in 'api-ms-win-core-processenvironment-l1-1-0.dll'
2848 find_iat                  124 Found import at 00007FF63CC16E68 (value is 00007FFBB5669850).
2848 hook_setter::commit       207 <<< Hook transaction committed.
2848 hook_setter::hook_setter  159 >>> Started hook transaction.
2848 hook_setter::attach_iat   316 Attempting to hook ReadConsoleW in IAT for module 00007FF63CBE0000.
2848 pe_info::iterate_imports  159 Found import in 'api-ms-win-core-console-l1-1-0.dll'
2848 find_iat                  124 Found import at 00007FF63CC16AE8 (value is 00007FFC3C7E5550).
2848 hook_setter::commit       207 <<< Hook transaction committed.
2848 hook_setter::hook_setter  159 >>> Started hook transaction.
2848 hook_setter::attach_iat   316 Attempting to hook SetConsoleTitleW in IAT for module 00007FF63CBE0000.
2848 pe_info::iterate_imports  159 Found import in 'api-ms-win-core-console-l2-2-0.dll'
2848 find_iat                  124 Found import at 00007FF63CC16B48 (value is 00007FFC3C7E5FE0).
2848 hook_setter::commit       207 <<< Hook transaction committed.
2848 win_screen_buffer::begin  279 Using native terminal support; found 'Windows build >= 15063, console V2'.
2848 init_cached_font          541 console font "新宋体", cell width 10, pitch and family 0x4
2848 init_cached_font          542 East Asian Ambiguous mode 3
2848 host_lua::load_scripts    158 Loaded 2 Lua scripts in 143 ms
2848 ={update.lua}               0 Clink updater: too soon to check for updates (1673920164 vs 1674019980).
2848 reset_handle              144 resetting mismatched stdout handle
2848 reset_handle              144 resetting mismatched stderr handle
2848 history_db::initialise   1264 master bank ctag: |CTAG_1673940559_253328_31752_0
2848 history_db::compact      1526 History:  50 active, 161 deleted
2848 get_wcwidth_from_font     384 ABC:  0x256D => A 9, B 11, C 0, cell 10
2848 get_wcwidth_from_font     384 ABC:  0x2500 => A 0, B 20, C 0, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B2 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE62A => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B1 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xF240 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xF00C => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B4 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B6 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B3 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xF5EF => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0x2570 => A 9, B 11, C 0, cell 10
2848 reset_cached_font         462 resetting cached font info
2848 host_lua::load_scripts    158 Loaded 2 Lua scripts in 135 ms
2848 reset_handle              144 resetting mismatched stdout handle
2848 reset_handle              144 resetting mismatched stderr handle
2848 init_cached_font          541 console font "新宋体", cell width 10, pitch and family 0x4
2848 init_cached_font          542 East Asian Ambiguous mode 3
2848 history_db::compact      1526 History:  50 active, 161 deleted
2848 get_wcwidth_from_font     384 ABC:  0x256D => A 9, B 11, C 0, cell 10
2848 get_wcwidth_from_font     384 ABC:  0x2500 => A 0, B 20, C 0, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B2 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE62A => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B1 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xF240 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xF00C => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B4 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B6 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xE0B3 => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0xF5EF => A 0, B 1, C 19, cell 10
2848 get_wcwidth_from_font     384 ABC:  0x2570 => A 9, B 11, C 0, cell 10

@andywowws
Copy link
Author

The'新宋体' is a font that have been intergrated into Microsoft Office,and it's use to desplay chinese characters

@chrisant996
Copy link
Owner

chrisant996 commented Jan 18, 2023

2848 init_cached_font          541 console font "新宋体", cell width 10, pitch and family 0x4

The'新宋体' is a font that have been intergrated into Microsoft Office,and it's use to desplay chinese characters

Aha! That explains it. Somehow that font has become selected as the default console font from the OS's perspective, and that font draws those as double-width characters. I don't know how to change what font the OS thinks is being used (it isn't done by changing the font in the Properties page of a console window).

Unfortunately there is no way for a console program to find out what font will be used by a terminal program. There is only a way to ask the OS what the default conhost terminal thinks the font would be. That's what Clink uses in the auto and font modes of the terminal.east_asian_ambiguous setting. But Windows Terminal uses a different font, and then the measurements are out of sync.

I could maybe add a setting that could be used to tell Clink what font to expect. But it would still be easy for that to be out of sync with the actual font, and it still isn't automatic.

I can't see any way to make this automatically work "properly" in CJK codepages. The only ways I know to get it to work properly are to use chcp 65001, or use a different font, or use different characters, or configure clink set terminal.east_asian_ambiguous to match the width of the font being used.

@chrisant996 chrisant996 changed the title Doesn't work well with oh my posh oh my posh theme lambdageneration.omp.json draws wrongly in Chinese codepage 936 (Simplified Chinese) Jan 18, 2023
@chrisant996
Copy link
Owner

chrisant996 commented Jan 18, 2023

You stated that powershell7 works correctly.
I think that powershell7 will not work correctly when the input line wraps at the right margin when using that oh-my-posh theme.

But I'll try to see if I can test that (it might be difficult since I don't have Windows installed using Simplified Chinese, and I wouldn't be able to read anything if i did). And I'll try to see if the powershell7 public source code is doing something special that I can learn from.

@andywowws
Copy link
Author

Wish this annoying bug could be fixed soon.

@chrisant996
Copy link
Owner

chrisant996 commented Jan 18, 2023

@andywowws Ugh. I've looked at what the PowerShell/PSReadLine library does.

I see why PowerShell "works":

  1. It doesn't refresh the prompt or input line while the terminal is resized -- it only remembers that a resize occurred, and then next time the user types something then it refreshes the prompt and input line. But that approach can't support a right-side prompt, and Clink supports a right-side prompt.
  2. Because it doesn't refresh the prompt while the terminal is resized, it's able to print the prompt and then ask the console APIs what the current cursor column is. That's how it avoids needing to accurately measure the width of the prompt text -- it prints it and then asks the console what's the current column. That approach will garble the prompt and input line if it's used while the terminal is resizing (and Clink has to do that). Also, I see how to make PowerShell put the cursor on the wrong line in certain cases, since PowerShell doesn't actually know how to accurately measure the prompt text width or height, and therefore doesn't know how to accurately position the cursor in certain edge cases.
  3. PowerShell assumes that all of the East Asian Ambiguous width characters are 1 cell wide. That means there will be many cases where it has the exact same kind of problems as Clink has, in the input line text (and also sometimes in the prompt text, if it has East Asian Ambiguous characters and also wraps around at the right margin).

And sure enough, as expected, it turns out to be pretty easy to get PowerShell's input line display to malfunction when using any of the four CJK codepages.

  • Example 1; PowerShell goes a little wrong in the default conhost terminal, when using the lambdageneration.omp.json theme for oh-my-posh:
    image
  • Example 2; look at this screenshot using the NSimSum font, which draws the East Asian Ambiguous characters as 2 cells wide -- I pressed End to move the cursor to the end of the line, but the cursor is 3 positions to the left of the actual end of the line.
    image
  • I also found many other examples.

So, while PowerShell may give the perception that it works in CJK codepages, it's pretty easy to get it to have the same kinds of problems that Clink has (and also some problems that Clink doesn't have).

I cannot make Clink do exactly the same thing PSReadLine does; it would break many Clink capabilities that PowerShell doesn't have (and therefore doesn't have to support).

However, I can add the following hack when using any of the 4 CJK codepages. This should make it behave like PowerShell does, except while resizing the terminal:

  • By default, assume that all East Asian Ambiguous characters are 1 cell wide. This will work pretty well with terminal programs like Windows Terminal and ConEmu and etc. But it will behave badly with the default Windows conhost terminal.
  • Don't measure the prompt text width. Instead print the prompt and then ask the console what is the current cursor column. If the prompt text wraps, then the cursor row can become incorrect and the display of the prompt and input line can become garbled (which can also happen in PowerShell). This may also cause problems when quickly resizing the terminal width.

The display won't be fully reliable in some edge cases. But it will be similarly reliable as PowerShell's display. So if the perception is that PowerShell works properly, then probably the perception will also be that the hack makes Clink work properly.

@chrisant996
Copy link
Owner

chrisant996 commented Jan 18, 2023

Wish this annoying bug could be fixed soon.

@andywowws clink set terminal.east_asian_ambiguous one should make the problem go away, in your case.

Making it automatically go away for everyone in all possible cases is a much, much, much harder problem to solve. But I'm working on getting it as close to that as possible.

@chrisant996
Copy link
Owner

(Also, the technique used by PowerShell can fail if the prompt is exactly the width of the terminal. That's uncommon, but people have reported exactly that situation in Clink, and the rewrite of the prompt/input display accommodated that case. But in CJK codepages it won't be able to handle that correctly anymore, just like PowerShell isn't able to handle it correctly.)

@chrisant996
Copy link
Owner

@andywowws Can you please try this new prototype version?

clink.1.4.12.aee2cb.zip

Please also run clink set terminal.east_asian_ambiguous auto to make sure the automatic support is used (we know that one is a workaround, and it's the new auto support that needs to be tested).

The improvements

  1. In modern terminal programs using CJK code pages, East Asian Ambiguous width measurement in auto mode assumes the character widths are 1, and in the default conhost or ConsoleZ terminals it uses the current font to measure the actual character widths.
  2. When using CJK code pages, after printing the prompt Clink asks the terminal what is the current cursor position. This helps compensate for cases where the terminal draws things differently than expected.
  3. The new %CLINK_EAST_ASIAN_AMBIGUOUS% environment variable can be set to override the terminal.east_asian_ambiguous setting in a specific Clink session.

Tested cases

These improvements make the prompt and input line work for me in the following cases:

  • ConsoleZ (with Consolas and with NSimSum fonts).
  • Windows Terminal (with Consolas and with NSimSum fonts).
  • conhost (with Consolas and with NSimSum fonts).
  • ConEmu and Cmder (with Consolas and with NSimSum fonts).
  • WezTerm (with Consolas and with NSimSum fonts).

Various combinations of terminal programs and fonts draw the prompt text slightly differently, but Clink is able to make the cursor position consistently match what was drawn by the terminal program.

The "Tabby" terminal program draws the text using one set of measurements, and positions the cursor using a different set of measurements. It malfunctions with CMD.exe by itself, and also with Clink. It is clearly due to bugs in "Tabby" itself, not CMD.exe or Clink.

Also, I have found and reproduced many different cases where PowerShell malfunctions and draws the prompt or input line incorrectly. Clink has only a couple of the same problems, which are simply not fixable in either program (PowerShell or Clink) with the current console APIs in Windows. As far as I can tell in my testing, Clink is now more reliable than PowerShell when displaying prompt text and input line text when using CJK code pages (and PowerShell completely fails to handle ambiguous width characters in CJK code pages when using conhost as the terminal, but Clink works as expected in that case).

@andywowws
Copy link
Author

ohhhh,finally it works!

@chrisant996
Copy link
Owner

ohhhh,finally it works!

Excellent. Thank you for reporting the issue and for your timely responses and helping to find and verify a fix; I appreciate it very much.

I expect to publish an update with the fix probably later tonight.

@chrisant996 chrisant996 added the bug Something isn't working label Jan 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants