summaryrefslogtreecommitdiff
path: root/lib/libedit
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2016-05-09 21:27:55 +0000
committerchristos <christos@NetBSD.org>2016-05-09 21:27:55 +0000
commit673b05f0edde75e70ac25cd2cc5d9d91a95b5cfa (patch)
treebde220e53365a70a89a357fa744c02ce1194a0d1 /lib/libedit
parent7e99177d9c5deab0ce5a9d53ee54e0c5e4b1104b (diff)
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)
Diffstat (limited to 'lib/libedit')
-rw-r--r--lib/libedit/editline.36
-rw-r--r--lib/libedit/editline.76
-rw-r--r--lib/libedit/readline.c32
3 files changed, 35 insertions, 9 deletions
diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3
index 962828f4947..8b21d421b7c 100644
--- a/lib/libedit/editline.3
+++ b/lib/libedit/editline.3
@@ -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
diff --git a/lib/libedit/editline.7 b/lib/libedit/editline.7
index ebee605c7b4..863bab96d51 100644
--- a/lib/libedit/editline.7
+++ b/lib/libedit/editline.7
@@ -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
diff --git a/lib/libedit/readline.c b/lib/libedit/readline.c
index 9c2fba77c9d..4c54aef28ec 100644
--- a/lib/libedit/readline.c
+++ b/lib/libedit/readline.c
@@ -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;
}