How can I properly use two-character-width emoji in my bash prompt?
Asked Answered
S

2

4

I want to use an American flag emoji in my bash prompt (i.e. PS1 environment variable). However, the American flag emoji causes the terminal cursor to offset an extra character to the right.

πŸ‡ΊπŸ‡Έ is comprised of two unicode characters, πŸ‡Ί and πŸ‡Έ. I believe terminal is converting this to a mono-spaced emoji character (the flag), yet still allocating space for two characters. How can I achieve my expected cursor position?

I want:
πŸ‡ΊπŸ‡Έ Desktop akirna πŸ—½ ls|

I get:
πŸ‡ΊπŸ‡Έ Desktop akirna πŸ—½ ls | << weird space offset before cursor

My ~/.bash_profile is:

export PS1='πŸ‡ΊπŸ‡Έ  \W \u πŸ—½ '
Semiporcelain answered 31/1, 2019 at 0:22 Comment(14)
Stack Overflow is for programming questions, not questions about using or configuring Linux and its applications. Super User or Unix & Linux would be better places for questions like this. – Finesse
See this Unix & Linux question: unix.stackexchange.com/questions/239041/… – Finesse
@Barmar, thanks, but that answer didn't help. I posted on Unix & Linux here – Semiporcelain
Try this – Finesse
@Barmar, I used the suggested hexdump for an American flag but the PS1 prompt just shows the hexdump code. export PS1='\[\xf0\x9f\x87\xba\xf0\x9f\x87\xb8\] \W \u πŸ—½ ' shows \xf0\x9f\x87\xba\xf0\x9f\x87\xb8 ~ akirna πŸ—½ – Semiporcelain
MacOS has bash 3, that answer says it works in bash 4. – Finesse
I’m running bash 4.4.23 – Semiporcelain
Looks like it doesn't understand hex, you need to use octal. But I don't think any of this really solves the problem. There's no way to tell bash that multiple bytes only use one column. \[ can be used for sequences that take no space at all, but everything else is assumed to be 1 for 1. – Finesse
Exactly. Even [] to ignore the space of different characters didn’t work. – Semiporcelain
maybe try \001 and \002 instead of \[ and \]: unix.stackexchange.com/a/447520/103120 – Overliberal
@Blauhirn, thanks but that didn't work. – Semiporcelain
here is what Im using in my terminal and it is working just fine (the vars in command are for sake of easy reading for me): export PS1="πŸ‡¦πŸ‡² $BPurple$gitBranch$BRed$PathShort$NewLine$BBlue$Dollar$Color_Off" if you want I can provide their values as well – Intemperate
@BigGinDaHouse, my problem arises from the American flag registering two spaces wide, while it should only take one. This causes a weird offset; i.e. text input appears one space before the cursor – Semiporcelain
Just because the place a question is on-topic doesn't provide an answer doesn't make it permissible places it's off-topic. – Hite
G
2

Updated Answer

The way your are setting the prompt is not evaluating the escape characters. Add a $ before the string to make it evaluate the escape codes:

pompt$ export PS1='XY \x08: '
XY \x08: echo "Well that didn't work..."

Should become:

pompt$ export PS1=$'XY \x08: '
XY: echo "Escape code success!"

(See Charles Duffy's comment on this answer for why I removed export.)

The example above sets the prompt to the characters X, Y, [space], [backspace], [colon] resulting in a displayed prompt of just "XY:".

On my system, the flag is rendered as two characters (πŸ‡Ί and πŸ‡Έ), so I cannot verify this, but I think adding a backspace (\x08) should work for you:

PS1=$'πŸ‡ΊπŸ‡Έ  \\W \\u πŸ—½\x08'

Notes about edits

My original answer suggested using a sub-shell as follows:

export PS1=$(printf "XY \x08")

Many thanks to Charles Duffy for his input~

Guck answered 16/4, 2019 at 1:4 Comment(2)
There's no reason whatsoever to prefer PS1=$(printf "XY \x08") over PS1=$'XY \x08', ANSI C-like string literal syntax. – Hite
...and note that generally speaking, exporting PS1 is not a great idea; that puts it into the environment for all shells -- including dash, zsh, etc -- to inherit should they be started as a subprocess of a shell running the export. If you just set PS1=whatever with no export in your .bashrc, it stays local to interactive shells sourcing that file. – Hite
I
0

I worked around this by converting the character to hex, and then putting zero width markers around the second part of the character

so for πŸ‡ΊπŸ‡Έ we get

PS1='\xf0\x9f\x87\xba\[\xf0\x9f\x87\xb8\] '
Imminent answered 20/6, 2019 at 14:26 Comment(1)
when I do that, I get the same exact hex string printed for my bash prompt. – Semiporcelain

© 2022 - 2024 β€” McMap. All rights reserved.