Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a276bf60da
|
||
|
|
3bfebe30ce
|
@@ -5,10 +5,11 @@
|
||||
|
||||
namespace bed::internal::io {
|
||||
struct Token {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
enum Kind : uint8_t {
|
||||
TempCurrent,
|
||||
BufferName,
|
||||
AddressSeperator,
|
||||
Address,
|
||||
Offset,
|
||||
@@ -23,7 +24,6 @@ struct Token {
|
||||
Shell,
|
||||
Ruby,
|
||||
File,
|
||||
Regex,
|
||||
Replacement,
|
||||
Suffix,
|
||||
Color1,
|
||||
|
||||
@@ -85,12 +85,12 @@ struct Parser {
|
||||
std::string_view cmd;
|
||||
uint16_t i;
|
||||
Command *command;
|
||||
std::vector<ui::Token> *tokens;
|
||||
std::vector<io::Token> *tokens;
|
||||
CompletionContext *completion;
|
||||
|
||||
explicit Parser(
|
||||
std::string_view cmd, BEd &bed, Command *command,
|
||||
std::vector<ui::Token> *tokens, CompletionContext *completion
|
||||
std::vector<io::Token> *tokens, CompletionContext *completion
|
||||
);
|
||||
|
||||
char peek(uint16_t = 0); // == \0 if at eof.
|
||||
@@ -107,7 +107,7 @@ struct Parser {
|
||||
void operation();
|
||||
|
||||
void parse();
|
||||
|
||||
static std::vector<io::Token> get_highlight(std::string_view cmd, BEd &bed);
|
||||
static Command get_command(std::string_view, BEd &);
|
||||
static std::vector<AddressPromise> get_addresses(std::string_view cmd, BEd &bed);
|
||||
};
|
||||
|
||||
@@ -4,31 +4,6 @@
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::ui {
|
||||
struct Token {
|
||||
enum struct Type : uint8_t {
|
||||
TempCurrent, // @
|
||||
AddressSeperator, // ; ,
|
||||
Address, // . $ % [ ] ^ ~
|
||||
Offset, // +N -N + -
|
||||
AddressRegex, // /re/ ?re?
|
||||
AddressSymbol, // >s> <s< <s>
|
||||
Number, // 10
|
||||
Mark, // 'm
|
||||
RubyFunction, // (func:arg)
|
||||
RubyArg,
|
||||
Function,
|
||||
Any,
|
||||
Shell,
|
||||
Ruby,
|
||||
File,
|
||||
Regex,
|
||||
Replacement,
|
||||
Suffix
|
||||
} type;
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
};
|
||||
|
||||
struct CommandIO {
|
||||
std::string cmd;
|
||||
uint16_t cursor;
|
||||
|
||||
@@ -29,8 +29,6 @@ uint64_t ShardBuffer::find_prev(std::string_view pattern, uint64_t start) {
|
||||
uint64_t ShardBuffer::next_closing(uint64_t start) {
|
||||
if (parse.lang) {
|
||||
uint64_t closing = syntax::next_closing(parse, start - 1);
|
||||
if (closing == UINT64_MAX)
|
||||
return lines();
|
||||
return closing + 1;
|
||||
} else {
|
||||
start += 10;
|
||||
|
||||
@@ -118,6 +118,39 @@ void Function::register_extented(BEd &ctx) {
|
||||
},
|
||||
}
|
||||
);
|
||||
ctx.functions.insert(
|
||||
"b",
|
||||
Function{
|
||||
.address_kind = Function::AddressKind::None,
|
||||
.argument_kind = Function::ArgumentKind::None,
|
||||
.input_mode = Function::InputMode::None,
|
||||
.desc = "List active buffers",
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.pre_text_mode = nullptr,
|
||||
.handle = [](
|
||||
BEd &ctx,
|
||||
const buffer::Address &addr_,
|
||||
vase::Shard *,
|
||||
const Argument &,
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
auto ¤t = std::get<std::string>(addr_);
|
||||
bool current_real = false;
|
||||
for (auto &[name, _] : ctx.buffers) {
|
||||
if (current == name) {
|
||||
ctx.io.write("* ");
|
||||
current_real = true;
|
||||
} else {
|
||||
ctx.io.write(" ");
|
||||
}
|
||||
ctx.io.write_line(name);
|
||||
}
|
||||
if (!current_real)
|
||||
ctx.io.write_line("* " + current);
|
||||
},
|
||||
}
|
||||
);
|
||||
ctx.functions.insert(
|
||||
"#",
|
||||
Function{
|
||||
@@ -137,6 +170,27 @@ void Function::register_extented(BEd &ctx) {
|
||||
) {},
|
||||
}
|
||||
);
|
||||
ctx.functions.insert(
|
||||
"`",
|
||||
Function{
|
||||
.address_kind = Function::AddressKind::None,
|
||||
.argument_kind = Function::ArgumentKind::Ruby,
|
||||
.input_mode = Function::InputMode::None,
|
||||
.desc = "Execute some ruby code",
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.pre_text_mode = nullptr,
|
||||
.handle = [](
|
||||
BEd &,
|
||||
const buffer::Address &,
|
||||
vase::Shard *,
|
||||
const Argument &,
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
// TODO: connect up to mruby.
|
||||
},
|
||||
}
|
||||
);
|
||||
ctx.functions.insert(
|
||||
"echo",
|
||||
Function{
|
||||
|
||||
@@ -745,10 +745,19 @@ void Function::register_posix(BEd &ctx) {
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
auto &addr = std::get<buffer::Range>(addr_);
|
||||
if (addr.start == addr.end)
|
||||
ctx.io.write_line(std::format(":{}:{}", addr.buffername, addr.start));
|
||||
else
|
||||
ctx.io.write_line(std::format(":{}:{},{}", addr.buffername, addr.start, addr.end));
|
||||
ctx.io.apply(io::Token::BufferName);
|
||||
ctx.io.write(":" + addr.buffername + ":");
|
||||
ctx.io.apply(io::Token::Number);
|
||||
if (addr.start == addr.end) {
|
||||
ctx.io.write_line(std::format(" {}", addr.start));
|
||||
} else {
|
||||
ctx.io.write(std::format(" {}", addr.start));
|
||||
ctx.io.apply(io::Token::AddressSeperator);
|
||||
ctx.io.write(",");
|
||||
ctx.io.apply(io::Token::Number);
|
||||
ctx.io.write_line(std::format("{}", addr.end));
|
||||
}
|
||||
ctx.io.reset();
|
||||
ctx.prev().buffername = addr.buffername;
|
||||
ctx.prev().start = addr.start;
|
||||
ctx.prev().end = addr.end;
|
||||
|
||||
@@ -6,34 +6,74 @@ void Parser::locator(AddressPromise &addr) {
|
||||
addr.base = AddressPromise::None{};
|
||||
switch (peek()) {
|
||||
case '.':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Current{};
|
||||
break;
|
||||
case '$':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Last{};
|
||||
break;
|
||||
case '%':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::LastRange{};
|
||||
break;
|
||||
case '[':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Block{Direction::Backward};
|
||||
break;
|
||||
case ']':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Block{Direction::Forward};
|
||||
break;
|
||||
case '^':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Diagnostic{Direction::Backward};
|
||||
break;
|
||||
case '~':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Diagnostic{Direction::Forward};
|
||||
break;
|
||||
case '\'':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)2,
|
||||
.type = io::Token::Mark}
|
||||
);
|
||||
advance();
|
||||
if (('a' <= peek() && peek() <= 'z')
|
||||
|| ('A' <= peek() && peek() <= 'Z'))
|
||||
@@ -43,6 +83,11 @@ void Parser::locator(AddressPromise &addr) {
|
||||
advance();
|
||||
break;
|
||||
case '{': {
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
uint16_t j = 0;
|
||||
std::string func;
|
||||
@@ -64,8 +109,24 @@ void Parser::locator(AddressPromise &addr) {
|
||||
arg = peek_str(j);
|
||||
else
|
||||
func = peek_str(j);
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)func.size(),
|
||||
.type = io::Token::RubyFunction}
|
||||
);
|
||||
if (arg.size())
|
||||
tokens->push_back(
|
||||
{.start = i + (uint64_t)func.size() + 1,
|
||||
.end = i + (uint64_t)func.size() + 1 + (uint64_t)arg.size(),
|
||||
.type = io::Token::RubyFunction}
|
||||
);
|
||||
addr.base = AddressPromise::Scripted{std::move(func), std::move(arg)};
|
||||
advance(j + 1);
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i - (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
} break;
|
||||
case '/': {
|
||||
advance();
|
||||
@@ -87,9 +148,19 @@ void Parser::locator(AddressPromise &addr) {
|
||||
Direction::Forward,
|
||||
std::string(peek_str(j))
|
||||
);
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)i - 1,
|
||||
.end = (uint64_t)i + j + 1,
|
||||
.type = io::Token::Regexp}
|
||||
);
|
||||
advance(j + 1);
|
||||
} break;
|
||||
case '?': {
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
uint16_t j = 0;
|
||||
while (true) {
|
||||
@@ -109,6 +180,11 @@ void Parser::locator(AddressPromise &addr) {
|
||||
Direction::Backward,
|
||||
std::string(peek_str(j))
|
||||
);
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)i - 1,
|
||||
.end = (uint64_t)i + j + 1,
|
||||
.type = io::Token::Regexp}
|
||||
);
|
||||
advance(j + 1);
|
||||
} break;
|
||||
case '<': {
|
||||
@@ -132,6 +208,11 @@ void Parser::locator(AddressPromise &addr) {
|
||||
};
|
||||
break;
|
||||
}
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)i - 1,
|
||||
.end = (uint64_t)i + j + 1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance(j + 1);
|
||||
} break;
|
||||
case '>': {
|
||||
@@ -149,9 +230,19 @@ void Parser::locator(AddressPromise &addr) {
|
||||
};
|
||||
break;
|
||||
}
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)i - 1,
|
||||
.end = (uint64_t)i + j + 1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance(j + 1);
|
||||
} break;
|
||||
case '+': {
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Current{};
|
||||
uint16_t j = 0;
|
||||
@@ -162,10 +253,20 @@ void Parser::locator(AddressPromise &addr) {
|
||||
}
|
||||
if (j == 0)
|
||||
num = 1;
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)i,
|
||||
.end = (uint64_t)i + j,
|
||||
.type = io::Token::Number}
|
||||
);
|
||||
advance(j);
|
||||
addr.offset += num;
|
||||
} break;
|
||||
case '-': {
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
addr.base = AddressPromise::Current{};
|
||||
uint16_t j = 0;
|
||||
@@ -176,17 +277,28 @@ void Parser::locator(AddressPromise &addr) {
|
||||
}
|
||||
if (j == 0)
|
||||
num = 1;
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)i,
|
||||
.end = (uint64_t)i + j,
|
||||
.type = io::Token::Number}
|
||||
);
|
||||
advance(j);
|
||||
addr.offset -= num;
|
||||
} break;
|
||||
default:
|
||||
if ('0' <= peek() && peek() <= '9') {
|
||||
uint16_t start = i;
|
||||
uint64_t num = 0;
|
||||
while ('0' <= peek() && peek() <= '9') {
|
||||
num = num * 10 + (peek() - '0');
|
||||
advance();
|
||||
}
|
||||
addr.base = AddressPromise::Number{num};
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)start,
|
||||
.end = (uint64_t)i,
|
||||
.type = io::Token::Number}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,14 +308,25 @@ int64_t Parser::offset() {
|
||||
while (peek() == '+' || peek() == '-'
|
||||
|| ('0' <= peek() && peek() <= '9')) {
|
||||
bool positive = peek() != '-';
|
||||
if (peek() == '+' || peek() == '-')
|
||||
if (peek() == '+' || peek() == '-') {
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSymbol}
|
||||
);
|
||||
advance();
|
||||
}
|
||||
uint16_t j = 0;
|
||||
int64_t num = 0;
|
||||
while ('0' <= peek(j) && peek(j) <= '9')
|
||||
num = num * 10 + (peek(j++) - '0');
|
||||
if (j == 0)
|
||||
num = 1;
|
||||
tokens->push_back(
|
||||
{.start = (uint64_t)i,
|
||||
.end = (uint64_t)i + j,
|
||||
.type = io::Token::Number}
|
||||
);
|
||||
advance(j);
|
||||
offset += positive ? num : -num;
|
||||
skip_ws();
|
||||
@@ -214,6 +337,7 @@ int64_t Parser::offset() {
|
||||
|
||||
void Parser::address(AddressPromise &addr) {
|
||||
if (peek() == ':') {
|
||||
uint16_t start = i;
|
||||
advance();
|
||||
uint16_t j = 0;
|
||||
while (peek(j) != ':' && peek(j) != '\0')
|
||||
@@ -222,6 +346,11 @@ void Parser::address(AddressPromise &addr) {
|
||||
advance(j);
|
||||
if (peek() == ':')
|
||||
advance();
|
||||
tokens->push_back(
|
||||
{.start = start,
|
||||
.end = i,
|
||||
.type = io::Token::BufferName}
|
||||
);
|
||||
}
|
||||
skip_ws();
|
||||
if (peek() == '\0')
|
||||
@@ -238,6 +367,11 @@ void Parser::addresses(std::vector<AddressPromise> &addresses) {
|
||||
address(*addr);
|
||||
while (peek() == ',' || peek() == ';') {
|
||||
addr->jumping = peek() == ';';
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::AddressSeperator}
|
||||
);
|
||||
advance();
|
||||
skip_ws();
|
||||
addresses.push_back({});
|
||||
|
||||
@@ -11,6 +11,11 @@ void Parser::operation() {
|
||||
if (len == 0)
|
||||
throw ed_error("Function not found.");
|
||||
functions::Function *function = bed.functions.get_ptr(peek_str(len));
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + len,
|
||||
.type = io::Token::Function}
|
||||
);
|
||||
advance(len);
|
||||
command->function = function;
|
||||
char suffix = '\0';
|
||||
@@ -27,10 +32,20 @@ void Parser::operation() {
|
||||
command->argument = peek();
|
||||
else
|
||||
throw ed_error("Valid mark needed.");
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::Mark}
|
||||
);
|
||||
advance();
|
||||
break;
|
||||
case functions::Function::ArgumentKind::Any:
|
||||
command->argument = std::string(peek_str());
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + peek_str().size(),
|
||||
.type = io::Token::Any}
|
||||
);
|
||||
advance(peek_str().size());
|
||||
break;
|
||||
case functions::Function::ArgumentKind::Global: {
|
||||
@@ -108,8 +123,18 @@ void Parser::operation() {
|
||||
skip_ws();
|
||||
switch (peek()) {
|
||||
case '!':
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = (uint64_t)i + 1,
|
||||
.type = io::Token::Error}
|
||||
);
|
||||
advance();
|
||||
command->argument = functions::Function::ShellArg(std::string(peek_str()));
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + peek_str().size(),
|
||||
.type = io::Token::Shell}
|
||||
);
|
||||
advance(peek_str().size());
|
||||
break;
|
||||
case '\0':
|
||||
@@ -117,6 +142,11 @@ void Parser::operation() {
|
||||
break;
|
||||
default:
|
||||
command->argument = std::filesystem::path(peek_str());
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + peek_str().size(),
|
||||
.type = io::Token::File}
|
||||
);
|
||||
advance(peek_str().size());
|
||||
break;
|
||||
}
|
||||
@@ -133,6 +163,7 @@ void Parser::operation() {
|
||||
char delim = peek();
|
||||
if (delim == '\0')
|
||||
throw ed_error("regex expected");
|
||||
uint16_t start = i;
|
||||
advance();
|
||||
uint16_t j = 0;
|
||||
while (true) {
|
||||
@@ -172,8 +203,18 @@ void Parser::operation() {
|
||||
advance(j);
|
||||
options = "p";
|
||||
}
|
||||
tokens->push_back(
|
||||
{.start = start,
|
||||
.end = i,
|
||||
.type = io::Token::Regexp}
|
||||
);
|
||||
if (peek() != '\0') {
|
||||
options = std::string(peek_str());
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + peek_str().size(),
|
||||
.type = io::Token::Suffix}
|
||||
);
|
||||
advance(peek_str().size());
|
||||
}
|
||||
std::erase_if(options, [&](char c) {
|
||||
@@ -185,17 +226,38 @@ void Parser::operation() {
|
||||
});
|
||||
command->argument = functions::Function::RegexArg(expression, replacement, options);
|
||||
} break;
|
||||
case functions::Function::ArgumentKind::Ruby:
|
||||
case functions::Function::ArgumentKind::Ruby: {
|
||||
command->argument = functions::Function::RubyArg(std::string(peek_str()));
|
||||
auto *ruby_parser = bed.languages["ruby"];
|
||||
void *state = ruby_parser->none_state();
|
||||
std::vector<syntax::ParseEvent> events;
|
||||
std::vector<io::Token> tokens_;
|
||||
ruby_parser->parse(&state, peek_str(), false, &tokens_, &events);
|
||||
for (auto &token : tokens_) {
|
||||
token.start += i;
|
||||
token.end += i;
|
||||
tokens->push_back(token);
|
||||
}
|
||||
ruby_parser->destroy(state);
|
||||
advance(peek_str().size());
|
||||
break;
|
||||
} break;
|
||||
case functions::Function::ArgumentKind::Shell:
|
||||
command->argument = functions::Function::ShellArg(std::string(peek_str()));
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + peek_str().size(),
|
||||
.type = io::Token::Shell}
|
||||
);
|
||||
advance(peek_str().size());
|
||||
break;
|
||||
}
|
||||
if (!suffix) {
|
||||
suffix = peek();
|
||||
tokens->push_back(
|
||||
{.start = i,
|
||||
.end = i + (uint64_t)1,
|
||||
.type = io::Token::Suffix}
|
||||
);
|
||||
advance();
|
||||
}
|
||||
if (suffix) {
|
||||
|
||||
@@ -22,6 +22,11 @@ void Parser::skip_ws() {
|
||||
void Parser::parse() {
|
||||
skip_ws();
|
||||
if (peek() == '@') {
|
||||
tokens->push_back(
|
||||
{.start = 0,
|
||||
.end = 1,
|
||||
.type = io::Token::TempCurrent}
|
||||
);
|
||||
advance();
|
||||
command->temp_address = true;
|
||||
} else {
|
||||
@@ -37,14 +42,26 @@ void Parser::parse() {
|
||||
|
||||
Parser::Parser(
|
||||
std::string_view cmd, BEd &bed, Command *command,
|
||||
std::vector<ui::Token> *tokens, CompletionContext *completion
|
||||
std::vector<io::Token> *tokens, CompletionContext *completion
|
||||
) : bed(bed), cmd(cmd), command(command), tokens(tokens), completion(completion) {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
std::vector<io::Token> Parser::get_highlight(std::string_view cmd, BEd &bed) {
|
||||
Command c;
|
||||
std::vector<io::Token> tokens;
|
||||
CompletionContext completion;
|
||||
try {
|
||||
Parser p(cmd, bed, &c, &tokens, &completion);
|
||||
p.parse();
|
||||
} catch (const ed_error &e) {
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
Command Parser::get_command(std::string_view cmd, BEd &bed) {
|
||||
Command c;
|
||||
std::vector<ui::Token> tokens;
|
||||
std::vector<io::Token> tokens;
|
||||
CompletionContext completion;
|
||||
Parser p(cmd, bed, &c, &tokens, &completion);
|
||||
p.parse();
|
||||
@@ -53,7 +70,7 @@ Command Parser::get_command(std::string_view cmd, BEd &bed) {
|
||||
|
||||
std::vector<AddressPromise> Parser::get_addresses(std::string_view cmd, BEd &bed) {
|
||||
std::vector<AddressPromise> result;
|
||||
std::vector<ui::Token> tokens;
|
||||
std::vector<io::Token> tokens;
|
||||
CompletionContext completion;
|
||||
Parser p(cmd, bed, nullptr, &tokens, &completion);
|
||||
p.addresses(result);
|
||||
|
||||
@@ -50,7 +50,7 @@ uint64_t next_closing(const ParserSnapshot &snap, uint64_t line) {
|
||||
c.next();
|
||||
first_leaf = false;
|
||||
}
|
||||
return (snap.root->lines() - line > 10 ? line + 10 : snap.root->lines());
|
||||
return (snap.root->lines() - line > 10 ? line + 10 : snap.root->lines() - 1);
|
||||
}
|
||||
|
||||
uint64_t prev_opening(const ParserSnapshot &snap, uint64_t line) {
|
||||
|
||||
@@ -15,28 +15,109 @@ io::Highlight Theme::get(const io::Token::Kind &token) const {
|
||||
|
||||
Theme Theme::default_theme() {
|
||||
Theme theme;
|
||||
theme.hl[io::Token::Color1] = {
|
||||
|
||||
theme.hl[io::Token::TempCurrent] = {
|
||||
.fg = 0x7AA2F7,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::BufferName] = {
|
||||
.fg = 0xBB9AF7,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::AddressSeperator] = {
|
||||
.fg = 0xA9B1D6,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Address] = {
|
||||
.fg = 0xE0AF68,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Offset] = {
|
||||
.fg = 0xFFAF70,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::AddressRegex] = {
|
||||
.fg = 0xD2A6FF,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::AddressSymbol] = {
|
||||
.fg = 0xFF9E64,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Mark] = {
|
||||
.fg = 0xFF757F,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::RubyFunction] = {
|
||||
.fg = 0x7DCFFF,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::RubyArg] = {
|
||||
.fg = 0xA9B1D6,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Any] = {
|
||||
.fg = 0x7DCFFF,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Shell] = {
|
||||
.fg = 0x89DDFF,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Ruby] = {
|
||||
.fg = 0x95E6CB,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::File] = {
|
||||
.fg = 0xAAD94C,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Replacement] = {
|
||||
.fg = 0x9ECE6A,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Suffix] = {
|
||||
.fg = 0xF07178,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Color1] = {
|
||||
.fg = 0x7AA2F7,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Color2] = {
|
||||
.fg = 0xAAD94C,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Color3] = {
|
||||
.fg = 0xFF8F40,
|
||||
.fg = 0xFF9E64,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Color4] = {
|
||||
.fg = 0xD2A6FF,
|
||||
.fg = 0xBB9AF7,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Color5] = {
|
||||
.fg = 0xEF5168,
|
||||
.fg = 0xFF757F,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
@@ -77,7 +158,7 @@ Theme Theme::default_theme() {
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
theme.hl[io::Token::Regexp] = {
|
||||
.fg = 0xD2A6FF,
|
||||
.fg = 0x7DCFFF,
|
||||
.bg = 0x000000,
|
||||
.flags = io::Highlight::None,
|
||||
};
|
||||
@@ -187,7 +268,6 @@ Theme Theme::default_theme() {
|
||||
Theme Theme::from_name(std::string_view name) {
|
||||
if (name == "default")
|
||||
return default_theme();
|
||||
throw std::runtime_error("Unknown theme: " + std::string(name));
|
||||
throw ed_error("Unknown theme: " + std::string(name));
|
||||
}
|
||||
|
||||
} // namespace bed::internal::theme
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "internal/ui/command.h"
|
||||
#include "bed.h"
|
||||
#include "internal/parser/parser.h"
|
||||
|
||||
namespace bed::internal::ui {
|
||||
/*template <typename F>
|
||||
@@ -162,7 +163,22 @@ void CommandIO::redraw() {
|
||||
bed.io.write("\x1b[2K", 4);
|
||||
bed.io.move_cursor(start, 1);
|
||||
bed.io.write(prompt);
|
||||
bed.io.write(cmd);
|
||||
const auto tokens = parser::Parser::get_highlight(cmd, bed);
|
||||
uint32_t pos = 0;
|
||||
for (const auto &token : tokens) {
|
||||
const uint32_t tstart = token.start;
|
||||
const uint32_t tend = token.end;
|
||||
if (tstart > cmd.size())
|
||||
break;
|
||||
if (pos < tstart)
|
||||
bed.io.write(cmd.data() + pos, tstart - pos);
|
||||
bed.io.apply(token.type);
|
||||
bed.io.write(cmd.data() + tstart, tend - tstart);
|
||||
bed.io.reset();
|
||||
pos = tend;
|
||||
}
|
||||
if (pos < cmd.size())
|
||||
bed.io.write(cmd.data() + pos, cmd.size() - pos);
|
||||
bed.io.move_cursor(start, prompt.size() + cursor + 1);
|
||||
}
|
||||
} // namespace bed::internal::ui
|
||||
|
||||
@@ -289,6 +289,8 @@ Shard *Shard::from_command(const char *cmd, bool posix_ending) {
|
||||
last = nullptr;
|
||||
if (!pieces.empty())
|
||||
last = (Petal *)pieces.back();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
if (last && ending[0] == '\r')
|
||||
last->length--;
|
||||
|
||||
Reference in New Issue
Block a user