diff --git a/src/Editor.cpp b/src/Editor.cpp index 322e647..696e720 100644 --- a/src/Editor.cpp +++ b/src/Editor.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include namespace groove { @@ -15,6 +14,7 @@ namespace groove { this->modes.emplace(Mode::QUIT, std::make_unique(*this)); this->modes.emplace(Mode::SAVE, std::make_unique(*this)); this->modes.emplace(Mode::EXIT, std::make_unique(*this)); + this->modes.emplace(Mode::SEARCH, std::make_unique(*this)); this->lineMode = this->config.get("linenumbers") == "relative" ? LineMode::RELATIVE : (this->config.get("linenumbers") == "none" ? LineMode::NONE : LineMode::NUMBERS); diff --git a/src/Editor.hpp b/src/Editor.hpp index 9460cef..3468964 100644 --- a/src/Editor.hpp +++ b/src/Editor.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,8 @@ namespace groove { EDIT, SAVE, QUIT, - EXIT + EXIT, + SEARCH }; enum LineMode { @@ -36,6 +38,7 @@ namespace groove { friend class modes::Quit; friend class modes::Save; friend class modes::Exit; + friend class modes::Search; friend class History; private: long x, y; diff --git a/src/modes/Edit.cpp b/src/modes/Edit.cpp index 86047ee..1aa4101 100644 --- a/src/modes/Edit.cpp +++ b/src/modes/Edit.cpp @@ -88,6 +88,10 @@ namespace groove { break; } break; + case 'f': + this->editor.mode_ = groove::Mode::SEARCH; + this->editor.input(' '); + break; case 'u': this->editor.history.undo(); break; diff --git a/src/modes/Search.cpp b/src/modes/Search.cpp new file mode 100644 index 0000000..36022b0 --- /dev/null +++ b/src/modes/Search.cpp @@ -0,0 +1,70 @@ +#include +#include +#include + + +namespace groove { + namespace modes { + + void Search::input(int c) { + this->editor.movement(c); + switch (c) { + case 27: + this->editor.mode_ = groove::Mode::EDIT; + this->editor.input(' '); + break; + case KEY_BACKSPACE: + if (this->keyword.size() > 0) + this->keyword.pop_back(); + break; + case KEY_ENTER: + case 10: + this->search(); + break; + default: + { + std::regex regex("[ -~]"); + std::string character(1, c); + if (!std::regex_match(character, regex)) + break; + this->keyword += c; + } + break; + } + } + + void Search::search() { + if (this->keyword == "") + return; + std::regex regex(this->keyword); + int pos = this->match == 0 ? this->position + 1 : this->position; + for (long i = pos; i < this->editor.buffer->size(); i++) { + if (i >= this->editor.buffer->size() - 1) + this->position = 0; + std::string line = this->editor.buffer->at(i); + try { + std::sregex_iterator next(line.begin(), line.end(), regex); + std::sregex_iterator end; + if (next == end) { + this->match = 0; + } + while (next != end) { + std::smatch match = *next; + for (unsigned n = this->match; n < match.size(); ++n) { + this->editor.y = i; + this->editor.offset = i - LINES / 2; + this->editor.x = match.position(n); + this->position = i; + this->match++; + return; + } + next++; + } + } catch (std::regex_error& e) { + // Syntax error in the regular expression + } + } + } + + } +} \ No newline at end of file diff --git a/src/modes/Search.hpp b/src/modes/Search.hpp new file mode 100644 index 0000000..4ff5c42 --- /dev/null +++ b/src/modes/Search.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace groove { + namespace modes { + + class Search : public Mode { + private: + std::string keyword; + long position; + int match; + + void search(); + public: + Search(groove::Editor& editor) : Mode(editor), keyword(""), position(0), match(0) {}; + std::string status() { + return "\tFind: " + this->keyword + ' ' + this->status_; + } + void input(int c); + }; + + } +} \ No newline at end of file