#include #include #include #include #include namespace { /// Trim ending whitespace inplace void trim(String & s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end()); } } ReplxxLineReader::ReplxxLineReader(const Suggest & suggest, const String & history_file_path_, char extender_, char delimiter_) : LineReader(history_file_path_, extender_, delimiter_) { using namespace std::placeholders; using Replxx = replxx::Replxx; if (!history_file_path.empty()) rx.history_load(history_file_path); auto callback = [&suggest] (const String & context, size_t context_size) { auto range = suggest.getCompletions(context, context_size); return Replxx::completions_t(range.first, range.second); }; rx.set_completion_callback(callback); rx.set_complete_on_empty(false); rx.set_word_break_characters(word_break_characters); /// By default C-p/C-n binded to COMPLETE_NEXT/COMPLETE_PREV, /// bind C-p/C-n to history-previous/history-next like readline. rx.bind_key(Replxx::KEY::control('N'), std::bind(&Replxx::invoke, &rx, Replxx::ACTION::HISTORY_NEXT, _1)); rx.bind_key(Replxx::KEY::control('P'), std::bind(&Replxx::invoke, &rx, Replxx::ACTION::HISTORY_PREVIOUS, _1)); /// By default COMPLETE_NEXT/COMPLETE_PREV was binded to C-p/C-n, re-bind /// to M-P/M-N (that was used for HISTORY_COMMON_PREFIX_SEARCH before, but /// it also binded to M-p/M-n). rx.bind_key(Replxx::KEY::meta('N'), std::bind(&Replxx::invoke, &rx, Replxx::ACTION::COMPLETE_NEXT, _1)); rx.bind_key(Replxx::KEY::meta('P'), std::bind(&Replxx::invoke, &rx, Replxx::ACTION::COMPLETE_PREVIOUS, _1)); } ReplxxLineReader::~ReplxxLineReader() { if (!history_file_path.empty()) rx.history_save(history_file_path); } LineReader::InputStatus ReplxxLineReader::readOneLine(const String & prompt) { input.clear(); const char* cinput = rx.input(prompt); if (cinput == nullptr) return (errno != EAGAIN) ? ABORT : RESET_LINE; input = cinput; trim(input); return INPUT_LINE; } void ReplxxLineReader::addToHistory(const String & line) { rx.history_add(line); } void ReplxxLineReader::enableBracketedPaste() { rx.enable_bracketed_paste(); };