Bash command line editing gets wrong cursor position #19523

Closed
opened 2026-01-31 06:46:00 +00:00 by claunia · 36 comments
Owner

Originally created by @dwmuller on GitHub (Mar 12, 2023).

Windows Terminal version

1.16.10262.0

Windows build number

10.0.22621.1265

Other Software

GNU bash, version 5.2.12(1)-release (x86_64-pc-msys)
Oh My Posh version 14.12.0 via winget pkg JanDeDobbeleer.OhMyPosh (only indirectly relevant)

Steps to reproduce

I am using Oh My Posh to generate complex command line prompts in bash. When browsing command line history, the text input cursor often gets stuck two characters to the right of where it should go, leaving two characters stuck at the start of the command line. These characters are not in the edit buffer, but command line editing is messed up because the position on the screen and in the edit buffer apparently no longer match.

I experimented a bit and the effect seems to be triggered by recalling command lines of a certain length in the history list. I think Oh My Posh is actually irrelevant to the problem, although the prompt it generates probably is. I got a repeatable state using this PS1 prompt:

PS1=\[ESC[38;2;0;119;194m\]<U+E0B6>\[ESC[0m\]\[ESC[48;2;0;119;194m\]\[ESC[38;2;255;255;255m\] <U+E62A> \[ESC[0m\]\[ESC[48;2;0;119;194m\]\[ESC[38;2;255;255;255m\] bash \[ESC[0m\]\[ESC[0m
ESC[38;2;1;87;155;49mESC[7m\]<U+E0B0>\[ESC[0m\]\[ESC[48;2;1;87;155m\]\[ESC[38;2;255;255;255m\] ~ \[ESC[0m\]\[ESC[38;2;1;87;155m\]<U+E0B0>\[ESC[0m\]\[ESC[1000C\]\[ESC[10D\]\[ESC[38;2;73;64;79m\]<U+E0B6>\[ESC[0m\]\[ESC[48;2;73;64;79m\]\[ESC[38;2;255;255;255m\] 2.574s \[ESC[0m\]\[ESC[38;2;73;64;79m\]<U+E0B4>\[ESC[0m\] \[ESC[38;2;255;255;255m\]danm@PEGASUS \[ESC[0m\]\[ESC[0m\]\[ESC[38;2;255;255;255m\]❯ \[ESC[0m\]\[ESC]0;^G\]\[ESC]9;9;C:\Users\danmESC\\\]

I checked the prompt carefully, and all non-printing sequences seem to be properly wrapped with matching [..]. I was suspicious of the OSC 9;9 sequence at the end, but removing it does not fix the problem.

Enter this command:
echo 67890123678901

Now recall the command with up-arrow, then go back to an empty line with down-arrow. The characters "ec" will appear on the command line, with the text cursor after them, but if you enter a new command you'll find that the "ec" text is not part of the edit buffer. Repeating this with an echo command one character shorter does not produce this effect.

Other possibly relevant environment variables:
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.webp=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:
TERM=xterm-256color

Expected Behavior

When recalling bash history, simply recalling the last command and then dismissing it should always leave the input line clear after the prompt, and the text cursor immediately after the prompt text.

Actual Behavior

Under some conditions, recalling history text and then dismissing it leaves extraneous characters on the current command line after the prompt, and the text cursor is positioned after them.

Originally created by @dwmuller on GitHub (Mar 12, 2023). ### Windows Terminal version 1.16.10262.0 ### Windows build number 10.0.22621.1265 ### Other Software GNU bash, version 5.2.12(1)-release (x86_64-pc-msys) Oh My Posh version 14.12.0 via winget pkg JanDeDobbeleer.OhMyPosh (only indirectly relevant) ### Steps to reproduce I am using Oh My Posh to generate complex command line prompts in bash. When browsing command line history, the text input cursor often gets stuck two characters to the right of where it should go, leaving two characters stuck at the start of the command line. These characters are not in the edit buffer, but command line editing is messed up because the position on the screen and in the edit buffer apparently no longer match. I experimented a bit and the effect seems to be triggered by recalling command lines of a certain length in the history list. I think Oh My Posh is actually irrelevant to the problem, although the prompt it generates probably is. I got a repeatable state using this PS1 prompt: ``` PS1=\[ESC[38;2;0;119;194m\]<U+E0B6>\[ESC[0m\]\[ESC[48;2;0;119;194m\]\[ESC[38;2;255;255;255m\] <U+E62A> \[ESC[0m\]\[ESC[48;2;0;119;194m\]\[ESC[38;2;255;255;255m\] bash \[ESC[0m\]\[ESC[0m ESC[38;2;1;87;155;49mESC[7m\]<U+E0B0>\[ESC[0m\]\[ESC[48;2;1;87;155m\]\[ESC[38;2;255;255;255m\] ~ \[ESC[0m\]\[ESC[38;2;1;87;155m\]<U+E0B0>\[ESC[0m\]\[ESC[1000C\]\[ESC[10D\]\[ESC[38;2;73;64;79m\]<U+E0B6>\[ESC[0m\]\[ESC[48;2;73;64;79m\]\[ESC[38;2;255;255;255m\] 2.574s \[ESC[0m\]\[ESC[38;2;73;64;79m\]<U+E0B4>\[ESC[0m\] \[ESC[38;2;255;255;255m\]danm@PEGASUS \[ESC[0m\]\[ESC[0m\]\[ESC[38;2;255;255;255m\]❯ \[ESC[0m\]\[ESC]0;^G\]\[ESC]9;9;C:\Users\danmESC\\\] ``` I checked the prompt carefully, and all non-printing sequences seem to be properly wrapped with matching \[..\]. I was suspicious of the OSC 9;9 sequence at the end, but removing it does not fix the problem. Enter this command: echo 67890123678901 Now recall the command with up-arrow, then go back to an empty line with down-arrow. The characters "ec" will appear on the command line, with the text cursor after them, but if you enter a new command you'll find that the "ec" text is not part of the edit buffer. Repeating this with an echo command one character shorter does not produce this effect. Other possibly relevant environment variables: LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36: TERM=xterm-256color ### Expected Behavior When recalling bash history, simply recalling the last command and then dismissing it should always leave the input line clear after the prompt, and the text cursor immediately after the prompt text. ### Actual Behavior Under some conditions, recalling history text and then dismissing it leaves extraneous characters on the current command line after the prompt, and the text cursor is positioned after them.
Author
Owner

@zadjii-msft commented on GitHub (Mar 13, 2023):

I bet it's the unicode characters - I'd reckon one is one of those "renders two wide but is technically one wide", or something like that.

  • <U+E0B6> \uE0B6 image
  • <U+E62A> \uE62A
  • <U+E0B0> \uE0B0 image
  • <U+E0B4> \uE0B4

Oh they're all powerline characters aren't they...

@zadjii-msft commented on GitHub (Mar 13, 2023): I bet it's the unicode characters - I'd reckon one is one of those "renders two wide but is technically one wide", or something like that. * <U+E0B6> `\uE0B6` ![image](https://user-images.githubusercontent.com/18356694/224690426-e88dc8b3-f8f9-466d-ae94-83cd23e04c53.png) * <U+E62A> `\uE62A` * <U+E0B0> `\uE0B0` ![image](https://user-images.githubusercontent.com/18356694/224690507-603a34d7-92d5-41a2-818c-ba6f427b38a7.png) * <U+E0B4> `\uE0B4` Oh they're all powerline characters aren't they...
Author
Owner

@carlos-zamora commented on GitHub (Mar 16, 2023):

Hi @dwmuller. We're having trouble visualizing this. Would you mind capturing a screen recording of the issue to help us out?

@carlos-zamora commented on GitHub (Mar 16, 2023): Hi @dwmuller. We're having trouble visualizing this. Would you mind capturing a screen recording of the issue to help us out?
Author
Owner

@zadjii-msft commented on GitHub (Mar 16, 2023):

Also, what's the literal text of your bashrc? that might help debug

@zadjii-msft commented on GitHub (Mar 16, 2023): Also, what's the literal text of your bashrc? that might help debug
Author
Owner

@dwmuller commented on GitHub (Mar 20, 2023):

Oh, you didn't really want to see my literal .bashrc:

danm@DanBook ❯ cat .bashrc
# .bashrc
# This file is read by BASH at startup of non-login interactive
# shells and, usually, non-interactive shells. It should be used for
# BASH-specific definitions, and for things like aliases and functions
# which are not inherited by child processes.

source ~/.shell/introspect.sh
source ~/.shell/functions.sh
source ~/.bash/settings.bash
source ~/.shell/bootstrap.sh
source ~/.shell/external.sh
source ~/.shell/aliases.sh
source ~/.bash/prompt.bash
source ~/.bash/completions.bash
source ~/.nvm/nvm.sh
source ~/.nvm/bash_completion

The only sourced file likely to have an effect on history scrolling is settings.bash, which contains this:

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# Check the window size after each command and update the values
# of LINES and COLUMNS if necessary.
shopt -s checkwinsize

I tried to get a video of it using Win11's built-in snipping tool, but kept ending up with a file that was way too large to attach here. Open to suggestions on how to do that.

Here are some static pix with explanations. First, context, showing the last four lines of history. The history command entered here was prefixed by a space to keep it from being added to the tail of the history list:

image

Then, I pressed pressed ^L to clear the terminal, and pressed the up arrow once:

image

Then I press up-arrow again:
image

And up-arrow a third time, now you can see the problem:
image

The spurious "ec" prefix is now sticky. Down-arrow twice, and hit enter to prove that what's actually in the edit buffer is "ls", not "ecls":
image

Hopefully that clarifies. Any command that's long enough triggers the problem.

@dwmuller commented on GitHub (Mar 20, 2023): Oh, you didn't really want to see my literal .bashrc: ``` danm@DanBook ❯ cat .bashrc # .bashrc # This file is read by BASH at startup of non-login interactive # shells and, usually, non-interactive shells. It should be used for # BASH-specific definitions, and for things like aliases and functions # which are not inherited by child processes. source ~/.shell/introspect.sh source ~/.shell/functions.sh source ~/.bash/settings.bash source ~/.shell/bootstrap.sh source ~/.shell/external.sh source ~/.shell/aliases.sh source ~/.bash/prompt.bash source ~/.bash/completions.bash source ~/.nvm/nvm.sh source ~/.nvm/bash_completion ``` The only sourced file likely to have an effect on history scrolling is settings.bash, which contains this: ``` # don't put duplicate lines or lines starting with space in the history. # See bash(1) for more options HISTCONTROL=ignoreboth # append to the history file, don't overwrite it shopt -s histappend # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) HISTSIZE=1000 HISTFILESIZE=2000 # Check the window size after each command and update the values # of LINES and COLUMNS if necessary. shopt -s checkwinsize ``` I tried to get a video of it using Win11's built-in snipping tool, but kept ending up with a file that was way too large to attach here. Open to suggestions on how to do that. Here are some static pix with explanations. First, context, showing the last four lines of history. The history command entered here was prefixed by a space to keep it from being added to the tail of the history list: ![image](https://user-images.githubusercontent.com/17508429/226469600-f862eadd-784a-4e9e-b3a4-c1b02aadb048.png) Then, I pressed pressed ^L to clear the terminal, and pressed the up arrow once: ![image](https://user-images.githubusercontent.com/17508429/226470094-4c6a9b4f-3cd6-4bfa-8592-aae7e569b8bf.png) Then I press up-arrow again: ![image](https://user-images.githubusercontent.com/17508429/226470231-d06ad4be-6409-4cde-b1f6-7f8bb87cf9fd.png) And up-arrow a third time, now you can see the problem: ![image](https://user-images.githubusercontent.com/17508429/226470343-3803a2f1-0caa-45f5-8dc9-67e14b64d04b.png) The spurious "ec" prefix is now sticky. Down-arrow twice, and hit enter to prove that what's _actually_ in the edit buffer is "ls", not "ecls": ![image](https://user-images.githubusercontent.com/17508429/226470525-1f2cab07-aee8-420e-9228-ad3bfa8befa5.png) Hopefully that clarifies. Any command that's long enough triggers the problem.
Author
Owner

@DHowett commented on GitHub (Mar 22, 2023):

Okay, so, there's one weird thing I couldn't account for...

Your PS1 has a newline in it that seems like it is guarded by \[ and \]. If I do that, I get an unprintable character right after the newline (bash 5.0.3). I wonder if that's related...

Reconstructing your actual PS1 from the version you shared was definitely challenging. 😄

@DHowett commented on GitHub (Mar 22, 2023): Okay, so, there's one weird thing I couldn't account for... Your `PS1` has a newline in it that seems like it is guarded by `\[` and `\]`. If I do that, I get an unprintable character right after the newline (bash 5.0.3). I wonder if that's related... Reconstructing your actual `PS1` from the version you shared was definitely challenging. :smile:
Author
Owner

@dwmuller commented on GitHub (Mar 23, 2023):

Reconstructing your actual PS1 from the version you shared was definitely challenging. 😄

I promise you, there is no way in hell that I could have created that PS1 value by hand. That's all courtesy of Oh My Posh. (Which, BTW, I made sure to update before I began documenting this problem.)

@dwmuller commented on GitHub (Mar 23, 2023): > Reconstructing your actual `PS1` from the version you shared was definitely challenging. 😄 I promise you, there is no way in hell that I could have created that PS1 value by hand. That's all courtesy of Oh My Posh. (Which, BTW, I made sure to update before I began documenting this problem.)
Author
Owner

@dwmuller commented on GitHub (Mar 23, 2023):

BTW, although I won't bore you with the whole of my ~/.bash/prompt.bash, because it has some conditional logic for different environments, in a Bash for Windows shell the key command in that file which sets up the prompt is this:

eval "$(oh-my-posh --init --shell bash --config ~/.config.omp.json)"

If you actually start mucking around with oh-my-posh, I can share the config file with you as well.

@dwmuller commented on GitHub (Mar 23, 2023): BTW, although I won't bore you with the whole of my ~/.bash/prompt.bash, because it has some conditional logic for different environments, in a Bash for Windows shell the key command in that file which sets up the prompt is this: ``` eval "$(oh-my-posh --init --shell bash --config ~/.config.omp.json)" ``` If you actually start mucking around with oh-my-posh, I can share the config file with you as well.
Author
Owner

@DHowett commented on GitHub (Mar 29, 2023):

Before I get into your OMP config (I'm glad you didn't write that yourself, it's a monster!), mind if I ask a couple followups?

  • Does this happen in the traditional windows console?
    • What about with TERM set to xterm?
    • ...set to cygwin?
  • Does this happen in mintty, the terminal emulator that comes with MSYS/Git Bash?
@DHowett commented on GitHub (Mar 29, 2023): Before I get into your OMP config (I'm glad you didn't write that yourself, it's a monster!), mind if I ask a couple followups? * Does this happen in the traditional windows console? * What about with `TERM` set to `xterm`? * ...set to `cygwin`? * Does this happen in mintty, the terminal emulator that comes with MSYS/Git Bash?
Author
Owner

@dwmuller commented on GitHub (Mar 30, 2023):

Excellent questions.

After export TERM=xterm: The problem still occurs.
After export TERM=cygwin: The problem still occurs.
Using mintty aka "Git Bash": The problem does not occur.

Tried the default Windows terminal, running bash under CMD. The problem does not occur.

Tried a very similar environment in WSL Ubuntu through Windows Terminal. The problem does not occur.

Note that the exact length of command needed to trigger the problem seems to vary a bit. The echo 6789012345678901 was not quite long enough sometimes. I don't know what causes the variation. But there's usually something long enough in my history buffer to trigger it.

@dwmuller commented on GitHub (Mar 30, 2023): Excellent questions. After `export TERM=xterm`: The problem still occurs. After `export TERM=cygwin`: The problem still occurs. Using mintty aka "Git Bash": The problem does not occur. Tried the default Windows terminal, running bash under CMD. The problem does not occur. Tried a very similar environment in WSL Ubuntu through Windows Terminal. The problem does not occur. Note that the exact length of command needed to trigger the problem seems to vary a bit. The `echo 6789012345678901` was not quite long enough sometimes. I don't know what causes the variation. But there's usually _something_ long enough in my history buffer to trigger it.
Author
Owner

@dwmuller commented on GitHub (Mar 30, 2023):

I thought it was interesting that the problem didn't appear in a Terminal window running bash on WSL Ubuntu. There may be some differences in the PS1 generated for the two environments by Oh My Posh and my configuration. It's hard to compare them directly because graphic characters are displayed differently in the two environments. So I tried URL encoding them (I have a urlencode utility handy) using urlencode "$PS1". Here is the result, first from the Windows environment, then from the WSL environment:

%5C%5B%1B%5B38%3B2%3B0%3B119%3B194m%5C%5D%EE%82%B6%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%EE%98%AA%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20bash%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155%3B49m%1B%5B7m%5C%5D%EE%82%B0%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%7E%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155m%5C%5D%EE%82%B0%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B1000C%1B%5B10D%1B%5B38%3B2%3B73%3B64%3B79m%EE%82%B6%1B%5B0m%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%200%2E111s%20%1B%5B0m%1B%5B38%3B2%3B73%3B64%3B79m%EE%82%B4%1B%5B0m%5C%5D%20%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5Ddanm%40DanBook%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%E2%9D%AF%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5D0%3B%07%5C%5D%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5D9%3B9%3B%22C%3A%5CUsers%5Cdanm%22%1B%5C%5C%5C%5D%20%2Dn

%5C%5B%1B%5B38%3B2%3B0%3B119%3B194m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5DWSL%20%2D%20%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5Dbash%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155%3B49m%1B%5B7m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%7E%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B1000C%5C%5D%5C%5B%1B%5B9D%5C%5D%5C%5B%1B%5B38%3B2%3B73%3B64%3B79m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D0%2E336%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B73%3B64%3B79m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%20%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5Ddanm%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%40%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5DDanBook%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5D9%3B9%3B%22%2F%2Fwsl%2Elocalhost%2FUbuntu%2Fhome%2Fdanm%22%1B%5C%5C%5C%5D%20%2Dn

TERM is set to xterm-256color in both of these environments.

Some differences are expected, because the prompts are visually different to signify the different environments:

image

versus:
image

And I just noticed that the greater-than sign isn't displaying in the WSL environment. Odd.

@dwmuller commented on GitHub (Mar 30, 2023): I thought it was interesting that the problem didn't appear in a Terminal window running bash on WSL Ubuntu. There may be some differences in the PS1 generated for the two environments by Oh My Posh and my configuration. It's hard to compare them directly because graphic characters are displayed differently in the two environments. So I tried URL encoding them (I have a urlencode utility handy) using `urlencode "$PS1"`. Here is the result, first from the Windows environment, then from the WSL environment: ``` %5C%5B%1B%5B38%3B2%3B0%3B119%3B194m%5C%5D%EE%82%B6%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%EE%98%AA%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20bash%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155%3B49m%1B%5B7m%5C%5D%EE%82%B0%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%7E%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155m%5C%5D%EE%82%B0%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B1000C%1B%5B10D%1B%5B38%3B2%3B73%3B64%3B79m%EE%82%B6%1B%5B0m%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%200%2E111s%20%1B%5B0m%1B%5B38%3B2%3B73%3B64%3B79m%EE%82%B4%1B%5B0m%5C%5D%20%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5Ddanm%40DanBook%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%E2%9D%AF%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5D0%3B%07%5C%5D%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5D9%3B9%3B%22C%3A%5CUsers%5Cdanm%22%1B%5C%5C%5C%5D%20%2Dn %5C%5B%1B%5B38%3B2%3B0%3B119%3B194m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5DWSL%20%2D%20%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5Dbash%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B0%3B119%3B194m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155%3B49m%1B%5B7m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%7E%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B1%3B87%3B155m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B1%3B87%3B155m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B1000C%5C%5D%5C%5B%1B%5B9D%5C%5D%5C%5B%1B%5B38%3B2%3B73%3B64%3B79m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D0%2E336%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B48%3B2%3B73%3B64%3B79m%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B73%3B64%3B79m%5C%5D%00%5C%5B%1B%5B0m%5C%5D%20%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5Ddanm%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%40%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5DDanBook%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B38%3B2%3B255%3B255%3B255m%5C%5D%20%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5B0m%5C%5D%5C%5B%1B%5D9%3B9%3B%22%2F%2Fwsl%2Elocalhost%2FUbuntu%2Fhome%2Fdanm%22%1B%5C%5C%5C%5D%20%2Dn ``` TERM is set to xterm-256color in both of these environments. Some differences are expected, because the prompts are visually different to signify the different environments: ![image](https://user-images.githubusercontent.com/17508429/228852256-21b99374-d483-4612-952b-5317802ab78c.png) versus: ![image](https://user-images.githubusercontent.com/17508429/228852380-ce4c5cc4-c851-45ed-a301-ed0931dbcaff.png) And I just noticed that the greater-than sign isn't displaying in the WSL environment. Odd.
Author
Owner

@DHowett commented on GitHub (Apr 27, 2023):

I just cannot come up with a rational reason that this would be happening! Ugh!

Time to pull out all the stops, I guess. Would you mind capturing a trace with the debug tap enabled? It shows off the communication between the console API translator and the Terminal. It's not conclusive, but it sure is enlightening.

@DHowett commented on GitHub (Apr 27, 2023): I just _cannot_ come up with a rational reason that this would be happening! Ugh! Time to pull out all the stops, I guess. Would you mind capturing a trace with the [debug tap](https://github.com/microsoft/terminal/wiki/Enabling-the-debug-tap) enabled? It shows off the communication between the console API translator and the Terminal. It's not conclusive, but it sure is enlightening.
Author
Owner

@dwmuller commented on GitHub (Apr 27, 2023):

image

In the history list, I happened to have "exit", and then a long command line starting with "winget". After opening the new tab, I pressed the up arrow twice, then the down arrow.

Hope that helps!

@dwmuller commented on GitHub (Apr 27, 2023): ![image](https://user-images.githubusercontent.com/17508429/234728671-97d52a13-67b9-43de-976f-5273f7c36c04.png) In the history list, I happened to have "exit", and then a long command line starting with "winget". After opening the new tab, I pressed the up arrow twice, then the down arrow. Hope that helps!
Author
Owner

@zadjii-msft commented on GitHub (Apr 27, 2023):

image

Uh, what

It's literally saying "go back to column 16, print winget upgrade....", THEN "go back to column 18 and print exit, then erase the rest of the line"

like, what

@zadjii-msft commented on GitHub (Apr 27, 2023): ![image](https://user-images.githubusercontent.com/18356694/234839165-e0bd0da6-faa2-4617-b2ce-9a7d373673d2.png) Uh, what It's literally saying "go back to column 16, print `winget upgrade....`", THEN "go back to column **18** and print `exit`, then erase the rest of the line" like, what
Author
Owner

@j4james commented on GitHub (Apr 27, 2023):

I'm not overly familiar with the way these prompts work, so I may have this wrong, but my understanding was that you used those \[ \] controls to indicate the portions of the prompt that are "non-printing" (e.g. things like the color escape sequences). That way the shell knows it can ignore those bits when calculating how much space the prompt will occupy.

Looking at PS1 prompt that was provided in initial comment of this issue, once you strip out all the "non-printing" sections, what you're left with is something like this (I'm just approximating the powerline characters here):

( *  bash > ~ >( 2.574s ) danm@PEGASUS ❯ 

But that's nothing like the real layout of the prompt. So if that's what the shell thinks it looks like, it's going to miscalculate how much space is remaining on the rest of the line, and it's going to assume the first line of input is wrapping sooner that it should.

If that's the case, it's not surprising that this ends up placing the cursor in the wrong position under certain circumstances (particularly when displaying input over a certain length).

@j4james commented on GitHub (Apr 27, 2023): I'm not overly familiar with the way these prompts work, so I may have this wrong, but my understanding was that you used those `\[ \]` controls to indicate the portions of the prompt that are "non-printing" (e.g. things like the color escape sequences). That way the shell knows it can ignore those bits when calculating how much space the prompt will occupy. Looking at PS1 prompt that was provided in initial comment of this issue, once you strip out all the "non-printing" sections, what you're left with is something like this (I'm just approximating the powerline characters here): ( * bash > ~ >( 2.574s ) danm@PEGASUS ❯ But that's nothing like the real layout of the prompt. So if that's what the shell *thinks* it looks like, it's going to miscalculate how much space is remaining on the rest of the line, and it's going to assume the first line of input is wrapping sooner that it should. If that's the case, it's not surprising that this ends up placing the cursor in the wrong position under certain circumstances (particularly when displaying input over a certain length).
Author
Owner

@dwmuller commented on GitHub (Apr 30, 2023):

I wonder if this is related to #3546

@dwmuller commented on GitHub (Apr 30, 2023): I wonder if this is related to #3546
Author
Owner

@dwmuller commented on GitHub (Apr 30, 2023):

Oh good lord. I started digging deeper into what Oh My Posh sets up using the --init option, and there's way more going on here than is apparent from the PS1 value. It defines PS0, PS2, a shell function, and sets PROMPT_COMMAND to execute the shell function. The function sets up some context, puts the cursor at a calculated position, and defines PS1.

So there's more going on here than is apparent from my PS1. I won't bore you with the details just yet, but I'm analyzing it. Sorry about missing all this relevant information.

@dwmuller commented on GitHub (Apr 30, 2023): Oh good lord. I started digging deeper into what Oh My Posh sets up using the --init option, and there's way more going on here than is apparent from the PS1 value. It defines PS0, PS2, a shell function, and sets PROMPT_COMMAND to execute the shell function. The function sets up some context, puts the cursor at a calculated position, and defines PS1. So there's more going on here than is apparent from my PS1. I won't bore you with the details just yet, but I'm analyzing it. Sorry about missing all this relevant information.
Author
Owner

@dwmuller commented on GitHub (Apr 30, 2023):

So here's what I found.

The PS0 value is irrelevant, it gets set to an empty string, but via side effects it records a start time for a command so that the elapsed time can be calculated later.

The PS2 value is irrelevant for the purposes of this bug.

The function executed by PROMPT_COMMAND has the following relevant effects:

  1. Calculates elapsed time if relevant, and stashes it in a local variable.
  2. Calculates the current cursor row and column and stashes those in exported variables POSH_CURSOR_LINE and POSH_CURSOR_COLUMN. More on this below.
  3. Runs oh-my-posh to calculate a new PS1 value. Oh My Posh presumably incorporates the line and column values.

The method of calculating the row and column values:

local oldstty=$(stty -g)
stty raw -echo min 0

local COL
local ROW
IFS=';' read -sdR -p $'\E[6n' ROW COL

stty $oldstty

export POSH_CURSOR_LINE=${ROW#*[}
export POSH_CURSOR_COLUMN=${COL}

Clever.

This makes me wonder if the problem arises in the terminal's response to the \E[6n sequence. But I don't think that's the problem. OMP seems to be working OK, it's really readline that's manipulating the text after the prompt when you navigate history. It seems more likely that readline is interrogating the terminal for cursor position, and is getting an incorrect response.

BTW, I also removed the option in my OMP config that was sending the PWD to the terminal. This removed some cruft from the end of the PS1 value, but had no effect on the bug.

@dwmuller commented on GitHub (Apr 30, 2023): So here's what I found. The PS0 value is irrelevant, it gets set to an empty string, but via side effects it records a start time for a command so that the elapsed time can be calculated later. The PS2 value is irrelevant for the purposes of this bug. The function executed by PROMPT_COMMAND has the following relevant effects: 1. Calculates elapsed time if relevant, and stashes it in a local variable. 2. Calculates the current cursor row and column and stashes those in exported variables POSH_CURSOR_LINE and POSH_CURSOR_COLUMN. More on this below. 3. Runs oh-my-posh to calculate a new PS1 value. Oh My Posh presumably incorporates the line and column values. The method of calculating the row and column values: local oldstty=$(stty -g) stty raw -echo min 0 local COL local ROW IFS=';' read -sdR -p $'\E[6n' ROW COL stty $oldstty export POSH_CURSOR_LINE=${ROW#*[} export POSH_CURSOR_COLUMN=${COL} Clever. This makes me wonder if the problem arises in the terminal's response to the `\E[6n` sequence. But I don't think that's the problem. OMP seems to be working OK, it's really readline that's manipulating the text after the prompt when you navigate history. It seems more likely that readline is interrogating the terminal for cursor position, and is getting an incorrect response. BTW, I also removed the option in my OMP config that was sending the PWD to the terminal. This removed some cruft from the end of the PS1 value, but had no effect on the bug.
Author
Owner

@zadjii-msft commented on GitHub (May 3, 2023):

Alright, yea we're basically at a loss. We don't think it should be a bad response to 6n, that wouldn't have to traverse ConPTY. Maybe someone has messed up the cursor position off the >, but even then, that would only be a single cell, not two.

I honestly don't know what else for us to do here except get this under a local repro and a live debugger.

Wait as a quick sanity check - if you set the default terminal emulator to Windows console host:

Does that repro this issue? That might be able to narrow it down to conpty or not.

@zadjii-msft commented on GitHub (May 3, 2023): Alright, yea we're basically at a loss. We don't think it should be a bad response to `6n`, that wouldn't have to traverse ConPTY. Maybe someone has messed up the cursor position off the `>`, but even then, that would only be a single cell, not two. I honestly don't know what else for us to do here except get this under a local repro and a live debugger. Wait as a quick sanity check - if you set the default terminal emulator to Windows console host: ![](https://user-images.githubusercontent.com/18356694/236057321-d2338e9e-3b8c-4eb3-b9b4-bea9d858ba65.png) Does _that_ repro this issue? That might be able to narrow it down to conpty or not.
Author
Owner

@dwmuller commented on GitHub (May 7, 2023):

Wait as a quick sanity check - if you set the default terminal emulator to Windows console host:

Does that repro this issue? That might be able to narrow it down to conpty or not.

Tried it, it has no effect on the bug.

@dwmuller commented on GitHub (May 7, 2023): > > Wait as a quick sanity check - if you set the default terminal emulator to Windows console host: ![](https://user-images.githubusercontent.com/18356694/236057321-d2338e9e-3b8c-4eb3-b9b4-bea9d858ba65.png) > > Does _that_ repro this issue? That might be able to narrow it down to conpty or not. Tried it, it has no effect on the bug.
Author
Owner

@rioka commented on GitHub (Jun 1, 2023):

I'm facing pretty much the same issue (using OMP, too): depending on the lenght of the prompt, the length of the command, and the width of the windows, the cursor get stuck

  • somewhere in the command line
  • in the previous line on the screen (i.e. the line above the one I'm trying to enter a command)
  • in the next line on the screen

Moreover, the cursor ends up in different positions depending on the key you enter

  • when I move one character at a time, the cursor stops somewhere in the middle of my command
  • when I move it using Home, the final position (column) is correct (but it may be on the current line, or in the previous one)
  • when I move it End, the final position is somewhere in the next line (which is empty of course)

As a side note, when used in Conemu or mintty , it works as expected (or at least I did not notice this behavior so far).

@rioka commented on GitHub (Jun 1, 2023): I'm facing pretty much the same issue (using OMP, too): depending on the lenght of the prompt, the length of the command, and the width of the windows, the cursor get stuck - somewhere in the command line - in the previous line on the screen (i.e. the line above the one I'm trying to enter a command) - in the next line on the screen Moreover, the cursor ends up in different positions depending on the key you enter - when I move one character at a time, the cursor stops somewhere in the middle of my command - when I move it using `Home`, the final position (column) is correct (but it may be on the current line, or in the previous one) - when I move it `End`, the final position is somewhere in the next line (which is empty of course) As a side note, when used in Conemu or mintty , it works as expected (or at least I did not notice this behavior so far).
Author
Owner

@DavideCanton commented on GitHub (Jun 15, 2023):

Don't know if it is really related, but I have the same problem without using OMP.

Basically I have a PS1="λ ", and it is enough to reproduce the issue:

image

I believe @zadjii-msft's guess of unicode characters being not handled correctly is correct.

Reproduced with version 1.17.230526001, win 10, git bash, apparently it doesn't reproduce with powershell or cmd (but I don't use them too often, maybe I simply did not try enough).

@DavideCanton commented on GitHub (Jun 15, 2023): Don't know if it is really related, but I have the same problem without using OMP. Basically I have a `PS1="λ "`, and it is enough to reproduce the issue: ![image](https://github.com/microsoft/terminal/assets/3042187/1701f670-77fb-428d-b53d-073e8262b765) I believe @zadjii-msft's guess of unicode characters being not handled correctly is correct. Reproduced with version 1.17.230526001, win 10, git bash, apparently it doesn't reproduce with powershell or cmd (but I don't use them too often, maybe I simply did not try enough).
Author
Owner

@j4james commented on GitHub (Jun 15, 2023):

@DavideCanton In your case it looks like git bash is miscalculating the length of the prompt. I added some logging to OpenConsole to see exactly what it is sending us, and when you press up arrow the second time we get this:

CR (moves the cursor to the start of the line)
CUF CUF CUF (moves the cursor forward 3 columns, up to the d in cd foo)
ICH 3 (inserts 3 spaces at that point, giving you c d foo
mkdir (overwrites the spaces and d, giving you cmkdirfoo
CUF CUF CUF CUF (moves the cursor forward 4 columns, one past the end of the line)

Those three CUF sequences at the start are the problem. It looks like it thought the lambda was two columns wide, making the prompt three columns wide (when it should have been two).

After some experimentation with other characters, I think it might be determining the width based on the UTF-8 byte count. For example, if you set the prompt to PS1="ᴀ ", it thinks it's four columns wide, because the (U+1D00) is a three byte UTF-8 sequence.

It's possible this is a misconfiguration of the locale, and it thinks its using an 8-bit code page. I don't know enough about git bash to know how you might fix that.

@j4james commented on GitHub (Jun 15, 2023): @DavideCanton In your case it looks like git bash is miscalculating the length of the prompt. I added some logging to OpenConsole to see exactly what it is sending us, and when you press up arrow the second time we get this: `CR` (moves the cursor to the start of the line) `CUF` `CUF` `CUF` (moves the cursor forward 3 columns, up to the `d` in `cd foo`) `ICH 3` (inserts 3 spaces at that point, giving you `c d foo` `mkdir` (overwrites the spaces and `d`, giving you `cmkdirfoo` `CUF` `CUF` `CUF` `CUF` (moves the cursor forward 4 columns, one past the end of the line) Those three `CUF` sequences at the start are the problem. It looks like it thought the lambda was two columns wide, making the prompt three columns wide (when it should have been two). After some experimentation with other characters, I think it might be determining the width based on the UTF-8 byte count. For example, if you set the prompt to `PS1="ᴀ "`, it thinks it's four columns wide, because the `ᴀ` (U+1D00) is a three byte UTF-8 sequence. It's possible this is a misconfiguration of the locale, and it thinks its using an 8-bit code page. I don't know enough about git bash to know how you might fix that.
Author
Owner

@DavideCanton commented on GitHub (Jun 15, 2023):

Hi, thanks for your response.

I suspected the problem was related to a wrong character length calculation, since adding many lambdas increases the count of wrong characters displayed when navigating through the history.

The strange thing is that opening the git bash standalone does not reproduce the issue, it happens only inside the windows terminal.

I fixed it by using tput sc and tput rc.

@DavideCanton commented on GitHub (Jun 15, 2023): Hi, thanks for your response. I suspected the problem was related to a wrong character length calculation, since adding many lambdas increases the count of wrong characters displayed when navigating through the history. The strange thing is that opening the git bash standalone does not reproduce the issue, it happens only inside the windows terminal. I fixed it by using `tput sc` and `tput rc`.
Author
Owner

@j4james commented on GitHub (Jun 15, 2023):

The strange thing is that opening the git bash standalone does not reproduce the issue, it happens only inside the windows terminal.

I reproduced it in a recent build of OpenConsole, so it's definitely not limited to Windows Terminal. But it's possible git bash is using the legacy console APIs rather than VT sequences when it detects an older versions of Windows.

I fixed it by using tput sc and tput rc.

This didn't help on my system. I can still reproduce the issue after executing those commands.

@j4james commented on GitHub (Jun 15, 2023): > The strange thing is that opening the git bash standalone does not reproduce the issue, it happens only inside the windows terminal. I reproduced it in a recent build of OpenConsole, so it's definitely not limited to Windows Terminal. But it's possible git bash is using the legacy console APIs rather than VT sequences when it detects an older versions of Windows. > I fixed it by using `tput sc` and `tput rc`. This didn't help on my system. I can still reproduce the issue after executing those commands.
Author
Owner

@DHowett commented on GitHub (Jun 15, 2023):

it's possible git bash is using the legacy console APIs rather than VT sequences when it detects an older versions of Windows.

It may also be using mintty in its default configuration, which could have a different (and less correct) understanding of the width of that character!

@DHowett commented on GitHub (Jun 15, 2023): > it's possible git bash is using the legacy console APIs rather than VT sequences when it detects an older versions of Windows. It may also be using mintty in its default configuration, which could have a different (and less correct) understanding of the width of that character!
Author
Owner

@DavideCanton commented on GitHub (Jun 15, 2023):

I reproduced it in a recent build of OpenConsole, so it's definitely not limited to Windows Terminal. But it's possible git bash is using the legacy console APIs rather than VT sequences when it detects an older versions of Windows.

Probably.

This didn't help on my system. I can still reproduce the issue after executing those commands.

My bad, they are part of the fix but executing them is not enough.

I would link the stackoverflow response where I read it, but it seems SO is down :/
This is the link of the SO response.

I fixed by setting PS1='\n\['"`tput sc`"'\] \['"`tput rc`"'λ \]'

@DavideCanton commented on GitHub (Jun 15, 2023): > I reproduced it in a recent build of OpenConsole, so it's definitely not limited to Windows Terminal. But it's possible git bash is using the legacy console APIs rather than VT sequences when it detects an older versions of Windows. Probably. > This didn't help on my system. I can still reproduce the issue after executing those commands. My bad, they are part of the fix but executing them is not enough. ~~I would link the stackoverflow response where I read it, but it seems SO is down :/~~ [This](https://stackoverflow.com/a/7123564) is the link of the SO response. I fixed by setting ``PS1='\n\['"`tput sc`"'\] \['"`tput rc`"'λ \]'``
Author
Owner

@j4james commented on GitHub (Jun 15, 2023):

I fixed by setting PS1='\n\['"`tput sc`"'\] \['"`tput rc`"'λ \]'

OK, that makes more sense. That works for me too. Interestingly they're not actually implementing the sc and rc operations with escape sequences, but with direct calls to the console SetConsoleCursorPosition API. I'm assuming this is all just legacy code that's evolved over time and only partially transitioned from the old console APIs to VT sequences.

It may also be using mintty in its default configuration

@DHowett I initially thought that too, but that's not the case. If I request a DA report I get back \x1b[?1;0c, which is what I would expect from old versions of conhost. Mintty would report something like \x1b[?64;...c.

@j4james commented on GitHub (Jun 15, 2023): > I fixed by setting `` PS1='\n\['"`tput sc`"'\] \['"`tput rc`"'λ \]' `` OK, that makes more sense. That works for me too. Interestingly they're not actually implementing the `sc` and `rc` operations with escape sequences, but with direct calls to the console `SetConsoleCursorPosition` API. I'm assuming this is all just legacy code that's evolved over time and only partially transitioned from the old console APIs to VT sequences. > It may also be using mintty in its default configuration @DHowett I initially thought that too, but that's not the case. If I request a DA report I get back `\x1b[?1;0c`, which is what I would expect from old versions of conhost. Mintty would report something like `\x1b[?64;...c`.
Author
Owner

@j4james commented on GitHub (Jun 15, 2023):

I just realised there are actually two versions of git bash. The one that shows up in the start menu is C:\Program Files\Git\git-bash.exe, and the one in Windows Terminal is C:\Program Files\Git\bin\bash.exe (this is also what I was testing in OpenConsole, which explains why it had the same issue as Windows Terminal). The former version appears to use console APIs, while the latter version is mostly VT sequences.

@j4james commented on GitHub (Jun 15, 2023): I just realised there are actually two versions of git bash. The one that shows up in the start menu is `C:\Program Files\Git\git-bash.exe`, and the one in Windows Terminal is `C:\Program Files\Git\bin\bash.exe` (this is also what I was testing in OpenConsole, which explains why it had the same issue as Windows Terminal). The former version appears to use console APIs, while the latter version is mostly VT sequences.
Author
Owner

@DavideCanton commented on GitHub (Jun 15, 2023):

I can confirm the problem arises with the bash.exe inside bin/.

@DavideCanton commented on GitHub (Jun 15, 2023): I can confirm the problem arises with the `bash.exe` inside `bin/`.
Author
Owner

@dwmuller commented on GitHub (Jun 30, 2023):

I realized that Oh My Posh configuration files can be in YAML, which makes it a lot easier to comment out parts for experimenting. I subsequently stripped my config down to almost nothing, and am still seeing the problem.

I also noticed this FAQ entry for Oh My Posh: https://ohmyposh.dev/docs/faq#windows-terminal-unexpected-space-between-segmentstext

I figured that might be related, so I preceded each special Unicode character in the remaining configuration with \u200a. That didn't help either.

My prompt is down to this, piped through od so you can be sure you're seeing a representation of every character:

❯ echo -n "$PS1" | od -c
0000000  \n   \   [ 033   [   3   8   ;   2   ;   2   5   5   ;   2   5
0000020   5   ;   2   5   5   m   \   ] 342 235 257       \   [ 033   [
0000040   0   m   \   ]   \   [ 033   ]   9   ;   9   ;   C   :   \   U
0000060   s   e   r   s   \   d   a   n   m 033   \   \   \   ]
0000076
@dwmuller commented on GitHub (Jun 30, 2023): I realized that Oh My Posh configuration files can be in YAML, which makes it a lot easier to comment out parts for experimenting. I subsequently stripped my config down to almost nothing, and am still seeing the problem. I also noticed this FAQ entry for Oh My Posh: https://ohmyposh.dev/docs/faq#windows-terminal-unexpected-space-between-segmentstext I figured that might be related, so I preceded each special Unicode character in the remaining configuration with \u200a. That didn't help either. My prompt is down to this, piped through od so you can be sure you're seeing a representation of every character: ``` ❯ echo -n "$PS1" | od -c 0000000 \n \ [ 033 [ 3 8 ; 2 ; 2 5 5 ; 2 5 0000020 5 ; 2 5 5 m \ ] 342 235 257 \ [ 033 [ 0000040 0 m \ ] \ [ 033 ] 9 ; 9 ; C : \ U 0000060 s e r s \ d a n m 033 \ \ \ ] 0000076 ```
Author
Owner

@dwmuller commented on GitHub (Jun 30, 2023):

I tried one more thing. The remaining visible character in my prompt was a Unicode character, which I didn't realize at first because it looks a lot like a greater-than sign. It shows up in the octal dump above as the sequence of bytes 342 235 257. Replacing that with an ASCII character makes the problem go away. Preceding the Unicode character with \u200a does not.

Further experimentation showed that putting any Unicode character in PS1 causes the problem. Try this:

export PS1="❤ "
@dwmuller commented on GitHub (Jun 30, 2023): I tried one more thing. The remaining visible character in my prompt was a Unicode character, which I didn't realize at first because it looks a lot like a greater-than sign. It shows up in the octal dump above as the sequence of bytes 342 235 257. Replacing that with an ASCII character makes the problem go away. Preceding the Unicode character with \u200a does not. Further experimentation showed that putting *any* Unicode character in PS1 causes the problem. Try this: ``` export PS1="❤ " ```
Author
Owner

@j4james commented on GitHub (Jul 1, 2023):

Further experimentation showed that putting any Unicode character in PS1 causes the problem.

Yeah. This is what I was saying in https://github.com/microsoft/terminal/issues/14982#issuecomment-1592842298. My guess is that it's calculating the prompt length based on the number of bytes in the UTF-8 representation, rather than the actual glyph count.

@j4james commented on GitHub (Jul 1, 2023): > Further experimentation showed that putting _any_ Unicode character in PS1 causes the problem. Yeah. This is what I was saying in https://github.com/microsoft/terminal/issues/14982#issuecomment-1592842298. My guess is that it's calculating the prompt length based on the number of bytes in the UTF-8 representation, rather than the actual glyph count.
Author
Owner

@dwmuller commented on GitHub (Jul 1, 2023):

Holy frijole, I finally found a simple fix for this.

I was experimenting some more and was befuddled as to why this was happening:
image

\u2764 should be equivalent to \342\235\244, so bash clearly wasn't interpreting the \u prefix correctly. A search for answers turned up a Stackoverflow article with an interesting top answer that pointed to locale settings.

I checked the output of locale and saw that LANG wasn't set:

❤ locale
LANG=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_ALL=

This appears to be the default state in Git Bash on Windows - my dotfiles don't change anything related to locale, and I've seen this problem on a variety of systems, including a new laptop that I freshly set up just a few weeks ago.

Executing set LANG='C.UTF-8' fixed the \u problem and the positioning problem! So as @j4james guessed, this does seem to be a bash issue. Exporting LANG to the environment also seems to work and is visible to subordinate bash shells.

In a bash shell on WSL2, where I wasn't seeing the problem, LANG is set to C.UTF-8 already.

Also, I'll mention another Stackoverflow article that I ran into along the way, because it had a very clever workaround for a similar problem, using the sc and rc escape sequences. See the first answer here.

I could close this, but I'll let the devs do that after verifying my assumption that it's purely a bash problem. Maybe you can think of some way to defend users against this .

@dwmuller commented on GitHub (Jul 1, 2023): Holy frijole, I finally found a simple fix for this. I was experimenting some more and was befuddled as to why this was happening: ![image](https://github.com/microsoft/terminal/assets/17508429/c8dfcde3-e305-4e10-97a4-d2cb390a5a33) \u2764 should be equivalent to \342\235\244, so bash clearly wasn't interpreting the \u prefix correctly. A search for answers turned up a Stackoverflow article with [an interesting top answer](https://stackoverflow.com/questions/10651975/unicode-utf-8-with-git-bash) that pointed to locale settings. I checked the output of ``locale`` and saw that LANG wasn't set: ``` ❤ locale LANG= LC_CTYPE="C.UTF-8" LC_NUMERIC="C.UTF-8" LC_TIME="C.UTF-8" LC_COLLATE="C.UTF-8" LC_MONETARY="C.UTF-8" LC_MESSAGES="C.UTF-8" LC_ALL= ``` This appears to be the default state in Git Bash on Windows - my dotfiles don't change anything related to locale, and I've seen this problem on a variety of systems, including a new laptop that I freshly set up just a few weeks ago. Executing ``set LANG='C.UTF-8'`` fixed the \u problem *and* the positioning problem! So as @j4james guessed, this does seem to be a bash issue. Exporting LANG to the environment also seems to work and is visible to subordinate bash shells. In a bash shell on WSL2, where I wasn't seeing the problem, LANG is set to C.UTF-8 already. Also, I'll mention another Stackoverflow article that I ran into along the way, because it had a very clever workaround for a similar problem, using the sc and rc escape sequences. See the first answer [here](https://stackoverflow.com/questions/7112774/how-to-escape-unicode-characters-in-bash-prompt-correctly). I could close this, but I'll let the devs do that after verifying my assumption that it's purely a bash problem. Maybe you can think of some way to defend users against this .
Author
Owner

@DHowett commented on GitHub (Jul 1, 2023):

AGH! Just today, I was going to ask you what LANG was set to. I decided that I must have already asked, and didn't choose to.

So instead... can you share the commandline for your Git Bash profile?

If it doesn't contain -l -i, it isn't starting with the correct environment. 😄

@DHowett commented on GitHub (Jul 1, 2023): AGH! Just today, I was going to ask you what `LANG` was set to. I decided that I must have already asked, and didn't choose to. So instead... can you share the commandline for your Git Bash profile? If it doesn't contain `-l -i`, it isn't starting with the correct environment. 😄
Author
Owner

@dwmuller commented on GitHub (Jul 1, 2023):

Ugh. The -l option causes LANG to be set, -i does not. The shortcut installed by (the choco version of) Git for Windows looks like this:
image

git-bash.exe seems to be a wrapper around bash.exe, which does set up the locale correctly.

I actually usually start it from Microsoft Terminal, where I set it up to run bash.exe directly without any options at all. Doh.

@dwmuller commented on GitHub (Jul 1, 2023): Ugh. The -l option causes LANG to be set, -i does not. The shortcut installed by (the choco version of) Git for Windows looks like this: ![image](https://github.com/microsoft/terminal/assets/17508429/8fbae4c3-59e6-4d35-847a-d478d7996334) git-bash.exe seems to be a wrapper around bash.exe, which *does* set up the locale correctly. I actually usually start it from Microsoft Terminal, where I set it up to run bash.exe directly without any options at all. Doh.
Author
Owner

@zadjii-msft commented on GitHub (Jul 5, 2023):

holy butts. Well. I'm glad you figured it out! LANG and LC_* have given us (and seemingly everyone) plenty of troubles in the past. I'm not sure there's any good way to immediately mitigate that. Hopefully though, this thread should have plenty of keywords in it to help some future folks hitting this find the right fix ☺️

Thanks for following up!

@zadjii-msft commented on GitHub (Jul 5, 2023): holy butts. Well. I'm glad you figured it out! `LANG` and `LC_*` have given us (and seemingly everyone) plenty of troubles in the past. I'm not sure there's any good way to immediately mitigate that. Hopefully though, this thread should have _plenty_ of keywords in it to help some future folks hitting this find the right fix ☺️ Thanks for following up!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#19523