don't set unbuffered unless they've already printed the prompt.
This avoids printing the prompt before the application has a chance
to process the input line.
From sjg@
Also, remove a test case which was not supposed to be there.
(While that test case works with the changes I committed, testing that
test case with the test program is not possible in its current form. I'm
working on that.)
For instance if the file name is "foo bar":
$ ls foo<TAB>
should get autocompleted to:
$ ls foo\ bar
Works for similar other characters too, which need escaping.
Also, add an accompanying test program to ensure the escaping is correct
in various scenarios (within quotes, without quotes, with other special characeters)
Thanks to Christos for reviews, help and feedback.
Patch from Yen Chi Hsuan in the PR, extracted from Apple's version of
readline.c, then modified by me to be consistent about what the return
value really is.
PR/51518: Jay West: prompt is interleaved with client output
Both these issues are caused by rl_restore_handler not DTRT; fix
it so that it kills the internal libedit state completely. This is
inefficient, but it works.
Also fix:
1. add append_history()/H_NSAVE_FP
2. call the rl_startup_hook before printing the first prompt as documented.
callint it from rl_initialize breaks python, because the callback ends
up being invoked before the readline module is installed, and we end up
dereferencing a NULL pointer.
3. add el_resize_terminal.
With those changes, s/lreadline/ledit/g in python works.
to be (perhaps part of) the "invisible" characters in a prompt, or the
required prompt character which follows the literal sequence (this character
must be one with a printing column width >= 1). The literal indicator
character (which is just a marker, and not printed anywhere) (the PSlit
parameter in sh(1)) can also be a wide char (passed to libedit as a wchar_t,
encoded as that by sh(1) or other applications that support this.)
Note: this has currently only been tested with everything ascii (C locale).
with the trailing newline, others don't so don't make any assumptions
about it when printing. Also print the correct event number (generated),
separate the event number from the event with a tab, and visually encode
the string (don't encode tabs and spaces though).
For example if you do
$mkdir -p /tmp/dir1/dir2
Then:
$ls /tmp/di <TAB> auto completes to
$ls /tmp/dir1/
Hitting <TAB> again auto completes to
$ls /tmp/dir1/dir2
Whereas it should auto complete to
$ls /tmp/dir1/dir2/
Essentially, in cases like above where you have to hit <TAB> twice to get
to the match and there is only one match (because only one file/sub-directory) then
auto complete doesn't work correctly. It doesn't append a trailing slash (in case
of directory) or a space (in case of a file) to the match name.
I have tested file name completion in sh(1) and symbol completion in gdb after
this change.
In libedit, the only way how H_ENTER can fail is memory exhaustion,
too, and of course it is handled gracefully, returning -1 from
history(). So of course, we will continue to handle it gracefully
in add_history() as well, but we are free to decide what to do with
the library state in this case because GNU just dies...
I think the most reasonable course of action is to simply not change
the library state in any way when add_history() fails due to memory
exhaustion, but just return.
If H_ENTER does not fail, we know that the history now contains at
least one entry, so there is no need any longer to check the H_GETSIZE
return value. And we can of course always set current_history_valid.
While testing these changes, i noticed three problems so closely
related that i'd like to fix them in the same diff.
1. libedit has the wrong prototype for add_history().
GNU readline-6.3 defines it as void add_history(const char *).
Of course, that is very stupid - no way to report problems to
the caller! But the whole point of a compatibility mode is
being compatible, so we should ultimately change this.
Of course, changing the prototype of a public symbol requires
a libedit major bump. I don't want to do that casually.
Rather, i will take a note and change the prototype the next
time we need a libedit major bump for more important reasons.
For now, let's just always return 0.
2. While *implicitely* pushing an old entry off the history
increments history_base in GNU readline, testing reveals that
*explicitly* deleting one does not. Again, this is not
documented, but it applies to both remove_history() and
stifle_history(). So delete history_base manipulation
from stifle_history(), which also allows to simplify the
code and delete two automatic variables.
3. GNU readline add_history(NULL) crashes with a segfault.
There is nothing wrong with having a public interface
behave that way. Many standard interfaces do, including
strlen(3). Such crashes can even be useful to catch
buggy application programs.
In libedit/readline.c rev. 1.104, Christos made add_history()
silently ignore this coding error, according to the commit
message to hide a bug in nslookup(1). That change was never
merged to OpenBSD. I strongly disagree with this change.
If nslookup(1) is still broken, that program needs to be
fixed instead. In any case, delete the bogus check; hiding
bugs is dangerous.
Reduce obfuscation of errno handling. There is only one purpose
non-local errno handling is needed for: Inside el_wgets(), several
functions call down indirectly to el_wgetc(), many of them via the
dispatch table. When el_wgetc() fails, it does properly report
failure, but then various cleanup is done which may clobber errno.
But when returning due to failure, el_wgets() wants to have errno
set to the reason of the original read failure, not to the reason
of some subsequent failure of some cleanup operation. So el_wgetc()
needs to save errno, and if it's non-zero, el_wgets() needs to
restore it on failure.
This core logic is currently obscured by the fact that el_errno
is set and inspected at some additional places where it isn't needed.
Besides, since el_wgetc() and and el_wgets() are both in read.c,
el_errno does not need to be in struct editline, it can and should
be local to read.c in struct el_read_t.
Let's look at what can be simplified.
1. keymacro_get() abuses el_errno instead of having a proper
error return code. Adding that error return code is easy
because node_trav() already detects the condition and an
adequate code is already defined. Returning it, testing
for it in read_getcmd(), and returning with error from there
removes the need to inspect el_errno from el_wgets() after
calling read_getcmd().
Note that resetting lastchar and cursor and clearing buffer[0]
is irrelevant. The code returns from el_wgets() right afterwards.
Outside el_wgets(), these variables are no longer relevant.
When el_wgets() is called the next time, it will call ch_reset()
anyway, resetting the two pointers. And as long as lastchar
points to the beginning of the buffer, the contents of the
buffer won't be used for anything.
2. read_getcmd() doesn't need to set el_errno again after el_wgetc()
failure since el_wgetc() already did so. While here, remove
the silly "if EOF or error" comments from the el_wgetc()
return value tests. It's a public interface documented in a
manual, so people working on the implementation can obviously
be expected to know how it works. It's a case of
count++; /* Increment count. */
3. In the two code paths of el_wgets() that lead up to "goto noedit",
there is no need to save the errno because nothing that might
change it happens before returning.
For clarity, since el_wgets() is the function restoring the errno,
also move initializing it to the same function.
Finally, note that restoring errno when the saved value is zero is
wrong. No library code is ever allowed to clear a previously set
value of errno. Only application programs are allowed to do that,
and even they usually don't need to do so, except when using certain
ill-designed interfaces like strtol(3).
I tested that the behaviour remains sane in the following cases,
all during execution of el_wgets(3) and with a signal handler
for USR1 installed without SA_RESTART.
* Enter some text and maybe move around a bit.
Then send a USR1 signal.
The signal gets processed, then read_char() resumes reading.
Send another USR1 signal.
Now el_wgets() sets errno=EINTR and returns -1.
* Press Ctrl-V to activate ed-quoted-insert.
Then send a USR1 signal.
The signal gets processed, then read_char() resumes reading.
Send another USR1 signal.
ed_quoted_insert() returns ed_end_of_file(), i.e. CC_EOF,
and el_wgets() returns 0.
* Press a key starting a keyboard macro.
Then send a USR1 signal.
The signal gets processed, then read_char() resumes reading.
Send another USR1 signal.
Now el_wgets() sets errno=EINTR and returns -1.
* Press : to enter builtin command mode.
Start typing a command.
Then send a USR1 signal.
The signal gets processed, then read_char() resumes reading.
Send another USR1 signal.
Now c_gets() returns -1, ed_command() beeps and returns CC_REFRESH,
and el_wgets() resumes operation as it should.
I also tested with "el_set(el, EL_EDITMODE, 0)", and it returns
the right value and sets errno correctly.