Skip to content

Commit

Permalink
Hints WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
antirez committed Apr 12, 2016
1 parent d97e766 commit 12a8680
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 1 deletion.
6 changes: 6 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ MongoDB, and Android.
* 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).

Expand Down Expand Up @@ -51,3 +52,8 @@ Patches should be provided in the respect of linenoise sensibility for small
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.
10 changes: 10 additions & 0 deletions example.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ void completion(const char *buf, linenoiseCompletions *lc) {
}
}

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];
Expand All @@ -34,6 +43,7 @@ int main(int argc, char **argv) {
/* 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. */
Expand Down
42 changes: 41 additions & 1 deletion linenoise.c
Original file line number Diff line number Diff line change
Expand Up @@ -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*/
Expand Down Expand Up @@ -407,6 +409,18 @@ void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
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
Expand Down Expand Up @@ -456,6 +470,27 @@ static void abFree(struct abuf *ab) {
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,
Expand Down Expand Up @@ -485,6 +520,8 @@ static void refreshSingleLine(struct linenoiseState *l) {
/* 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));
Expand Down Expand Up @@ -538,6 +575,9 @@ static void refreshMultiLine(struct linenoiseState *l) {
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 &&
Expand Down Expand Up @@ -598,7 +638,7 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
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;
Expand Down
4 changes: 4 additions & 0 deletions linenoise.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ typedef struct linenoiseCompletions {
} 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);
Expand Down

0 comments on commit 12a8680

Please sign in to comment.