diff options
-rw-r--r-- | Libraries/LibLine/Editor.cpp | 120 | ||||
-rw-r--r-- | Libraries/LibLine/Editor.h | 3 |
2 files changed, 79 insertions, 44 deletions
diff --git a/Libraries/LibLine/Editor.cpp b/Libraries/LibLine/Editor.cpp index fe97776cd0..9f258a47bf 100644 --- a/Libraries/LibLine/Editor.cpp +++ b/Libraries/LibLine/Editor.cpp @@ -68,6 +68,7 @@ void Editor::clear_line() fflush(stdout); m_buffer.clear(); m_cursor = 0; + m_inline_search_cursor = m_cursor; } void Editor::insert(const String& string) @@ -82,12 +83,14 @@ void Editor::insert(const char ch) if (m_cursor == m_buffer.size()) { m_buffer.append(ch); m_cursor = m_buffer.size(); + m_inline_search_cursor = m_cursor; return; } m_buffer.insert(m_cursor, ch); ++m_chars_inserted_in_the_middle; ++m_cursor; + m_inline_search_cursor = m_cursor; } void Editor::register_character_input_callback(char ch, Function<bool(Editor&)> callback) @@ -195,50 +198,67 @@ String Editor::get_line(const String& prompt) case InputState::ExpectFinal: switch (ch) { case 'A': // up - if (m_history_cursor > 0) - --m_history_cursor; - if (m_history_cursor < m_history.size()) { - auto& line = m_history[m_history_cursor]; - m_buffer.clear(); - for (auto& c : line) - m_buffer.append(c); - m_cursor = m_buffer.size(); - m_refresh_needed = true; + { + m_searching_backwards = true; + auto inline_search_cursor = m_inline_search_cursor; + String search_phrase { m_buffer.data(), inline_search_cursor }; + if (search(search_phrase, true, true)) { + ++m_search_offset; + } else { + insert(search_phrase); } + m_inline_search_cursor = inline_search_cursor; m_state = InputState::Free; continue; + } case 'B': // down - if (m_history_cursor < m_history.size()) - ++m_history_cursor; - if (m_history_cursor < m_history.size()) { - auto& line = m_history[m_history_cursor]; + { + auto inline_search_cursor = m_inline_search_cursor; + String search_phrase { m_buffer.data(), inline_search_cursor }; + auto search_changed_directions = m_searching_backwards; + m_searching_backwards = false; + if (m_search_offset > 0) { + m_search_offset -= 1 + search_changed_directions; + if (!search(search_phrase, true, true)) { + insert(search_phrase); + } + } else { + m_search_offset = 0; + m_cursor = 0; m_buffer.clear(); - for (auto& c : line) - m_buffer.append(c); - m_cursor = m_buffer.size(); + insert(search_phrase); m_refresh_needed = true; } + m_inline_search_cursor = inline_search_cursor; m_state = InputState::Free; continue; + } case 'D': // left if (m_cursor > 0) { --m_cursor; } + m_inline_search_cursor = m_cursor; m_state = InputState::Free; continue; case 'C': // right if (m_cursor < m_buffer.size()) { ++m_cursor; } + m_inline_search_cursor = m_cursor; + m_search_offset = 0; m_state = InputState::Free; continue; case 'H': m_cursor = 0; + m_inline_search_cursor = m_cursor; + m_search_offset = 0; m_state = InputState::Free; continue; case 'F': m_cursor = m_buffer.size(); m_state = InputState::Free; + m_inline_search_cursor = m_cursor; + m_search_offset = 0; continue; case 'Z': // shift+tab reverse_tab = true; @@ -252,6 +272,7 @@ String Editor::get_line(const String& prompt) } m_buffer.remove(m_cursor); m_refresh_needed = true; + m_search_offset = 0; m_state = InputState::ExpectTerminator; continue; default: @@ -278,6 +299,8 @@ String Editor::get_line(const String& prompt) } } + m_search_offset = 0; // reset search offset on any key + if (ch == '\t' || reverse_tab) { if (!on_tab_complete_first_token || !on_tab_complete_other_token) continue; @@ -379,6 +402,7 @@ String Editor::get_line(const String& prompt) for (size_t i = m_next_suggestion_invariant_offset; i < shown_length; ++i) m_buffer.remove(actual_offset); m_cursor = actual_offset; + m_inline_search_cursor = m_cursor; m_refresh_needed = true; } m_last_shown_suggestion = m_suggestions[m_next_suggestion_index]; @@ -525,6 +549,7 @@ String Editor::get_line(const String& prompt) } m_buffer.remove(m_cursor - 1); --m_cursor; + m_inline_search_cursor = m_cursor; // we will have to redraw :( m_refresh_needed = true; }; @@ -580,34 +605,7 @@ String Editor::get_line(const String& prompt) m_search_editor = make<Editor>(true); // Has anyone seen 'Inception'? m_search_editor->initialize(); m_search_editor->on_display_refresh = [this](Editor& search_editor) { - int last_matching_offset = -1; - - // do not search for empty strings - if (search_editor.buffer().size() > 0) { - size_t search_offset = m_search_offset; - StringView search_term { search_editor.buffer().data(), search_editor.buffer().size() }; - for (size_t i = m_history_cursor; i > 0; --i) { - if (m_history[i - 1].contains(search_term)) { - last_matching_offset = i - 1; - if (search_offset == 0) - break; - --search_offset; - } - } - - if (last_matching_offset == -1) { - fputc('\a', stdout); - fflush(stdout); - return; - } - } - - m_buffer.clear(); - m_cursor = 0; - if (last_matching_offset >= 0) - insert(m_history[last_matching_offset]); - // always needed - m_refresh_needed = true; + search(StringView { search_editor.buffer().data(), search_editor.buffer().size() }); refresh_display(); return; }; @@ -691,6 +689,40 @@ String Editor::get_line(const String& prompt) } } +bool Editor::search(const StringView& phrase, bool allow_empty, bool from_beginning) +{ + + int last_matching_offset = -1; + + // do not search for empty strings + if (allow_empty || phrase.length() > 0) { + size_t search_offset = m_search_offset; + for (size_t i = m_history_cursor; i > 0; --i) { + auto contains = from_beginning ? m_history[i - 1].starts_with(phrase) : m_history[i - 1].contains(phrase); + if (contains) { + last_matching_offset = i - 1; + if (search_offset == 0) + break; + --search_offset; + } + } + + if (last_matching_offset == -1) { + fputc('\a', stdout); + fflush(stdout); + } + } + + m_buffer.clear(); + m_cursor = 0; + if (last_matching_offset >= 0) { + insert(m_history[last_matching_offset]); + } + // always needed + m_refresh_needed = true; + return last_matching_offset >= 0; +} + void Editor::recalculate_origin() { // changing the columns can affect our origin if diff --git a/Libraries/LibLine/Editor.h b/Libraries/LibLine/Editor.h index aa735c531b..4909ea458f 100644 --- a/Libraries/LibLine/Editor.h +++ b/Libraries/LibLine/Editor.h @@ -160,6 +160,7 @@ private: Style find_applicable_style(size_t offset) const; + bool search(const StringView&, bool allow_empty = false, bool from_beginning = false); inline void end_search() { m_is_searching = false; @@ -222,6 +223,7 @@ private: bool m_is_searching { false }; bool m_reset_buffer_on_search_end { true }; size_t m_search_offset { 0 }; + bool m_searching_backwards { true }; size_t m_pre_search_cursor { 0 }; Vector<char, 1024> m_pre_search_buffer; @@ -229,6 +231,7 @@ private: ByteBuffer m_pending_chars; size_t m_cursor { 0 }; size_t m_drawn_cursor { 0 }; + size_t m_inline_search_cursor { 0 }; size_t m_chars_inserted_in_the_middle { 0 }; size_t m_times_tab_pressed { 0 }; size_t m_num_columns { 0 }; |