jump history
This commit is contained in:
@@ -996,7 +996,7 @@ API void UndoEdit(Buffer *buffer, Array<Caret> *carets) {
|
||||
|
||||
if (buffer->undo_stack.len > 0) {
|
||||
HistoryEntry *next = GetLast(buffer->undo_stack);
|
||||
if (entry.time - next->time <= 0.3) {
|
||||
if (entry.time - next->time <= StyleUndoMergeTimeout) {
|
||||
UndoEdit(buffer, carets);
|
||||
}
|
||||
}
|
||||
@@ -1017,6 +1017,16 @@ API void ResetHistory(Buffer *buffer) {
|
||||
DeallocHistoryEntries(&buffer->undo_stack);
|
||||
}
|
||||
|
||||
API void ResetBuffer(Buffer *buffer) {
|
||||
ResetHistory(buffer);
|
||||
buffer->change_id += 1;
|
||||
buffer->line_starts.len = 0;
|
||||
buffer->len = 0;
|
||||
if (!buffer->no_line_starts) {
|
||||
Add(&buffer->line_starts, (Int)0);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearRedoStack(Buffer *buffer) {
|
||||
DeallocHistoryEntries(&buffer->redo_stack);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,64 @@
|
||||
void CheckpointBeforeGoto(Window *window, View *view) {
|
||||
if (window->jump_history == false) return;
|
||||
Add(&window->goto_history, {view->id, view->carets[0], GetTimeSeconds()});
|
||||
window->goto_redo.len = 0;
|
||||
}
|
||||
|
||||
void CheckpointBeforeGoto(Window *window) {
|
||||
CheckpointBeforeGoto(window, GetView(window->active_view));
|
||||
}
|
||||
|
||||
GotoCrumb GetCrumb(Array<GotoCrumb> *cr) {
|
||||
for (; cr->len;) {
|
||||
GotoCrumb c = Pop(cr);
|
||||
View *view = FindView(c.view_id);
|
||||
if (view) return c;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void GotoBackward(Window *window) {
|
||||
if (window->jump_history == false) return;
|
||||
if (window->goto_history.len <= 0) return;
|
||||
BSet set = GetBSet(window);
|
||||
Add(&window->goto_redo, {set.view->id, set.view->carets[0], GetTimeSeconds()});
|
||||
|
||||
GotoCrumb c = GetCrumb(&window->goto_history);
|
||||
window->active_view = c.view_id;
|
||||
View *view = GetView(c.view_id);
|
||||
view->carets[0] = c.caret;
|
||||
UpdateScroll(window, true);
|
||||
|
||||
if (window->goto_history.len) {
|
||||
GotoCrumb *next = GetLast(window->goto_history);
|
||||
if (c.time - next->time <= StyleUndoMergeTimeout) {
|
||||
GotoBackward(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GotoForward(Window *window) {
|
||||
if (window->goto_redo.len <= 0) return;
|
||||
if (window->jump_history == false) return;
|
||||
BSet set = GetBSet(window);
|
||||
Add(&window->goto_history, {set.view->id, set.view->carets[0], GetTimeSeconds()});
|
||||
|
||||
GotoCrumb c = GetCrumb(&window->goto_redo);
|
||||
window->active_view = c.view_id;
|
||||
View *view = GetView(c.view_id);
|
||||
view->carets[0] = c.caret;
|
||||
UpdateScroll(window, true);
|
||||
|
||||
if (window->goto_redo.len) {
|
||||
GotoCrumb *next = GetLast(window->goto_redo);
|
||||
if (c.time - next->time <= StyleUndoMergeTimeout) {
|
||||
GotoForward(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JumpGarbageBuffer(BSet *set, String buffer_name = "") {
|
||||
CheckpointBeforeGoto(set->window);
|
||||
if (buffer_name.len == 0) {
|
||||
String current_dir = ChopLastSlash(set->buffer->name);
|
||||
buffer_name = GetUniqueBufferName(current_dir, "temp");
|
||||
@@ -9,6 +69,7 @@ void JumpGarbageBuffer(BSet *set, String buffer_name = "") {
|
||||
}
|
||||
|
||||
void Command_BeginJump(BSet *set, BufferID buffer_id = NullBufferID) {
|
||||
CheckpointBeforeGoto(set->window);
|
||||
set->buffer = GetBuffer(buffer_id);
|
||||
set->view = WindowOpenBufferView(set->window, set->buffer->name);
|
||||
}
|
||||
@@ -855,6 +916,43 @@ void Command_Find(View *seek_view, String16 needle, bool forward = true) {
|
||||
IF_DEBUG(AssertRanges(seek_view->carets));
|
||||
}
|
||||
|
||||
void Command_GotoNextInList(Window *window, Int line_offset = 1) {
|
||||
Assert(line_offset == 1 || line_offset == -1);
|
||||
View *active_view = GetView(window->active_view);
|
||||
|
||||
View *view_goto = GetView(window->active_goto_list);
|
||||
window->active_view = view_goto->id;
|
||||
|
||||
Buffer *buffer_goto = GetBuffer(view_goto->active_buffer);
|
||||
int64_t pos = window->goto_list_pos;
|
||||
Int line = PosToLine(buffer_goto, pos);
|
||||
|
||||
bool opened = false;
|
||||
for (Int i = line + line_offset; i >= 0 && i < buffer_goto->line_starts.len; i += line_offset) {
|
||||
Range line_range = GetLineRangeWithoutNL(buffer_goto, i);
|
||||
String16 line = GetString(buffer_goto, line_range);
|
||||
view_goto->carets[0] = MakeCaret(line_range.min);
|
||||
window->goto_list_pos = line_range.min;
|
||||
line = Trim(line);
|
||||
|
||||
MergeCarets(buffer_goto, &view_goto->carets);
|
||||
IF_DEBUG(AssertRanges(view_goto->carets));
|
||||
if (line.len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BSet set = Command_Open(line, "goto_build");
|
||||
if (set.window == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
opened = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!opened) window->active_view = active_view->id;
|
||||
}
|
||||
|
||||
void Command_FuzzySort(View *view, String16 needle) {
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
|
||||
@@ -1051,6 +1149,7 @@ BSet Command_Open(Window *window, String path, String meta, bool set_active = tr
|
||||
Command_Appendf(set.view, "%S\n", it.filename);
|
||||
}
|
||||
} else {
|
||||
CheckpointBeforeGoto(set.window);
|
||||
View *view = WindowOpenBufferView(set.window, ores.file_path);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
if (ores.line != -1) {
|
||||
@@ -1122,6 +1221,8 @@ int Lua_Cmd(lua_State *L) {
|
||||
BSet main = GetLastActiveLayoutSet();
|
||||
if (kind == "console") {
|
||||
BSet set = GetConsoleSet();
|
||||
main.window->active_goto_list = set.view->id;
|
||||
main.window->goto_list_pos = set.buffer->len;
|
||||
Command_SelectRangeOneCursor(set.view, MakeRange(set.buffer->len));
|
||||
Command_BeginJump(&set);
|
||||
Exec(set.view->id, true, cmd, working_dir);
|
||||
@@ -1133,6 +1234,8 @@ int Lua_Cmd(lua_State *L) {
|
||||
ActiveWindow = main.window->id;
|
||||
} else {
|
||||
JumpGarbageBuffer(&main);
|
||||
main.window->active_goto_list = main.view->id;
|
||||
main.window->goto_list_pos = 0;
|
||||
Exec(main.view->id, true, cmd, working_dir);
|
||||
ActiveWindow = main.window->id;
|
||||
}
|
||||
@@ -1140,10 +1243,11 @@ int Lua_Cmd(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Command_ListBuffers() {
|
||||
BSet main = GetActiveSet();
|
||||
void Command_ShowBufferList() {
|
||||
BSet main = GetBSet(CommandBarWindowID);
|
||||
main.window->visible = true;
|
||||
ActiveWindow = main.window->id;
|
||||
JumpGarbageBuffer(&main);
|
||||
ResetBuffer(main.buffer);
|
||||
For(Buffers) {
|
||||
RawAppendf(main.buffer, "%-80S || %S\n", SkipToLastSlash(it->name), it->name);
|
||||
}
|
||||
@@ -1152,11 +1256,6 @@ void Command_ListBuffers() {
|
||||
Command_SelectRangeOneCursor(main.view, GetBufferEndAsRange(main.buffer));
|
||||
}
|
||||
|
||||
int Lua_ListBuffers(lua_State *L) {
|
||||
Command_ListBuffers();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Command_ListViews() {
|
||||
BSet main = GetLastActiveLayoutSet();
|
||||
ActiveWindow = main.window->id;
|
||||
|
||||
@@ -126,6 +126,7 @@ void OnCommand(Event event) {
|
||||
Assert(ScrollbarSelected.id == -1);
|
||||
BSet selected = GetBSet(DocumentSelected);
|
||||
|
||||
|
||||
Vec2I mouse = MouseVec2I();
|
||||
// Special case for full-screen where we can have document
|
||||
// aligned with monitor screen in which case mouse cursor cannot
|
||||
@@ -184,6 +185,13 @@ void OnCommand(Event event) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Mouse(X2)) {
|
||||
GotoForward(GetLastActiveLayoutSet().window);
|
||||
}
|
||||
if (Mouse(X1)) {
|
||||
GotoBackward(GetLastActiveLayoutSet().window);
|
||||
}
|
||||
|
||||
if (Ctrl() && Shift() && Mouse(RIGHT)) {
|
||||
|
||||
} else if (Alt() && Ctrl() && Mouse(RIGHT)) {
|
||||
@@ -232,6 +240,8 @@ void OnCommand(Event event) {
|
||||
bool mouse_in_line_numbers = AreOverlapping(mouse, active.window->line_numbers_rect);
|
||||
if (mouse_in_document || mouse_in_line_numbers) {
|
||||
DocumentSelected = active.window->id;
|
||||
CheckpointBeforeGoto(active.window);
|
||||
|
||||
|
||||
Int p = ScreenSpaceToBufferPos(active.window, active.view, active.buffer, mouse);
|
||||
if (Alt()) Insert(&active.view->carets, MakeCaret(p, p), 0);
|
||||
@@ -293,12 +303,7 @@ void OnCommand(Event event) {
|
||||
|
||||
if (CtrlAltPress(SDLK_P)) {
|
||||
} else if (CtrlPress(SDLK_P)) {
|
||||
// Command_ListCode();
|
||||
Window *window = GetWindow(CommandBarWindowID);
|
||||
window->visible = !window->visible;
|
||||
ActiveWindow = window->id;
|
||||
BSet set = GetBSet(window);
|
||||
Command_ListBuffers();
|
||||
Command_ShowBufferList();
|
||||
}
|
||||
|
||||
if (CtrlPress(SDLK_0)) {
|
||||
@@ -350,6 +355,10 @@ void OnCommand(Event event) {
|
||||
WindowOpenBufferView(active.window, event.text);
|
||||
}
|
||||
|
||||
if (Press(SDLK_DOWN) || Press(SDLK_RIGHT) || Press(SDLK_LEFT) || Press(SDLK_UP)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
}
|
||||
|
||||
if (CtrlAltPress(SDLK_DOWN)) {
|
||||
Command_DuplicateLine(active.view, DIR_DOWN);
|
||||
} else if (AltShiftPress(SDLK_DOWN)) {
|
||||
@@ -428,30 +437,40 @@ void OnCommand(Event event) {
|
||||
}
|
||||
|
||||
if (ShiftPress(SDLK_PAGEUP)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsByPageSize(active.window, DIR_UP, SHIFT_PRESS);
|
||||
} else if (CtrlPress(SDLK_PAGEUP)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_SelectRangeOneCursor(active.view, MakeRange(0));
|
||||
} else if (Press(SDLK_PAGEUP)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsByPageSize(active.window, DIR_UP);
|
||||
}
|
||||
|
||||
if (ShiftPress(SDLK_PAGEDOWN)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsByPageSize(active.window, DIR_DOWN, SHIFT_PRESS);
|
||||
} else if (CtrlPress(SDLK_PAGEDOWN)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_SelectRangeOneCursor(active.view, MakeRange(active.buffer->len));
|
||||
} else if (Press(SDLK_PAGEDOWN)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsByPageSize(active.window, DIR_DOWN);
|
||||
}
|
||||
|
||||
if (ShiftPress(SDLK_HOME)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsToSide(active.view, DIR_LEFT, SHIFT_PRESS);
|
||||
} else if (Press(SDLK_HOME)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsToSide(active.view, DIR_LEFT);
|
||||
}
|
||||
|
||||
if (ShiftPress(SDLK_END)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsToSide(active.view, DIR_RIGHT, SHIFT_PRESS);
|
||||
} else if (Press(SDLK_END)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
Command_MoveCursorsToSide(active.view, DIR_RIGHT);
|
||||
}
|
||||
|
||||
@@ -494,6 +513,7 @@ void OnCommand(Event event) {
|
||||
}
|
||||
|
||||
if (CtrlPress(SDLK_D)) {
|
||||
CheckpointBeforeGoto(active.window);
|
||||
String16 string = GetString(active.buffer, active.view->carets[0].range);
|
||||
Caret caret = FindNext(active.buffer, string, active.view->carets[0]);
|
||||
Insert(&active.view->carets, caret, 0);
|
||||
@@ -558,10 +578,6 @@ void OnCommand(Event event) {
|
||||
window->visible = !window->visible;
|
||||
}
|
||||
|
||||
// if (CtrlPress(SDLK_N)) {
|
||||
// Command_New();
|
||||
// }
|
||||
|
||||
if (CtrlPress(SDLK_S)) {
|
||||
SaveBuffer(active.buffer);
|
||||
}
|
||||
@@ -585,6 +601,10 @@ void OnCommand(Event event) {
|
||||
|
||||
}
|
||||
|
||||
if (AltPress(SDLK_Q)) {
|
||||
GotoBackward(main.window);
|
||||
}
|
||||
|
||||
|
||||
if (CtrlPress(SDLK_Q)) {
|
||||
if (active.view->fuzzy_search) {
|
||||
@@ -597,6 +617,14 @@ void OnCommand(Event event) {
|
||||
if (Press(SDLK_ESCAPE)) {
|
||||
active.view->carets.len = 1;
|
||||
active.view->carets[0] = MakeCaret(GetFront(active.view->carets[0]));
|
||||
|
||||
if (active.window->lose_focus_on_escape && active.window->id == ActiveWindow) {
|
||||
if (active.window->layout) {
|
||||
//
|
||||
} else {
|
||||
ActiveWindow = LastActiveLayoutWindowID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// :OnCommandEnding
|
||||
|
||||
@@ -210,21 +210,21 @@ String GetFieldString(lua_State *L, String name) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Int GetFieldInt(lua_State *L, const char *name) {
|
||||
Int GetFieldAInt(lua_State *L, const char *name) {
|
||||
lua_getfield(L, -1, name);
|
||||
lua_Integer num = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return (Int)num;
|
||||
}
|
||||
|
||||
double GetFieldFloat(lua_State *L, const char *name) {
|
||||
double GetFieldAFloat(lua_State *L, const char *name) {
|
||||
lua_getfield(L, -1, name);
|
||||
double num = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return num;
|
||||
}
|
||||
|
||||
const char *GetFieldString(lua_State *L, const char *name) {
|
||||
const char *GetFieldAString(lua_State *L, const char *name) {
|
||||
lua_getfield(L, -1, name);
|
||||
const char *result = lua_tostring(L, -1);
|
||||
|
||||
@@ -256,7 +256,7 @@ int Lua_Play(lua_State *L) {
|
||||
defer { lua_pop(L, 1); };
|
||||
|
||||
Event event = {};
|
||||
#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetField##KIND(L, #NAME);
|
||||
#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetFieldA##KIND(L, #NAME);
|
||||
EVENT_FIELDS
|
||||
#undef X
|
||||
Add(&EventPlayback, event);
|
||||
|
||||
@@ -29,7 +29,6 @@ luaL_Reg LuaFunctions[] = {
|
||||
{"C", Lua_C},
|
||||
{"Open", Lua_Open},
|
||||
{"Cmd", Lua_Cmd},
|
||||
{"ListBuffers", Lua_ListBuffers},
|
||||
{"ListViews", Lua_ListViews},
|
||||
{"Eval", Lua_Eval},
|
||||
{"SetProjectFile", Lua_SetProjectFile},
|
||||
|
||||
@@ -157,6 +157,7 @@ Window *CreateWind() {
|
||||
w->draw_scrollbar = StyleDrawScrollbar;
|
||||
w->draw_line_numbers = StyleDrawLineNumbers;
|
||||
w->draw_line_highlight = true;
|
||||
w->jump_history = true;
|
||||
w->id = AllocWindowID(w);
|
||||
w->weight = 1.0;
|
||||
Add(&Windows, w);
|
||||
@@ -380,11 +381,23 @@ View *WindowOpenBufferView(Window *new_parent_window, String name) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ViewIsCrumb(ViewID view_id) {
|
||||
ForItem(window, Windows) {
|
||||
For(window->goto_history) if (it.view_id == view_id) return true;
|
||||
For(window->goto_redo) if (it.view_id == view_id) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewIsReferenced(ViewID view) {
|
||||
if (view == NullViewID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ViewIsCrumb(view)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
For(Windows) {
|
||||
if (it->active_view == view) {
|
||||
return true;
|
||||
@@ -455,6 +468,8 @@ void GarbageCollect() {
|
||||
IterRemove(Windows) {
|
||||
IterRemovePrepare(Windows);
|
||||
if (it->kill) {
|
||||
Dealloc(&it->goto_history);
|
||||
Dealloc(&it->goto_redo);
|
||||
Dealloc(sys_allocator, it);
|
||||
remove_item = true;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,12 @@ struct View {
|
||||
String16 prev_search_line;
|
||||
};
|
||||
|
||||
struct GotoCrumb {
|
||||
ViewID view_id;
|
||||
Caret caret;
|
||||
double time;
|
||||
};
|
||||
|
||||
struct Window {
|
||||
WindowID id;
|
||||
ViewID active_view;
|
||||
@@ -32,6 +38,12 @@ struct Window {
|
||||
double weight;
|
||||
Int status_bar_last_buffer_change_id;
|
||||
|
||||
Array<GotoCrumb> goto_history;
|
||||
Array<GotoCrumb> goto_redo;
|
||||
|
||||
ViewID active_goto_list;
|
||||
Int goto_list_pos;
|
||||
|
||||
struct {
|
||||
bool draw_scrollbar : 1;
|
||||
bool draw_line_numbers : 1;
|
||||
@@ -41,6 +53,8 @@ struct Window {
|
||||
bool layout : 1;
|
||||
bool kill : 1;
|
||||
bool sync_visibility_with_focus : 1;
|
||||
bool lose_focus_on_escape : 1;
|
||||
bool jump_history : 1;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -16,17 +16,7 @@ Int GetExpandingBarSize(Window *window) {
|
||||
void InitWindows() {
|
||||
Scratch scratch;
|
||||
|
||||
{
|
||||
Window *window = CreateWind();
|
||||
window->active_view = CreateView(ScratchBuffer->id)->id;
|
||||
window->weight = 1.0;
|
||||
{
|
||||
Window *window = CreateWind();
|
||||
window->active_view = TraceView->id;
|
||||
CreateWind();
|
||||
CreateWind();
|
||||
}
|
||||
}
|
||||
|
||||
// COMMAND BAR
|
||||
{
|
||||
@@ -42,7 +32,8 @@ void InitWindows() {
|
||||
window->layout = false;
|
||||
window->visible = false;
|
||||
window->sync_visibility_with_focus = true;
|
||||
buffer->no_history = true;
|
||||
window->lose_focus_on_escape = true;
|
||||
window->jump_history = false;
|
||||
}
|
||||
|
||||
// SEARCH BAR
|
||||
@@ -60,6 +51,7 @@ void InitWindows() {
|
||||
window->draw_line_highlight = false;
|
||||
window->layout = false;
|
||||
window->visible = false;
|
||||
window->lose_focus_on_escape = true;
|
||||
}
|
||||
|
||||
// STATUS BAR at the bottom
|
||||
|
||||
Reference in New Issue
Block a user