Reqrite project as BEd specific.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#include "definitions.h"
|
||||
#include "internal/generic.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::address {
|
||||
struct address_error : ed_error {
|
||||
address_error(const char *msg) : ed_error(msg) {}
|
||||
};
|
||||
|
||||
struct Address {
|
||||
// % refers to range of whatever was resulted from the previous modification.
|
||||
// it expands in theory to a Num,Num and so can be followed by chaining more adresses the ed way.
|
||||
// this is handled and resolved by the handle function,
|
||||
// the constuctor and resolve etc. are also only called in the handle function,
|
||||
// i.e. handle is the only public facing API from this namespace & class for now.
|
||||
//
|
||||
// in case of any issue an instance of address_error(const char *) is thrown.
|
||||
|
||||
struct Result {
|
||||
std::array<uint64_t, 2> data{};
|
||||
uint8_t size{0};
|
||||
std::span<const uint64_t> span(uint8_t max = UINT8_MAX) const {
|
||||
return {data.data(), std::min(size, max)};
|
||||
}
|
||||
};
|
||||
|
||||
struct None {};
|
||||
|
||||
// Posix ed types of addressing.
|
||||
struct Current {}; // .
|
||||
|
||||
struct Last {}; // $
|
||||
|
||||
struct Number { // n
|
||||
uint64_t i;
|
||||
};
|
||||
|
||||
struct Mark { // 'm
|
||||
char m;
|
||||
};
|
||||
|
||||
struct RegexLine { // /re/ or ?re?
|
||||
internal::Direction dir;
|
||||
std::string re;
|
||||
};
|
||||
|
||||
// BEd Extended types of addressing.
|
||||
struct Regex { // &/re/ or &?re?
|
||||
internal::Direction dir; // returns next/previous line containing the regex
|
||||
std::string re; // (not only if it matches full line)
|
||||
};
|
||||
|
||||
struct Diagnostic { // #n# for diagnostic number n. (From lsp.)
|
||||
uint16_t n;
|
||||
};
|
||||
|
||||
struct DiagnosticNext { // ^ or % for previous/next diagnostic
|
||||
internal::Direction dir;
|
||||
};
|
||||
|
||||
struct SymbolDefinition { // <sym> goto symbol definition. (From lsp or using internal language parsers)
|
||||
std::string sym;
|
||||
};
|
||||
|
||||
struct SymbolReference { // <sym:n> goto nth symbol reference
|
||||
uint16_t n;
|
||||
std::string sym;
|
||||
};
|
||||
|
||||
struct SymbolReferenceNext { // >sym> or <sym<
|
||||
internal::Direction dir; // goto next or previous symbol reference
|
||||
std::string sym;
|
||||
};
|
||||
|
||||
struct Block { // [ or ] goto start/end of containing block.
|
||||
internal::Direction dir;
|
||||
};
|
||||
|
||||
struct Scripted { // (function_name:arguments)
|
||||
std::string func; // Calls ruby mapping with name giving the argument as string.
|
||||
std::string arg; // resolves to line number returned by function (or throws error).
|
||||
// The mruby runtime also has the full context of the file and extentions etc.
|
||||
};
|
||||
|
||||
std::variant<
|
||||
std::monostate,
|
||||
None,
|
||||
Current,
|
||||
Last,
|
||||
Number,
|
||||
Mark,
|
||||
RegexLine,
|
||||
Regex,
|
||||
Diagnostic,
|
||||
DiagnosticNext,
|
||||
SymbolDefinition,
|
||||
SymbolReference,
|
||||
SymbolReferenceNext,
|
||||
Block,
|
||||
Scripted>
|
||||
base{};
|
||||
|
||||
// they can then be followed by any number of +n or -n etc accumulating in.
|
||||
int64_t offset = 0;
|
||||
|
||||
Address(std::string &cmd, uint64_t &i);
|
||||
Address() = default;
|
||||
|
||||
uint64_t resolve(BEd &ctx);
|
||||
|
||||
static Result handle(BEd &ctx, std::string &cmd, uint64_t &i);
|
||||
};
|
||||
} // namespace bed::internal::address
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "definitions.h"
|
||||
#include "internal/marks/marks.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::buffer {
|
||||
struct Buffer {
|
||||
internal::vase::Vase vase;
|
||||
internal::marks::MarksEngine marks;
|
||||
uint64_t line = 0;
|
||||
bool modified;
|
||||
std::filesystem::path save_path = "";
|
||||
struct {
|
||||
uint64_t start{0};
|
||||
uint64_t end{0};
|
||||
} prev_range;
|
||||
|
||||
Buffer();
|
||||
Buffer(std::string command);
|
||||
Buffer(std::filesystem::path path);
|
||||
|
||||
~Buffer() = default;
|
||||
|
||||
void load(std::string command);
|
||||
void load(std::filesystem::path path);
|
||||
void jump(uint64_t n_line);
|
||||
void join(uint64_t start_line, uint64_t end_line);
|
||||
void remove(uint64_t start_line, uint64_t end_line);
|
||||
void append(std::string text, uint64_t line);
|
||||
void print(uint64_t start_line, uint64_t end_line);
|
||||
std::string list_string(std::string_view s);
|
||||
};
|
||||
} // namespace bed::internal::buffer
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "definitions.h"
|
||||
#include "internal/trie/trie.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::commands {
|
||||
struct Command {
|
||||
enum struct AddressMode : uint8_t {
|
||||
None,
|
||||
Single,
|
||||
Range
|
||||
} address_mode;
|
||||
|
||||
enum struct SuffixKind : uint8_t {
|
||||
None,
|
||||
Suffix,
|
||||
Argument,
|
||||
Continuation
|
||||
} suffix;
|
||||
|
||||
std::string desc;
|
||||
|
||||
bool accept_zero;
|
||||
|
||||
void (*handle)(BEd &, std::span<const uint64_t>, std::string_view);
|
||||
|
||||
static void register_posix(BEd &ctx);
|
||||
};
|
||||
} // namespace bed::internal::commands
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "definitions.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::commands {
|
||||
struct Suffix {
|
||||
std::string desc;
|
||||
void (*handle)(BEd &);
|
||||
|
||||
static void register_suffixes(BEd &ctx);
|
||||
};
|
||||
} // namespace bed::internal::commands
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../shard.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal {
|
||||
enum struct Direction : uint8_t {
|
||||
Forward,
|
||||
Backward
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::marks {
|
||||
struct MarksEngine {};
|
||||
} // namespace bed::internal::marks
|
||||
@@ -0,0 +1,246 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::trie {
|
||||
template <typename T = void>
|
||||
struct Trie {
|
||||
using V = std::conditional_t<std::is_void_v<T>, std::monostate, T>;
|
||||
|
||||
struct Node {
|
||||
std::string edge;
|
||||
std::optional<V> value{};
|
||||
std::vector<Node *> children;
|
||||
Node(std::string e = {}) : edge(std::move(e)) {}
|
||||
~Node() {
|
||||
for (auto *c : children)
|
||||
delete c;
|
||||
};
|
||||
} root;
|
||||
|
||||
bool case_sensitive;
|
||||
|
||||
Trie(bool cs = true) : case_sensitive(cs) {}
|
||||
|
||||
void insert(std::string_view key)
|
||||
requires std::is_void_v<T>
|
||||
{
|
||||
_insert(key, std::monostate{});
|
||||
}
|
||||
|
||||
void insert(std::string_view key, V el)
|
||||
requires(!std::is_void_v<T>)
|
||||
{
|
||||
_insert(key, std::move(el));
|
||||
}
|
||||
|
||||
void _insert(std::string_view key, V &&el) {
|
||||
Node *current = &root;
|
||||
uint64_t pos = 0;
|
||||
while (pos < key.size()) {
|
||||
Node *child = find_child(*current, key[pos]);
|
||||
if (!child) {
|
||||
auto *node = new Node(std::string(key.substr(pos)));
|
||||
node->value = std::move(el);
|
||||
current->children.push_back(node);
|
||||
return;
|
||||
}
|
||||
const auto common = common_prefix(child->edge, key.substr(pos));
|
||||
if (common == child->edge.size()) {
|
||||
pos += common;
|
||||
current = child;
|
||||
continue;
|
||||
}
|
||||
auto *split = new Node(child->edge.substr(0, common));
|
||||
child->edge.erase(0, common);
|
||||
split->children.push_back(child);
|
||||
current->children.erase(
|
||||
std::find(current->children.begin(), current->children.end(), child)
|
||||
);
|
||||
current->children.push_back(split);
|
||||
pos += common;
|
||||
if (pos == key.size()) {
|
||||
split->value = std::move(el);
|
||||
return;
|
||||
}
|
||||
auto *node = new Node(std::string(key.substr(pos)));
|
||||
node->value = std::move(el);
|
||||
split->children.push_back(node);
|
||||
return;
|
||||
}
|
||||
current->value = std::move(el);
|
||||
}
|
||||
|
||||
void remove(std::string_view key) {
|
||||
_remove(root, key, 0);
|
||||
}
|
||||
|
||||
bool _remove(Node &node, std::string_view key, uint64_t pos) {
|
||||
if (pos == key.size()) {
|
||||
if (!node.value)
|
||||
return false;
|
||||
node.value.reset();
|
||||
return true;
|
||||
}
|
||||
Node *child = find_child(node, key[pos]);
|
||||
if (!child)
|
||||
return false;
|
||||
const auto remaining = key.substr(pos);
|
||||
const auto common = common_prefix(child->edge, remaining);
|
||||
if (common != child->edge.size())
|
||||
return false;
|
||||
const auto child_pos = pos + common;
|
||||
if (!_remove(*child, key, child_pos))
|
||||
return false;
|
||||
if (!child->value && child->children.empty()) {
|
||||
auto it = std::find(
|
||||
node.children.begin(),
|
||||
node.children.end(),
|
||||
child
|
||||
);
|
||||
node.children.erase(it);
|
||||
delete child;
|
||||
return true;
|
||||
}
|
||||
if (!child->value && child->children.size() == 1) {
|
||||
Node *grandchild = child->children.front();
|
||||
child->edge += grandchild->edge;
|
||||
child->value = std::move(grandchild->value);
|
||||
child->children = std::move(grandchild->children);
|
||||
grandchild->children.clear();
|
||||
delete grandchild;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> search(std::string_view prefix) {
|
||||
std::vector<std::string> result;
|
||||
Node *current = &root;
|
||||
std::string key;
|
||||
uint64_t pos = 0;
|
||||
while (pos < prefix.size()) {
|
||||
Node *child = find_child(*current, prefix[pos]);
|
||||
if (!child)
|
||||
return result;
|
||||
const auto remaining = prefix.substr(pos);
|
||||
const auto common = common_prefix(child->edge, remaining);
|
||||
if (common == 0)
|
||||
return result;
|
||||
if (common < child->edge.size()) {
|
||||
if (common == remaining.size()) {
|
||||
key += child->edge;
|
||||
collect(*child, key, result);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
key += child->edge;
|
||||
pos += common;
|
||||
current = child;
|
||||
}
|
||||
collect(*current, key, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void collect(
|
||||
const Node &node,
|
||||
std::string &key,
|
||||
std::vector<std::string> &result
|
||||
) {
|
||||
if (node.value)
|
||||
result.push_back(key);
|
||||
for (auto *child : node.children) {
|
||||
const auto old_size = key.size();
|
||||
key += child->edge;
|
||||
collect(*child, key, result);
|
||||
key.resize(old_size);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t longest_match(std::string_view input) {
|
||||
Node *current = &root;
|
||||
uint64_t pos = 0;
|
||||
uint64_t longest = 0;
|
||||
if (current->value)
|
||||
longest = 0;
|
||||
while (pos < input.size()) {
|
||||
Node *child = find_child(*current, input[pos]);
|
||||
if (!child)
|
||||
break;
|
||||
const auto remaining = input.substr(pos);
|
||||
const auto common = common_prefix(child->edge, remaining);
|
||||
if (common != child->edge.size())
|
||||
break;
|
||||
pos += common;
|
||||
current = child;
|
||||
if (current->value)
|
||||
longest = pos;
|
||||
}
|
||||
return longest;
|
||||
}
|
||||
|
||||
bool matches(std::string_view key)
|
||||
requires(std::is_void_v<T>)
|
||||
{
|
||||
Node *current = &root;
|
||||
uint64_t pos = 0;
|
||||
while (pos < key.size()) {
|
||||
Node *child = find_child(*current, key[pos]);
|
||||
if (!child)
|
||||
return false;
|
||||
const auto remaining = key.substr(pos);
|
||||
const auto common = common_prefix(child->edge, remaining);
|
||||
if (common != child->edge.size())
|
||||
return false;
|
||||
pos += common;
|
||||
current = child;
|
||||
}
|
||||
return current->value.has_value();
|
||||
}
|
||||
|
||||
std::optional<V> get(std::string_view key)
|
||||
requires(!std::is_void_v<T>)
|
||||
{
|
||||
Node *current = &root;
|
||||
uint64_t pos = 0;
|
||||
while (pos < key.size()) {
|
||||
Node *child = find_child(*current, key[pos]);
|
||||
if (!child)
|
||||
return std::nullopt;
|
||||
const auto remaining = key.substr(pos);
|
||||
const auto common = common_prefix(child->edge, remaining);
|
||||
if (common != child->edge.size())
|
||||
return std::nullopt;
|
||||
pos += common;
|
||||
current = child;
|
||||
}
|
||||
if (!current->value)
|
||||
return std::nullopt;
|
||||
return *current->value;
|
||||
}
|
||||
|
||||
bool equal_char(char a, char b) const {
|
||||
if (case_sensitive)
|
||||
return a == b;
|
||||
return std::tolower((unsigned char)a) == std::tolower((unsigned char)b);
|
||||
}
|
||||
|
||||
uint64_t common_prefix(
|
||||
std::string_view a,
|
||||
std::string_view b
|
||||
) {
|
||||
const auto n = std::min(a.size(), b.size());
|
||||
uint64_t i = 0;
|
||||
while (i < n && equal_char(a[i], b[i]))
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
Node *find_child(Node &node, char first) {
|
||||
for (auto *child : node.children)
|
||||
if (equal_char(child->edge.front(), first))
|
||||
return child;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
} // namespace bed::internal::trie
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "buffer.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
struct AppendBuffer : Buffer {
|
||||
char *buf = nullptr;
|
||||
uint64_t allocated_capacity = 0;
|
||||
@@ -22,4 +22,4 @@ struct AppendBuffer : Buffer {
|
||||
private:
|
||||
void grow(uint64_t len);
|
||||
};
|
||||
} // namespace crib::internal::vase
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
struct Buffer {
|
||||
virtual const char *read(uint64_t pos) = 0;
|
||||
virtual uint64_t length() = 0;
|
||||
virtual ~Buffer() = default;
|
||||
};
|
||||
} // namespace crib::internal::vase
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "buffer.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
struct OriginalBuffer : Buffer {
|
||||
const char *buf;
|
||||
uint64_t len;
|
||||
@@ -16,4 +16,4 @@ struct OriginalBuffer : Buffer {
|
||||
const char *read(uint64_t pos) override;
|
||||
uint64_t length() override;
|
||||
};
|
||||
} // namespace crib::internal::vase
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
constexpr uint64_t PETAL_SIZE_MAX = 32 * 1024;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "pch.h"
|
||||
#include "petal.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
struct LineIterator {
|
||||
PetalIterator it;
|
||||
const char *chunk;
|
||||
@@ -70,4 +70,4 @@ struct Iterator {
|
||||
private:
|
||||
LineIterator it;
|
||||
};
|
||||
} // namespace crib::internal::vase
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "../shard.h"
|
||||
#include "iter.h"
|
||||
#include "internal/generic.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
struct PetalIterator {
|
||||
Direction dir;
|
||||
Shard *root = nullptr;
|
||||
@@ -26,4 +26,4 @@ struct PetalIterator {
|
||||
private:
|
||||
Petal *_next(uint64_t *offset);
|
||||
};
|
||||
} // namespace crib::internal::vase
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "constants.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
struct Shard {
|
||||
enum struct Kind : uint8_t {
|
||||
Branch,
|
||||
@@ -63,4 +63,4 @@ struct Petal : Shard {
|
||||
source(source), pos(pos) {};
|
||||
};
|
||||
|
||||
} // namespace crib::internal::vase
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "pch.h"
|
||||
#include "shard.h"
|
||||
|
||||
namespace crib::internal::vase {
|
||||
namespace bed::internal::vase {
|
||||
struct Point {
|
||||
uint64_t row;
|
||||
uint64_t col;
|
||||
@@ -114,4 +114,4 @@ private:
|
||||
std::string_view pattern, Range range, std::string_view options
|
||||
);
|
||||
};
|
||||
} // namespace crib::internal::vase
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
Reference in New Issue
Block a user