Fix EvalCommandsLineByLine wholly failing on any error, redesign :Set
This commit is contained in:
@@ -2,10 +2,9 @@
|
|||||||
! From a user (novice) point of view, how does it look like?
|
! From a user (novice) point of view, how does it look like?
|
||||||
|
|
||||||
Use session 4
|
Use session 4
|
||||||
- SkipLoadWord
|
- Add <<File>> <<WorkDir>> template strings to Open (Then remove SEtWorkdirhere)
|
||||||
- Delete file command
|
- :Set Filename to name current buffer ??? :O and others like that!!
|
||||||
- :Close Fuzzy search exact match doesn't match with Close
|
- :Close Fuzzy search exact match doesn't match with Close
|
||||||
- Maybe search everything window should have a special buffer
|
|
||||||
- Setting variables maybe should create and modify config, commit these changes immediately? So user can change keybindings in command window and commit immediately
|
- Setting variables maybe should create and modify config, commit these changes immediately? So user can change keybindings in command window and commit immediately
|
||||||
- Make the special view hooks also available for modification and registered but maybe under different name or something
|
- Make the special view hooks also available for modification and registered but maybe under different name or something
|
||||||
|
|
||||||
|
|||||||
@@ -339,6 +339,22 @@ API Array<String> Split(Allocator allocator, String string, String delimiter) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API Array<String> SplitWhitespace(Allocator allocator, String string) {
|
||||||
|
Array<String> result = {allocator};
|
||||||
|
String it = {string.data, 0};
|
||||||
|
for (int64_t i = 0; i < string.len; i += 1) {
|
||||||
|
if (IsWhitespace(string[i])) {
|
||||||
|
if (it.len) Add(&result, it);
|
||||||
|
it.len = 0;
|
||||||
|
it.data = string.data + (i + 1);
|
||||||
|
} else {
|
||||||
|
it.len += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (it.len) Add(&result, it);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
API String Merge(Allocator allocator, Array<String> list, String separator) {
|
API String Merge(Allocator allocator, Array<String> list, String separator) {
|
||||||
int64_t char_count = 0;
|
int64_t char_count = 0;
|
||||||
For(list) char_count += it.len;
|
For(list) char_count += it.len;
|
||||||
@@ -441,3 +457,58 @@ API Int ChopNumber(String *string) {
|
|||||||
Int result = strtoll(col.data, NULL, 10) - 1;
|
Int result = strtoll(col.data, NULL, 10) - 1;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String SkipIdent(String *string) {
|
||||||
|
String begin = {string->data, 0};
|
||||||
|
if (IsIdent(At(*string, 0))) {
|
||||||
|
for (;string->len;) {
|
||||||
|
char c = At(*string, 0);
|
||||||
|
if (!IsIdent(c) && !IsDigit(c)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*string = Skip(*string, 1);
|
||||||
|
begin.len += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
String SkipString(String *string) {
|
||||||
|
String saved_string = *string;
|
||||||
|
char c = At(*string, 0);
|
||||||
|
String q = {&c, 1};
|
||||||
|
if (c == '"' || c == '\'') {
|
||||||
|
*string = Skip(*string, 1);
|
||||||
|
String quote = SkipUntil(string, q);
|
||||||
|
if (At(*string, 0) != c) {
|
||||||
|
*string = saved_string;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return quote;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
API String SkipFloatEx(String *string) {
|
||||||
|
String 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(String *string) {
|
||||||
|
String col = SkipFloatEx(string);
|
||||||
|
if (col.len == 0) return 0;
|
||||||
|
Float result = strtod(string->data, NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1399,6 +1399,10 @@ void InitBuffers() {
|
|||||||
EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "events"));
|
EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "events"));
|
||||||
EventBuffer->no_history = true;
|
EventBuffer->no_history = true;
|
||||||
EventBuffer->special = true;
|
EventBuffer->special = true;
|
||||||
|
Buffer *search_project = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "search_project"));
|
||||||
|
search_project->no_history = true;
|
||||||
|
search_project->special = true;
|
||||||
|
SearchProjectBufferID = search_project->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int ConvertUTF8ToUTF16UnixLine(String string, char16_t *buffer, Int buffer_cap) {
|
Int ConvertUTF8ToUTF16UnixLine(String string, char16_t *buffer, Int buffer_cap) {
|
||||||
|
|||||||
@@ -480,6 +480,135 @@ bool IsOpenBoundary(char c) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ExpectP(x, ...) \
|
||||||
|
if (!(x)) { \
|
||||||
|
ReportErrorf("Failed to parse '" __FUNCTION__ "' command, " __VA_ARGS__); \
|
||||||
|
return; \
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetWorkDirHere(String dir) {
|
||||||
|
WorkDir = Intern(&GlobalInternTable, dir);
|
||||||
|
Scratch scratch;
|
||||||
|
For (Buffers) {
|
||||||
|
if (it->special) {
|
||||||
|
String name = SkipToLastSlash(it->name);
|
||||||
|
it->name = Intern(&GlobalInternTable, Format(scratch, "%S/%S", dir, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set(String string) {
|
||||||
|
String name = SkipIdent(&string);
|
||||||
|
ExpectP(name.len != 0, "expected a variable name, instead got '%S'", string);
|
||||||
|
|
||||||
|
Variable *var = NULL;
|
||||||
|
For (Variables) {
|
||||||
|
if (name == it.name) {
|
||||||
|
var = ⁢
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var) {
|
||||||
|
SkipWhitespace(&string);
|
||||||
|
if (var->type == VariableType_String) {
|
||||||
|
char c = At(string, 0);
|
||||||
|
ExpectP(c == u'"' || c == u'\'', "Expected string to follow the command name, instead got %S", string);
|
||||||
|
string = Skip(string, 1);
|
||||||
|
String quote = SkipUntil(&string, {&c, 1});
|
||||||
|
ExpectP(At(string, 0) == c, ":Set %S <error here>, unclosed quote", name);
|
||||||
|
ReportConsolef(":Set %S %c%S%c", name, c, quote, c);
|
||||||
|
*var->string = Intern(&GlobalInternTable, quote);
|
||||||
|
} else if (var->type == VariableType_Int) {
|
||||||
|
ExpectP(IsDigit(At(string, 0)), "Expected an integer to follow the command name, instead got: %S", string);
|
||||||
|
Int number = SkipInt(&string);
|
||||||
|
ReportConsolef(":Set %S %lld", name, number);
|
||||||
|
*var->i = number;
|
||||||
|
} else if (var->type == VariableType_Float) {
|
||||||
|
ExpectP(IsDigit(At(string, 0)), "Expected float to follow the command name, instead got: %S", string);
|
||||||
|
Float number = SkipFloat(&string);
|
||||||
|
ReportConsolef(":Set %S %f", name, number);
|
||||||
|
*var->f = number;
|
||||||
|
} else if (var->type == VariableType_Color) {
|
||||||
|
ExpectP(IsHexDigit(At(string, 0)), "Expected hex integer to follow the command name, instead got: %S", string);
|
||||||
|
String begin = {string.data, 0};
|
||||||
|
while (IsHexDigit(At(string, 0))) {
|
||||||
|
string = Skip(string, 1);
|
||||||
|
begin.len += 1;
|
||||||
|
}
|
||||||
|
ReportConsolef(":Set %S %S", name, begin);
|
||||||
|
var->color->value = (uint32_t)strtoll(begin.data, NULL, 16);
|
||||||
|
} ElseInvalidCodepath();
|
||||||
|
|
||||||
|
|
||||||
|
if (name == "FontSize" || name == "Font") {
|
||||||
|
ReloadFont(Font, (U32)FontSize);
|
||||||
|
} else if (name == "WorkDir") {
|
||||||
|
SetWorkDirHere(*var->string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandData *cmd = NULL;
|
||||||
|
For (CommandFunctions) {
|
||||||
|
if (it.name == name) {
|
||||||
|
cmd = ⁢
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd) {
|
||||||
|
SkipWhitespace(&string);
|
||||||
|
char c = At(string, 0);
|
||||||
|
ExpectP(c == u'"' || c == u'\'', "Expected string to follow the command name, instead got %S", string);
|
||||||
|
string = Skip(string, 1);
|
||||||
|
String quote = SkipUntil(&string, {&c, 1});
|
||||||
|
ExpectP(At(string, 0) == c, "Failed to parse command, unclose quote");
|
||||||
|
quote = Intern(&GlobalInternTable, quote);
|
||||||
|
ReportConsolef(":Set %S %c%S%c", name, c, quote, c);
|
||||||
|
Trigger *trigger = ParseKeyCached(quote);
|
||||||
|
if (trigger) {
|
||||||
|
cmd->binding = quote;
|
||||||
|
cmd->trigger = trigger;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReportErrorf("Failed to :Set, no such variable found: %S", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvalCommandsLineByLine(BSet set) {
|
||||||
|
WindowID save_last = PrimaryWindowID;
|
||||||
|
WindowID save_active = ActiveWindowID;
|
||||||
|
WindowID save_next = NextActiveWindowID;
|
||||||
|
Caret save_caret = set.view->carets[0];
|
||||||
|
ActiveWindowID = set.window->id;
|
||||||
|
PrimaryWindowID = set.window->id;
|
||||||
|
NextActiveWindowID = set.window->id;
|
||||||
|
for (Int i = 0; i < set.buffer->line_starts.len; i += 1) {
|
||||||
|
Range range = GetLineRangeWithoutNL(set.buffer, i);
|
||||||
|
String16 string = GetString(set.buffer, range);
|
||||||
|
string = Trim(string);
|
||||||
|
if (string.len == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (StartsWith(string, u"//")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Open(string);
|
||||||
|
}
|
||||||
|
set.view->carets[0] = save_caret;
|
||||||
|
PrimaryWindowID = save_last;
|
||||||
|
ActiveWindowID = save_active;
|
||||||
|
NextActiveWindowID = save_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMD_EvalCommandsLineByLine() {
|
||||||
|
BSet set = GetBSet(PrimaryWindowID);
|
||||||
|
EvalCommandsLineByLine(set);
|
||||||
|
} RegisterCommand(CMD_EvalCommandsLineByLine, "", "Goes line by line over a buffer and evaluates every line as a command, ignores empty or lines starting with '//'");
|
||||||
|
|
||||||
ResolvedOpen ResolveOpen(Allocator alo, String path, ResolveOpenMeta meta) {
|
ResolvedOpen ResolveOpen(Allocator alo, String path, ResolveOpenMeta meta) {
|
||||||
ResolvedOpen result = {};
|
ResolvedOpen result = {};
|
||||||
path = Trim(path);
|
path = Trim(path);
|
||||||
@@ -487,6 +616,12 @@ ResolvedOpen ResolveOpen(Allocator alo, String path, ResolveOpenMeta meta) {
|
|||||||
// Editor command
|
// Editor command
|
||||||
if(!(ResolveOpenMeta_DontExec & meta)) {
|
if(!(ResolveOpenMeta_DontExec & meta)) {
|
||||||
if (StartsWith(path, ":")) {
|
if (StartsWith(path, ":")) {
|
||||||
|
if (StartsWith(path, ":Set ")) {
|
||||||
|
result.kind = OpenKind_Set;
|
||||||
|
result.path = Skip(path, 5);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result.kind = OpenKind_Command;
|
result.kind = OpenKind_Command;
|
||||||
path = Skip(path, 1);
|
path = Skip(path, 1);
|
||||||
result.path.data = path.data;
|
result.path.data = path.data;
|
||||||
@@ -654,6 +789,8 @@ BSet Open(Window *window, String path, ResolveOpenMeta meta, bool set_active = t
|
|||||||
Exec(NullViewID, false, o.path, GetMainDir());
|
Exec(NullViewID, false, o.path, GetMainDir());
|
||||||
} else if (o.kind == OpenKind_Command) {
|
} else if (o.kind == OpenKind_Command) {
|
||||||
EvalCommand(o.path);
|
EvalCommand(o.path);
|
||||||
|
} else if (o.kind == OpenKind_Set) {
|
||||||
|
Set(o.path);
|
||||||
} else if (o.kind == OpenKind_Skip) {
|
} else if (o.kind == OpenKind_Skip) {
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
@@ -708,45 +845,10 @@ void CMD_ToggleFullscreen() {
|
|||||||
IsInFullscreen = !IsInFullscreen;
|
IsInFullscreen = !IsInFullscreen;
|
||||||
} RegisterCommand(CMD_ToggleFullscreen, "f11");
|
} RegisterCommand(CMD_ToggleFullscreen, "f11");
|
||||||
|
|
||||||
String16 FetchStringForCommandParsing() {
|
void CMD_SetWorkDirHere() {
|
||||||
BSet set = GetBSet(ActiveWindowID);
|
|
||||||
Range range = set.view->carets[0].range;
|
|
||||||
range.max = range.min; // We only scan for :Set
|
|
||||||
if (GetSize(range) == 0) {
|
|
||||||
range = EncloseLoadWord(set.buffer, range.min);
|
|
||||||
}
|
|
||||||
Int line_end = GetLineEnd(set.buffer, range.min);
|
|
||||||
String16 string = GetString(set.buffer, {range.min, line_end});
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetWorkDir(String string) {
|
|
||||||
Scratch scratch;
|
|
||||||
WorkDir = Intern(&GlobalInternTable, string);
|
|
||||||
For (Buffers) {
|
|
||||||
if (it->special) {
|
|
||||||
String name = SkipToLastSlash(it->name);
|
|
||||||
it->name = Intern(&GlobalInternTable, Format(scratch, "%S/%S", WorkDir, name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMD_SetWorkDir() {
|
|
||||||
Scratch scratch;
|
|
||||||
BSet main = GetBSet(PrimaryWindowID);
|
BSet main = GetBSet(PrimaryWindowID);
|
||||||
SetWorkDir(GetDir(main.buffer));
|
SetWorkDirHere(GetDir(main.buffer));
|
||||||
} RegisterCommand(CMD_SetWorkDir, "", "Sets work directory to the directory of the current buffer, it also renames couple special buffers to make them accomodate the new WorkDir");
|
} RegisterCommand(CMD_SetWorkDirHere, "", "Sets work directory to the directory of the current buffer, it also renames couple special buffers to make them accomodate the new WorkDir");
|
||||||
|
|
||||||
void CMD_SetWorkDirAt() {
|
|
||||||
String16 string = FetchStringForCommandParsing();
|
|
||||||
string = Skip(string, 1);
|
|
||||||
SkipIdent(&string);
|
|
||||||
SkipWhitespace(&string);
|
|
||||||
Scratch scratch;
|
|
||||||
String16 arg = SkipString(&string);
|
|
||||||
String arg8 = ToString(scratch, arg);
|
|
||||||
SetWorkDir(arg8);
|
|
||||||
} RegisterCommand(CMD_SetWorkDirAt, "", "Sets work directory using the argument string passed here, it also renames couple special buffers to make them accomodate the new WorkDir");
|
|
||||||
|
|
||||||
void Coro_OpenCode(mco_coro *co) {
|
void Coro_OpenCode(mco_coro *co) {
|
||||||
Array<String> patterns = Split(CoCurr->arena, NonCodePatterns_EndsWith, "|");
|
Array<String> patterns = Split(CoCurr->arena, NonCodePatterns_EndsWith, "|");
|
||||||
@@ -790,17 +892,6 @@ void CMD_OpenCode() {
|
|||||||
OpenCode(WorkDir);
|
OpenCode(WorkDir);
|
||||||
} RegisterCommand(CMD_OpenCode, "", "Open all code files in current WorkDir, the code files are determined through NonCodePatterns_EndsWith config variable list");
|
} RegisterCommand(CMD_OpenCode, "", "Open all code files in current WorkDir, the code files are determined through NonCodePatterns_EndsWith config variable list");
|
||||||
|
|
||||||
void CMD_OpenCodeAt() {
|
|
||||||
String16 string = FetchStringForCommandParsing();
|
|
||||||
string = Skip(string, 1);
|
|
||||||
SkipIdent(&string);
|
|
||||||
SkipWhitespace(&string);
|
|
||||||
Scratch scratch;
|
|
||||||
String16 arg = SkipString(&string);
|
|
||||||
String arg8 = ToString(scratch, arg);
|
|
||||||
OpenCode(arg8);
|
|
||||||
} RegisterCommand(CMD_OpenCodeAt, "", "Open all code files pointed to by string argument following the command");
|
|
||||||
|
|
||||||
void CMD_KillProcess() {
|
void CMD_KillProcess() {
|
||||||
BSet main = GetBSet(PrimaryWindowID);
|
BSet main = GetBSet(PrimaryWindowID);
|
||||||
KillProcess(main.view);
|
KillProcess(main.view);
|
||||||
@@ -936,6 +1027,13 @@ void CMD_Close() {
|
|||||||
CoResume(data);
|
CoResume(data);
|
||||||
} RegisterCommand(CMD_Close, "ctrl-w", "Close open view in the last active primary window");
|
} RegisterCommand(CMD_Close, "ctrl-w", "Close open view in the last active primary window");
|
||||||
|
|
||||||
|
void CMD_DeleteFile() {
|
||||||
|
BSet main = GetBSet(PrimaryWindowID);
|
||||||
|
String buffer_name = main.buffer->name;
|
||||||
|
DeleteFile(main.buffer->name);
|
||||||
|
Close(main.buffer->id);
|
||||||
|
} RegisterCommand(CMD_DeleteFile, "", "Close the open buffer and delete it's corresponding file on disk");
|
||||||
|
|
||||||
// Considerations with coroutines:
|
// Considerations with coroutines:
|
||||||
// 1. Does scratch memory leak across Yield boundary? Or interacts badly with Yield stuff in any way?
|
// 1. Does scratch memory leak across Yield boundary? Or interacts badly with Yield stuff in any way?
|
||||||
// 2. Are pointers and globals correct over time? Or might they get deleted etc.
|
// 2. Are pointers and globals correct over time? Or might they get deleted etc.
|
||||||
@@ -1250,10 +1348,10 @@ void CMD_SelectToLineEnd() {
|
|||||||
MoveCursorToSide(active.view, DIR_RIGHT, SHIFT_PRESS);
|
MoveCursorToSide(active.view, DIR_RIGHT, SHIFT_PRESS);
|
||||||
} RegisterCommand(CMD_SelectToLineEnd, "shift-end");
|
} RegisterCommand(CMD_SelectToLineEnd, "shift-end");
|
||||||
|
|
||||||
void CMD_Delete() {
|
void CMD_DeleteCharacter() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
Delete(active.view, DIR_LEFT);
|
Delete(active.view, DIR_LEFT);
|
||||||
} RegisterCommand(CMD_Delete, "shift-backspace | backspace");
|
} RegisterCommand(CMD_DeleteCharacter, "shift-backspace | backspace");
|
||||||
|
|
||||||
void CMD_DeleteBoundary() {
|
void CMD_DeleteBoundary() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
@@ -1343,173 +1441,6 @@ void CMD_ClearCarets() {
|
|||||||
}
|
}
|
||||||
} RegisterCommand(CMD_ClearCarets, "escape", "Clear all carets and reset to 1 caret, also do some windowing stuff that closes things on escape");
|
} RegisterCommand(CMD_ClearCarets, "escape", "Clear all carets and reset to 1 caret, also do some windowing stuff that closes things on escape");
|
||||||
|
|
||||||
void Set(String16 string) {
|
|
||||||
Scratch scratch;
|
|
||||||
|
|
||||||
SkipWhitespace(&string);
|
|
||||||
if (At(string, 0) != u':') {
|
|
||||||
ReportErrorf("Expected :Set");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string = Skip(string, 1);
|
|
||||||
|
|
||||||
if (!MatchIdent(&string, u"Set")) {
|
|
||||||
ReportErrorf("Expected :Set");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 <error here>, 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 <expected string>", 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 <expected integer>", 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 <expected float>", name8);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (var->type == VariableType_Color) {
|
|
||||||
if (IsHexDigit(At(string, 0))) {
|
|
||||||
String16 begin = {string.data, 0};
|
|
||||||
while (IsHexDigit(At(string, 0))) {
|
|
||||||
string = Skip(string, 1);
|
|
||||||
begin.len += 1;
|
|
||||||
}
|
|
||||||
String p = ToString(scratch, begin);
|
|
||||||
ReportConsolef(":Set %S %S", name8, p);
|
|
||||||
var->color->value = (uint32_t)strtoll(p.data, NULL, 16);
|
|
||||||
} else {
|
|
||||||
ReportErrorf("Failed to parse :Set %S <expected integer>", name8);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} ElseInvalidCodepath();
|
|
||||||
|
|
||||||
|
|
||||||
if (name8 == "FontSize" || name8 == "Font") {
|
|
||||||
ReloadFont(Font, (U32)FontSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 <error here>, 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 <expected string>", name8);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReportErrorf("Failed to :Set, no such variable found: %S", name8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMD_Set() {
|
|
||||||
String16 string = FetchStringForCommandParsing();
|
|
||||||
Set(string);
|
|
||||||
} RegisterCommand(CMD_Set, "", "Sets a named editor variable to the text argument following the command, the format is ':Set FormatCode 0'");
|
|
||||||
|
|
||||||
void EvalCommandsLineByLine(BSet set) {
|
|
||||||
WindowID save_last = PrimaryWindowID;
|
|
||||||
WindowID save_active = ActiveWindowID;
|
|
||||||
WindowID save_next = NextActiveWindowID;
|
|
||||||
Caret save_caret = set.view->carets[0];
|
|
||||||
ActiveWindowID = set.window->id;
|
|
||||||
PrimaryWindowID = set.window->id;
|
|
||||||
NextActiveWindowID = set.window->id;
|
|
||||||
for (Int i = 0; i < set.buffer->line_starts.len; i += 1) {
|
|
||||||
Int pos = GetLineRangeWithoutNL(set.buffer, i).min;
|
|
||||||
SelectRange(set.view, MakeRange(pos));
|
|
||||||
Range range = EncloseLoadWord(set.buffer, pos);
|
|
||||||
String16 string = GetString(set.buffer, range);
|
|
||||||
string = Trim(string);
|
|
||||||
if (string.len == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (StartsWith(string, u"//")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Open(string);
|
|
||||||
}
|
|
||||||
set.view->carets[0] = save_caret;
|
|
||||||
PrimaryWindowID = save_last;
|
|
||||||
ActiveWindowID = save_active;
|
|
||||||
NextActiveWindowID = save_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMD_EvalCommandsLineByLine() {
|
|
||||||
BSet set = GetBSet(PrimaryWindowID);
|
|
||||||
EvalCommandsLineByLine(set);
|
|
||||||
} RegisterCommand(CMD_EvalCommandsLineByLine, "", "Goes line by line over a buffer and evaluates every line as a command, ignores empty or lines starting with '//'");
|
|
||||||
|
|
||||||
void GenerateConfig(View *view) {
|
void GenerateConfig(View *view) {
|
||||||
For (Variables) {
|
For (Variables) {
|
||||||
if (it.type == VariableType_String) {
|
if (it.type == VariableType_String) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ BufferID SearchBufferID;
|
|||||||
WindowID BuildWindowID;
|
WindowID BuildWindowID;
|
||||||
ViewID BuildViewID;
|
ViewID BuildViewID;
|
||||||
BufferID BuildBufferID;
|
BufferID BuildBufferID;
|
||||||
|
BufferID SearchProjectBufferID;
|
||||||
|
|
||||||
WindowID NextActiveWindowID;
|
WindowID NextActiveWindowID;
|
||||||
WindowID ActiveWindowID;
|
WindowID ActiveWindowID;
|
||||||
@@ -51,7 +52,6 @@ Buffer *EventBuffer;
|
|||||||
Buffer *TraceBuffer;
|
Buffer *TraceBuffer;
|
||||||
View *TraceView;
|
View *TraceView;
|
||||||
|
|
||||||
String WorkDir;
|
|
||||||
RandomSeed UniqueBufferNameSeed = {};
|
RandomSeed UniqueBufferNameSeed = {};
|
||||||
Array<Event> EventPlayback;
|
Array<Event> EventPlayback;
|
||||||
BlockArena Perm;
|
BlockArena Perm;
|
||||||
@@ -155,6 +155,7 @@ RegisterVariable(Int, DrawLineNumbers, 1);
|
|||||||
RegisterVariable(Int, DrawScrollbar, 1);
|
RegisterVariable(Int, DrawScrollbar, 1);
|
||||||
RegisterVariable(Int, IndentSize, 4);
|
RegisterVariable(Int, IndentSize, 4);
|
||||||
RegisterVariable(Int, FontSize, 15);
|
RegisterVariable(Int, FontSize, 15);
|
||||||
|
RegisterVariable(String, WorkDir, "");
|
||||||
RegisterVariable(String, Font, "");
|
RegisterVariable(String, Font, "");
|
||||||
RegisterVariable(String, VCVarsall, "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat");
|
RegisterVariable(String, VCVarsall, "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat");
|
||||||
RegisterVariable(Float, UndoMergeTime, 0.3);
|
RegisterVariable(Float, UndoMergeTime, 0.3);
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ enum OpenKind {
|
|||||||
OpenKind_BackgroundExec,
|
OpenKind_BackgroundExec,
|
||||||
OpenKind_Goto,
|
OpenKind_Goto,
|
||||||
OpenKind_Command,
|
OpenKind_Command,
|
||||||
|
OpenKind_Set,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t ResolveOpenMeta;
|
typedef uint32_t ResolveOpenMeta;
|
||||||
|
|||||||
@@ -245,11 +245,13 @@ void FuzzySearchViewUpdate() {
|
|||||||
|
|
||||||
void CMD_SearchProject() {
|
void CMD_SearchProject() {
|
||||||
BSet main = GetBSet(PrimaryWindowID);
|
BSet main = GetBSet(PrimaryWindowID);
|
||||||
JumpTempBuffer(&main);
|
|
||||||
NextActiveWindowID = main.window->id;
|
NextActiveWindowID = main.window->id;
|
||||||
main.view->kind = ViewKind_ActiveSearch;
|
Buffer *search_project_buffer = GetBuffer(SearchProjectBufferID);
|
||||||
AddHook(&main.view->hooks, "Open", "ctrl-q | enter", CMD_CommandWindowOpen);
|
View *view = WindowOpenBufferView(main.window, search_project_buffer->name);
|
||||||
main.buffer->no_history = true;
|
view->special = true;
|
||||||
|
view->kind = ViewKind_ActiveSearch;
|
||||||
|
AddHook(&view->hooks, "Open", "ctrl-q | enter", CMD_CommandWindowOpen);
|
||||||
|
SelectRange(view, GetLineRangeWithoutNL(search_project_buffer, 0));
|
||||||
} RegisterCommand(CMD_SearchProject, "ctrl-shift-f", "Interactive search over the entire project in a new buffer view");
|
} RegisterCommand(CMD_SearchProject, "ctrl-shift-f", "Interactive search over the entire project in a new buffer view");
|
||||||
|
|
||||||
void SetFuzzy(View *view) {
|
void SetFuzzy(View *view) {
|
||||||
|
|||||||
Reference in New Issue
Block a user