Setup cli routing & other cleanup.
This commit is contained in:
@@ -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
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
@@ -2,3 +2,9 @@
|
|||||||
|
|
||||||
#include "internal/vase/vase.h"
|
#include "internal/vase/vase.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
|
namespace crib::commands::ed {
|
||||||
|
std::string summary();
|
||||||
|
void help();
|
||||||
|
void run(int argc, char *argv[]);
|
||||||
|
} // namespace crib::commands::ed
|
||||||
|
|||||||
@@ -18,18 +18,19 @@ struct Range {
|
|||||||
Point end;
|
Point end;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegexGroup {
|
struct Vase {
|
||||||
uint64_t start{UINT32_MAX};
|
struct RegexGroup {
|
||||||
uint64_t end{UINT32_MAX};
|
uint64_t start{0};
|
||||||
};
|
uint64_t end{0};
|
||||||
|
};
|
||||||
|
|
||||||
struct RegexMatch {
|
struct RegexMatch {
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
uint64_t end;
|
uint64_t end;
|
||||||
RegexGroup groups[9]{};
|
RegexGroup groups[9]{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReplacePart {
|
struct ReplacePart {
|
||||||
enum struct PartType {
|
enum struct PartType {
|
||||||
FullMatch,
|
FullMatch,
|
||||||
CaptureGroup,
|
CaptureGroup,
|
||||||
@@ -37,9 +38,8 @@ struct ReplacePart {
|
|||||||
} type;
|
} type;
|
||||||
|
|
||||||
std::variant<uint8_t, Shard *> value;
|
std::variant<uint8_t, Shard *> value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vase {
|
|
||||||
OriginalBuffer *original;
|
OriginalBuffer *original;
|
||||||
AppendBuffer *append;
|
AppendBuffer *append;
|
||||||
Shard *root;
|
Shard *root;
|
||||||
|
|||||||
@@ -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<std::string, Command> 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 <command> [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
|
||||||
@@ -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
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "internal/vase/vase.h"
|
#include "internal/vase/vase.h"
|
||||||
|
|
||||||
namespace crib::internal::vase {
|
namespace crib::internal::vase {
|
||||||
std::vector<ReplacePart> Vase::parse_replace(std::string_view s) {
|
std::vector<Vase::ReplacePart> Vase::parse_replace(std::string_view s) {
|
||||||
std::vector<ReplacePart> parts;
|
std::vector<ReplacePart> parts;
|
||||||
std::string constant;
|
std::string constant;
|
||||||
auto flush_constant = [&]() {
|
auto flush_constant = [&]() {
|
||||||
@@ -100,7 +100,7 @@ void Vase::regex_search_replace(
|
|||||||
uint8_t idx = std::get<uint8_t>(part.value);
|
uint8_t idx = std::get<uint8_t>(part.value);
|
||||||
if (idx <= 9) {
|
if (idx <= 9) {
|
||||||
const RegexGroup &group = match.groups[idx - 1];
|
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 ls = group.start - match.start;
|
||||||
uint64_t le = group.end - match.start;
|
uint64_t le = group.end - match.start;
|
||||||
auto [a, b] = Shard::split(dropped, ls);
|
auto [a, b] = Shard::split(dropped, ls);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "internal/vase/vase.h"
|
#include "internal/vase/vase.h"
|
||||||
|
|
||||||
namespace crib::internal::vase {
|
namespace crib::internal::vase {
|
||||||
std::vector<RegexMatch> Vase::_regex_search(
|
std::vector<Vase::RegexMatch> Vase::_regex_search(
|
||||||
std::string_view pattern, Range range, std::string_view options
|
std::string_view pattern, Range range, std::string_view options
|
||||||
) {
|
) {
|
||||||
bool global = false;
|
bool global = false;
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
#include "cli/cli.h"
|
#include "cli.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
return crib::cli::run(argc, argv);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user