summaryrefslogtreecommitdiffstats
path: root/linenoise
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-06 13:03:18 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-06 13:03:18 -0700
commit7ffe8d302ab56ffe96023daf015a477934b7f17b (patch)
tree2a083344ce79ed4564361848e6d28b3dd36f88b4 /linenoise
parent52d027ad3df5905371519ba07ec9d2fe6150c21c (diff)
downloadtxr-7ffe8d302ab56ffe96023daf015a477934b7f17b.tar.gz
txr-7ffe8d302ab56ffe96023daf015a477934b7f17b.tar.bz2
txr-7ffe8d302ab56ffe96023daf015a477934b7f17b.zip
linenoise: error code distinguishes interrupt from eof.
In this commit, we introduce a persistent error variable stored in the lino_t structure, and functions to access it. * linenoise/linenoise.c (struct lino_state): New member, error. (enable_raw_mode): Don't set errno to ENOTTY; set linenoise error to lino_notty. (complete_line, edit, go_raw, linenoise, lino_hist_save, lino_hist_load): Set linenoise error before returning -1. (lino_get_error, lino_set_error): New functions. * linenoise/linenoise.h (enum lino_error, lino_error_t): New enum. (lino_get_error, lino_set_error): Declared.
Diffstat (limited to 'linenoise')
-rw-r--r--linenoise/linenoise.c53
-rw-r--r--linenoise/linenoise.h11
2 files changed, 55 insertions, 9 deletions
diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c
index b44d4450..d64e9f7c 100644
--- a/linenoise/linenoise.c
+++ b/linenoise/linenoise.c
@@ -153,6 +153,7 @@ struct lino_state {
size_t cols; /* Number of columns in terminal. */
size_t maxrows; /* Maximum num of rows used so far (multiline mode) */
int history_index; /* The history index we are currently editing. */
+ lino_error_t error; /* Most recent error. */
};
enum key_action {
@@ -260,7 +261,7 @@ static int enable_raw_mode(lino_t *ls) {
return 0;
fatal:
- errno = ENOTTY;
+ ls->error = lino_notty;
return -1;
}
@@ -390,6 +391,7 @@ static int complete_line(lino_t *ls) {
nread = read(ls->ifd,&c,1);
if (nread <= 0) {
free_completions(&lc);
+ ls->error = (nread < 0 ? lino_ioerr : lino_eof);
return -1;
}
@@ -797,7 +799,10 @@ static int edit(lino_t *l, const char *prompt)
* initially is just an empty string. */
lino_hist_add(l, "");
- if (write(l->ofd,prompt,l->plen) == -1) return -1;
+ if (write(l->ofd,prompt,l->plen) == -1) {
+ l->error = lino_ioerr;
+ return -1;
+ }
while(1) {
char c;
int nread;
@@ -808,7 +813,10 @@ static int edit(lino_t *l, const char *prompt)
return l->len ? (int) l->len : -1;
if (verbatim) {
- if (edit_insert(l,c)) return -1;
+ if (edit_insert(l,c)) {
+ l->error = lino_ioerr;
+ return -1;
+ }
verbatim = 0;
continue;
}
@@ -834,7 +842,7 @@ static int edit(lino_t *l, const char *prompt)
if (l->mlmode) edit_move_end(l);
return (int)l->len;
case CTRL_C:
- errno = EAGAIN;
+ l->error = lino_intr;
return -1;
case BACKSPACE: /* backspace */
case CTRL_H:
@@ -850,6 +858,7 @@ static int edit(lino_t *l, const char *prompt)
free(l->history[l->history_len]);
l->history[l->history_len] = 0;
}
+ l->error = lino_eof;
return -1;
}
break;
@@ -930,7 +939,10 @@ static int edit(lino_t *l, const char *prompt)
}
break;
default:
- if (edit_insert(l,c)) return -1;
+ if (edit_insert(l,c)) {
+ l->error = lino_ioerr;
+ return -1;
+ }
break;
case CTRL_U: /* delete the whole line. */
l->data[0] = '\0';
@@ -1000,7 +1012,10 @@ static int go_raw(lino_t *ls, const char *prompt)
if (!isatty(STDIN_FILENO)) {
char buf[LINENOISE_MAX_LINE];
/* Not a tty: read from file / pipe. */
- if (fgets(buf, sizeof buf, stdin) == NULL) return -1;
+ if (fgets(buf, sizeof buf, stdin) == NULL) {
+ ls->error = (ferror(stdin) ? lino_ioerr : lino_eof);
+ return -1;
+ }
count = strlen(buf);
if (count && buf[count-1] == '\n') {
count--;
@@ -1011,7 +1026,8 @@ static int go_raw(lino_t *ls, const char *prompt)
if (enable_raw_mode(ls) == -1) return -1;
count = edit(ls, prompt);
disable_raw_mode(ls);
- printf("\n");
+ if (count != -1 || ls->error == lino_eof)
+ printf("\n");
}
return count;
}
@@ -1079,6 +1095,18 @@ char *linenoise(lino_t *ls, const char *prompt) {
}
}
+lino_error_t lino_get_error(lino_t *l)
+{
+ return l->error;
+}
+
+lino_error_t lino_set_error(lino_t *l, lino_error_t set)
+{
+ lino_error_t old = l->error;
+ l->error = set;
+ return old;
+}
+
/* ================================ History ================================= */
/* Free the history, but does not reset it. Only used when we have to
@@ -1178,7 +1206,11 @@ int lino_hist_save(lino_t *ls, const char *filename) {
FILE *fp = fopen(filename,"w");
int j;
- if (fp == NULL) return -1;
+ if (fp == NULL) {
+ ls->error = lino_error;
+ return -1;
+ }
+
for (j = 0; j < ls->history_len; j++)
fprintf(fp,"%s\n",ls->history[j]);
fclose(fp);
@@ -1194,7 +1226,10 @@ int lino_hist_load(lino_t *ls, const char *filename) {
FILE *fp = fopen(filename,"r");
char buf[LINENOISE_MAX_LINE];
- if (fp == NULL) return -1;
+ if (fp == NULL) {
+ ls->error = lino_error;
+ return -1;
+ }
while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {
char *p;
diff --git a/linenoise/linenoise.h b/linenoise/linenoise.h
index acf9ffe2..0822a59b 100644
--- a/linenoise/linenoise.h
+++ b/linenoise/linenoise.h
@@ -36,6 +36,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+typedef enum lino_error {
+ lino_no_error, /* No error has occurred. */
+ lino_error, /* Unspecified error */
+ lino_eof, /* Line input terminated by Ctrl-D or EOF. */
+ lino_ioerr, /* Line input terminated by I/O error. */
+ lino_notty, /* Input is not a terminal. */
+ lino_intr /* Line innput terminated by Ctrl-C or interrupt */
+} lino_error_t;
+
typedef struct lino_state lino_t;
typedef struct lino_completions {
@@ -51,6 +60,8 @@ lino_t *lino_make(int ifd, int ofd);
void lino_free(lino_t *);
char *linenoise(lino_t *, const char *prompt);
+lino_error_t lino_get_error(lino_t *);
+lino_error_t lino_set_error(lino_t *, lino_error_t); /* returns old */
int lino_hist_add(lino_t *, const char *line);
int lino_hist_set_max_len(lino_t *, int len);
int lino_hist_save(lino_t *, const char *filename);