summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-12 23:42:01 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-12 23:42:01 -0700
commit0c1bd0da13ec070f52f3144b50868fb4153471e5 (patch)
tree9c0bb2a66d07256cf27e684be591a7925683eb15
parent1bdd343418bdf65f8c7aa95ed21d6d0fe4730237 (diff)
downloadtxr-0c1bd0da13ec070f52f3144b50868fb4153471e5.tar.gz
txr-0c1bd0da13ec070f52f3144b50868fb4153471e5.tar.bz2
txr-0c1bd0da13ec070f52f3144b50868fb4153471e5.zip
linenoise: support completion in the middle of line.
* linenoise/linenoise.c (compare_completions): Restructure with help of new lino_copy function to collect completions just for the prefix of the line up to the cursor position, and recombine those with the suffix. * txr.1: Doc updated.
-rw-r--r--linenoise/linenoise.c32
-rw-r--r--txr.18
2 files changed, 23 insertions, 17 deletions
diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c
index 0ea057ab..5af71ed0 100644
--- a/linenoise/linenoise.c
+++ b/linenoise/linenoise.c
@@ -298,10 +298,17 @@ static int compare_completions(const void *larg, const void *rarg)
* structure as described in the structure definition. */
static int complete_line(lino_t *ls) {
lino_completions_t lc = { 0, NULL };
- int nread, nwritten;
+ int nread;
char c = 0;
+ char save = ls->data[ls->dpos];
+ lino_t *lt = lino_copy(ls);
+ if (lt == 0)
+ return -1;
+
+ ls->data[ls->dpos] = 0;
ls->completion_callback(ls->data, &lc, ls->cb_ctx);
+ ls->data[ls->dpos] = save;
qsort(lc.cvec, lc.len, sizeof *lc.cvec, compare_completions);
@@ -313,14 +320,12 @@ static int complete_line(lino_t *ls) {
while(!stop) {
/* Show completion or original buffer */
if (i < lc.len) {
- lino_t saved = *ls;
-
- ls->dpos = ls->dlen = strlen(lc.cvec[i]);
- strncpy(ls->data, lc.cvec[i], sizeof ls->data);
- ls->data[sizeof ls->data - 1] = 0;
- sync_data_to_buf(ls);
- refresh_line(ls);
- *ls = saved;
+ size_t n = snprintf(lt->data, sizeof lt->data,
+ "%s%s", lc.cvec[i], ls->data + ls->dpos);
+ lt->dlen = n;
+ lt->dpos = strlen(lc.cvec[i]);
+ sync_data_to_buf(lt);
+ refresh_line(lt);
} else {
refresh_line(ls);
}
@@ -328,11 +333,12 @@ static int complete_line(lino_t *ls) {
nread = read(ls->ifd,&c,1);
if (nread <= 0) {
free_completions(&lc);
+ free(lt);
ls->error = (nread < 0 ? lino_ioerr : lino_eof);
return -1;
}
- switch(c) {
+ switch (c) {
case TAB:
i = (i+1) % (lc.len+1);
if (i == lc.len) generate_beep(ls);
@@ -346,8 +352,9 @@ static int complete_line(lino_t *ls) {
default:
/* Update buffer and return */
if (i < lc.len) {
- nwritten = snprintf(ls->data, sizeof ls->data, "%s", lc.cvec[i]);
- ls->dpos = ls->dlen = nwritten;
+ ls->dpos = lt->dpos;
+ ls->dlen = lt->dlen;
+ strcpy(ls->data, lt->data);
sync_data_to_buf(ls);
refresh_line(ls);
}
@@ -358,6 +365,7 @@ static int complete_line(lino_t *ls) {
}
free_completions(&lc);
+ lino_free(lt);
return c; /* Return last read character */
}
diff --git a/txr.1 b/txr.1
index c7cf6171..c725465d 100644
--- a/txr.1
+++ b/txr.1
@@ -33601,13 +33601,11 @@ in that directory, then the history isn't saved.
.NP* Symbolic Completion
If the Tab key is pressed while editing a line, it is interpreted as a
-request for completion. This only happens if the cursor is at the end
-of the line (to the right of the rightmost character); completion in
-the middle of a line is not supported.
+request for completion.
When completion is invoked with the Tab key, the listener looks at a few of the
-trailing characters of the line in order to determine the applicable list of
-completions. Completions are determined from among the \*(TL symbols which have
+trailing characters to the left of the cursor position to determine the
+applicable list of completions. Completions are determined from among the \*(TL symbols which have
global variable, function, macro and symbolic macro bindings. Symbols which
have operator binding are also taken into consideration. If a
package-qualified symbol is completed, then completion is restricted to that