Add line_iterator_t

Adds support for splitting a collection into lines.
This commit is contained in:
ridiculousfish 2018-10-20 13:44:10 -07:00
parent a23894ca37
commit ce1463bde6
2 changed files with 53 additions and 0 deletions

View file

@ -379,6 +379,42 @@ wcstring_list_t split_string(const wcstring &val, wchar_t sep);
/// Join a list of strings by a separator character. /// Join a list of strings by a separator character.
wcstring join_strings(const wcstring_list_t &vals, wchar_t sep); wcstring join_strings(const wcstring_list_t &vals, wchar_t sep);
/// Support for iterating over a newline-separated string.
template <typename Collection>
class line_iterator_t {
// Storage for each line.
Collection storage;
// The collection we're iterating. Note we hold this by reference.
const Collection &coll;
// The current location in the iteration.
typename Collection::const_iterator current;
public:
/// Construct from a collection (presumably std::string or std::wcstring).
line_iterator_t(const Collection &coll) : coll(coll), current(coll.cbegin()) {}
/// Access the storage in which the last line was stored.
const Collection &line() const {
return storage;
}
/// Advances to the next line. \return true on success, false if we have exhausted the string.
bool next() {
if (current == coll.end())
return false;
auto newline_or_end = std::find(current, coll.cend(), '\n');
storage.assign(current, newline_or_end);
current = newline_or_end;
// Skip the newline.
if (current != coll.cend())
++current;
return true;
}
};
enum fuzzy_match_type_t { enum fuzzy_match_type_t {
// We match the string exactly: FOOBAR matches FOOBAR. // We match the string exactly: FOOBAR matches FOOBAR.
fuzzy_match_exact = 0, fuzzy_match_exact = 0,

View file

@ -2809,6 +2809,22 @@ static void test_input() {
} }
} }
static void test_line_iterator() {
say(L"Testing line iterator");
std::string text1 = "Alpha\nBeta\nGamma\n\nDelta\n";
std::vector<std::string> lines1;
line_iterator_t<std::string> iter1(text1);
while (iter1.next()) lines1.push_back(iter1.line());
do_test((lines1 == std::vector<std::string>{"Alpha", "Beta", "Gamma", "", "Delta"}));
wcstring text2 = L"\n\nAlpha\nBeta\nGamma\n\nDelta";
std::vector<wcstring> lines2;
line_iterator_t<wcstring> iter2(text2);
while (iter2.next()) lines2.push_back(iter2.line());
do_test((lines2 == std::vector<wcstring>{L"", L"", L"Alpha", L"Beta", L"Gamma", L"", L"Delta"}));
}
#define UVARS_PER_THREAD 8 #define UVARS_PER_THREAD 8
#define UVARS_TEST_PATH L"test/fish_uvars_test/varsfile.txt" #define UVARS_TEST_PATH L"test/fish_uvars_test/varsfile.txt"
@ -4805,6 +4821,7 @@ int main(int argc, char **argv) {
if (should_test_function("colors")) test_colors(); if (should_test_function("colors")) test_colors();
if (should_test_function("complete")) test_complete(); if (should_test_function("complete")) test_complete();
if (should_test_function("input")) test_input(); if (should_test_function("input")) test_input();
if (should_test_function("line_iterator")) test_line_iterator();
if (should_test_function("universal")) test_universal(); if (should_test_function("universal")) test_universal();
if (should_test_function("universal")) test_universal_callbacks(); if (should_test_function("universal")) test_universal_callbacks();
if (should_test_function("notifiers")) test_universal_notifiers(); if (should_test_function("notifiers")) test_universal_notifiers();