diff --git a/src/backup/todo.txt b/src/backup/todo.txt index c145d26..bb85d5a 100644 --- a/src/backup/todo.txt +++ b/src/backup/todo.txt @@ -1,6 +1,10 @@ ! What precise workflow do I need for me to be viable to use this? ! From a user (novice) point of view, how does it look like? +- Make all the keybinding / hook parsing initialize at the start to reduce runtime problems +- RegisterCommand should_appear_in_listing variable +- Maybe one list for all variables including the commands etc? +- make variables nicer named Use session 3: - Maybe status view, commit changes (like to buffer name or line) on enter? diff --git a/src/basic/basic_string.cpp b/src/basic/basic_string.cpp index 42f9e63..8490544 100644 --- a/src/basic/basic_string.cpp +++ b/src/basic/basic_string.cpp @@ -378,7 +378,7 @@ API bool Chop(String *string, String ending) { return false; } -API String SkipNumberEx(String *string) { +API String SkipIntEx(String *string) { String col = {string->data, 0}; for (int64_t i = 0; i < string->len; i += 1) { if (IsDigit(string->data[i])) { @@ -391,8 +391,8 @@ API String SkipNumberEx(String *string) { return col; } -API Int SkipNumber(String *string) { - String col = SkipNumberEx(string); +API Int SkipInt(String *string) { + String col = SkipIntEx(string); if (col.len == 0) return -1; Int result = strtoll(col.data, NULL, 10); return result; diff --git a/src/basic/basic_string16.cpp b/src/basic/basic_string16.cpp index 5ef3602..a796bdc 100644 --- a/src/basic/basic_string16.cpp +++ b/src/basic/basic_string16.cpp @@ -384,8 +384,12 @@ API Int GetSize(Array array) { return result; } -API String16 SkipNumberEx(String16 *string) { +API String16 SkipIntEx(String16 *string) { String16 col = {string->data, 0}; + if (At(*string, 0) == '-') { + col.len += 1; + *string = Skip(*string, 1); + } for (int64_t i = 0; i < string->len; i += 1) { if (IsDigit(string->data[i])) { col.len += 1; @@ -397,15 +401,41 @@ API String16 SkipNumberEx(String16 *string) { return col; } -API Int SkipNumber(String16 *string) { - String16 col = SkipNumberEx(string); - if (col.len == 0) return -1; +API Int SkipInt(String16 *string) { + String16 col = SkipIntEx(string); + if (col.len == 0) return 0; Scratch scratch; String num_string = ToString(scratch, col); Int result = strtoll(num_string.data, NULL, 10); return result; } +API String16 SkipFloatEx(String16 *string) { + String16 col = {string->data, 0}; + if (At(*string, 0) == '-') { + col.len += 1; + *string = Skip(*string, 1); + } + for (int64_t i = 0; i < string->len; i += 1) { + if (IsDigit(string->data[i]) || string->data[i] == u'.') { + col.len += 1; + } else { + break; + } + } + *string = Skip(*string, col.len); + return col; +} + +API Float SkipFloat(String16 *string) { + String16 col = SkipFloatEx(string); + if (col.len == 0) return 0; + Scratch scratch; + String num_string = ToString(scratch, col); + Float result = strtod(num_string.data, NULL); + return result; +} + API String16 SkipUntil(String16 *string, String16 str) { String16 begin = *string; begin.len = 0; @@ -419,14 +449,31 @@ API String16 SkipUntil(String16 *string, String16 str) { API String16 SkipWhitespace(String16 *string) { String16 begin = {string->data, 0}; - for (Int i = 0; i < string->len; i += 1) { - if (!IsWhitespace(string->data[i])) break; + for (;string->len;) { + if (!IsWhitespace(At(*string, 0))) { + break; + } *string = Skip(*string, 1); begin.len += 1; } return begin; } +String16 SkipIdent(String16 *string) { + String16 begin = {string->data, 0}; + if (IsIdent(At(*string, 0))) { + for (;string->len;) { + char16_t c = At(*string, 0); + if (!IsIdent(c) && !IsDigit(c)) { + break; + } + *string = Skip(*string, 1); + begin.len += 1; + } + } + return begin; +} + API bool Chop(String16 *string, String16 ending) { if (EndsWith(*string, ending)) { *string = Chop(*string, ending.len); diff --git a/src/basic/basic_string16.h b/src/basic/basic_string16.h index ab381f5..3a8c818 100644 --- a/src/basic/basic_string16.h +++ b/src/basic/basic_string16.h @@ -81,8 +81,8 @@ API String16 CutPrefix(String16 *string, int64_t len); API String16 CutPostfix(String16 *string, int64_t len); // @todo: think about this API, for parsing, maybe redesign or something -API String16 SkipNumberEx(String16 *string); -API Int SkipNumber(String16 *string); +API String16 SkipIntEx(String16 *string); +API Int SkipInt(String16 *string); API String16 SkipUntil(String16 *string, String16 str); API String16 SkipWhitespace(String16 *string); API String16 ChopNumberEx(String16 *string); diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index ebd1af0..7c50e16 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -167,7 +167,7 @@ void UIMessagef(const char *fmt, ...) { NextActiveWindowID = main.window->id; RawAppendf(main.buffer, "\n %S\n :Close\n", string); main.view->carets[0] = FindNext(main.buffer, u":Close", MakeCaret(0)); - AddHook(&main.view->hooks, "Close", "escape", [](){ + AddHook(&main.view->hooks, "Close", "escape | enter", [](){ BSet active = GetBSet(ActiveWindowID); Close(active.buffer->id); }); @@ -179,7 +179,6 @@ void ReportErrorf(const char *fmt, ...) { View *view = GetView(NullViewID); if (view) { Appendf(view, "%S\n", string); - NextActiveWindowID = NullWindowID; } UIMessagef("%S", string); } @@ -526,18 +525,18 @@ ResolvedOpen ResolveOpen(Allocator alo, String path, String meta) { if (At(p, 0) == ':') { p = Skip(p, 1); - result.line = SkipNumber(&p); + result.line = SkipInt(&p); if (At(p, 0) == ':') { p = Skip(p, 1); - Int b = SkipNumber(&p); + Int b = SkipInt(&p); result.col = b; } } else if (At(p, 0) == '(') { p = Skip(p, 1); - result.line = SkipNumber(&p); + result.line = SkipInt(&p); if (At(p, 0) == ',') { p = Skip(p, 1); - Int b = SkipNumber(&p); + Int b = SkipInt(&p); result.col = b; } } @@ -1245,3 +1244,108 @@ void Command_ClearCarets() { } } } RegisterCommand(Command_ClearCarets, "escape"); + +void Command_Set() { + Scratch scratch; + BSet set = GetBSet(ActiveWindowID); + Range range = set.view->carets[0].range; + if (GetSize(range) == 0) { + range = EncloseLoadWord(set.buffer, range.min); + } + Int line_end = GetLineEnd(set.buffer, range.min); + String16 string = GetString(set.buffer, {range.max, line_end}); + + SkipWhitespace(&string); + String16 name = SkipIdent(&string); + if (name.len == 0) { + ReportErrorf("Set command failed to parse at the variable name"); + return; + } + + String name8 = ToString(scratch, name); + Variable *var = NULL; + For (Variables) { + if (name8 == it.name) { + var = ⁢ + break; + } + } + + if (var) { + SkipWhitespace(&string); + if (var->type == VariableType_String) { + char16_t c = At(string, 0); + String16 q = {&c, 1}; + if (c == u'"' || c == u'\'') { + string = Skip(string, 1); + String16 quote = SkipUntil(&string, q); + if (At(string, 0) != c) { + ReportErrorf("Failed to parse :Set %S , unclosed quote", name8); + return; + } + String quote8 = ToString(scratch, quote); + ReportConsolef(":Set %S %c%S%c", name8, c, quote8, c); + *var->string = Intern(&GlobalInternTable, quote8); + } else { + ReportErrorf("Failed to parse :Set %S ", name8); + return; + } + } else if (var->type == VariableType_Int) { + if (IsDigit(At(string, 0))) { + Int number = SkipInt(&string); + ReportConsolef(":Set %S %lld", name8, number); + *var->i = number; + } else { + ReportErrorf("Failed to parse :Set %S ", name8); + return; + } + } else if (var->type == VariableType_Float) { + if (IsDigit(At(string, 0)) || At(string, 0) == '.') { + Float number = SkipFloat(&string); + ReportConsolef(":Set %S %f", name8, number); + *var->f = number; + } else { + ReportErrorf("Failed to parse :Set %S ", name8); + return; + } + } ElseInvalidCodepath(); + return; + } + + CommandData *cmd = NULL; + For (CommandFunctions) { + if (it.name == name8) { + cmd = ⁢ + break; + } + } + + if (cmd) { + SkipWhitespace(&string); + char16_t c = At(string, 0); + String16 q = {&c, 1}; + if (c == u'"' || c == u'\'') { + string = Skip(string, 1); + String16 quote = SkipUntil(&string, q); + if (At(string, 0) != c) { + ReportErrorf("Failed to parse :Set %S , unclosed quote", name8); + return; + } + String quote8 = Intern(&GlobalInternTable, ToString(scratch, quote)); + ReportConsolef(":Set %S %c%S%c", name8, c, quote8, c); + Trigger *trigger = ParseKeyCached(quote8); + if (trigger) { + cmd->binding = quote8; + cmd->trigger = trigger; + } + } else { + ReportErrorf("Failed to parse :Set %S ", name8); + return; + } + + return; + } + + + ReportErrorf("Failed to :Set, no such variable found: %S", name8); +} RegisterCommand(Command_Set, ""); \ No newline at end of file