Work on Open
This commit is contained in:
@@ -253,7 +253,18 @@ function ExtractLineAndColumn(s)
|
||||
end
|
||||
end
|
||||
|
||||
return 0, 0, s
|
||||
return -1, -1, s
|
||||
end
|
||||
|
||||
function BufferNameExists(name)
|
||||
buffers = ListBuffers()
|
||||
for i = 1,#buffers do
|
||||
buff = buffers[i]
|
||||
if buff == name then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function GenericTextFileRule(_s)
|
||||
@@ -286,8 +297,12 @@ function GenericTextFileRule(_s)
|
||||
return s
|
||||
end
|
||||
|
||||
if BufferNameExists(s) then
|
||||
return s
|
||||
end
|
||||
|
||||
-- other_random_filename
|
||||
return s
|
||||
return GetCurrentBufferDir()..'/'..s
|
||||
end
|
||||
|
||||
line, col, _s = ExtractLineAndColumn(_s)
|
||||
@@ -295,21 +310,6 @@ function GenericTextFileRule(_s)
|
||||
return {kind = "text", file_path = file_path, line = line, col = col}
|
||||
end
|
||||
|
||||
-- function RuleFindExistingBuffer(_s)
|
||||
-- line, col, _s = ExtractLineAndColumn(_s)
|
||||
--
|
||||
-- buffers = list_buffers_object()
|
||||
-- for i = 1,#buffers do
|
||||
-- buff = buffers[i]
|
||||
-- if buff == _s then
|
||||
-- return {kind = "text", file_path = buff, line = line, col = col}
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- return nil
|
||||
-- end
|
||||
|
||||
|
||||
Rules = {}
|
||||
Rules[#Rules + 1] = GenericTextFileRule
|
||||
-- Rules[#Rules + 2] = RuleFindExistingBuffer
|
||||
@@ -397,7 +397,7 @@ void GenerateConfig() {
|
||||
Array<Var> style = {};
|
||||
style.add({"DrawLineNumbers", "1"});
|
||||
style.add({"DrawScrollbar", "1"});
|
||||
style.add({"IndentSize", "2"});
|
||||
style.add({"IndentSize", "4"});
|
||||
style.add({"TrimWhitespaceOnSave", "1"});
|
||||
|
||||
{
|
||||
|
||||
@@ -171,7 +171,10 @@ Int PosToLine(Buffer &buffer, Int pos) {
|
||||
Add(&buffer.line_starts, buffer.len + 1);
|
||||
|
||||
// binary search
|
||||
Int low = 0;
|
||||
Int low = 0;
|
||||
|
||||
// -2 here because we use 2 indices and combine them into one line range so we
|
||||
// don't want to access last item since that would index past array.
|
||||
Int high = buffer.line_starts.len - 2;
|
||||
Int result = 0;
|
||||
|
||||
@@ -217,6 +220,14 @@ Int XYToPosWithoutNL(Buffer &buffer, XY xy) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
Int XYToPosErrorOutOfBounds(Buffer &buffer, XY xy) {
|
||||
if (xy.line < 0 || xy.line >= buffer.line_starts.len) return -1;
|
||||
Range line_range = GetLineRange(buffer, xy.line);
|
||||
Int pos = xy.col + line_range.min;
|
||||
if (pos < line_range.min || pos > line_range.max) return -1;
|
||||
return pos;
|
||||
}
|
||||
|
||||
Int GetWordStart(Buffer *buffer, Int pos) {
|
||||
pos = Clamp(pos, (Int)0, buffer->len);
|
||||
for (Int i = pos - 1; i >= 0; i -= 1) {
|
||||
@@ -350,3 +361,9 @@ Range EncloseLoadWord(Buffer *buffer, Int pos) {
|
||||
Range result = {GetLoadWordStart(buffer, pos), GetLoadWordEnd(buffer, pos)};
|
||||
return result;
|
||||
}
|
||||
|
||||
Int OffsetByLine(Buffer *buffer, Int pos, Int line_offset) {
|
||||
XY xy = PosToXY(*buffer, pos);
|
||||
Int result = XYToPosWithoutNL(*buffer, {xy.col, xy.line + line_offset});
|
||||
return result;
|
||||
}
|
||||
@@ -66,12 +66,6 @@ Int MoveOnWhitespaceBoundaryVertical(Buffer &buffer, Int pos, int direction) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Int MovePosByXY(Buffer &buffer, Int pos, XY offset) {
|
||||
XY xy = PosToXY(buffer, pos);
|
||||
Int result = XYToPosWithoutNL(buffer, {xy.col + offset.col, xy.line + offset.line});
|
||||
return result;
|
||||
}
|
||||
|
||||
Int MovePos(Buffer &buffer, Int pos, int direction, bool ctrl_pressed = false) {
|
||||
ProfileFunction();
|
||||
Assert(direction >= 0 && direction <= 3);
|
||||
@@ -87,8 +81,8 @@ Int MovePos(Buffer &buffer, Int pos, int direction, bool ctrl_pressed = false) {
|
||||
switch (direction) {
|
||||
case DIR_RIGHT: return Clamp(pos + 1, (Int)0, buffer.len);
|
||||
case DIR_LEFT: return Clamp(pos - 1, (Int)0, buffer.len);
|
||||
case DIR_DOWN: return MovePosByXY(buffer, pos, {0, 1});
|
||||
case DIR_UP: return MovePosByXY(buffer, pos, {0, -1});
|
||||
case DIR_DOWN: return OffsetByLine(&buffer, pos, 1);
|
||||
case DIR_UP: return OffsetByLine(&buffer, pos, -1);
|
||||
default: return pos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +375,33 @@ void WindowCommand(Event event, Window *window, View *view) {
|
||||
}
|
||||
}
|
||||
|
||||
// Underline
|
||||
if (event.ctrl) {
|
||||
Caret caret = view->carets[0];
|
||||
if (GetSize(caret.range) == 0) {
|
||||
view->underline_pos[view->underline_count++] = caret.range.min;
|
||||
Assert(view->underline_count <= 2);
|
||||
}
|
||||
|
||||
{
|
||||
Vec2I mouse = MouseVec2I();
|
||||
Vec2I mworld = mouse - window->document_rect.min + view->scroll;
|
||||
Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing};
|
||||
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
||||
Int p = XYToPosErrorOutOfBounds(*buffer, xy);
|
||||
if (p != -1) {
|
||||
view->underline_pos[view->underline_count++] = p;
|
||||
Assert(view->underline_count <= 2);
|
||||
|
||||
if (Mouse(LEFT)) {
|
||||
Range enclose = EncloseLoadWord(buffer, p);
|
||||
String16 string = GetString(*buffer, enclose);
|
||||
Open(string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CtrlAlt(SDLK_DOWN)) {
|
||||
Command_DuplicateLine(view, DIR_DOWN);
|
||||
} else if (AltShift(SDLK_DOWN)) {
|
||||
@@ -665,8 +692,7 @@ void WindowCommand(Event event, Window *window, View *view) {
|
||||
|
||||
{
|
||||
|
||||
Vec2 mouse_vec2 = MouseVec2();
|
||||
Vec2I mouse = MouseVec2I();
|
||||
Vec2I mouse = MouseVec2I();
|
||||
|
||||
// Special case for full-screen where we can have document
|
||||
// aligned with monitor screen in which case mouse cursor cannot
|
||||
@@ -707,7 +733,7 @@ void WindowCommand(Event event, Window *window, View *view) {
|
||||
} else {
|
||||
view->selection_anchor = Rng(p);
|
||||
}
|
||||
} else if (mouse_in_document && Mouse(LEFT) && event.ctrl) {
|
||||
} else if (mouse_in_document && Mouse(LEFT) && event.alt) {
|
||||
Insert(&view->carets, MakeCaret(p, p), 0);
|
||||
view->selection_anchor = view->carets[0].range;
|
||||
} else if (mouse_in_document && Mouse(LEFT)) {
|
||||
@@ -737,9 +763,10 @@ void WindowCommand(Event event, Window *window, View *view) {
|
||||
MergeCarets(view, &view->selection_anchor);
|
||||
}
|
||||
} else if (!(mouse_in_document || window->mouse_selecting) && mouse_in_scrollbar || window->mouse_selecting_scrollbar) {
|
||||
Scroller s = ComputeScrollerRect(window);
|
||||
double size_y = (double)GetSize(window->scrollbar_rect).y;
|
||||
double p = mouse_vec2.y - window->scrollbar_rect.min.y;
|
||||
Vec2 mouse_vec2 = MouseVec2();
|
||||
Scroller s = ComputeScrollerRect(window);
|
||||
double size_y = (double)GetSize(window->scrollbar_rect).y;
|
||||
double p = mouse_vec2.y - window->scrollbar_rect.min.y;
|
||||
|
||||
if (Mouse(LEFT)) {
|
||||
window->mouse_selecting_scrollbar = true;
|
||||
|
||||
@@ -57,7 +57,7 @@ Color.TitleBarSelection = GruvboxLight3
|
||||
Style = {}
|
||||
Style.DrawLineNumbers = 1
|
||||
Style.DrawScrollbar = 1
|
||||
Style.IndentSize = 2
|
||||
Style.IndentSize = 4
|
||||
Style.TrimWhitespaceOnSave = 1
|
||||
|
||||
-- @todo: should we rewrite linux paths to windows on windows and vice-versa?
|
||||
@@ -123,7 +123,18 @@ function ExtractLineAndColumn(s)
|
||||
end
|
||||
end
|
||||
|
||||
return 0, 0, s
|
||||
return -1, -1, s
|
||||
end
|
||||
|
||||
function BufferNameExists(name)
|
||||
buffers = ListBuffers()
|
||||
for i = 1,#buffers do
|
||||
buff = buffers[i]
|
||||
if buff == name then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function GenericTextFileRule(_s)
|
||||
@@ -156,8 +167,12 @@ function GenericTextFileRule(_s)
|
||||
return s
|
||||
end
|
||||
|
||||
if BufferNameExists(s) then
|
||||
return s
|
||||
end
|
||||
|
||||
-- other_random_filename
|
||||
return s
|
||||
return GetCurrentBufferDir()..'/'..s
|
||||
end
|
||||
|
||||
line, col, _s = ExtractLineAndColumn(_s)
|
||||
@@ -165,21 +180,6 @@ function GenericTextFileRule(_s)
|
||||
return {kind = "text", file_path = file_path, line = line, col = col}
|
||||
end
|
||||
|
||||
-- function RuleFindExistingBuffer(_s)
|
||||
-- line, col, _s = ExtractLineAndColumn(_s)
|
||||
--
|
||||
-- buffers = list_buffers_object()
|
||||
-- for i = 1,#buffers do
|
||||
-- buff = buffers[i]
|
||||
-- if buff == _s then
|
||||
-- return {kind = "text", file_path = buff, line = line, col = col}
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- return nil
|
||||
-- end
|
||||
|
||||
|
||||
Rules = {}
|
||||
Rules[#Rules + 1] = GenericTextFileRule
|
||||
-- Rules[#Rules + 2] = RuleFindExistingBuffer
|
||||
|
||||
@@ -54,5 +54,5 @@ Color ColorTitleBarBackground = GruvboxLight1;
|
||||
Color ColorTitleBarSelection = GruvboxLight3;
|
||||
Int StyleDrawLineNumbers = 1;
|
||||
Int StyleDrawScrollbar = 1;
|
||||
Int StyleIndentSize = 2;
|
||||
Int StyleIndentSize = 4;
|
||||
Int StyleTrimWhitespaceOnSave = 1;
|
||||
@@ -28,36 +28,49 @@ String FieldString(lua_State *L, String name) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int LuaOpen(lua_State *L) {
|
||||
void Open(String path) {
|
||||
Scratch scratch;
|
||||
String path = luaL_checkstring(L, 1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "ApplyRules");
|
||||
lua_pushlstring(L, path.data, path.len);
|
||||
if (lua_pcall(L, 1, 1, 0) != 0) {
|
||||
lua_getglobal(LuaState, "ApplyRules");
|
||||
lua_pushlstring(LuaState, path.data, path.len);
|
||||
if (lua_pcall(LuaState, 1, 1, 0) != 0) {
|
||||
const char *error_message = lua_tostring(LuaState, -1);
|
||||
ReportWarningf("Failed the call to ApplyRules! %s", error_message);
|
||||
lua_pop(LuaState, 1);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (FieldString(L, "kind") == "text") {
|
||||
String file_path = FieldString(L, "file_path");
|
||||
String line_string = FieldString(L, "line");
|
||||
if (FieldString(LuaState, "kind") == "text") {
|
||||
String file_path = FieldString(LuaState, "file_path");
|
||||
String line_string = FieldString(LuaState, "line");
|
||||
Int line = strtoll(line_string.data, NULL, 10);
|
||||
String col_string = FieldString(L, "col");
|
||||
String col_string = FieldString(LuaState, "col");
|
||||
Int col = strtoll(col_string.data, NULL, 10);
|
||||
|
||||
Window *window = GetWindow(GetLastActiveWindow());
|
||||
View *view = WindowOpenBufferView(window, file_path);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
view->carets[0] = MakeCaret(XYToPos(*buffer, {col - 1, line - 1}));
|
||||
Window *window = GetWindow(GetLastActiveWindow());
|
||||
View *view = WindowOpenBufferView(window, file_path);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
if (line != -1 && col != -1) {
|
||||
view->carets[0] = MakeCaret(XYToPos(*buffer, {col - 1, line - 1}));
|
||||
}
|
||||
UpdateScroll(window, true);
|
||||
SetActiveWindow(window->id);
|
||||
} else {
|
||||
ReportWarningf("Failed to match any of ApplyRules results!");
|
||||
}
|
||||
}
|
||||
|
||||
void Open(String16 path) {
|
||||
Scratch scratch;
|
||||
String string = ToString(scratch, path);
|
||||
Open(string);
|
||||
}
|
||||
|
||||
int LuaOpen(lua_State *L) {
|
||||
Scratch scratch;
|
||||
String path = luaL_checkstring(L, 1);
|
||||
lua_pop(L, 1);
|
||||
Open(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -86,6 +99,14 @@ int LuaListOpenBuffersObject(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaFileExists(lua_State *L) {
|
||||
String path = luaL_checkstring(L, 1);
|
||||
lua_pop(L, 1);
|
||||
bool exists = FileExists(path);
|
||||
lua_pushinteger(L, (int)exists);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaGetWorkingDir(lua_State *L) {
|
||||
lua_pushlstring(LuaState, WorkingDir.data, WorkingDir.len);
|
||||
return 1;
|
||||
@@ -104,6 +125,18 @@ int LuaOpenBigBuffer(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaGetCurrentBufferName(lua_State *L) {
|
||||
String name = GetCurrentBufferName();
|
||||
lua_pushlstring(LuaState, name.data, name.len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaGetCurrentBufferDir(lua_State *L) {
|
||||
String name = GetCurrentBufferDir();
|
||||
lua_pushlstring(LuaState, name.data, name.len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InitLua() {
|
||||
LuaState = luaL_newstate();
|
||||
luaL_openlibs(LuaState);
|
||||
@@ -115,13 +148,22 @@ void InitLua() {
|
||||
lua_setglobal(LuaState, "list_buffers");
|
||||
|
||||
lua_pushcfunction(LuaState, LuaListOpenBuffersObject);
|
||||
lua_setglobal(LuaState, "list_buffers_object");
|
||||
lua_setglobal(LuaState, "ListBuffers");
|
||||
|
||||
lua_pushcfunction(LuaState, LuaOpenBigBuffer);
|
||||
lua_setglobal(LuaState, "open_big_buffer");
|
||||
|
||||
lua_pushcfunction(LuaState, LuaGetWorkingDir);
|
||||
lua_setglobal(LuaState, "GetWorkingDir");
|
||||
|
||||
lua_pushcfunction(LuaState, LuaFileExists);
|
||||
lua_setglobal(LuaState, "FileExists");
|
||||
|
||||
lua_pushcfunction(LuaState, LuaGetCurrentBufferName);
|
||||
lua_setglobal(LuaState, "GetCurrentBufferName");
|
||||
|
||||
lua_pushcfunction(LuaState, LuaGetCurrentBufferDir);
|
||||
lua_setglobal(LuaState, "GetCurrentBufferDir");
|
||||
}
|
||||
|
||||
String16 EvalString(Allocator allocator, String16 string16) {
|
||||
|
||||
@@ -143,6 +143,22 @@ View *FindViewWithBufferName(String name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
String GetCurrentBufferName() {
|
||||
Window *window = GetWindow(ActiveWindow);
|
||||
if (window->is_title_bar) {
|
||||
window = GetWindow(window->title_bar_window);
|
||||
}
|
||||
View *view = GetView(window->active_view);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
return buffer->name;
|
||||
}
|
||||
|
||||
String GetCurrentBufferDir() {
|
||||
String buffer_name = GetCurrentBufferName();
|
||||
String name = ChopLastSlash(buffer_name);
|
||||
return name;
|
||||
}
|
||||
|
||||
// This function as name suggests tries to open a buffer,
|
||||
// there is no name resolution here, path should already be resolved etc.
|
||||
//
|
||||
@@ -233,14 +249,12 @@ View *WindowOpenBufferView(Window *new_parent_window, String name) {
|
||||
SetActiveView(new_parent_window, view->id);
|
||||
return view;
|
||||
}
|
||||
|
||||
bool view_actively_used = window->active_view.id == view->id.id;
|
||||
if (view_actively_used) {
|
||||
View *result = OpenBufferView(name);
|
||||
new_parent_window->active_view = result->id;
|
||||
return result;
|
||||
if (window == new_parent_window) {
|
||||
return view;
|
||||
}
|
||||
|
||||
SetActiveView(new_parent_window, view->id);
|
||||
return view;
|
||||
Assert(window->active_view.id == view->id.id);
|
||||
View *result = OpenBufferView(name);
|
||||
new_parent_window->active_view = result->id;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -156,6 +156,7 @@ void Update(const Event &event) {
|
||||
view->main_caret_on_begin_frame = view->carets[0];
|
||||
view->update_scroll = true;
|
||||
window->mouse_in_scrollbar = false;
|
||||
view->underline_count = 0;
|
||||
}
|
||||
|
||||
HandleEvent(event);
|
||||
|
||||
@@ -50,12 +50,15 @@ struct View {
|
||||
Range selection_anchor;
|
||||
Caret main_caret_on_begin_frame;
|
||||
bool update_scroll;
|
||||
|
||||
int underline_count;
|
||||
Int underline_pos[2];
|
||||
};
|
||||
|
||||
struct Window {
|
||||
WindowID id;
|
||||
ViewID active_view;
|
||||
CircularArray<ViewID> view_history;
|
||||
CircularArray<ViewID> view_history; // @todo: use this
|
||||
|
||||
WindowID title_bar_window;
|
||||
Int title_bar_last_buffer_change_id;
|
||||
@@ -117,6 +120,8 @@ void MergeCarets(View *view, Range *mouse_selection_anchor = NULL);
|
||||
inline BufferID AllocBufferID();
|
||||
void Command_SelectEntireBuffer(View *view);
|
||||
void Command_Replace(View *view, String16 string);
|
||||
void Open(String path);
|
||||
void Open(String16 path);
|
||||
|
||||
void ReportErrorf(const char *fmt, ...);
|
||||
void ReportWarningf(const char *fmt, ...);
|
||||
@@ -1,14 +1,14 @@
|
||||
- bugs:
|
||||
- page up and down should also scroll and leave you in exactly same scroll
|
||||
- I think the way sublime text and we display line highlights is confusing with multiple cursors (line highlight can be confused with selection)
|
||||
- don't trim lines with cursor or selection on it
|
||||
- fix history of ctrl + enter
|
||||
|
||||
- delete till indent
|
||||
- indent on enter
|
||||
- maybe my mouse selection is wrong? seems like on double click lite and sublime start to enclosing words!!
|
||||
- click 3 times to select line
|
||||
- save location on open and allow for revert
|
||||
- we could rewrite kill lines with simpler commands - extend selection to encompass lines->replace
|
||||
- improve cursor movement, it's too clunky, too much stopping
|
||||
- better enclosures
|
||||
- should be able click on title bar of windows which disappear on losing focus
|
||||
- search backwards
|
||||
- load selected string or auto enclosed word when midclick?, ctrl + click, ctrl + e?
|
||||
@@ -31,6 +31,8 @@
|
||||
- Search and replace
|
||||
- Search result buffer
|
||||
- yeet sheet
|
||||
- select space between parens,braces
|
||||
- color parens, braces
|
||||
|
||||
|
||||
- Windows
|
||||
|
||||
@@ -167,24 +167,18 @@ void DrawWindow(Window *window) {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_active) {
|
||||
Caret caret = view->carets[0];
|
||||
if (GetSize(caret.range) == 0) {
|
||||
Int pos = caret.range.min;
|
||||
if (pos < buffer->len) {
|
||||
Range range = EncloseLoadWord(buffer, pos);
|
||||
for (int i = 0; is_active && i < view->underline_count; i += 1) {
|
||||
Range range = EncloseLoadWord(buffer, view->underline_pos[i]);
|
||||
|
||||
XY xy_min = PosToXY(*buffer, range.min);
|
||||
XY xy_max = PosToXY(*buffer, range.max);
|
||||
XY xy_min = PosToXY(*buffer, range.min);
|
||||
XY xy_max = PosToXY(*buffer, range.max);
|
||||
|
||||
Vec2I min = {xy_min.col * FontCharSpacing, (xy_min.line) * FontLineSpacing};
|
||||
Vec2I max = {xy_max.col * FontCharSpacing, (xy_max.line + 1) * FontLineSpacing};
|
||||
Rect2I rect = {min, max};
|
||||
rect -= view->scroll;
|
||||
rect += window->document_rect.min;
|
||||
DrawRect(rect, ColorLoadTextHighlight);
|
||||
}
|
||||
}
|
||||
Vec2I min = {xy_min.col * FontCharSpacing, (xy_min.line + 1) * FontLineSpacing - 1};
|
||||
Vec2I max = {xy_max.col * FontCharSpacing, (xy_max.line + 1) * FontLineSpacing};
|
||||
Rect2I rect = {min, max};
|
||||
rect -= view->scroll;
|
||||
rect += window->document_rect.min;
|
||||
DrawRectOutline(rect, ColorText);
|
||||
}
|
||||
|
||||
if (window->fuzzy_search) {
|
||||
|
||||
Reference in New Issue
Block a user