PyREPL: Add ctrl+up/down for multiline history retrieving

When I enter a multiline block like a function definition and press Enter, I can press the up arrow to recall that whole block from history. Pressing up again moves the cursor up one line inside the block. But sometimes I actually want to go further back in history instead of moving within the current block.

Can we add a key combination, e.g. Ctrl+up/down, to skip the current multiline block and retrieve the previous (or next) complete history entry. This would give a clear way to choose between moving within the current block and navigating the broader history.

21 Likes

+1, Nice to have when prototyping :slight_smile:
If you’re not planning on already, would love to contribute a PR :wink:

5 Likes

Thanks! I wasn’t yet planning for a PR. We’ve gained 11+ likes in a few hours, that shows some community interest. I see your draft PR, good luck!

2 Likes

Good news, Guido’s time machine strikes again!

You can use Ctrl+P and Ctrl+N show the previous and next blocks.

See also @trey’s pyrepl-hacks which lists some of the stdlib bindings:

  • clear-screen: Clear screen (Ctrl+L)
  • previous-history: Show previous block (Ctrl+P)
  • next-history: Show next block (Ctrl+N)
  • accept: Run current code block (Alt+Enter)
  • beginning-of-line: Move cursor to the first character of the current line (Ctrl+A or Home)
  • end-of-line: Move cursor to the last character of the current line (Ctrl+E or End)
  • home: Move cursor the first character in the code block
  • end: Move cursor the last character in the code block
  • kill-line: Delete to end of line (Ctrl+K)
  • unix-line-discard: Delete to beginning of line (Ctrl+U)
  • backward-word: Move cursor back one word (Ctrl+Left)
  • forward-word: Move cursor forward one word (Ctrl+Right)
  • backward-kill-word: Delete to beginning of word (Alt+Backspace)
  • kill-word: Delete to end of word (Alt+D)

And has a package to add some custom ones:

  • move-to-indentation: Move to first non-space in current line
  • dedent: Dedent the whole code block
  • move-line-down: Swap current line with next one in the block
  • move-line-up: Swap current line with previous one in the block
  • previous-paragraph: Move to the previous blank line
  • next-paragraph: Move to the next blank line
15 Likes

Ohh thanks @hugovk guess I got to excited and didn’t realize hehe. Thanks!

2 Likes

We should document them, or at least link to Trey’s article: Python REPL Shortcuts & Features - Python Morsels

3 Likes

Idea/PR aside, this is a really good resource, thanks!!

2 Likes

It’s also worth mentioning in general the Readline Command Names section in man bash, and the EDITING COMMANDS section in man readline, which are not the same.

Bash lists / implements some extra goodies like shell-forward-word, shell-backward-word and shell-backward-kill-word that figures out how quotation should affect delimiting for movement etc, rather than using naive whitespace delimiting. Readline on its own doesn’t have these, and they’re very useful in Bash for moving through filenames with spaces etc. :smiley:

I have them in my $INPUTRC:

"\e\C-b": shell-backward-word
"\e\C-f": shell-forward-word
"\e\C-w": shell-backward-kill-word

…you saved my life.
Ty anyway to @tanloong and @edvilme , you are my heroes too :smiley:

I think it’s useful having a shortcut also for them by default. What about CTRL or ALT + Home / End, or ALT + A and ALT + E?

They already have shortcuts: Home and End.

1 Like

Well, no. Home and end go to the start / end of the line, not of the code block:

3 Likes

Indeed there is a shortcut for home and end in _pyrepl/reader.py:

default_keymaps: Keymap = tuple([
  (r"\<end>", "end-of-line"),  # was 'end'
  (r"\<home>", "beginning-of-line"),  # was 'home'
  ...
  (r"\EOF", "end"),  # the entries in the terminfo database for xterms
  (r"\EOH", "home"),  # seem to be wrong.  this is a less than ideal
  ])

But I don’t know how to trigger the \EOF and \EOH sequences from the keyboard…


I tried with a key.py to show the sequences of my input, it tells me that the \EOH and \EOF are exactly Home and End.

It seems a bit more complicated, at least on Linux:

1 Like

I think ctrl+home and ctrl+end would be more intuitive than the current keybinding\EOF and \EOH. It works logically the same as in Excel, where ctrl+home goes to uppermost-and-leftmost A1 and ctrl+end goes to the lowest-and-rightmost cell.

1 Like