From fdb67b449db90815431622631986fc1932bfa6e9 Mon Sep 17 00:00:00 2001 From: Syed Daanish Date: Thu, 6 Aug 2026 23:21:38 +0100 Subject: [PATCH] Setup cli routing & other cleanup. --- include/cli.h | 9 ++++ include/cli/cli.h | 3 -- include/commands/ed/ed.h | 6 +++ include/internal/vase/vase.h | 42 ++++++++--------- src/cli/cli.cc | 83 +++++++++++++++++++++++++++++++++ src/commands/ed/ed.cc | 11 +++++ src/internal/vase/regex/api.cc | 4 +- src/internal/vase/regex/core.cc | 2 +- src/main.cc | 3 +- 9 files changed, 135 insertions(+), 28 deletions(-) create mode 100644 include/cli.h delete mode 100644 include/cli/cli.h create mode 100644 src/cli/cli.cc create mode 100644 src/commands/ed/ed.cc diff --git a/include/cli.h b/include/cli.h new file mode 100644 index 0000000..663f432 --- /dev/null +++ b/include/cli.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pch.h" + +namespace crib::cli { +extern bool use_colors; +void help(); +int run(int argc, char *argv[]); +} // namespace crib::cli diff --git a/include/cli/cli.h b/include/cli/cli.h deleted file mode 100644 index b0c558d..0000000 --- a/include/cli/cli.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include "pch.h" diff --git a/include/commands/ed/ed.h b/include/commands/ed/ed.h index 1c808ba..47d0f90 100644 --- a/include/commands/ed/ed.h +++ b/include/commands/ed/ed.h @@ -2,3 +2,9 @@ #include "internal/vase/vase.h" #include "pch.h" + +namespace crib::commands::ed { +std::string summary(); +void help(); +void run(int argc, char *argv[]); +} // namespace crib::commands::ed diff --git a/include/internal/vase/vase.h b/include/internal/vase/vase.h index 8b0706f..7fe03bc 100644 --- a/include/internal/vase/vase.h +++ b/include/internal/vase/vase.h @@ -18,28 +18,28 @@ struct Range { Point end; }; -struct RegexGroup { - uint64_t start{UINT32_MAX}; - uint64_t end{UINT32_MAX}; -}; - -struct RegexMatch { - uint64_t start; - uint64_t end; - RegexGroup groups[9]{}; -}; - -struct ReplacePart { - enum struct PartType { - FullMatch, - CaptureGroup, - Constant - } type; - - std::variant value; -}; - struct Vase { + struct RegexGroup { + uint64_t start{0}; + uint64_t end{0}; + }; + + struct RegexMatch { + uint64_t start; + uint64_t end; + RegexGroup groups[9]{}; + }; + + struct ReplacePart { + enum struct PartType { + FullMatch, + CaptureGroup, + Constant + } type; + + std::variant value; + }; + OriginalBuffer *original; AppendBuffer *append; Shard *root; diff --git a/src/cli/cli.cc b/src/cli/cli.cc new file mode 100644 index 0000000..82649ff --- /dev/null +++ b/src/cli/cli.cc @@ -0,0 +1,83 @@ +#include "cli.h" +#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, + crib::commands::ed::summary, + crib::commands::ed::help}}, +}; + +bool use_color() { + if (std::getenv("NO_COLOR")) + return false; + if (std::getenv("CLICOLOR_FORCE")) + return true; + if (!isatty(STDERR_FILENO)) + return false; + const char *term = std::getenv("TERM"); + if (!term || std::string_view(term) == "dumb" || std::string_view(term) == "xterm") + return false; + if (const char *clicolor = std::getenv("CLICOLOR")) + return std::string_view(clicolor) != "0"; + return true; +} + +bool use_colors = use_color(); + +void help() { + std::cout << "Usage: crib [options]\n\n" + << "Where command is one of\n"; + for (auto &[name, cmd] : commands) + std::cout << " " << name << " - " << cmd.summary() << "\n"; +} + +int execute(const std::string &name, const Command &cmd, int argc, char **argv) { + try { + cmd.run(argc - 1, argv + 1); + return 0; + } catch (const cli_error &e) { + std::cerr << "Error running " << name << ": " << e.what() << '\n'; + return e.exit_code; + } catch (const std::exception &e) { + std::cerr << "Error running " << name << ": " << e.what() << '\n'; + return 1; + } catch (...) { + std::cerr << "Unknown error running " << name << '\n'; + return 1; + } +} + +int run(int argc, char *argv[]) { + std::string invoked_as = std::filesystem::path(argv[0]).filename(); + + if (auto it = commands.find(invoked_as); it != commands.end()) + return execute(it->first, it->second, argc, argv); + + if (argc > 1) + if (auto it = commands.find(argv[1]); it != commands.end()) + return execute(it->first, it->second, argc, argv); + + if (argc > 1 && std::string(argv[1]) == "--help") { + help(); + return 0; + } + + std::cerr << "Invalid command given.\n\n"; + help(); + return 2; +} +} // namespace crib::cli diff --git a/src/commands/ed/ed.cc b/src/commands/ed/ed.cc new file mode 100644 index 0000000..32b983c --- /dev/null +++ b/src/commands/ed/ed.cc @@ -0,0 +1,11 @@ +#include "commands/ed/ed.h" + +namespace crib::commands::ed { +std::string summary() { + return "A POSIX-compliant line editor."; +} +void help() {} +void run(int, char *[]) { + return; +} +} // namespace crib::commands::ed diff --git a/src/internal/vase/regex/api.cc b/src/internal/vase/regex/api.cc index 63e7fee..308b7d6 100644 --- a/src/internal/vase/regex/api.cc +++ b/src/internal/vase/regex/api.cc @@ -1,7 +1,7 @@ #include "internal/vase/vase.h" namespace crib::internal::vase { -std::vector Vase::parse_replace(std::string_view s) { +std::vector Vase::parse_replace(std::string_view s) { std::vector parts; std::string constant; auto flush_constant = [&]() { @@ -100,7 +100,7 @@ void Vase::regex_search_replace( uint8_t idx = std::get(part.value); if (idx <= 9) { const RegexGroup &group = match.groups[idx - 1]; - if (group.start != UINT32_MAX) { + if (group.start > group.end) { uint64_t ls = group.start - match.start; uint64_t le = group.end - match.start; auto [a, b] = Shard::split(dropped, ls); diff --git a/src/internal/vase/regex/core.cc b/src/internal/vase/regex/core.cc index 0a62663..7f8c51a 100644 --- a/src/internal/vase/regex/core.cc +++ b/src/internal/vase/regex/core.cc @@ -1,7 +1,7 @@ #include "internal/vase/vase.h" namespace crib::internal::vase { -std::vector Vase::_regex_search( +std::vector Vase::_regex_search( std::string_view pattern, Range range, std::string_view options ) { bool global = false; diff --git a/src/main.cc b/src/main.cc index 2bf6373..734069c 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,6 @@ -#include "cli/cli.h" +#include "cli.h" #include "pch.h" int main(int argc, char *argv[]) { + return crib::cli::run(argc, argv); }