From b5bf8f1525508eee3bb74d84e5e99c9486e3cd2c 2023-12-17 15:40:54 From: Matthias Bussonnier Date: 2023-12-17 15:40:54 Subject: [PATCH] Feature/add line numbers to prompt (#14223) This PR adds line numbers to the default prompt (#13965). You can now display absolute, relative of both line number in the emacs and vi prompt by using the `TerminalInteractiveShell.prompt_line_number_format` option the at takes string to format with both `line` (1 base int) and `rel_line` (int)`. For example: `c.TerminalInteractiveShell.prompt_line_number_format='{line: 4d}/{rel_line:+03d} | '` --- diff --git a/IPython/terminal/interactiveshell.py b/IPython/terminal/interactiveshell.py index 997fd82..532287f 100644 --- a/IPython/terminal/interactiveshell.py +++ b/IPython/terminal/interactiveshell.py @@ -588,6 +588,17 @@ class TerminalInteractiveShell(InteractiveShell): help="Display the current vi mode (when using vi editing mode)." ).tag(config=True) + prompt_line_number_format = Unicode( + "", + help="The format for line numbering, will be passed `line` (int, 1 based)" + " the current line number and `rel_line` the relative line number." + " for example to display both you can use the following template string :" + " c.TerminalInteractiveShell.prompt_line_number_format='{line: 4d}/{rel_line:+03d} | '" + " This will display the current line number, with leading space and a width of at least 4" + " character, as well as the relative line number 0 padded and always with a + or - sign." + " Note that when using Emacs mode the prompt of the first line may not update.", + ).tag(config=True) + @observe('term_title') def init_term_title(self, change=None): # Enable or disable the terminal title. @@ -736,7 +747,7 @@ class TerminalInteractiveShell(InteractiveShell): def get_message(): return PygmentsTokens(self.prompts.in_prompt_tokens()) - if self.editing_mode == 'emacs': + if self.editing_mode == "emacs" and self.prompt_line_number_format == "": # with emacs mode the prompt is (usually) static, so we call only # the function once. With VI mode it can toggle between [ins] and # [nor] so we can't precompute. @@ -753,7 +764,7 @@ class TerminalInteractiveShell(InteractiveShell): "message": get_message, "prompt_continuation": ( lambda width, lineno, is_soft_wrap: PygmentsTokens( - self.prompts.continuation_prompt_tokens(width) + self.prompts.continuation_prompt_tokens(width, lineno=lineno) ) ), "multiline": True, diff --git a/IPython/terminal/prompts.py b/IPython/terminal/prompts.py index 3f5c07b..ca56d91 100644 --- a/IPython/terminal/prompts.py +++ b/IPython/terminal/prompts.py @@ -25,11 +25,21 @@ class Prompts(object): return '['+mode+'] ' return '' + def current_line(self) -> int: + if self.shell.pt_app is not None: + return self.shell.pt_app.default_buffer.document.cursor_position_row or 0 + return 0 def in_prompt_tokens(self): return [ - (Token.Prompt, self.vi_mode() ), - (Token.Prompt, 'In ['), + (Token.Prompt, self.vi_mode()), + ( + Token.Prompt, + self.shell.prompt_line_number_format.format( + line=1, rel_line=-self.current_line() + ), + ), + (Token.Prompt, "In ["), (Token.PromptNum, str(self.shell.execution_count)), (Token.Prompt, ']: '), ] @@ -37,11 +47,20 @@ class Prompts(object): def _width(self): return fragment_list_width(self.in_prompt_tokens()) - def continuation_prompt_tokens(self, width=None): + def continuation_prompt_tokens(self, width=None, *, lineno=None): if width is None: width = self._width() + line = lineno + 1 if lineno is not None else 0 + prefix = " " * len( + self.vi_mode() + ) + self.shell.prompt_line_number_format.format( + line=line, rel_line=line - self.current_line() - 1 + ) return [ - (Token.Prompt, (' ' * (width - 5)) + '...: '), + ( + Token.Prompt, + prefix + (" " * (width - len(prefix) - 5)) + "...: ", + ), ] def rewrite_prompt_tokens(self): diff --git a/docs/source/whatsnew/pr/incompat-line-numbers.rst b/docs/source/whatsnew/pr/incompat-line-numbers.rst new file mode 100644 index 0000000..f57c917 --- /dev/null +++ b/docs/source/whatsnew/pr/incompat-line-numbers.rst @@ -0,0 +1,4 @@ +Line Numbers +============ + +This PR add line numbers to the default prompt.