X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=src%2Flib%2Fcmdline_rdline.c;h=7f3494640a3029501a4f8be2d5177d45dfdc04cd;hb=f32d30f48ddfb55b86efd695e0dd144e9d15401e;hp=5783d6598064b0740601a797c35e10ab24d4fcdc;hpb=504b523d94543a7bb7301a3b1bfe929aabf7fb36;p=libcmdline.git diff --git a/src/lib/cmdline_rdline.c b/src/lib/cmdline_rdline.c index 5783d65..7f34946 100644 --- a/src/lib/cmdline_rdline.c +++ b/src/lib/cmdline_rdline.c @@ -65,13 +65,11 @@ #include #include #include +#include #include "cmdline_cirbuf.h" #include "cmdline_rdline.h" - -static void rdline_puts(struct rdline *rdl, const char *buf); -static void rdline_miniprintf(struct rdline *rdl, - const char *buf, unsigned int val); +#include "cmdline_parse.h" #ifndef NO_RDLINE_HISTORY static void rdline_remove_old_history_item(struct rdline *rdl); @@ -93,14 +91,17 @@ isblank2(char c) void rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, - rdline_validate_t *validate, - rdline_complete_t *complete) + int fd_in, int fd_out, + rdline_validate_t *validate, + rdline_complete_t *complete, + rdline_help_t *help) { memset(rdl, 0, sizeof(*rdl)); + rdl->fd_in = fd_in; + rdl->fd_out = fd_out; rdl->validate = validate; rdl->complete = complete; - rdl->write_char = write_char; + rdl->help = help; rdl->status = RDLINE_INIT; #ifndef NO_RDLINE_HISTORY cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); @@ -110,18 +111,15 @@ rdline_init(struct rdline *rdl, void rdline_newline(struct rdline *rdl, const char *prompt) { - unsigned int i; - vt100_init(&rdl->vt100); cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); + /* if pointer is the same, don't copy it */ if (prompt != rdl->prompt) - memcpy(rdl->prompt, prompt, sizeof(rdl->prompt)-1); - rdl->prompt_size = strlen(prompt); + snprintf(rdl->prompt, sizeof(rdl->prompt), "%s", prompt); - for (i=0 ; iprompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); + rdline_printf(rdl, "%s", rdl->prompt); rdl->status = RDLINE_RUNNING; #ifndef NO_RDLINE_HISTORY @@ -158,8 +156,7 @@ rdline_get_buffer(struct rdline *rdl) len_r = CIRBUF_GET_LEN(&rdl->right); memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r); - rdl->left_buf[len_l + len_r] = '\n'; - rdl->left_buf[len_l + len_r + 1] = '\0'; + rdl->left_buf[len_l + len_r] = '\0'; return rdl->left_buf; } @@ -172,13 +169,13 @@ display_right_buffer(struct rdline *rdl, int force) if (!force && CIRBUF_IS_EMPTY(&rdl->right)) return; - rdline_puts(rdl, vt100_clear_right); + rdline_printf(rdl, vt100_clear_right); CIRBUF_FOREACH(&rdl->right, i, tmp) { - rdl->write_char(rdl, tmp); + rdline_printf(rdl, "%c", tmp); } if (!CIRBUF_IS_EMPTY(&rdl->right)) - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->right)); + rdline_printf(rdl, vt100_multi_left, + CIRBUF_GET_LEN(&rdl->right)); } void @@ -187,17 +184,16 @@ rdline_redisplay(struct rdline *rdl) unsigned int i; char tmp; - rdline_puts(rdl, vt100_home); - for (i=0 ; iprompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); + rdline_printf(rdl, vt100_home); + rdline_printf(rdl, "%s", rdl->prompt); CIRBUF_FOREACH(&rdl->left, i, tmp) { - rdl->write_char(rdl, tmp); + rdline_printf(rdl, "%c", tmp); } display_right_buffer(rdl, 1); } -int -rdline_char_in(struct rdline *rdl, char c) +static int +rdline_parse_char(struct rdline *rdl, char c) { unsigned int i; int cmd; @@ -206,11 +202,6 @@ rdline_char_in(struct rdline *rdl, char c) char *buf; #endif - if (rdl->status == RDLINE_EXITED) - return RDLINE_RES_EXITED; - if (rdl->status != RDLINE_RUNNING) - return RDLINE_RES_NOT_RUNNING; - cmd = vt100_parser(&rdl->vt100, c); if (cmd == VT100_NOT_COMPLETE) return RDLINE_RES_SUCCESS; @@ -224,7 +215,7 @@ rdline_char_in(struct rdline *rdl, char c) tmp = cirbuf_get_tail(&rdl->left); cirbuf_del_tail(&rdl->left); cirbuf_add_head(&rdl->right, tmp); - rdline_puts(rdl, vt100_left_arr); + rdline_printf(rdl, vt100_left_arr); break; case CMDLINE_KEY_CTRL_F: @@ -234,21 +225,21 @@ rdline_char_in(struct rdline *rdl, char c) tmp = cirbuf_get_head(&rdl->right); cirbuf_del_head(&rdl->right); cirbuf_add_tail(&rdl->left, tmp); - rdline_puts(rdl, vt100_right_arr); + rdline_printf(rdl, vt100_right_arr); break; case CMDLINE_KEY_WLEFT: while (! CIRBUF_IS_EMPTY(&rdl->left) && (tmp = cirbuf_get_tail(&rdl->left)) && isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); + rdline_printf(rdl, vt100_left_arr); cirbuf_del_tail(&rdl->left); cirbuf_add_head(&rdl->right, tmp); } while (! CIRBUF_IS_EMPTY(&rdl->left) && (tmp = cirbuf_get_tail(&rdl->left)) && !isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); + rdline_printf(rdl, vt100_left_arr); cirbuf_del_tail(&rdl->left); cirbuf_add_head(&rdl->right, tmp); } @@ -258,14 +249,14 @@ rdline_char_in(struct rdline *rdl, char c) while (! CIRBUF_IS_EMPTY(&rdl->right) && (tmp = cirbuf_get_head(&rdl->right)) && isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); + rdline_printf(rdl, vt100_right_arr); cirbuf_del_head(&rdl->right); cirbuf_add_tail(&rdl->left, tmp); } while (! CIRBUF_IS_EMPTY(&rdl->right) && (tmp = cirbuf_get_head(&rdl->right)) && !isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); + rdline_printf(rdl, vt100_right_arr); cirbuf_del_head(&rdl->right); cirbuf_add_tail(&rdl->left, tmp); } @@ -273,28 +264,32 @@ rdline_char_in(struct rdline *rdl, char c) case CMDLINE_KEY_BKSPACE: if(!cirbuf_del_tail_safe(&rdl->left)) { - rdline_puts(rdl, vt100_bs); + rdline_printf(rdl, vt100_bs); display_right_buffer(rdl, 1); } break; case CMDLINE_KEY_META_BKSPACE: case CMDLINE_KEY_CTRL_W: - while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); + while (! CIRBUF_IS_EMPTY(&rdl->left) && + isblank2(cirbuf_get_tail(&rdl->left))) { + rdline_printf(rdl, vt100_bs); cirbuf_del_tail(&rdl->left); } - while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); + while (! CIRBUF_IS_EMPTY(&rdl->left) && + !isblank2(cirbuf_get_tail(&rdl->left))) { + rdline_printf(rdl, vt100_bs); cirbuf_del_tail(&rdl->left); } display_right_buffer(rdl, 1); break; case CMDLINE_KEY_META_D: - while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right))) + while (! CIRBUF_IS_EMPTY(&rdl->right) && + isblank2(cirbuf_get_head(&rdl->right))) cirbuf_del_head(&rdl->right); - while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right))) + while (! CIRBUF_IS_EMPTY(&rdl->right) && + !isblank2(cirbuf_get_head(&rdl->right))) cirbuf_del_head(&rdl->right); display_right_buffer(rdl, 1); break; @@ -314,8 +309,8 @@ rdline_char_in(struct rdline *rdl, char c) case CMDLINE_KEY_CTRL_A: if (CIRBUF_IS_EMPTY(&rdl->left)) break; - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->left)); + rdline_printf(rdl, vt100_multi_left, + CIRBUF_GET_LEN(&rdl->left)); while (! CIRBUF_IS_EMPTY(&rdl->left)) { tmp = cirbuf_get_tail(&rdl->left); cirbuf_del_tail(&rdl->left); @@ -326,8 +321,8 @@ rdline_char_in(struct rdline *rdl, char c) case CMDLINE_KEY_CTRL_E: if (CIRBUF_IS_EMPTY(&rdl->right)) break; - rdline_miniprintf(rdl, vt100_multi_right, - CIRBUF_GET_LEN(&rdl->right)); + rdline_printf(rdl, vt100_multi_right, + CIRBUF_GET_LEN(&rdl->right)); while (! CIRBUF_IS_EMPTY(&rdl->right)) { tmp = cirbuf_get_head(&rdl->right); cirbuf_del_head(&rdl->right); @@ -340,7 +335,7 @@ rdline_char_in(struct rdline *rdl, char c) cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE); rdl->kill_size = CIRBUF_GET_LEN(&rdl->right); cirbuf_del_buf_head(&rdl->right, rdl->kill_size); - rdline_puts(rdl, vt100_clear_right); + rdline_printf(rdl, vt100_clear_right); break; case CMDLINE_KEY_CTRL_Y: @@ -349,7 +344,7 @@ rdline_char_in(struct rdline *rdl, char c) RDLINE_BUF_SIZE && i < rdl->kill_size) { cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]); - rdl->write_char(rdl, rdl->kill_buf[i]); + rdline_printf(rdl, "%c", rdl->kill_buf[i]); i++; } display_right_buffer(rdl, 0); @@ -357,7 +352,7 @@ rdline_char_in(struct rdline *rdl, char c) #endif /* !NO_RDLINE_KILL_BUF */ case CMDLINE_KEY_CTRL_C: - rdline_puts(rdl, "\r\n"); + rdline_printf(rdl, "\r\n"); rdline_newline(rdl, rdl->prompt); break; @@ -365,66 +360,64 @@ rdline_char_in(struct rdline *rdl, char c) rdline_redisplay(rdl); break; - case CMDLINE_KEY_TAB: - case CMDLINE_KEY_HELP: + case CMDLINE_KEY_HELP: { + if (rdl->help == NULL) + break; + + cirbuf_align_left(&rdl->left); + rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; + rdline_printf(rdl, "\r\n"); + rdl->help(rdl, rdl->left_buf, rdline_write, rdl); + rdline_redisplay(rdl); + break; + } + + case CMDLINE_KEY_TAB: { + char tmp_buf[CMDLINE_MAX_TOKEN_SIZE]; + int ret; //, curline = 0; + unsigned int tmp_size; + + if (rdl->complete == NULL) + break; + cirbuf_align_left(&rdl->left); rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; - if (rdl->complete) { - char tmp_buf[BUFSIZ]; - int complete_state; - int ret; - unsigned int tmp_size; - - if (cmd == CMDLINE_KEY_TAB) - complete_state = 0; - else - complete_state = -1; - - /* see in parse.h for help on complete() */ - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - /* no completion or error */ - if (ret <= 0) { - return RDLINE_RES_COMPLETE; - } - - tmp_size = strlen(tmp_buf); - /* add chars */ - if (ret == RDLINE_RES_COMPLETE) { - i=0; - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < - RDLINE_BUF_SIZE && - i < tmp_size) { - cirbuf_add_tail(&rdl->left, tmp_buf[i]); - rdl->write_char(rdl, tmp_buf[i]); - i++; - } - display_right_buffer(rdl, 1); - return RDLINE_RES_COMPLETE; /* ?? */ - } - - /* choice */ - rdline_puts(rdl, "\r\n"); - while (ret) { - rdl->write_char(rdl, ' '); - for (i=0 ; tmp_buf[i] ; i++) - rdl->write_char(rdl, tmp_buf[i]); - rdline_puts(rdl, "\r\n"); - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - } + /* see in parse.h for help on complete() */ + ret = rdl->complete(rdl, rdl->left_buf, + tmp_buf, sizeof(tmp_buf)); + /* no completion or error */ + if (ret == CMDLINE_COMPLETE_NONE || + ret == CMDLINE_COMPLETE_MANY) { + cirbuf_align_left(&rdl->left); + rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; + rdline_printf(rdl, "\r\n"); + rdl->help(rdl, rdl->left_buf, rdline_write, rdl); rdline_redisplay(rdl); + break; } - return RDLINE_RES_COMPLETE; + + tmp_size = strlen(tmp_buf); + /* add chars */ + i = 0; + while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < + RDLINE_BUF_SIZE && + i < tmp_size) { + cirbuf_add_tail(&rdl->left, tmp_buf[i]); + rdline_printf(rdl, "%c", tmp_buf[i]); + i++; + } + display_right_buffer(rdl, 1); + break; + } case CMDLINE_KEY_RETURN: case CMDLINE_KEY_RETURN2: - rdline_get_buffer(rdl); + cirbuf_align_left(&rdl->left); + rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\n'; + rdl->left_buf[CIRBUF_GET_LEN(&rdl->left) + 1] = '\0'; rdl->status = RDLINE_INIT; - rdline_puts(rdl, "\r\n"); + rdline_printf(rdl, "\r\n"); #ifndef NO_RDLINE_HISTORY if (rdl->history_cur_line != -1) rdline_remove_first_history_item(rdl); @@ -496,12 +489,56 @@ rdline_char_in(struct rdline *rdl, char c) if (cirbuf_add_tail_safe(&rdl->left, c)) return RDLINE_RES_SUCCESS; - rdl->write_char(rdl, c); + rdline_printf(rdl, "%c", c); display_right_buffer(rdl, 0); return RDLINE_RES_SUCCESS; } +int +rdline_char_in(struct rdline *rdl, char c) +{ + int ret, same = 0; + const char *history, *buffer; + + if (rdl->status == RDLINE_EXITED) + return RDLINE_RES_EXITED; + if (rdl->status != RDLINE_RUNNING) + return RDLINE_RES_NOT_RUNNING; + + ret = rdline_parse_char(rdl, c); + + /* add line to history */ + if (ret == RDLINE_RES_VALIDATED) { + buffer = rdline_get_buffer(rdl); + history = rdline_get_history_item(rdl, 0); + if (history) + same = !strcmp(buffer, history); + + if (strlen(buffer) >= 1 && same == 0) + rdline_add_history(rdl, buffer); + } + + return ret; +} + +int +rdline(struct rdline *rdl, const char *prompt) +{ + char c; + int ret = RDLINE_RES_NOT_RUNNING; + + rdline_newline(rdl, prompt); + while (1) { + if (read(rdl->fd_in, &c, 1) < 0) + break; + ret = rdline_char_in(rdl, c); + if (ret != RDLINE_RES_SUCCESS) + break; + } + + return ret; +} /* HISTORY */ @@ -578,20 +615,13 @@ rdline_get_history_item(struct rdline * rdl, unsigned int idx) int rdline_add_history(struct rdline * rdl, const char * buf) { - unsigned int len, i; + unsigned int len; len = strlen(buf); - for (i=0; i= RDLINE_HISTORY_BUF_SIZE ) + if (len >= RDLINE_HISTORY_BUF_SIZE) return -1; - while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) { + while (len >= CIRBUF_GET_FREELEN(&rdl->history)) { rdline_remove_old_history_item(rdl); } @@ -609,52 +639,68 @@ rdline_clear_history(struct rdline * rdl) #else /* !NO_RDLINE_HISTORY */ -int rdline_add_history(struct rdline * rdl, const char * buf) {return -1;} -void rdline_clear_history(struct rdline * rdl) {} -char * rdline_get_history_item(struct rdline * rdl, unsigned int i) {return NULL;} +int rdline_add_history(struct rdline * rdl, const char * buf) +{ + return -1; +} +void rdline_clear_history(struct rdline * rdl) +{ + return; +} -#endif /* !NO_RDLINE_HISTORY */ +char * rdline_get_history_item(struct rdline * rdl, unsigned int i) +{ + return NULL; +} -/* STATIC USEFUL FUNCS */ +#endif /* !NO_RDLINE_HISTORY */ -static void -rdline_puts(struct rdline * rdl, const char * buf) + +ssize_t +rdline_write(const struct rdline *rdl, void *buf, size_t count) { - char c; - while ( (c = *(buf++)) != '\0' ) { - rdl->write_char(rdl, c); - } + return write(rdl->fd_out, buf, count); } -/* a very very basic printf with one arg and one format 'u' */ -static void -rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val) +int +rdline_vprintf(const struct rdline *rdl, const char *fmt, va_list ap) { - char c, started=0, div=100; + int ret; +#ifndef _GNU_SOURCE + char *buf; +#endif - while ( (c=*(buf++)) ) { - if (c != '%') { - rdl->write_char(rdl, c); - continue; - } - c = *(buf++); - if (c != 'u') { - rdl->write_char(rdl, '%'); - rdl->write_char(rdl, c); - continue; - } - /* val is never more than 255 */ - while (div) { - c = (char)(val / div); - if (c || started) { - rdl->write_char(rdl, (char)(c+'0')); - started = 1; - } - val %= div; - div /= 10; - } - } + if (rdl->fd_out < 0) + return -1; + +#ifdef _GNU_SOURCE + ret = vdprintf(rdl->fd_out, fmt, ap); +#else + buf = malloc(BUFSIZ); + if (buf == NULL) + return -1; + + ret = vsnprintf(buf, BUFSIZ, fmt, ap); + + if (ret > 0) + write(rdl->fd_out, buf, (ret >= BUFSIZ) ? BUFSIZ : ret); + free(buf); +#endif + + return ret; } +int +rdline_printf(const struct rdline *rdl, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = rdline_vprintf(rdl, fmt, ap); + va_end(ap); + + return ret; +}