src/cforth/linenoise.c
static int linenoiseEdit(char *buf, size_t buflen, const char *prompt)
{
    struct linenoiseState l;

    /* Populate the linenoise state that we pass to functions implementing
     * specific editing functionalities. */
    l.buf = buf;
    l.buflen = buflen;
    l.prompt = prompt;
    l.plen = strlen(prompt);
    l.oldpos = l.pos = 0;
    l.len = 0;
    l.cols = getColumns();
    l.maxrows = 0;
    l.history_index = 0;

    /* Buffer starts empty. */
    buf[0] = '\0';
    buflen--; /* Make sure there is always space for the nulterm */

    /* The latest history entry is always our current buffer, that
     * initially is just an empty string. */
    linenoiseHistoryAdd("");
    
    if (l.plen && !linenoise_already_prompted)
	write_console(prompt,l.plen);

    while(1) {
        int c;
        char seq[2], seq2[2];

	c = key();

        /* Only autocomplete when the callback is set. It returns < 0 when
         * there was an input error. Otherwise it will return the
         * character that should be handled next. */
        if (c == 9 && completionCallback != NULL) {
            c = completeLine(&l);
            /* Return on errors */
            if (c < 0) return l.len;
            /* Read next character when 0 */
            if (c == 0) continue;
        }

        switch(c) {
        case 10:    /* linefeed */
        case 13:    /* enter */
            history_len--;
            free(history[history_len]);
            return (int)l.len;
        case 3:     /* ctrl-c */
            errno = EAGAIN;
            return -1;
        case 127:   /* backspace */
        case 8:     /* ctrl-h */
            linenoiseEditBackspace(&l);
            break;
        case 4:     /* ctrl-d, remove char at right of cursor, or of the
                       line is empty, act as end-of-file. */
	case SPECIAL_DELETE:
            if (l.len > 0) {
                linenoiseEditDelete(&l);
            } else if  (c != SPECIAL_DELETE) {
                history_len--;
                free(history[history_len]);
                return -1;
            }
            break;
        case 20:    /* ctrl-t, swaps current character with previous. */
            if (l.pos > 0 && l.pos < l.len) {
                int aux = buf[l.pos-1];
                buf[l.pos-1] = buf[l.pos];
                buf[l.pos] = aux;
                if (l.pos != l.len-1) l.pos++;
                refreshLine(&l);
            }
            break;
        case 2:     /* ctrl-b */
	case SPECIAL_LEFT:
            linenoiseEditMoveLeft(&l);
            break;
        case 6:     /* ctrl-f */
	case SPECIAL_RIGHT:
            linenoiseEditMoveRight(&l);
            break;
        case 16:    /* ctrl-p */
	case SPECIAL_UP:
            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
            break;
        case 14:    /* ctrl-n */
	case SPECIAL_DOWN:
            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
            break;
        case 27:    /* escape sequence */
            /* Read the next two bytes representing the escape sequence. */
	    seq[0] = key();  if (seq[0] == -1) break;
	    seq[1] = key();  if (seq[0] == -1) break;

            if (seq[0] == 91 && seq[1] == 68) {
                /* Left arrow */
                linenoiseEditMoveLeft(&l);
            } else if (seq[0] == 91 && seq[1] == 67) {
                /* Right arrow */
                linenoiseEditMoveRight(&l);
            } else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) {
                /* Up and Down arrows */
                linenoiseEditHistoryNext(&l,
                    (seq[1] == 65) ? LINENOISE_HISTORY_PREV :
                                     LINENOISE_HISTORY_NEXT);
            } else if (seq[0] == 91 && seq[1] > 48 && seq[1] < 55) {
                /* extended escape, read additional two bytes. */
		seq[0] = key();  if (seq[0] == -1) break;
		seq[1] = key();  if (seq[0] == -1) break;
                if (seq[1] == 51 && seq2[0] == 126) {
                    /* Delete key. */
                    linenoiseEditDelete(&l);
                }
            }
            break;
        default:
            if (linenoiseEditInsert(&l, (char)c)) return -1;
            break;
        case 21: /* Ctrl+u, delete the whole line. */
            buf[0] = '\0';
            l.pos = l.len = 0;
            refreshLine(&l);
            break;
        case 11: /* Ctrl+k, delete from current to end of line. */
            buf[l.pos] = '\0';
            l.len = l.pos;
            refreshLine(&l);
            break;
        case 1: /* Ctrl+a, go to the start of the line */
	case SPECIAL_HOME:
            l.pos = 0;
            refreshLine(&l);
            break;
        case 5: /* ctrl+e, go to the end of the line */
	case SPECIAL_END:
            l.pos = l.len;
            refreshLine(&l);
            break;
        case 12: /* ctrl+l, clear screen */
            linenoiseClearScreen();
            refreshLine(&l);
            break;
        case 23: /* ctrl+w, delete previous word */
            linenoiseEditDeletePrevWord(&l);
            break;
        }
    }
    return l.len;
}
/* This function is the core of the line editing capability of linenoise.
 * It expects the input stream to be already in "raw mode" so that every key pressed
 * will be returned ASAP to key().
 *
 * The resulting string is put into 'buf' when the user type enter, or
 * when ctrl+d is typed.
 *
 * The function returns the length of the current buffer. */
