X-Git-Url: http://git.droids-corp.org/?p=libcmdline.git;a=blobdiff_plain;f=src%2Flib%2Fcmdline_rdline.h;h=47ab6c99b90803a947c330221207e30e1614550b;hp=a6b32752f9c308c31d4cdf3216766b95c17adfea;hb=568d6d51fc9e6e2d8842fc1abe63c23de503f8bc;hpb=c39d452741fe5b6c771bb655fa0c827a064f4460 diff --git a/src/lib/cmdline_rdline.h b/src/lib/cmdline_rdline.h index a6b3275..47ab6c9 100644 --- a/src/lib/cmdline_rdline.h +++ b/src/lib/cmdline_rdline.h @@ -63,26 +63,19 @@ #define _RDLINE_H_ /** - * This file is a small equivalent to the GNU readline library, but it - * was originally designed for small systems, like Atmel AVR - * microcontrollers (8 bits). Indeed, we don't use any malloc that is - * sometimes not implemented (or just not recommended) on such - * systems. + * This file is a small equivalent to the GNU readline library, it was + * originally designed for very small systems (an 8-bits Atmel AVR + * microcontroller), but the library can now run on many emmbedded + * systems with or without OS. * * Obviously, it does not support as many things as the GNU readline, * but at least it supports some interresting features like a kill * buffer and a command history. * * It also have a feature that does not have the GNU readline (as far - * as I know): we can have several instances of it running at the same - * time, even on a monothread program, since it works with callbacks. - * - * The lib is designed for a client-side or a server-side use: - * - server-side: the server receives all data from a socket, including - * control chars, like arrows, tabulations, ... The client is - * very simple, it can be a telnet or a minicom through a serial line. - * - client-side: the client receives its data through its stdin for - * instance. + * as I know): it is possible to have several instances of readline + * running at the same time, even on a monothread program, since it + * works with callbacks. */ #include @@ -94,24 +87,38 @@ #define RDLINE_VT100_BUF_SIZE 8 #define RDLINE_HISTORY_BUF_SIZE BUFSIZ #define RDLINE_HISTORY_MAX_LINE 64 +#define RDLINE_MAX_LINES 23 enum rdline_status { - RDLINE_INIT, + RDLINE_STOPPED, RDLINE_RUNNING, RDLINE_EXITED }; struct rdline; -typedef void (rdline_write_char_t)(struct rdline *rdl, char); +/** + * callback given to rdline_help() to display the content of the + * help. The first argument is an opaque pointer. The other args + * are buffer and size. + */ +typedef ssize_t (rdline_write_t)(struct rdline *, void *, size_t); + + typedef void (rdline_validate_t)(struct rdline *rdl, const char *buf, unsigned int size); typedef int (rdline_complete_t)(struct rdline *rdl, const char *buf, - char *dstbuf, unsigned int dstsize, - int *state); + char *dstbuf, unsigned int dstsize); +typedef int (rdline_help_t)(struct rdline *rdl, const char *buf, + rdline_write_t *write, void *opaque); + +typedef void (rdline_asyncpager_cb_t)(struct rdline *, void *); struct rdline { enum rdline_status status; + int fd_in; + int fd_out; + /* rdline bufs */ struct cirbuf left; struct cirbuf right; @@ -119,7 +126,6 @@ struct rdline { char right_buf[RDLINE_BUF_SIZE]; char prompt[RDLINE_PROMPT_SIZE]; - unsigned int prompt_size; #ifndef NO_RDLINE_KILL_BUF char kill_buf[RDLINE_BUF_SIZE]; @@ -134,62 +140,98 @@ struct rdline { #endif /* callbacks and func pointers */ - rdline_write_char_t *write_char; rdline_validate_t *validate; rdline_complete_t *complete; + rdline_help_t *help; /* vt100 parser */ struct cmdline_vt100 vt100; /* opaque pointer */ void *opaque; + +#ifndef NO_PAGER + char *pager_buf; /* buffer used to store paged data */ + int pager_len; /* total len of buffer */ + int pager_off; /* offset of next data */ + int pager_lines; /* number of lines displayed */ + rdline_asyncpager_cb_t *pager_cb; /* callback once paging is finished */ + void *pager_arg; /* argument of callback */ + int pager_ret; /* saved return value */ +#endif }; /** - * Init fields for a struct rdline. Call this only once at the beginning - * of your program. - * \param rdl A pointer to an uninitialized struct rdline - * \param write_char The function used by the function to write a character - * \param validate A pointer to the function to execute when the - * user validates the buffer. - * \param complete A pointer to the function to execute when the - * user completes the buffer. + * Init fields for a struct rdline. + * + * @param rdl A pointer to an uninitialized struct rdline + * @param fd_in + * Input file descriptor + * @param fd_out + * Output file descriptor + * @param validate + * A pointer to the function to execute when the user validates the + * buffer. + * @param complete + * A pointer to the function to execute when the user completes the + * buffer. + * @param help + * A pointer to the function to execute when the user ask for + * contextual help. */ void rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, + int fd_in, int fd_out, rdline_validate_t *validate, - rdline_complete_t *complete); + rdline_complete_t *complete, + rdline_help_t *help); /** * Init the current buffer, and display a prompt. - * \param rdl A pointer to a struct rdline - * \param prompt A string containing the prompt + * + * Also set the rdline status to "running", overriding previous + * rdline_stop() or rdline_quit(). + * + * @param rdl + * A pointer to an initialized struct rdline + * @param prompt + * A string containing the prompt */ void rdline_newline(struct rdline *rdl, const char *prompt); /** - * Call it and all received chars will be ignored. - * \param rdl A pointer to a struct rdline + * Ignore all subsequent received chars. + * + * @param rdl + * A pointer to a struct rdline */ void rdline_stop(struct rdline *rdl); /** + * Exit from running rdline loop + * * Same than rdline_stop() except that next calls to rdline_char_in() - * will return RDLINE_RES_EXITED. - * \param rdl A pointer to a struct rdline + * will return RDLINE_RES_EXITED. Hence, any running rdline() function is + * interrupted. + * + * @param rdl + * A pointer to a struct rdline */ void rdline_quit(struct rdline *rdl); /** * Restart after a call to rdline_stop() or rdline_quit() - * \param rdl A pointer to a struct rdline + * + * @param rdl + * A pointer to a struct rdline */ void rdline_restart(struct rdline *rdl); /** * Redisplay the current buffer - * \param rdl A pointer to a struct rdline + * + * @param rdl + * A pointer to a struct rdline */ void rdline_redisplay(struct rdline *rdl); @@ -197,49 +239,188 @@ void rdline_redisplay(struct rdline *rdl); /* return status for rdline_char_in() */ #define RDLINE_RES_SUCCESS 0 #define RDLINE_RES_VALIDATED 1 -#define RDLINE_RES_COMPLETE 2 #define RDLINE_RES_NOT_RUNNING -1 #define RDLINE_RES_EOF -2 #define RDLINE_RES_EXITED -3 /** - * append a char to the readline buffer. - * Return RDLINE_RES_VALIDATE when the line has been validated. - * Return RDLINE_RES_COMPLETE when the user asked to complete the buffer. - * Return RDLINE_RES_NOT_RUNNING if it is not running. - * Return RDLINE_RES_EOF if EOF (ctrl-d on an empty line). - * Else return RDLINE_RES_SUCCESS. - * XXX error case when the buffer is full ? + * Append a char to the readline buffer. * - * \param rdl A pointer to a struct rdline - * \param c The character to append + * @param rdl + * A pointer to a struct rdline + * @param c + * The character to append + * @return + * - RDLINE_RES_VALIDATED when the line has been validated. + * - RDLINE_RES_NOT_RUNNING if it is not running. + * - RDLINE_RES_EOF if EOF (ctrl-d on an empty line). + * - RDLINE_RES_EXITED if user called rdline_quit() + * - Else return RDLINE_RES_SUCCESS. */ int rdline_char_in(struct rdline *rdl, char c); +/** + * Read (and edit) a line + * + * @param rdl + * A pointer to a struct rdline + * @param prompt + * The prompt string + * @return + * - RDLINE_RES_VALIDATED when the line has been validated. + * - RDLINE_RES_NOT_RUNNING if it is not running. + * - RDLINE_RES_EOF if EOF (ctrl-d on an empty line). + * - RDLINE_RES_EXITED if user called rdline_quit() + */ +int rdline(struct rdline *rdl, const char *prompt); + +/** + * write a buffer on rdline file descriptor + * + * @param rdl + * The rdline descriptor + * @param buf + * Pointer to the buffer + * @param count + * Number of bytes to write + * @return + * On success, the number of bytes written is returned (zero + * indicates nothing was written). On error, -1 is returned, and + * errno is set appropriately + */ +ssize_t rdline_write(const struct rdline *rdl, void *buf, size_t count); + +/** + * write on rdline file descriptor according to a format string + * + * @param rdl + * The rdline descriptor + * @param fmt + * The format strings + * @return + * Upon successful return, these functions return the number of + * characters printed (not including the trailing '\0' used to end + * output to strings). On error, a negative value is returned. + */ +int rdline_printf(const struct rdline *rdl, const char *fmt, ...); + +/** + * write on rdline file descriptor according to a format string + * + * @param rdl + * The rdline descriptor + * @param fmt + * The format strings + * @param ap + * Variable argument list + * @return + * Upon successful return, these functions return the number of + * characters printed (not including the trailing '\0' used to end + * output to strings). On error, a negative value is returned. + */ +int rdline_vprintf(const struct rdline *rdl, const char *fmt, va_list ap); + /** * Return the current buffer, terminated by '\0'. - * \param rdl A pointer to a struct rdline + * + * @param rdl + * A pointer to a struct rdline + * @return + * The rdline buffer */ const char *rdline_get_buffer(struct rdline *rdl); - /** * Add the buffer to history. - * return < 0 on error. - * \param rdl A pointer to a struct rdline - * \param buf A buffer that is terminated by '\0' + * + * @param rdl + * A pointer to a struct rdline + * @param buf + * A buffer that is terminated by '\0' + * @return + * - 0 on success + * - negative on error */ int rdline_add_history(struct rdline *rdl, const char *buf); /** * Clear current history - * \param rdl A pointer to a struct rdline + * + * @param rdl + * A pointer to a struct rdline */ void rdline_clear_history(struct rdline *rdl); /** * Get the i-th history item + * + * @param rdl + * A pointer to a struct rdline + * @param i + * The index of the history item + * @return + * The i-th string of history, or NULL on error. */ char *rdline_get_history_item(struct rdline *rdl, unsigned int i); +#ifndef NO_PAGER +/** + * Write data asynchronously (using pager if needed) + * + * If there is enough place to print data on the current page, it is + * printed synchronously. Else, a temporary buffer is allocated and + * the data is stored in it. When the main rdline is called again, the + * pager is flushed before parsing any other commands. + * + * @param rdl + * The rdline descriptor + * @param buf + * Buffer to be sent + * @param len + * Length of buffer to be sent + * @return + * On success, the number of bytes written is returned (zero + * indicates nothing was written). On error, -1 is returned, and + * errno is set appropriately + */ +ssize_t rdline_asyncpager_write(struct rdline *rdl, void *buf, size_t len); + +/** + * Print data asynchronously (using pager if needed) + * + * If there is enough place to print data on the current page, it is + * printed synchronously. Else, a temporary buffer is allocated and + * the data is stored in it. When the main rdline is called again, the + * pager is flushed before parsing any other commands. + * + * @param rdl + * The rdline descriptor + * @param fmt + * The format strings + * @return + * Upon successful return, these functions return the number of + * characters printed (not including the trailing '\0' used to end + * output to strings). On error, a negative value is returned. + */ +int rdline_asyncpager_printf(struct rdline *rdl, const char *fmt, ...); + +/** + * Set the callback for the pager + * + * If there is some data in the pager to be printed, set a callback + * function that will be called when all the data will be printed. If + * the pager is empty, don't do anything and return -1. + * @param rdl + * The rdline descriptor + * @return + * - 0 if there is some data in the pager buffer and the callback + * is loaded + * - -1 if there is no data in pager buffer (in this case the callback + * is not called) + */ +int rdline_asyncpager_set_cb(struct rdline *rdl, rdline_asyncpager_cb_t *cb, + void *arg); +#endif + + #endif /* _RDLINE_H_ */