diff options
author | Tom de Vries <tdevries@suse.de> | 2024-12-20 18:34:50 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2024-12-20 18:34:50 +0100 |
commit | 602f66f5aba3b3871cef08306f9c3c2962992784 (patch) | |
tree | 93f71d719d80f2aed3260d3f40f67ba353029933 | |
parent | 66834f8da920eb2f2c348259046667decdcfb822 (diff) | |
download | binutils-602f66f5aba3b3871cef08306f9c3c2962992784.zip binutils-602f66f5aba3b3871cef08306f9c3c2962992784.tar.gz binutils-602f66f5aba3b3871cef08306f9c3c2962992784.tar.bz2 |
[gdb/cli] Don't prefill for operate-and-get-next of last command
Consider operate-and-get-next [1] in bash:
...
$ <echo 1>echo 1<enter>
1
$ <echo 2>echo 2<enter>
2
$ <Ctrl-r>(reverse-i-search)`': <echo 1>echo 1<Ctrl-o>
1
$ echo 2<Ctrl-o>
2
$ echo 1
...
So, typing Ctrl-o:
- executes the recalled command, and
- prefills the next one (which then can be executed again with Ctrl-o).
We have the same functionality in gdb, but when recalling the last command
from history with bash we have no prefill:
...
$ <echo 1>echo 1<enter>
1
$ <Ctrl-r>(reverse-i-search)`': <echo 1>echo 1<Ctrl-o>
1
$
...
but with gdb do we have a prefill:
...
(gdb) echo 1\n
1
(gdb) <Ctrl-r>(reverse-i-search)`': <echo 1>echo 1\n<Ctrl-o>
1
(gdb) echo 1\n
...
Following the principle of least surprise [2], I think gdb should do what bash
does.
Fix this by:
- signalling this case in gdb_rl_operate_and_get_next using
"operate_saved_history = -1", and
- handling operate_saved_history == -1 in
gdb_rl_operate_and_get_next_completion.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR cli/32485
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32485
[1] https://www.man7.org/linux/man-pages/man3/readline.3.html
[2] https://en.wikipedia.org/wiki/Principle_of_least_astonishment
-rw-r--r-- | gdb/testsuite/gdb.base/readline.exp | 42 | ||||
-rw-r--r-- | gdb/top.c | 16 |
2 files changed, 52 insertions, 6 deletions
diff --git a/gdb/testsuite/gdb.base/readline.exp b/gdb/testsuite/gdb.base/readline.exp index db49e90..4e613d6 100644 --- a/gdb/testsuite/gdb.base/readline.exp +++ b/gdb/testsuite/gdb.base/readline.exp @@ -260,3 +260,45 @@ save_vars { env(TERM) } { } } } + +# Test operate_and_get_next when selecting the last command. +with_test_prefix "operate_and_get_next last command" { + clean_restart + + # Expected output from echo 1\n. + set re1 \ + [multi_line \ + "" \ + "1"] + + # Expected output from echo 2\n. + set re2 \ + [multi_line \ + "" \ + "2"] + + # Enter command into history. + gdb_test {echo 1\n} $re1 \ + "enter command" + + # Recall command from history (Ctrl-r, 022), and do operate-and-get-next + # (Ctrl-o, 017). There shouldn't be a prefill, but if there is one, + # prevent a possible timeout using -no-prompt-anchor. + send_gdb "\022echo 1\017" + gdb_test -no-prompt-anchor "" $re1 \ + "recall command" + + # Regression test for PR32485: Since we recalled the last command, there + # shouldn't be a prefil, so check that here. + # If there is no prefil, we simple have: + # (gdb) echo 2\n^M + # 2^M + # (gdb) + # If there is a prefil, we have: + # (gdb) echo 1\necho 2\n^M + # 1^M + # echo 2^M + # (gdb) + gdb_test {echo 2\n} $re2 \ + "no prefill" +} @@ -1054,11 +1054,14 @@ static int operate_saved_history = -1; static void gdb_rl_operate_and_get_next_completion (void) { - int delta = where_history () - operate_saved_history; + if (operate_saved_history != -1) + { + int delta = where_history () - operate_saved_history; - /* The `key' argument to rl_get_previous_history is ignored. */ - rl_get_previous_history (delta, 0); - operate_saved_history = -1; + /* The `key' argument to rl_get_previous_history is ignored. */ + rl_get_previous_history (delta, 0); + operate_saved_history = -1; + } /* readline doesn't automatically update the display for us. */ rl_redisplay (); @@ -1083,9 +1086,10 @@ gdb_rl_operate_and_get_next (int count, int key) /* Find the current line, and find the next line to use. */ where = where_history(); - if ((history_is_stifled () && (history_length >= history_max_entries)) - || (where >= history_length - 1)) + if (history_is_stifled () && history_length >= history_max_entries) operate_saved_history = where; + else if (where >= history_length - 1) + operate_saved_history = -1; else operate_saved_history = where + 1; |