GNU readline(3) regards history chronologically, that is, from the
perspective of the dawn of time, so "next" means "newer" and "previous" means "older". Libedit, by contrast, uses reverse chronology and regards history from the perspective of the present, such that "next" means "longer ago" and "previous" means "not so long ago". The following patch fixes previous_history() and next_history() as proposed by Bastian Maerkisch. But there is a related problem demonstrated by Bastian's regression tests that his patch did not fix: next_history() can advance not only to the newest entry, but beyond it, which core libedit cannot do. So that feature must be implemented locally in readline.c. With that, the last of Bastians tests is fixed, test_movement_direction(). This patch also improves libedit documentation to more clearly state what "previous" and "next" mean. GNU readline documentation is just as unclear, but we can't easily fix that since libedit doesn't include its own readline.3 manual. (Ingo Schwarze)
This commit is contained in:
parent
05b61ce72a
commit
f9ed317e87
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: editline.3,v 1.89 2016/04/28 15:50:33 christos Exp $
|
||||
.\" $NetBSD: editline.3,v 1.90 2016/05/09 21:27:55 christos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997-2014 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
@ -26,7 +26,7 @@
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd February 24, 2016
|
||||
.Dd May 9, 2016
|
||||
.Dt EDITLINE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -761,8 +761,10 @@ Return the first element in the history.
|
||||
Return the last element in the history.
|
||||
.It Dv H_PREV
|
||||
Return the previous element in the history.
|
||||
It is newer than the current one.
|
||||
.It Dv H_NEXT
|
||||
Return the next element in the history.
|
||||
It is older than the current one.
|
||||
.It Dv H_CURR
|
||||
Return the current element in the history.
|
||||
.It Dv H_SET
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: editline.7,v 1.4 2016/05/02 12:51:25 wiz Exp $
|
||||
.\" $NetBSD: editline.7,v 1.5 2016/05/09 21:27:55 christos Exp $
|
||||
.\" $OpenBSD: editline.7,v 1.1 2016/04/20 01:11:45 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd May 2, 2016
|
||||
.Dd May 7, 2016
|
||||
.Dt EDITLINE 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -408,6 +408,7 @@ It is an error if the cursor is already at the end of the edit
|
||||
buffer.
|
||||
.It Ic ed-next-history Pq vi command: j, +, Ctrl-N; emacs: Ctrl-N
|
||||
Replace the edit buffer with the next history line.
|
||||
That line is older than the current line.
|
||||
With an argument, go forward by that number of history lines.
|
||||
It is a non-fatal error to advance by more lines than are available.
|
||||
.It Ic ed-next-line Pq not bound by default
|
||||
@ -427,6 +428,7 @@ It is an error if the cursor is already at the beginning of the
|
||||
edit buffer.
|
||||
.It Ic ed-prev-history Pq vi command: k, -, Ctrl-P; emacs: Ctrl-P
|
||||
Replace the edit buffer with the previous history line.
|
||||
That line is newer than the current line.
|
||||
With an argument, go back by that number of lines.
|
||||
It is a non-fatal error to back up by more lines than are available.
|
||||
.It Ic ed-prev-line Pq not bound by default
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: readline.c,v 1.131 2016/05/09 21:25:11 christos Exp $ */
|
||||
/* $NetBSD: readline.c,v 1.132 2016/05/09 21:27:55 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#if !defined(lint) && !defined(SCCSID)
|
||||
__RCSID("$NetBSD: readline.c,v 1.131 2016/05/09 21:25:11 christos Exp $");
|
||||
__RCSID("$NetBSD: readline.c,v 1.132 2016/05/09 21:27:55 christos Exp $");
|
||||
#endif /* not lint && not SCCSID */
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -156,6 +156,14 @@ char *rl_special_prefixes = NULL;
|
||||
*/
|
||||
int rl_completion_append_character = ' ';
|
||||
|
||||
/*
|
||||
* When the history cursor is on the newest element and next_history()
|
||||
* is called, GNU readline moves the cursor beyond the newest element.
|
||||
* The editline library does not provide data structures to express
|
||||
* that state, so we need a local flag.
|
||||
*/
|
||||
static int current_history_valid = 1;
|
||||
|
||||
/* stuff below is used internally by libedit for readline emulation */
|
||||
|
||||
static History *h = NULL;
|
||||
@ -291,6 +299,8 @@ rl_initialize(void)
|
||||
int editmode = 1;
|
||||
struct termios t;
|
||||
|
||||
current_history_valid = 1;
|
||||
|
||||
if (e != NULL)
|
||||
el_end(e);
|
||||
if (h != NULL)
|
||||
@ -1451,6 +1461,7 @@ add_history(const char *line)
|
||||
(void)history(h, &ev, H_ENTER, line);
|
||||
if (history(h, &ev, H_GETSIZE) == 0)
|
||||
history_length = ev.num;
|
||||
current_history_valid = 1;
|
||||
|
||||
return !(history_length > 0); /* return 0 if all is okay */
|
||||
}
|
||||
@ -1543,6 +1554,7 @@ clear_history(void)
|
||||
|
||||
(void)history(h, &ev, H_CLEAR);
|
||||
history_length = 0;
|
||||
current_history_valid = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1575,7 +1587,7 @@ HIST_ENTRY *
|
||||
current_history(void)
|
||||
{
|
||||
|
||||
return _move_history(H_CURR);
|
||||
return current_history_valid ? _move_history(H_CURR) : NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -1620,6 +1632,7 @@ history_set_pos(int pos)
|
||||
|
||||
(void)history(h, &ev, H_CURR);
|
||||
curr_num = ev.num;
|
||||
current_history_valid = 1;
|
||||
|
||||
/*
|
||||
* use H_DELDATA to set to nth history (without delete) by passing
|
||||
@ -1635,12 +1648,17 @@ history_set_pos(int pos)
|
||||
|
||||
/*
|
||||
* returns previous event in history and shifts pointer accordingly
|
||||
* Note that readline and editline define directions in opposite ways.
|
||||
*/
|
||||
HIST_ENTRY *
|
||||
previous_history(void)
|
||||
{
|
||||
|
||||
return _move_history(H_PREV);
|
||||
if (current_history_valid == 0) {
|
||||
current_history_valid = 1;
|
||||
return _move_history(H_CURR);
|
||||
}
|
||||
return _move_history(H_NEXT);
|
||||
}
|
||||
|
||||
|
||||
@ -1650,8 +1668,12 @@ previous_history(void)
|
||||
HIST_ENTRY *
|
||||
next_history(void)
|
||||
{
|
||||
HIST_ENTRY *he;
|
||||
|
||||
return _move_history(H_NEXT);
|
||||
he = _move_history(H_PREV);
|
||||
if (he == NULL)
|
||||
current_history_valid = 0;
|
||||
return he;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user