Пример #1
0
        int prompt_loop(mutex * lock, CommandHistory & history)
        {
            int fd = STDIN_FILENO;
            size_t plen = prompt.size();
            int history_index = 0;
            raw_buffer.clear();
            raw_cursor = 0;
            /* The latest history entry is always our current buffer, that
             * initially is just an empty string. */
            const std::string empty;
            history.add(empty);
            if (::write(fd,prompt.c_str(),prompt.size()) == -1) return -1;
            while(1)
            {
                unsigned char c;
                int isok;
                unsigned char seq[2], seq2;
                lock->unlock();
                if(!read_char(c))
                {
                    lock->lock();
                    return -2;
                }
                lock->lock();
                /* Only autocomplete when the callback is set. It returns < 0 when
                 * there was an error reading from fd. Otherwise it will return the
                 * character that should be handled next. */
                if (c == 9)
                {
                    /*
                    if( completionCallback != NULL) {
                        c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols);
                        // Return on errors
                        if (c < 0) return len;
                        // Read next character when 0
                        if (c == 0) continue;
                    }
                    else
                    {
                        // ignore tab
                        continue;
                    }
                    */
                    // just ignore tabs
                    continue;
                }

                switch(c)
                {
                case 13:    // enter
                    history.remove();
                    return raw_buffer.size();
                case 3:     // ctrl-c
                    errno = EAGAIN;
                    return -1;
                case 127:   // backspace
                case 8:     // ctrl-h
                    if (raw_cursor > 0 && raw_buffer.size() > 0)
                    {
                        raw_buffer.erase(raw_cursor-1,1);
                        raw_cursor--;
                        prompt_refresh();
                    }
                    break;
                case 27:    // escape sequence
                    lock->unlock();
                    if(!read_char(seq[0]) || !read_char(seq[1]))
                    {
                        lock->lock();
                        return -2;
                    }
                    lock->lock();
                    if(seq[0] == '[')
                    {
                        if (seq[1] == 'D')
                        {
                            left_arrow:
                            if (raw_cursor > 0)
                            {
                                raw_cursor--;
                                prompt_refresh();
                            }
                        }
                        else if ( seq[1] == 'C')
                        {
                            right_arrow:
                            /* right arrow */
                            if (raw_cursor != raw_buffer.size())
                            {
                                raw_cursor++;
                                prompt_refresh();
                            }
                        }
                        else if (seq[1] == 'A' || seq[1] == 'B')
                        {
                            /* up and down arrow: history */
                            if (history.size() > 1)
                            {
                                /* Update the current history entry before to
                                 * overwrite it with tne next one. */
                                history[history_index] = raw_buffer;
                                /* Show the new entry */
                                history_index += (seq[1] == 'A') ? 1 : -1;
                                if (history_index < 0)
                                {
                                    history_index = 0;
                                    break;
                                }
                                else if (history_index >= history.size())
                                {
                                    history_index = history.size()-1;
                                    break;
                                }
                                raw_buffer = history[history_index];
                                raw_cursor = raw_buffer.size();
                                prompt_refresh();
                            }
                        }
                        else if(seq[1] == 'H')
                        {
                            // home
                            raw_cursor = 0;
                            prompt_refresh();
                        }
                        else if(seq[1] == 'F')
                        {
                            // end
                            raw_cursor = raw_buffer.size();
                            prompt_refresh();
                        }
                        else if (seq[1] > '0' && seq[1] < '7')
                        {
                            // extended escape
                            lock->unlock();
                            if(!read_char(seq2))
                            {
                                lock->lock();
                                return -2;
                            }
                            lock->lock();
                            if (seq[1] == '3' && seq2 == '~' )
                            {
                                // delete
                                if (raw_buffer.size() > 0 && raw_cursor < raw_buffer.size())
                                {
                                    raw_buffer.erase(raw_cursor,1);
                                    prompt_refresh();
                                }
                            }
                        }
                    }
                    break;
                default:
                    if (raw_buffer.size() == raw_cursor)
                    {
                        raw_buffer.append(1,c);
                        raw_cursor++;
                        if (plen+raw_buffer.size() < get_columns())
                        {
                            /* Avoid a full update of the line in the
                             * trivial case. */
                            if (::write(fd,&c,1) == -1) return -1;
                        }
                        else
                        {
                            prompt_refresh();
                        }
                    }
                    else
                    {
                        raw_buffer.insert(raw_cursor,1,c);
                        raw_cursor++;
                        prompt_refresh();
                    }
                    break;
                case 21: // Ctrl+u, delete the whole line.
                    raw_buffer.clear();
                    raw_cursor = 0;
                    prompt_refresh();
                    break;
                case 11: // Ctrl+k, delete from current to end of line.
                    raw_buffer.erase(raw_cursor);
                    prompt_refresh();
                    break;
                case 1: // Ctrl+a, go to the start of the line
                    raw_cursor = 0;
                    prompt_refresh();
                    break;
                case 5: // ctrl+e, go to the end of the line
                    raw_cursor = raw_buffer.size();
                    prompt_refresh();
                    break;
                case 12: // ctrl+l, clear screen
                    clear();
                    prompt_refresh();
                }
            }
            return raw_buffer.size();
        }