Mercurial > public > mercurial-scm > hg-stable
changeset 52253:b3214b7d2390 stable
ui: fix escape sequences in in readline prompts (issue6930)
Text that is meant to represent zero-width output in a readline
prompt, such as terminal escape sequences, is supposed to be
delimited by \001 ... \002:
> Applications may indicate that the prompt contains characters that
> take up no physical screen space when displayed by bracketing a
> sequence of such characters with the special markers
> RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE (declared in
> readline.h `\001' and `\002', respectively). This may be used to
> embed terminal-specific escape sequences in prompts.
https://tiswww.cwru.edu/php/chet/readline/readline.html#index-rl_005fexpand_005fprompt
When formatting a readline prompt in ui._readline, arrange to do this
in the color.py labelling routines. Keeping mutable dynamically
scoped state like this isn't great but threading it as a parameter
through all the subroutines seems like much more trouble.
(This doesn't address the missing line break -- that's a separate bug
in libedit.)
https://bz.mercurial-scm.org/show_bug.cgi?id=6930
author | Taylor R Campbell <campbell+mercurial@mumble.net> |
---|---|
date | Thu, 05 Dec 2024 20:46:21 +0000 |
parents | 64baff9f7dad |
children | bcf6a219d235 |
files | mercurial/color.py mercurial/ui.py |
diffstat | 2 files changed, 13 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/color.py Thu Dec 05 13:48:22 2024 +0000 +++ b/mercurial/color.py Thu Dec 05 20:46:21 2024 +0000 @@ -386,6 +386,9 @@ ] start = b'\033[' + b';'.join(start) + b'm' stop = b'\033[' + pycompat.bytestr(activeeffects[b'none']) + b'm' + if ui._readlineprompt: + start = b'\001' + start + b'\001' + stop = b'\002' + stop + b'\002' return _mergeeffects(text, start, stop) @@ -518,7 +521,8 @@ else: origattr = csbi.wAttributes ansire = re.compile( - br'\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL + br'\001?\033\[([^m]*)m\002?([^\033]*)(.*)', + re.MULTILINE | re.DOTALL, ) def win32print(ui, writefunc, text, **opts):
--- a/mercurial/ui.py Thu Dec 05 13:48:22 2024 +0000 +++ b/mercurial/ui.py Thu Dec 05 20:46:21 2024 +0000 @@ -265,6 +265,8 @@ self.logblockedtimes = False # color mode: see mercurial/color.py for possible value self._colormode = None + # readline prompt: is this currently for a readline prompt? + self._readlineprompt = False self._terminfoparams = {} self._styles = {} self._uninterruptible = False @@ -1745,7 +1747,12 @@ self.flush() prompt = b' ' else: - prompt = self.label(prompt, b'ui.prompt') + b' ' + wasreadlineprompt = self._readlineprompt + try: + self._readlineprompt = True + prompt = self.label(prompt, b'ui.prompt') + b' ' + finally: + self._readlineprompt = wasreadlineprompt # prompt ' ' must exist; otherwise readline may delete entire line # - http://bugs.python.org/issue12833