/* @history_funcs{"go"} */ static JSBool history_go(JSContext *ctx, unsigned int argc, jsval *rval) { struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct document_view *doc_view = interpreter->vs->doc_view; struct session *ses = doc_view->session; jsval *argv = JS_ARGV(ctx, rval); int index; struct location *loc; if (argc != 1) return JS_TRUE; index = atol(jsval_to_string(ctx, &argv[0])); for (loc = cur_loc(ses); loc != (struct location *) &ses->history.history; loc = index > 0 ? loc->next : loc->prev) { if (!index) { go_history(ses, loc); break; } index += index > 0 ? -1 : 1; } JS_SET_RVAL(ctx, rval, JSVAL_NULL); return 2; }
std::string cmd_handler::readline(const std::string & prompt) { char c; char arrow[2]; const char del[] = "\b \b"; auto clear_line = [del](int count) { for (int i = 0; i < count; i++) { if (write(STDOUT_FILENO, &del, 3) < 0) { std::cerr << "write: " << strerror(errno) << std::endl; } } }; history_iter_ = history_.end(); std::string line, word; struct termios tty, tty_change; tcgetattr(STDIN_FILENO, &tty); tty_change = tty; tty_change.c_lflag &= ~ICANON; tty_change.c_lflag &= ~ECHO; tcsetattr(STDIN_FILENO, TCSAFLUSH, &tty_change); if (write(STDOUT_FILENO, prompt.data(), prompt.size()) < 0) { std::cerr << "write: " << strerror(errno) << std::endl; } auto dir = direction_none; size_t current_size = 0; std::string value; while(true) { if (read(STDIN_FILENO, &c, 1) < 0) { std::cerr << "read: " << strerror(errno) << std::endl; } if (std::iscntrl(c)) { switch(c) { case '\033': current_size = line.size(); // eat the rest of the input if (read(STDIN_FILENO, &arrow, 2) < 0) { std::cerr << "read: " << strerror(errno) << std::endl; } if (arrow[1] == 'A') { dir = direction_back; } else if (arrow[1] == 'B') { dir = direction_forward; } if (dir != direction_none && go_history(dir, line)) { clear_line(current_size); if (write(STDOUT_FILENO, line.data(), line.size()) < 0) { std::cerr << "write: " << strerror(errno) << std::endl; } dir = direction_none; current_size = 0; } break; case '\n': tcsetattr(STDIN_FILENO, TCSANOW, &tty); std::cout << std::endl; if (line.empty() && !history_.empty()) { value = history_.back(); } else { value = rtrim(ltrim(line)); } if (log_.is_open()) { log_ << prompt << value << std::endl; } return value; case '\b': case 127: if (!line.empty()) { line.erase(line.end()-1, line.end()); if (write(STDOUT_FILENO, &del, 3) < 0) { std::cerr << "write: " << strerror(errno) << std::endl; } } break; case '\t': // TODO : tab complete break; } } else { if (write(STDOUT_FILENO, &c, 1) < 0) { std::cerr << "write: " << strerror(errno) << std::endl; } if (std::iswspace(c)) { if (!word.empty()) { word.clear(); } } else { word.push_back(c); } line.push_back(c); } } }