diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..5538b7e --- /dev/null +++ b/build.bat @@ -0,0 +1 @@ +..\odin\odin.exe build src/ -out:bin\editor.exe -debug diff --git a/plugin-rs-bindings/src/lib.rs b/plugin-rs-bindings/src/lib.rs index c1d0ecb..e875a36 100644 --- a/plugin-rs-bindings/src/lib.rs +++ b/plugin-rs-bindings/src/lib.rs @@ -1,6 +1,7 @@ use std::{ borrow::Cow, - ffi::{c_char, c_void, CStr}, + ffi::{c_char, c_void, CStr, CString}, + fmt::write, path::Path, }; @@ -133,8 +134,11 @@ impl BufferVTable { } } pub fn open_buffer(&self, path: impl AsRef, line: i32, col: i32) { - let c_str = path.as_ref().to_string_lossy().as_ptr(); - (self.open_buffer)(c_str, line as isize, col as isize); + let Ok(c_str) = CString::new(path.as_ref().as_os_str().as_encoded_bytes()) else { + eprintln!("grep plugin failed to open buffer"); + return; + }; + (self.open_buffer)(c_str.as_ptr() as *const u8, line as isize, col as isize); } pub fn open_virtual_buffer(&self) -> Buffer { Buffer { diff --git a/plugins/highlighter/src/plugin.odin b/plugins/highlighter/src/plugin.odin index fa98094..6fe77fe 100644 --- a/plugins/highlighter/src/plugin.odin +++ b/plugins/highlighter/src/plugin.odin @@ -1,7 +1,7 @@ // The default syntax highlighter plugin for Odin & Rust package highlighter; -import "core:runtime" +import "base:runtime" import "core:fmt" import p "../../../src/plugin" diff --git a/src/core/core.odin b/src/core/core.odin index 986618c..702bf48 100644 --- a/src/core/core.odin +++ b/src/core/core.odin @@ -1,6 +1,6 @@ package core -import "core:runtime" +import "base:runtime" import "core:reflect" import "core:fmt" import "core:log" @@ -97,6 +97,10 @@ current_buffer :: proc(state: ^State) -> ^FileBuffer { return &state.log_buffer; } + if len(state.buffers) < 1 { + return nil + } + return &state.buffers[state.current_buffer]; } @@ -167,7 +171,7 @@ new_input_actions :: proc() -> InputActions { return input_actions; } delete_input_map :: proc(input_map: ^InputMap) { - for _, &actions in &input_map.mode { + for _, &actions in input_map.mode { delete_input_actions(&actions); } delete(input_map.mode); diff --git a/src/core/error.odin b/src/core/error.odin index e8dfe14..8e8a14d 100644 --- a/src/core/error.odin +++ b/src/core/error.odin @@ -1,6 +1,6 @@ package core; -import "core:runtime" +import "base:runtime" ErrorType :: enum { None, diff --git a/src/core/file_buffer.odin b/src/core/file_buffer.odin index 2dc292c..75a7422 100644 --- a/src/core/file_buffer.odin +++ b/src/core/file_buffer.odin @@ -6,7 +6,7 @@ import "core:mem" import "core:fmt" import "core:math" import "core:slice" -import "core:runtime" +import "base:runtime" import "core:strings" import "../theme" @@ -672,8 +672,10 @@ new_virtual_file_buffer :: proc(allocator: mem.Allocator) -> FileBuffer { new_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: string = "") -> (FileBuffer, Error) { context.allocator = allocator; + fmt.eprintln("attempting to open", file_path); + fd, err := os.open(file_path); - if err != os.ERROR_NONE { + if err != nil { return FileBuffer{}, make_error(ErrorType.FileIOError, fmt.aprintf("failed to open file: errno=%x", err)); } defer os.close(fd); @@ -696,10 +698,12 @@ new_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: s width := 256; height := 256; + fmt.eprintln("file path", fi.fullpath[4:]); + buffer := FileBuffer { allocator = allocator, directory = dir, - file_path = fi.fullpath, + file_path = fi.fullpath[4:], extension = extension, original_content = slice.clone_to_dynamic(original_content), @@ -951,7 +955,6 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, sho draw_rect(state, sel_x, text_y, width, state.source_font_height, .Green); } - } } diff --git a/src/core/gfx.odin b/src/core/gfx.odin index 17bb911..9957324 100644 --- a/src/core/gfx.odin +++ b/src/core/gfx.odin @@ -26,6 +26,7 @@ gen_font_atlas :: proc(state: ^State, path: cstring) -> FontAtlas { // FIXME: check if this failed font = ttf.OpenFont(path, font_height), } + assert(atlas.font != nil); ttf.SetFontStyle(atlas.font, ttf.STYLE_NORMAL); // NOTE: not sure if I like the look of this or not yet diff --git a/src/main.odin b/src/main.odin index 62c477e..b182f64 100644 --- a/src/main.odin +++ b/src/main.odin @@ -1,10 +1,11 @@ package main +import "core:c" import "core:os" import "core:path/filepath" import "core:math" import "core:strings" -import "core:runtime" +import "base:runtime" import "core:fmt" import "core:log" import "core:mem" @@ -18,6 +19,8 @@ import "theme" import "ui" import "plugin" +HardcodedFontPath :: "bin/BerkeleyMono-Regular.ttf"; + State :: core.State; FileBuffer :: core.FileBuffer; @@ -146,7 +149,7 @@ register_default_input_actions :: proc(input_map: ^core.InputActions) { state.source_font_height -= 2; state.source_font_width = state.source_font_height / 2; - state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf"); + state.font_atlas = core.gen_font_atlas(state, HardcodedFontPath); } log.debug(state.source_font_height); }, "increase font size"); @@ -154,7 +157,7 @@ register_default_input_actions :: proc(input_map: ^core.InputActions) { state.source_font_height += 2; state.source_font_width = state.source_font_height / 2; - state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf"); + state.font_atlas = core.gen_font_atlas(state, HardcodedFontPath); }, "decrease font size"); } @@ -286,10 +289,10 @@ ui_font_height :: proc() -> i32 { } draw :: proc(state_with_ui: ^StateWithUi) { - buffer := core.current_buffer(state_with_ui.state); - - buffer.glyph_buffer_height = math.min(256, int((state_with_ui.state.screen_height - state_with_ui.state.source_font_height*2) / state_with_ui.state.source_font_height)) + 1; - buffer.glyph_buffer_width = math.min(256, int((state_with_ui.state.screen_width - state_with_ui.state.source_font_width) / state_with_ui.state.source_font_width)); + if buffer := core.current_buffer(state_with_ui.state); buffer != nil { + buffer.glyph_buffer_height = math.min(256, int((state_with_ui.state.screen_height - state_with_ui.state.source_font_height*2) / state_with_ui.state.source_font_height)) + 1; + buffer.glyph_buffer_width = math.min(256, int((state_with_ui.state.screen_width - state_with_ui.state.source_font_width) / state_with_ui.state.source_font_width)); + } render_color := theme.get_palette_color(.Background); sdl2.SetRenderDrawColor(state_with_ui.state.sdl_renderer, render_color.r, render_color.g, render_color.b, render_color.a); @@ -832,6 +835,8 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin { open_buffer = proc "c" (path: cstring, line: int, col: int) { context = state.ctx; + fmt.eprintln("opening file from dll", path) + path := string(path); should_create_buffer := true; for buffer, index in state.buffers { @@ -1106,7 +1111,7 @@ main :: proc() { sdl_window := sdl2.CreateWindow( "odin_editor - [now with more ui]", sdl2.WINDOWPOS_UNDEFINED, - 0, + sdl2.WINDOWPOS_UNDEFINED, 640, 480, {.SHOWN, .RESIZABLE, .ALLOW_HIGHDPI} @@ -1129,7 +1134,7 @@ main :: proc() { log.error("Failed to create renderer:", sdl2.GetError()); return; } - state.font_atlas = core.gen_font_atlas(&state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf"); + state.font_atlas = core.gen_font_atlas(&state, HardcodedFontPath); defer { if state.font_atlas.font != nil { ttf.CloseFont(state.font_atlas.font); @@ -1170,9 +1175,29 @@ main :: proc() { } // ********************************************************************** - L := lua.L_newstate(); - state.L = L; - lua.L_openlibs(L); + lua_allocator :: proc "c" (ud: rawptr, ptr: rawptr, osize, nsize: c.size_t) -> (buf: rawptr) { + old_size := int(osize) + new_size := int(nsize) + context = (^runtime.Context)(ud)^ + + if ptr == nil { + data, err := runtime.mem_alloc(new_size) + return raw_data(data) if err == .None else nil + } else { + if nsize > 0 { + data, err := runtime.mem_resize(ptr, old_size, new_size) + return raw_data(data) if err == .None else nil + } else { + runtime.mem_free(ptr) + return + } + } + } + _context := context; + // L := lua.newstate(lua_allocator, &_context); + // L := lua.L_newstate(); + state.L = lua.L_newstate(); + lua.L_openlibs(state.L); bbb: [^]lua.L_Reg; editor_lib := [?]lua.L_Reg { @@ -1780,93 +1805,93 @@ main :: proc() { }; // TODO: generate this from the plugin.Key enum - lua.newtable(L); + lua.newtable(state.L); { - lua.newtable(L); - lua.pushinteger(L, lua.Integer(plugin.Key.B)); - lua.setfield(L, -2, "B"); + lua.newtable(state.L); + lua.pushinteger(state.L, lua.Integer(plugin.Key.B)); + lua.setfield(state.L, -2, "B"); - lua.pushinteger(L, lua.Integer(plugin.Key.T)); - lua.setfield(L, -2, "T"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.T)); + lua.setfield(state.L, -2, "T"); - lua.pushinteger(L, lua.Integer(plugin.Key.Y)); - lua.setfield(L, -2, "Y"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.Y)); + lua.setfield(state.L, -2, "Y"); - lua.pushinteger(L, lua.Integer(plugin.Key.P)); - lua.setfield(L, -2, "P"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.P)); + lua.setfield(state.L, -2, "P"); - lua.pushinteger(L, lua.Integer(plugin.Key.M)); - lua.setfield(L, -2, "M"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.M)); + lua.setfield(state.L, -2, "M"); - lua.pushinteger(L, lua.Integer(plugin.Key.K)); - lua.setfield(L, -2, "K"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.K)); + lua.setfield(state.L, -2, "K"); - lua.pushinteger(L, lua.Integer(plugin.Key.J)); - lua.setfield(L, -2, "J"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.J)); + lua.setfield(state.L, -2, "J"); - lua.pushinteger(L, lua.Integer(plugin.Key.Q)); - lua.setfield(L, -2, "Q"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.Q)); + lua.setfield(state.L, -2, "Q"); - lua.pushinteger(L, lua.Integer(plugin.Key.BACKQUOTE)); - lua.setfield(L, -2, "Backtick"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.BACKQUOTE)); + lua.setfield(state.L, -2, "Backtick"); - lua.pushinteger(L, lua.Integer(plugin.Key.ESCAPE)); - lua.setfield(L, -2, "Escape"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.ESCAPE)); + lua.setfield(state.L, -2, "Escape"); - lua.pushinteger(L, lua.Integer(plugin.Key.ENTER)); - lua.setfield(L, -2, "Enter"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.ENTER)); + lua.setfield(state.L, -2, "Enter"); - lua.pushinteger(L, lua.Integer(plugin.Key.SPACE)); - lua.setfield(L, -2, "Space"); + lua.pushinteger(state.L, lua.Integer(plugin.Key.SPACE)); + lua.setfield(state.L, -2, "Space"); } - lua.setfield(L, -2, "Key"); + lua.setfield(state.L, -2, "Key"); { - lua.newtable(L); - lua.pushinteger(L, lua.Integer(plugin.Hook.BufferInput)); - lua.setfield(L, -2, "OnBufferInput"); - lua.pushinteger(L, lua.Integer(plugin.Hook.Draw)); - lua.setfield(L, -2, "OnDraw"); + lua.newtable(state.L); + lua.pushinteger(state.L, lua.Integer(plugin.Hook.BufferInput)); + lua.setfield(state.L, -2, "OnBufferInput"); + lua.pushinteger(state.L, lua.Integer(plugin.Hook.Draw)); + lua.setfield(state.L, -2, "OnDraw"); } - lua.setfield(L, -2, "Hook"); + lua.setfield(state.L, -2, "Hook"); - lua.L_setfuncs(L, bbb, 0); - lua.setglobal(L, "Editor"); + lua.L_setfuncs(state.L, bbb, 0); + lua.setglobal(state.L, "Editor"); - lua.newtable(L); + lua.newtable(state.L); { - lua.pushinteger(L, lua.Integer(ui.Axis.Horizontal)); - lua.setfield(L, -2, "Horizontal"); - lua.pushinteger(L, lua.Integer(ui.Axis.Vertical)); - lua.setfield(L, -2, "Vertical"); - push_lua_semantic_size_table(L, { ui.SemanticSizeKind.Fill, 0 }); - lua.setfield(L, -2, "Fill"); - push_lua_semantic_size_table(L, { ui.SemanticSizeKind.ChildrenSum, 0 }); - lua.setfield(L, -2, "ChildrenSum"); - push_lua_semantic_size_table(L, { ui.SemanticSizeKind.FitText, 0 }); - lua.setfield(L, -2, "FitText"); + lua.pushinteger(state.L, lua.Integer(ui.Axis.Horizontal)); + lua.setfield(state.L, -2, "Horizontal"); + lua.pushinteger(state.L, lua.Integer(ui.Axis.Vertical)); + lua.setfield(state.L, -2, "Vertical"); + push_lua_semantic_size_table(state.L, { ui.SemanticSizeKind.Fill, 0 }); + lua.setfield(state.L, -2, "Fill"); + push_lua_semantic_size_table(state.L, { ui.SemanticSizeKind.ChildrenSum, 0 }); + lua.setfield(state.L, -2, "ChildrenSum"); + push_lua_semantic_size_table(state.L, { ui.SemanticSizeKind.FitText, 0 }); + lua.setfield(state.L, -2, "FitText"); - lua.L_setfuncs(L, raw_data(&ui_lib), 0); - lua.setglobal(L, "UI"); + lua.L_setfuncs(state.L, raw_data(&ui_lib), 0); + lua.setglobal(state.L, "UI"); } - if lua.L_dofile(L, "plugins/lua/view.lua") == i32(lua.OK) { - lua.pop(L, lua.gettop(L)); + if lua.L_dofile(state.L, "plugins/lua/view.lua") == i32(lua.OK) { + lua.pop(state.L, lua.gettop(state.L)); } else { - err := lua.tostring(L, lua.gettop(L)); - lua.pop(L, lua.gettop(L)); + err := lua.tostring(state.L, lua.gettop(state.L)); + lua.pop(state.L, lua.gettop(state.L)); log.error(err); } // Initialize Lua Plugins { - lua.getglobal(L, "OnInit"); - if lua.pcall(L, 0, 0, 0) == i32(lua.OK) { - lua.pop(L, lua.gettop(L)); + lua.getglobal(state.L, "OnInit"); + if lua.pcall(state.L, 0, 0, 0) == i32(lua.OK) { + lua.pop(state.L, lua.gettop(state.L)); } else { - err := lua.tostring(L, lua.gettop(L)); - lua.pop(L, lua.gettop(L)); + err := lua.tostring(state.L, lua.gettop(state.L)); + lua.pop(state.L, lua.gettop(state.L)); log.error("failed to initialize plugin (OnInit):", err); } @@ -1989,16 +2014,18 @@ main :: proc() { // } - for hook_ref in state.lua_hooks[plugin.Hook.Draw] { - lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref)); - lua.pushlightuserdata(state.L, &ui_context); - if lua.pcall(state.L, 1, 0, 0) != i32(lua.OK) { - err := lua.tostring(L, lua.gettop(L)); - lua.pop(L, lua.gettop(L)); + if draw_hooks, ok := state.lua_hooks[plugin.Hook.Draw]; ok { + for hook_ref in draw_hooks { + lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref)); + lua.pushlightuserdata(state.L, &ui_context); + if lua.pcall(state.L, 1, 0, 0) != i32(lua.OK) { + err := lua.tostring(state.L, lua.gettop(state.L)); + lua.pop(state.L, lua.gettop(state.L)); - log.error(err); - } else { - lua.pop(L, lua.gettop(L)); + log.error(err); + } else { + lua.pop(state.L, lua.gettop(state.L)); + } } } @@ -2053,12 +2080,12 @@ main :: proc() { case core.LuaEditorAction: lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref)); if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { - err := lua.tostring(L, lua.gettop(L)); - lua.pop(L, lua.gettop(L)); + err := lua.tostring(state.L, lua.gettop(state.L)); + lua.pop(state.L, lua.gettop(state.L)); log.error(err); } else { - lua.pop(L, lua.gettop(L)); + lua.pop(state.L, lua.gettop(state.L)); } if value.maybe_input_map.ctrl_key_actions != nil { @@ -2078,12 +2105,12 @@ main :: proc() { case core.LuaEditorAction: lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref)); if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { - err := lua.tostring(L, lua.gettop(L)); - lua.pop(L, lua.gettop(L)); + err := lua.tostring(state.L, lua.gettop(state.L)); + lua.pop(state.L, lua.gettop(state.L)); log.error(err); } else { - lua.pop(L, lua.gettop(L)); + lua.pop(state.L, lua.gettop(state.L)); } if value.maybe_input_map.key_actions != nil { @@ -2138,12 +2165,12 @@ main :: proc() { for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] { lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref)); if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { - err := lua.tostring(L, lua.gettop(L)); - lua.pop(L, lua.gettop(L)); + err := lua.tostring(state.L, lua.gettop(state.L)); + lua.pop(state.L, lua.gettop(state.L)); log.error(err); } else { - lua.pop(L, lua.gettop(L)); + lua.pop(state.L, lua.gettop(state.L)); } } } @@ -2168,12 +2195,12 @@ main :: proc() { for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] { lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref)); if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { - err := lua.tostring(L, lua.gettop(L)); - lua.pop(L, lua.gettop(L)); + err := lua.tostring(state.L, lua.gettop(state.L)); + lua.pop(state.L, lua.gettop(state.L)); log.error(err); } else { - lua.pop(L, lua.gettop(L)); + lua.pop(state.L, lua.gettop(state.L)); } } } @@ -2227,7 +2254,7 @@ main :: proc() { plugin.on_exit(); } } - lua.close(L); + lua.close(state.L); sdl2.Quit(); } diff --git a/src/plugin/plugin.odin b/src/plugin/plugin.odin index a9e9ef5..d3e3efa 100644 --- a/src/plugin/plugin.odin +++ b/src/plugin/plugin.odin @@ -1,6 +1,6 @@ package plugin; -import "core:intrinsics" +import "base:intrinsics" import "core:dynlib" import "core:fmt" import "core:log"