diff --git a/docs/tutorial.rst b/docs/tutorial.rst index 17f4829a8..57f475c62 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -1656,6 +1656,7 @@ By default, the following variables are available for use: * ``time_format``: A time format string, defaulting to ``"%H:%M:%S"``. * ``last_return_code``: The return code of the last issued command. * ``last_return_code_if_nonzero``: The return code of the last issued command if it is non-zero, otherwise ``None``. This is useful for only printing the code in case of errors. + * ``SOFT_NL``: add new line character if the prompt end is near terminal border. .. note:: See the section below on ``PROMPT_FIELDS`` for more information on changing. diff --git a/xonsh/prompt/base.py b/xonsh/prompt/base.py index 23176f9b6..33939d84f 100644 --- a/xonsh/prompt/base.py +++ b/xonsh/prompt/base.py @@ -144,14 +144,14 @@ def default_prompt(): dp = ( "{YELLOW}{env_name}{RESET}" "{BOLD_GREEN}{user}@{hostname}" - "{BOLD_BLUE} {cwd} {prompt_end}{RESET} " + "{BOLD_BLUE} {cwd} {SOFT_NL}{prompt_end}{RESET} " ) elif xp.ON_WINDOWS and not xp.win_ansi_support(): dp = ( "{YELLOW}{env_name}{RESET}" "{BOLD_INTENSE_GREEN}{user}@{hostname}{BOLD_INTENSE_CYAN} " "{cwd}{branch_color}{curr_branch: {}}{RESET} " - "{BOLD_INTENSE_CYAN}{prompt_end}{RESET} " + "{SOFT_NL}{BOLD_INTENSE_CYAN}{prompt_end}{RESET} " ) else: dp = ( @@ -159,7 +159,7 @@ def default_prompt(): "{BOLD_GREEN}{user}@{hostname}{BOLD_BLUE} " "{cwd}{branch_color}{curr_branch: {}}{RESET} " "{RED}{last_return_code_if_nonzero:[{BOLD_INTENSE_RED}{}{RED}] }{RESET}" - "{BOLD_BLUE}{prompt_end}{RESET} " + "{SOFT_NL}{BOLD_BLUE}{prompt_end}{RESET} " ) return dp diff --git a/xonsh/ptk_shell/shell.py b/xonsh/ptk_shell/shell.py index c50afbd57..cc54e612d 100644 --- a/xonsh/ptk_shell/shell.py +++ b/xonsh/ptk_shell/shell.py @@ -440,6 +440,27 @@ class PromptToolkitShell(BaseShell): else: break + def _replace_soft_nl(self, toks): + """Replace ``{SOFT_NL}`` tag to new line.""" + SOFT_NL = '{SOFT_NL}' + prompt_len = 0 + soft_nl_pos = None + for i, t in enumerate(toks): + nt = t[1].replace(SOFT_NL, '') + prompt_len += len(nt) + if len(t[1]) != len(nt): + soft_nl_pos = i + + if soft_nl_pos is not None: + try: + import shutil + term_w, h = shutil.get_terminal_size() + c = '\n' if (term_w - prompt_len%term_w) < 10 else '' + toks[soft_nl_pos] = (toks[soft_nl_pos][0], toks[soft_nl_pos][1].replace(SOFT_NL, c)) + except: + toks[soft_nl_pos] = (toks[soft_nl_pos][0], toks[soft_nl_pos][1].replace(SOFT_NL, '')) + return toks + def _get_prompt_tokens(self, env_name: str, prompt_name: str, **kwargs): env = XSH.env # type:ignore p = env.get(env_name) @@ -455,7 +476,7 @@ class PromptToolkitShell(BaseShell): print_exception() toks = partial_color_tokenize(p) - + toks = self._replace_soft_nl(toks) return tokenize_ansi(PygmentsTokens(toks)) def prompt_tokens(self):