Hints WIP
diff --git a/README.markdown b/README.markdown
index a0661a0..a876428 100644
--- a/README.markdown
+++ b/README.markdown
@@ -6,6 +6,7 @@
* Single and multi line editing mode with the usual key bindings implemented.
* History handling.
* Completion.
+* Hints (suggestions at the right of the prompt as you type).
* About 1,100 lines of BSD license source code.
* Only uses a subset of VT100 escapes (ANSI.SYS compatible).
@@ -51,3 +52,8 @@
easy to understand code.
Send feedbacks to antirez at gmail
+
+## The API
+
+Linenoise is very easy to use, and reading the example shipped with the
+library will make it trivial.
diff --git a/example.c b/example.c
index a2f0936..3a544d3 100644
--- a/example.c
+++ b/example.c
@@ -11,6 +11,15 @@
}
}
+char *hints(const char *buf, int *color, int *bold) {
+ if (!strcasecmp(buf,"hello")) {
+ *color = 35;
+ *bold = 0;
+ return " World";
+ }
+ return NULL;
+}
+
int main(int argc, char **argv) {
char *line;
char *prgname = argv[0];
@@ -34,6 +43,7 @@
/* Set the completion callback. This will be called every time the
* user uses the <tab> key. */
linenoiseSetCompletionCallback(completion);
+ linenoiseSetHintsCallback(hints);
/* Load history from file. The history file is just a plain text file
* where entries are separated by newlines. */
diff --git a/linenoise.c b/linenoise.c
index 30d64ec..193adff 100644
--- a/linenoise.c
+++ b/linenoise.c
@@ -120,6 +120,8 @@
#define LINENOISE_MAX_LINE 4096
static char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
static linenoiseCompletionCallback *completionCallback = NULL;
+static linenoiseHintsCallback *hintsCallback = NULL;
+static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
static struct termios orig_termios; /* In order to restore at exit.*/
static int rawmode = 0; /* For atexit() function to check if restore is needed*/
@@ -407,6 +409,18 @@
completionCallback = fn;
}
+/* Register a hits function to be called to show hits to the user at the
+ * right of the prompt. */
+void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {
+ hintsCallback = fn;
+}
+
+/* Register a function to free the hints returned by the hints callback
+ * registered with linenoiseSetHintsCallback(). */
+void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
+ freeHintsCallback = fn;
+}
+
/* This function is used by the callback function registered by the user
* in order to add completion options given the input string when the
* user typed <tab>. See the example.c source code for a very easy to
@@ -456,6 +470,27 @@
free(ab->b);
}
+/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
+ * to the right of the prompt. */
+void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
+ char seq[64];
+ if (hintsCallback && plen+l->len < l->cols) {
+ int color, bold;
+ char *hint = hintsCallback(l->buf,&color,&bold);
+ if (hint) {
+ int hintlen = strlen(hint);
+ int hintmaxlen = l->cols-(plen+l->len);
+ if (hintlen > hintmaxlen) hintlen = hintmaxlen;
+ snprintf(seq,64,"\033[%d;%d;49m",bold,color);
+ abAppend(ab,seq,strlen(seq));
+ abAppend(ab,hint,hintlen);
+ abAppend(ab,"\033[0m",4);
+ /* Call the function to free the hint returned. */
+ if (freeHintsCallback) freeHintsCallback(hint);
+ }
+ }
+}
+
/* Single line low level line refresh.
*
* Rewrite the currently edited line accordingly to the buffer content,
@@ -485,6 +520,8 @@
/* Write the prompt and the current buffer content */
abAppend(&ab,l->prompt,strlen(l->prompt));
abAppend(&ab,buf,len);
+ /* Show hits if any. */
+ refreshShowHints(&ab,l,plen);
/* Erase to right */
snprintf(seq,64,"\x1b[0K");
abAppend(&ab,seq,strlen(seq));
@@ -538,6 +575,9 @@
abAppend(&ab,l->prompt,strlen(l->prompt));
abAppend(&ab,l->buf,l->len);
+ /* Show hits if any. */
+ refreshShowHints(&ab,l,plen);
+
/* If we are at the very end of the screen with our prompt, we need to
* emit a newline and move the prompt to the first column. */
if (l->pos &&
@@ -598,7 +638,7 @@
l->pos++;
l->len++;
l->buf[l->len] = '\0';
- if ((!mlmode && l->plen+l->len < l->cols) /* || mlmode */) {
+ if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
/* Avoid a full update of the line in the
* trivial case. */
if (write(l->ofd,&c,1) == -1) return -1;
diff --git a/linenoise.h b/linenoise.h
index fbb01cf..b1d0a80 100644
--- a/linenoise.h
+++ b/linenoise.h
@@ -49,7 +49,11 @@
} linenoiseCompletions;
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
+typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);
+typedef char*(linenoiseFreeHintsCallback)(char *);
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
+void linenoiseSetHintsCallback(linenoiseHintsCallback *);
+void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
void linenoiseAddCompletion(linenoiseCompletions *, const char *);
char *linenoise(const char *prompt);