diff --git a/include/cli.h b/include/cli.h index 663f432..e54ae0b 100644 --- a/include/cli.h +++ b/include/cli.h @@ -3,7 +3,20 @@ #include "pch.h" namespace crib::cli { +struct Command { + void (*run)(std::vector); + std::string (*summary)(); + void (*help)(); +}; + +struct cli_error : std::runtime_error { + int exit_code; + cli_error(std::string msg, int code) + : std::runtime_error(std::move(msg)), exit_code(code) {} +}; + extern bool use_colors; void help(); +int execute(const std::string &name, const Command &cmd, int argc, char *argv[]); int run(int argc, char *argv[]); } // namespace crib::cli diff --git a/include/commands/ed/ed.h b/include/commands/ed/ed.h index 47d0f90..03ba39f 100644 --- a/include/commands/ed/ed.h +++ b/include/commands/ed/ed.h @@ -6,5 +6,5 @@ namespace crib::commands::ed { std::string summary(); void help(); -void run(int argc, char *argv[]); +void run(std::vector); } // namespace crib::commands::ed diff --git a/include/internal/vase/iterators/line.h b/include/internal/vase/iterators/line.h index efb848a..4e703a4 100644 --- a/include/internal/vase/iterators/line.h +++ b/include/internal/vase/iterators/line.h @@ -19,4 +19,56 @@ struct LineIterator { bool next(std::string *line); uint64_t byte_offset(); }; + +struct Iterator { + Shard *root; + std::string line; + + Iterator(Shard *root, uint64_t line_num) + : root(root), it(root, line_num, Direction::Forward) { + Shard::retain(root); + } + + ~Iterator() { + Shard::release(root); + } + + Iterator(const Iterator &other) + : root(other.root), it(other.it) { + Shard::retain(root); + } + + Iterator &operator=(const Iterator &other) { + if (this != &other) { + Shard::retain(other.root); + Shard::release(root); + root = other.root; + it = other.it; + } + return *this; + } + + Iterator(Iterator &&other) noexcept + : root(other.root), it(std::move(other.it)) { + other.root = nullptr; + } + + Iterator &operator=(Iterator &&other) noexcept { + if (this != &other) { + Shard::release(root); + root = other.root; + it = std::move(other.it); + other.root = nullptr; + } + return *this; + } + + std::string &next() { + it.next(&line); + return line; + } + +private: + LineIterator it; +}; } // namespace crib::internal::vase diff --git a/include/internal/vase/vase.h b/include/internal/vase/vase.h index 7fe03bc..6a6f116 100644 --- a/include/internal/vase/vase.h +++ b/include/internal/vase/vase.h @@ -53,9 +53,7 @@ struct Vase { std::string to_string(); std::string to_string(Range range); - Point resolve_column(uint64_t line, uint64_t column); - - LineIterator iterate(uint64_t line); + Iterator iterate(uint64_t line); void insert(Point *point, char key); void insert(Point *point, const char *data, uint64_t len); diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 82649ff..5bcb045 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2,18 +2,6 @@ #include "commands/ed/ed.h" namespace crib::cli { -struct Command { - void (*run)(int, char **); - std::string (*summary)(); - void (*help)(); -}; - -struct cli_error : std::runtime_error { - int exit_code; - cli_error(std::string msg, int code) - : std::runtime_error(std::move(msg)), exit_code(code) {} -}; - static const std::unordered_map commands = { {"ed", {crib::commands::ed::run, @@ -45,9 +33,10 @@ void help() { std::cout << " " << name << " - " << cmd.summary() << "\n"; } -int execute(const std::string &name, const Command &cmd, int argc, char **argv) { +int execute(const std::string &name, const Command &cmd, int argc, char *argv[]) { try { - cmd.run(argc - 1, argv + 1); + std::vector args(argv, argv + argc); + cmd.run(args); return 0; } catch (const cli_error &e) { std::cerr << "Error running " << name << ": " << e.what() << '\n'; @@ -69,7 +58,7 @@ int run(int argc, char *argv[]) { if (argc > 1) if (auto it = commands.find(argv[1]); it != commands.end()) - return execute(it->first, it->second, argc, argv); + return execute(it->first, it->second, argc - 1, argv + 1); if (argc > 1 && std::string(argv[1]) == "--help") { help(); diff --git a/src/commands/ed/ed.cc b/src/commands/ed/ed.cc index 32b983c..2376dba 100644 --- a/src/commands/ed/ed.cc +++ b/src/commands/ed/ed.cc @@ -5,7 +5,7 @@ std::string summary() { return "A POSIX-compliant line editor."; } void help() {} -void run(int, char *[]) { +void run(std::vector args) { return; } } // namespace crib::commands::ed diff --git a/src/internal/vase/vase.cc b/src/internal/vase/vase.cc index de19143..1eafa63 100644 --- a/src/internal/vase/vase.cc +++ b/src/internal/vase/vase.cc @@ -55,8 +55,8 @@ std::string Vase::to_string(Range range) { return out; } -LineIterator Vase::iterate(uint64_t line) { - return LineIterator(root, line, Direction::Forward); +Iterator Vase::iterate(uint64_t line) { + return Iterator(root, line); } bool Vase::undo() {