This function is the core of the line editing capability of linenoise.
It expects the input stream to be already in "raw mode" so that every key pressed
will be returned ASAP to key().

The resulting string is put into 'buf' when the user type enter, or
when ctrl+d is typed.

The function returns the length of the current buffer.
This function is the core of the line editing capability of linenoise . It expects the input stream to be already in " raw mode " so that every key pressed will be returned ASAP to key () . The resulting string is put into ' buf ' when the user type enter or when ctrl + d is typed . The function returns the length of the current buffer .
static int linenoiseEdit(char *buf, size_t buflen, const char *prompt)
{
    struct linenoiseState l;
    l.buf = buf;
    l.buflen = buflen;
    l.prompt = prompt;
    l.plen = strlen(prompt);
    l.oldpos = l.pos = 0;
    l.len = 0;
    l.cols = getColumns();
    l.maxrows = 0;
    l.history_index = 0;
    buf[0] = '\0';
    buflen--; 
    linenoiseHistoryAdd("");
    if (l.plen && !linenoise_already_prompted)
	write_console(prompt,l.plen);
    while(1) {
        int c;
        char seq[2], seq2[2];
	c = key();
        if (c == 9 && completionCallback != NULL) {
            c = completeLine(&l);
            if (c < 0) return l.len;
            if (c == 0) continue;
        }
        switch(c) {
        case 10:    
        case 13:    
            history_len--;
            free(history[history_len]);
            return (int)l.len;
        case 3:     
            errno = EAGAIN;
            return -1;
        case 127:   
        case 8:     
            linenoiseEditBackspace(&l);
            break;
        case 4:     
	case SPECIAL_DELETE:
            if (l.len > 0) {
                linenoiseEditDelete(&l);
            } else if  (c != SPECIAL_DELETE) {
                history_len--;
                free(history[history_len]);
                return -1;
            }
            break;
        case 20:    
            if (l.pos > 0 && l.pos < l.len) {
                int aux = buf[l.pos-1];
                buf[l.pos-1] = buf[l.pos];
                buf[l.pos] = aux;
                if (l.pos != l.len-1) l.pos++;
                refreshLine(&l);
            }
            break;
        case 2:     
	case SPECIAL_LEFT:
            linenoiseEditMoveLeft(&l);
            break;
        case 6:     
	case SPECIAL_RIGHT:
            linenoiseEditMoveRight(&l);
            break;
        case 16:    
	case SPECIAL_UP:
            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
            break;
        case 14:    
	case SPECIAL_DOWN:
            linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
            break;
        case 27:    
	    seq[0] = key();  if (seq[0] == -1) break;
	    seq[1] = key();  if (seq[0] == -1) break;
            if (seq[0] == 91 && seq[1] == 68) {
                linenoiseEditMoveLeft(&l);
            } else if (seq[0] == 91 && seq[1] == 67) {
                linenoiseEditMoveRight(&l);
            } else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) {
                linenoiseEditHistoryNext(&l,
                    (seq[1] == 65) ? LINENOISE_HISTORY_PREV :
                                     LINENOISE_HISTORY_NEXT);
            } else if (seq[0] == 91 && seq[1] > 48 && seq[1] < 55) {
		seq[0] = key();  if (seq[0] == -1) break;
		seq[1] = key();  if (seq[0] == -1) break;
                if (seq[1] == 51 && seq2[0] == 126) {
                    linenoiseEditDelete(&l);
                }
            }
            break;
        default:
            if (linenoiseEditInsert(&l, (char)c)) return -1;
            break;
        case 21: 
            buf[0] = '\0';
            l.pos = l.len = 0;
            refreshLine(&l);
            break;
        case 11: 
            buf[l.pos] = '\0';
            l.len = l.pos;
            refreshLine(&l);
            break;
        case 1: 
	case SPECIAL_HOME:
            l.pos = 0;
            refreshLine(&l);
            break;
        case 5: 
	case SPECIAL_END:
            l.pos = l.len;
            refreshLine(&l);
            break;
        case 12: 
            linenoiseClearScreen();
            refreshLine(&l);
            break;
        case 23: 
            linenoiseEditDeletePrevWord(&l);
            break;
        }
    }
    return l.len;
}
static int linenoiseEdit ( char * buf , size_t buflen , const char * prompt ) { struct linenoiseState l ; l . buf = buf ; l . buflen = buflen ; l . prompt = prompt ; l . plen = strlen ( prompt ) ; l . oldpos = l . pos = 0 ; l . len = 0 ; l . cols = getColumns ( ) ; l . maxrows = 0 ; l . history_index = 0 ; buf [ 0 ] = ' \0 ' ; buflen -- ; linenoiseHistoryAdd ( " " ) ; if ( l . plen && ! linenoise_already_prompted ) write_console ( prompt , l . plen ) ; while ( 1 ) { int c ; char seq [ 2 ] , seq2 [ 2 ] ; c = key ( ) ; if ( c == 9 && completionCallback != NULL ) { c = completeLine ( & l ) ; if ( c < 0 ) return l . len ; if ( c == 0 ) continue ; } switch ( c ) { case 10 : case 13 : history_len -- ; free ( history [ history_len ] ) ; return ( int ) l . len ; case 3 : errno = EAGAIN ; return -1 ; case 127 : case 8 : linenoiseEditBackspace ( & l ) ; break ; case 4 : case SPECIAL_DELETE : if ( l . len > 0 ) { linenoiseEditDelete ( & l ) ; } else if ( c != SPECIAL_DELETE ) { history_len -- ; free ( history [ history_len ] ) ; return -1 ; } break ; case 20 : if ( l . pos > 0 && l . pos < l . len ) { int aux = buf [ l . pos - 1 ] ; buf [ l . pos - 1 ] = buf [ l . pos ] ; buf [ l . pos ] = aux ; if ( l . pos != l . len - 1 ) l . pos ++ ; refreshLine ( & l ) ; } break ; case 2 : case SPECIAL_LEFT : linenoiseEditMoveLeft ( & l ) ; break ; case 6 : case SPECIAL_RIGHT : linenoiseEditMoveRight ( & l ) ; break ; case 16 : case SPECIAL_UP : linenoiseEditHistoryNext ( & l , LINENOISE_HISTORY_PREV ) ; break ; case 14 : case SPECIAL_DOWN : linenoiseEditHistoryNext ( & l , LINENOISE_HISTORY_NEXT ) ; break ; case 27 : seq [ 0 ] = key ( ) ; if ( seq [ 0 ] == -1 ) break ; seq [ 1 ] = key ( ) ; if ( seq [ 0 ] == -1 ) break ; if ( seq [ 0 ] == 91 && seq [ 1 ] == 68 ) { linenoiseEditMoveLeft ( & l ) ; } else if ( seq [ 0 ] == 91 && seq [ 1 ] == 67 ) { linenoiseEditMoveRight ( & l ) ; } else if ( seq [ 0 ] == 91 && ( seq [ 1 ] == 65 || seq [ 1 ] == 66 ) ) { linenoiseEditHistoryNext ( & l , ( seq [ 1 ] == 65 ) ? LINENOISE_HISTORY_PREV : LINENOISE_HISTORY_NEXT ) ; } else if ( seq [ 0 ] == 91 && seq [ 1 ] > 48 && seq [ 1 ] < 55 ) { seq [ 0 ] = key ( ) ; if ( seq [ 0 ] == -1 ) break ; seq [ 1 ] = key ( ) ; if ( seq [ 0 ] == -1 ) break ; if ( seq [ 1 ] == 51 && seq2 [ 0 ] == 126 ) { linenoiseEditDelete ( & l ) ; } } break ; default : if ( linenoiseEditInsert ( & l , ( char ) c ) ) return -1 ; break ; case 21 : buf [ 0 ] = ' \0 ' ; l . pos = l . len = 0 ; refreshLine ( & l ) ; break ; case 11 : buf [ l . pos ] = ' \0 ' ; l . len = l . pos ; refreshLine ( & l ) ; break ; case 1 : case SPECIAL_HOME : l . pos = 0 ; refreshLine ( & l ) ; break ; case 5 : case SPECIAL_END : l . pos = l . len ; refreshLine ( & l ) ; break ; case 12 : linenoiseClearScreen ( ) ; refreshLine ( & l ) ; break ; case 23 : linenoiseEditDeletePrevWord ( & l ) ; break ; } } return l . len ; }
This function is the core of the line editing capability of linenoise.
This function is the core of the line editing capability of linenoise .
/* Populate the linenoise state that we pass to functions implementing
     * specific editing functionalities. */ /* Buffer starts empty. */ /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that
     * initially is just an empty string. */ /* Only autocomplete when the callback is set. It returns < 0 when
         * there was an input error. Otherwise it will return the
         * character that should be handled next. */ /* Return on errors */ /* Read next character when 0 */ /* linefeed */ /* enter */ /* ctrl-c */ /* backspace */ /* ctrl-h */ /* ctrl-d, remove char at right of cursor, or of the
                       line is empty, act as end-of-file. */ /* ctrl-t, swaps current character with previous. */ /* ctrl-b */ /* ctrl-f */ /* ctrl-p */ /* ctrl-n */ /* escape sequence */ /* Read the next two bytes representing the escape sequence. */ /* Left arrow */ /* Right arrow */ /* Up and Down arrows */ /* extended escape, read additional two bytes. */ /* Delete key. */ /* Ctrl+u, delete the whole line. */ /* Ctrl+k, delete from current to end of line. */ /* Ctrl+a, go to the start of the line */ /* ctrl+e, go to the end of the line */ /* ctrl+l, clear screen */ /* ctrl+w, delete previous word */