Bug #6601
[readline] Alt-* commands do not work in reverse-i-search
Description
=begin
= Steps to reproduce
Below are the steps to reproduce from an (({irb})) session. ^ is used to denote the cursor position on the screen.
Type ((%puts :a%)) then ((%Enter%)). This is to populate the history for reverse-i-search.
irb(main):001:0> puts :a
a
=> nilHit ((%Ctrl-R%)) (for reverse-i-search), followed by ((%u%)):
(reverse-i-search)`u': puts :a
^Hit ((%Alt-F%)) (for forward-word).
Observed: reverse-i-search terminated, with an 'f' inserted at cursor position.
irb(main):002:0> pfuts :a
^
Expected: reverse-i-search terminated, nothing inserted, cursor moves to end of the word (({puts})):
irb(main):002:0> puts :a
^
Note that other ((%Alt-*%)) commands don't work too (ie ((%x%)) is inserted instead of the command ((%Alt-x%)) being performed), including
- ((%Alt-B%)) (move backward a word)
- ((%Alt-C%)) (capitalize letter)
- ((%Alt-D%)) (delete till end of word)
= Fix
When we hit ((%Alt-F%)) from reverse-i-search, execution arrives at this piece of code in libreadline's (({isearch.c})):
387 /* ESC still terminates the search, but if there is pending
388 input or if input arrives within 0.1 seconds (on systems
389 with select(2)) it is used as a prefix character
390 with rl_execute_next. WATCH OUT FOR THIS! This is intended
391 to allow the arrow keys to be used like F and B are used
392 to terminate the search and execute the movement command.
393 XXX - since _rl_input_available depends on the application-
394 settable keyboard timeout value, this could alternatively
395 use _rl_input_queued(100000) */
396 if (cxt->lastc == ESC && _rl_input_available ())
397 rl_execute_next (ESC);
Due to (({readline_getc()})), our (({rl_getc_function()})) implementation, (({IO::getbyte()})) is called, causing all input characters to be "swallowed" into our byte buffer in (({readline_instream})). Thus (({_rl_input_available()})) incorrectly returns false, and the keystrokes (eg. Alt, F) fail to be recognized as a binding for a command.
The proposed fix (attached) uses (({rb_io_read_pending()})) to emulate (({_rl_input_available()})), and calls (({rl_execute_next()})), as libreadline does.
= Affected Versions
Ruby trunk and 1.9.3 (latest) exhibits this issue.
Ruby 1.8 also has exhibits this issue, but the fix would be different since (({rl_getc_function()})) isn't overriden in (({ext/readline/readline.c})).
Tested on readline 6.2; blame'ing the above snippet shows that readline as far back as 5.1 should also give this behaviour.
=end
Files
Related issues
Associated revisions
History
Updated by rctay (Tay Ray Chuan) over 6 years ago
Oops, forgot to enter a proper title/subject. Can someone with sufficient privileges update it to
[readline] Alt-* commands do not work in reverse-i-search
? Many thanks.
Updated by nobu (Nobuyoshi Nakada) over 6 years ago
- Subject changed from [readline] to [readline] Alt-* commands do not work in reverse-i-search
- Category set to ext
- Status changed from Open to Assigned
- Assignee set to kouji (Kouji Takao)
- Target version set to 1.9.3
Updated by nobu (Nobuyoshi Nakada) over 6 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r36123.
Tay, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
ext/readline/readline.c: [Bug #6601]
- ext/readline/readline.c (readline_getc): deal with ESC just followed by ASCII as meta prefix in incremental search mode. based on the patch from rctay (Tay Ray Chuan) at [ruby-core:45682]. [Bug #6601]
Updated by drbrain (Eric Hodel) over 6 years ago
- Status changed from Closed to Assigned
=begin
This breaks compilation on OS X 10.7 with editline:
compiling readline.c
readline.c:177:22: error: use of undeclared identifier 'ESC'
if (c == INT2FIX(ESC) &&
^
../.././include/ruby/ruby.h:228:45: note: expanded from macro 'INT2FIX'
#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG))
^
readline.c:178:2: warning: implicit declaration of function 'RL_ISSTATE' is
invalid in C99 [-Wimplicit-function-declaration]
RL_ISSTATE(RL_STATE_ISEARCH) && /* isn't needed in other states? /
^
readline.c:178:13: error: use of undeclared identifier 'RL_STATE_ISEARCH'
RL_ISSTATE(RL_STATE_ISEARCH) && / isn't needed in other states? */
^
readline.c:182:21: warning: implicit declaration of function 'isascii' is
invalid in C99 [-Wimplicit-function-declaration]
if (FIXNUM_P(c) && isascii(FIX2INT(c))) meta = 1;
^
readline.c:184:12: warning: implicit declaration of function 'rl_execute_next'
is invalid in C99 [-Wimplicit-function-declaration]
if (meta) rl_execute_next(ESC);
^
readline.c:184:28: error: use of undeclared identifier 'ESC'
if (meta) rl_execute_next(ESC);
^
readline.c:185:9: error: use of undeclared identifier 'ESC'
return ESC;
^
editline does not have the ESC macro not the rl_readline_state variable (for RL_ISSTATE)
Checking for rl_readline_state in extconf.rb allows the second chunk of this patch to be ignored when compiled against editline, but I'm unsure how to update the test to get it to pass.
=end
Updated by naruse (Yui NARUSE) over 6 years ago
- Status changed from Assigned to Closed
ext/readline/readline.c: [Bug #6601]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36123 b2dd03c8-39d4-4d8f-98ff-823fe69b080e