start re-writing the plugin system
parent
402205a2e3
commit
b52a2c38fe
|
@ -0,0 +1,38 @@
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
M.version = "0.1"
|
||||||
|
M.name = "Default_View"
|
||||||
|
M.namespace = "nl_spacegirl_plugin_Default"
|
||||||
|
|
||||||
|
function M.open_file_search_window()
|
||||||
|
local input = {
|
||||||
|
{Editor.Key.Enter, "Open File", function() Editor.log("this should open a file") end}
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.spawn_floating_window(input, function(ctx)
|
||||||
|
UI.label(ctx, "eventually this will be a window where you can search through a bunch of files 1")
|
||||||
|
UI.label(ctx, "eventually this will be a window where you can search through a bunch of files 2")
|
||||||
|
UI.label(ctx, "eventually this will be a window where you can search through a bunch of files 3")
|
||||||
|
UI.label(ctx, "eventually this will be a window where you can search through a bunch of files 4")
|
||||||
|
UI.label(ctx, "eventually this will be a window where you can search through a bunch of files 5")
|
||||||
|
UI.label(ctx, "eventually this will be a window where you can search through a bunch of files 6")
|
||||||
|
UI.label(ctx, "eventually this will be a window where you can search through a bunch of files 7")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.OnLoad()
|
||||||
|
Editor.log("default view loaded")
|
||||||
|
Editor.log(nl_spacegirl_plugin_Default_Legacy_View['namespace'])
|
||||||
|
|
||||||
|
Editor.register_key_group({
|
||||||
|
{Editor.Key.Space, "", {
|
||||||
|
{Editor.Key.F, "Open File", M.open_file_search_window}
|
||||||
|
}}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.view_render(cx)
|
||||||
|
UI.label(cx, "Look its a me, a plugin")
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
|
@ -1,3 +1,9 @@
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
M.version = "0.1"
|
||||||
|
M.name = "Legacy_View"
|
||||||
|
M.namespace = "nl_spacegirl_plugin_Default"
|
||||||
|
|
||||||
local BufferSearchOpen = false
|
local BufferSearchOpen = false
|
||||||
local BufferSearchOpenElapsed = 0
|
local BufferSearchOpenElapsed = 0
|
||||||
|
|
||||||
|
@ -235,7 +241,7 @@ function ui_code_view(ctx, code_view_index)
|
||||||
return code_view_interaction
|
return code_view_interaction
|
||||||
end
|
end
|
||||||
|
|
||||||
function render_ui_window(ctx)
|
function M.render_ui_window(ctx)
|
||||||
current_buffer_index = Editor.get_current_buffer_index()
|
current_buffer_index = Editor.get_current_buffer_index()
|
||||||
x,y = UI.get_mouse_pos(ctx)
|
x,y = UI.get_mouse_pos(ctx)
|
||||||
delta_x = LastMouseX - x
|
delta_x = LastMouseX - x
|
||||||
|
@ -307,7 +313,7 @@ function render_ui_window(ctx)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
render_buffer_search(ctx)
|
-- render_buffer_search(ctx)
|
||||||
render_command_search(ctx)
|
render_command_search(ctx)
|
||||||
render_log_window(ctx)
|
render_log_window(ctx)
|
||||||
|
|
||||||
|
@ -315,24 +321,47 @@ function render_ui_window(ctx)
|
||||||
LastMouseY = y
|
LastMouseY = y
|
||||||
end
|
end
|
||||||
|
|
||||||
function render_buffer_search(ctx)
|
function M.open_buffer_search_window(ctx)
|
||||||
if BufferSearchOpen or BufferSearchOpenElapsed > 0 then
|
-- if BufferSearchOpen or BufferSearchOpenElapsed > 0 then
|
||||||
if BufferSearchOpen and BufferSearchOpenElapsed < numFrames then
|
-- if BufferSearchOpen and BufferSearchOpenElapsed < numFrames then
|
||||||
BufferSearchOpenElapsed = BufferSearchOpenElapsed + 1
|
-- BufferSearchOpenElapsed = BufferSearchOpenElapsed + 1
|
||||||
elseif not BufferSearchOpen and BufferSearchOpenElapsed > 0 then
|
-- elseif not BufferSearchOpen and BufferSearchOpenElapsed > 0 then
|
||||||
BufferSearchOpenElapsed = BufferSearchOpenElapsed - 1
|
-- BufferSearchOpenElapsed = BufferSearchOpenElapsed - 1
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
|
|
||||||
if BufferSearchOpen or BufferSearchOpenElapsed > 0 then
|
-- if BufferSearchOpen or BufferSearchOpenElapsed > 0 then
|
||||||
window_percent = 75
|
-- window_percent = 75
|
||||||
if BufferSearchOpenElapsed > 0 then
|
-- if BufferSearchOpenElapsed > 0 then
|
||||||
window_percent = ((BufferSearchOpenElapsed/numFrames) * 75)
|
-- window_percent = ((BufferSearchOpenElapsed/numFrames) * 75)
|
||||||
end
|
-- end
|
||||||
|
|
||||||
UI.push_parent(ctx, UI.push_floating(ctx, "buffer search canvas", 0, 0))
|
local input = {
|
||||||
centered(ctx, "buffer search window", UI.Horizontal, UI.PercentOfParent(window_percent), UI.PercentOfParent(window_percent), (
|
{Editor.Key.Escape, "Close Window", (
|
||||||
function ()
|
function ()
|
||||||
|
Editor.request_window_close()
|
||||||
|
BufferSearchOpen = false
|
||||||
|
end
|
||||||
|
)},
|
||||||
|
{Editor.Key.Enter, "Switch to Buffer", (
|
||||||
|
function ()
|
||||||
|
buffer_info = Editor.buffer_info_from_index(BufferSearchIndex)
|
||||||
|
add_buffer_to_code_view(ActiveCodeView, buffer_info.file_path, BufferSearchIndex)
|
||||||
|
|
||||||
|
Editor.set_current_buffer_from_index(BufferSearchIndex)
|
||||||
|
Editor.request_window_close()
|
||||||
|
BufferSearchOpen = false
|
||||||
|
end
|
||||||
|
)},
|
||||||
|
-- TODO: don't scroll past buffers
|
||||||
|
{Editor.Key.K, "Move Selection Up", (function () BufferSearchIndex = BufferSearchIndex - 1 end)},
|
||||||
|
{Editor.Key.J, "Move Selection Down", (function () BufferSearchIndex = BufferSearchIndex + 1 end)},
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.spawn_floating_window(input, function(ctx)
|
||||||
|
-- UI.push_parent(ctx, UI.push_floating(ctx, "buffer search canvas", 0, 0))
|
||||||
|
-- centered(ctx, "buffer search window", UI.Horizontal, UI.PercentOfParent(window_percent), UI.PercentOfParent(window_percent), (
|
||||||
|
-- function ()
|
||||||
list_with_iter(ctx, "buffer list", BufferSearchIndex, buffer_list_iter(BufferSearchIndex),
|
list_with_iter(ctx, "buffer list", BufferSearchIndex, buffer_list_iter(BufferSearchIndex),
|
||||||
function(ctx, buffer_info, is_selected)
|
function(ctx, buffer_info, is_selected)
|
||||||
flags = {"DrawText"}
|
flags = {"DrawText"}
|
||||||
|
@ -359,10 +388,11 @@ function render_buffer_search(ctx)
|
||||||
-- UI.pop_parent(ctx)
|
-- UI.pop_parent(ctx)
|
||||||
-- UI.buffer(ctx, BufferSearchIndex)
|
-- UI.buffer(ctx, BufferSearchIndex)
|
||||||
-- UI.pop_parent(ctx)
|
-- UI.pop_parent(ctx)
|
||||||
end
|
-- end
|
||||||
))
|
-- ))
|
||||||
UI.pop_parent(ctx)
|
-- UI.pop_parent(ctx)
|
||||||
end
|
end)
|
||||||
|
-- end
|
||||||
end
|
end
|
||||||
|
|
||||||
function render_command_search(ctx)
|
function render_command_search(ctx)
|
||||||
|
@ -437,8 +467,9 @@ end
|
||||||
function handle_buffer_input()
|
function handle_buffer_input()
|
||||||
end
|
end
|
||||||
|
|
||||||
function OnInit()
|
function M.OnLoad()
|
||||||
Editor.log("Main View plugin initialized")
|
Editor.log("Legacy View plugin loaded")
|
||||||
|
|
||||||
Editor.register_key_group({
|
Editor.register_key_group({
|
||||||
{Editor.Key.Backtick, "Open Editor Logs", (function ()
|
{Editor.Key.Backtick, "Open Editor Logs", (function ()
|
||||||
if not LogWindowOpen then
|
if not LogWindowOpen then
|
||||||
|
@ -481,36 +512,12 @@ function OnInit()
|
||||||
{Editor.Key.J, "Move Selection Down", (function () CommandSearchIndex = CommandSearchIndex + 1 end)},
|
{Editor.Key.J, "Move Selection Down", (function () CommandSearchIndex = CommandSearchIndex + 1 end)},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{Editor.Key.B, "Buffer Search", (
|
{Editor.Key.B, "Buffer Search", M.open_buffer_search_window}
|
||||||
function ()
|
|
||||||
BufferSearchOpen = true
|
|
||||||
BufferSearchIndex = 0
|
|
||||||
end
|
|
||||||
),
|
|
||||||
{
|
|
||||||
{Editor.Key.Escape, "Close Window", (
|
|
||||||
function ()
|
|
||||||
Editor.request_window_close()
|
|
||||||
BufferSearchOpen = false
|
|
||||||
end
|
|
||||||
)},
|
|
||||||
{Editor.Key.Enter, "Switch to Buffer", (
|
|
||||||
function ()
|
|
||||||
buffer_info = Editor.buffer_info_from_index(BufferSearchIndex)
|
|
||||||
add_buffer_to_code_view(ActiveCodeView, buffer_info.file_path, BufferSearchIndex)
|
|
||||||
|
|
||||||
Editor.set_current_buffer_from_index(BufferSearchIndex)
|
|
||||||
Editor.request_window_close()
|
|
||||||
BufferSearchOpen = false
|
|
||||||
end
|
|
||||||
)},
|
|
||||||
-- TODO: don't scroll past buffers
|
|
||||||
{Editor.Key.K, "Move Selection Up", (function () BufferSearchIndex = BufferSearchIndex - 1 end)},
|
|
||||||
{Editor.Key.J, "Move Selection Down", (function () BufferSearchIndex = BufferSearchIndex + 1 end)},
|
|
||||||
}}
|
|
||||||
}}
|
}}
|
||||||
})
|
})
|
||||||
|
|
||||||
Editor.register_hook(Editor.Hook.OnDraw, render_ui_window)
|
Editor.register_hook(Editor.Hook.OnDraw, render_ui_window)
|
||||||
Editor.register_hook(Editor.Hook.OnBufferInput, handle_buffer_input)
|
Editor.register_hook(Editor.Hook.OnBufferInput, handle_buffer_input)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
|
|
|
@ -27,6 +27,10 @@ Window :: struct {
|
||||||
|
|
||||||
user_data: rawptr,
|
user_data: rawptr,
|
||||||
}
|
}
|
||||||
|
NewWindow :: struct {
|
||||||
|
input_map: InputActions,
|
||||||
|
lua_draw_proc: i32,
|
||||||
|
}
|
||||||
request_window_close :: proc(state: ^State) {
|
request_window_close :: proc(state: ^State) {
|
||||||
state.should_close_window = true;
|
state.should_close_window = true;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +47,11 @@ close_window_and_free :: proc(state: ^State) {
|
||||||
state.window = nil;
|
state.window = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if window, ok := &state.new_window.(NewWindow); ok {
|
||||||
|
delete_input_actions(&window.input_map);
|
||||||
|
state.new_window = nil
|
||||||
|
}
|
||||||
|
|
||||||
state.current_input_map = &state.input_map.mode[.Normal];
|
state.current_input_map = &state.input_map.mode[.Normal];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +82,7 @@ State :: struct {
|
||||||
log_buffer: FileBuffer,
|
log_buffer: FileBuffer,
|
||||||
|
|
||||||
window: ^Window,
|
window: ^Window,
|
||||||
|
new_window: Maybe(NewWindow),
|
||||||
should_close_window: bool,
|
should_close_window: bool,
|
||||||
|
|
||||||
input_map: InputMap,
|
input_map: InputMap,
|
||||||
|
@ -83,6 +93,7 @@ State :: struct {
|
||||||
command_args: [dynamic]EditorCommandArgument,
|
command_args: [dynamic]EditorCommandArgument,
|
||||||
|
|
||||||
plugins: [dynamic]plugin.Interface,
|
plugins: [dynamic]plugin.Interface,
|
||||||
|
new_plugins: [dynamic]plugin.NewInterface,
|
||||||
plugin_vtable: plugin.Plugin,
|
plugin_vtable: plugin.Plugin,
|
||||||
highlighters: map[string]plugin.OnColorBufferProc,
|
highlighters: map[string]plugin.OnColorBufferProc,
|
||||||
hooks: map[plugin.Hook][dynamic]plugin.OnHookProc,
|
hooks: map[plugin.Hook][dynamic]plugin.OnHookProc,
|
||||||
|
@ -281,7 +292,7 @@ query_editor_commands_by_name :: proc(command_list: ^EditorCommandList, name: st
|
||||||
for cmd in list {
|
for cmd in list {
|
||||||
if cmd.name == name {
|
if cmd.name == name {
|
||||||
append(&commands, cmd);
|
append(&commands, cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,7 +358,7 @@ where intrinsics.type_is_struct(T) {
|
||||||
ok = false
|
ok = false
|
||||||
log.error("invalid number of arguments", len(args), ", expected", v.field_count);
|
log.error("invalid number of arguments", len(args), ", expected", v.field_count);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for arg, i in args {
|
for arg, i in args {
|
||||||
switch varg in arg {
|
switch varg in arg {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import "core:runtime"
|
import "base:runtime"
|
||||||
|
|
||||||
import "core:reflect"
|
import "core:reflect"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
|
|
@ -0,0 +1,925 @@
|
||||||
|
package lua
|
||||||
|
|
||||||
|
import "core:os"
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:strings"
|
||||||
|
import "core:log"
|
||||||
|
import "core:path/filepath"
|
||||||
|
|
||||||
|
import core "../core"
|
||||||
|
import plugin "../plugin"
|
||||||
|
import ui "../ui"
|
||||||
|
|
||||||
|
import lua "vendor:lua/5.4"
|
||||||
|
|
||||||
|
state: ^core.State = nil
|
||||||
|
|
||||||
|
new_state :: proc(_state: ^core.State) {
|
||||||
|
state = _state
|
||||||
|
|
||||||
|
state.L = lua.L_newstate();
|
||||||
|
lua.L_openlibs(state.L);
|
||||||
|
|
||||||
|
bbb: [^]lua.L_Reg;
|
||||||
|
editor_lib := [?]lua.L_Reg {
|
||||||
|
lua.L_Reg {
|
||||||
|
"quit",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
|
||||||
|
state.should_close = true;
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"log",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
text := string(lua.L_checkstring(L, 1));
|
||||||
|
log.info("[LUA]:", text);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"register_hook",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
hook := lua.L_checkinteger(L, 1);
|
||||||
|
|
||||||
|
lua.L_checktype(L, 2, i32(lua.TFUNCTION));
|
||||||
|
lua.pushvalue(L, 2);
|
||||||
|
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
||||||
|
|
||||||
|
core.add_lua_hook(state, plugin.Hook(hook), fn_ref);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"register_key_group",
|
||||||
|
register_key_group,
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"spawn_floating_window",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
core.close_window_and_free(state);
|
||||||
|
|
||||||
|
window_input_map := core.new_input_actions();
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TTABLE));
|
||||||
|
table_to_action(L, 1, &window_input_map);
|
||||||
|
|
||||||
|
lua.L_checktype(L, 2, i32(lua.TFUNCTION));
|
||||||
|
lua.pushvalue(L, 2);
|
||||||
|
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
||||||
|
|
||||||
|
state.new_window = core.NewWindow {
|
||||||
|
input_map = window_input_map,
|
||||||
|
lua_draw_proc = fn_ref
|
||||||
|
}
|
||||||
|
state.current_input_map = &(&state.new_window.?).input_map
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"request_window_close",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
core.request_window_close(state);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"get_current_buffer_index",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(state.current_buffer));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"set_current_buffer_from_index",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
buffer_index := int(lua.L_checkinteger(L, 1));
|
||||||
|
if buffer_index != -2 && (buffer_index < 0 || buffer_index >= len(state.buffers)) {
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
} else {
|
||||||
|
state.current_buffer = buffer_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"buffer_info_from_index",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
buffer_index := int(lua.L_checkinteger(L, 1));
|
||||||
|
if buffer_index < 0 || buffer_index >= len(state.buffers) {
|
||||||
|
lua.pushnil(L);
|
||||||
|
} else {
|
||||||
|
push_lua_buffer_info :: proc(L: ^lua.State, buffer: ^core.FileBuffer) {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushlightuserdata(L, buffer);
|
||||||
|
lua.setfield(L, -2, "buffer");
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(buffer.cursor.col));
|
||||||
|
lua.setfield(L, -2, "col");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(buffer.cursor.line));
|
||||||
|
lua.setfield(L, -2, "line");
|
||||||
|
}
|
||||||
|
lua.setfield(L, -2, "cursor");
|
||||||
|
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(buffer.file_path, context.temp_allocator));
|
||||||
|
lua.setfield(L, -2, "full_file_path");
|
||||||
|
|
||||||
|
relative_file_path, _ := filepath.rel(state.directory, buffer.file_path, context.temp_allocator)
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(relative_file_path, context.temp_allocator));
|
||||||
|
lua.setfield(L, -2, "file_path");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_lua_buffer_info(L, core.buffer_from_index(state, buffer_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"query_command_group",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
group := lua.L_checkstring(L, 1);
|
||||||
|
cmds := core.query_editor_commands_by_group(&state.commands, string(group), context.temp_allocator);
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
for cmd, i in cmds {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(cmd.name, context.temp_allocator));
|
||||||
|
lua.setfield(L, -2, "name");
|
||||||
|
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(cmd.description, context.temp_allocator));
|
||||||
|
lua.setfield(L, -2, "description");
|
||||||
|
}
|
||||||
|
lua.rawseti(L, -2, lua.Integer(i+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"run_command",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
group := lua.L_checkstring(L, 1);
|
||||||
|
name := lua.L_checkstring(L, 2);
|
||||||
|
core.run_command(state, string(group), string(name));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bbb = raw_data(editor_lib[:]);
|
||||||
|
|
||||||
|
get_lua_semantic_size :: proc(L: ^lua.State, index: i32) -> ui.SemanticSize {
|
||||||
|
if lua.istable(L, index) {
|
||||||
|
lua.rawgeti(L, index, 1);
|
||||||
|
semantic_kind := ui.SemanticSizeKind(lua.tointeger(L, -1));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
lua.rawgeti(L, index, 2);
|
||||||
|
semantic_value := int(lua.tointeger(L, -1));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
return {semantic_kind, semantic_value};
|
||||||
|
} else {
|
||||||
|
semantic_kind := ui.SemanticSizeKind(lua.L_checkinteger(L, index));
|
||||||
|
return {semantic_kind, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_lua_semantic_size_table :: proc(L: ^lua.State, size: ui.SemanticSize) {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(i32(size.kind)));
|
||||||
|
lua.rawseti(L, -2, 1);
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(size.value));
|
||||||
|
lua.rawseti(L, -2, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_lua_box_interaction :: proc(L: ^lua.State, interaction: ui.Interaction) {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushboolean(L, b32(interaction.clicked));
|
||||||
|
lua.setfield(L, -2, "clicked");
|
||||||
|
|
||||||
|
lua.pushboolean(L, b32(interaction.hovering));
|
||||||
|
lua.setfield(L, -2, "hovering");
|
||||||
|
|
||||||
|
lua.pushboolean(L, b32(interaction.dragging));
|
||||||
|
lua.setfield(L, -2, "dragging");
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_pos.x));
|
||||||
|
lua.setfield(L, -2, "x");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_pos.y));
|
||||||
|
lua.setfield(L, -2, "y");
|
||||||
|
}
|
||||||
|
lua.setfield(L, -2, "box_pos");
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_size.x));
|
||||||
|
lua.setfield(L, -2, "x");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_size.y));
|
||||||
|
lua.setfield(L, -2, "y");
|
||||||
|
}
|
||||||
|
lua.setfield(L, -2, "box_size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_lib := [?]lua.L_Reg {
|
||||||
|
lua.L_Reg {
|
||||||
|
"get_mouse_pos",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_x));
|
||||||
|
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_y));
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"Exact",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
value := lua.L_checknumber(L, 1);
|
||||||
|
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.Exact, int(value) });
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"PercentOfParent",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
value := lua.L_checknumber(L, 1);
|
||||||
|
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.PercentOfParent, int(value) });
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_parent",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
lua.L_checktype(L, 2, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 2);
|
||||||
|
box := transmute(^ui.Box)lua.touserdata(L, -1);
|
||||||
|
if box == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
ui.push_parent(ui_ctx, box);
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"pop_parent",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
ui.pop_parent(ui_ctx);
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_floating",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
x := int(lua.L_checkinteger(L, 3));
|
||||||
|
y := int(lua.L_checkinteger(L, 4));
|
||||||
|
|
||||||
|
box, interaction := ui.push_floating(ui_ctx, strings.clone(string(label), context.temp_allocator), {x,y});
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_box",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
flags, err := ui_flags(L, 3);
|
||||||
|
axis := ui.Axis(lua.L_checkinteger(L, 4));
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 5);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 6);
|
||||||
|
|
||||||
|
box, interaction := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
||||||
|
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"_box_interaction",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
lua.L_checktype(L, 2, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 2);
|
||||||
|
box := transmute(^ui.Box)lua.touserdata(L, -1);
|
||||||
|
if box == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
interaction := ui.test_box(ui_ctx, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_box",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
flags, err := ui_flags(L, 3);
|
||||||
|
axis := ui.Axis(lua.L_checkinteger(L, 4));
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 5);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 6);
|
||||||
|
|
||||||
|
box, interaction := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_rect",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
background := bool(lua.toboolean(L, 3));
|
||||||
|
border := bool(lua.toboolean(L, 4));
|
||||||
|
axis := ui.Axis(lua.L_checkinteger(L, 5));
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 6);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 7);
|
||||||
|
|
||||||
|
box, interaction := ui.push_rect(ui_ctx, strings.clone(string(label), context.temp_allocator), background, border, axis, { semantic_width, semantic_height });
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"spacer",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
|
interaction := ui.spacer(ui_ctx, strings.clone(string(label), context.temp_allocator), semantic_size = {{.Fill, 0}, {.Fill, 0}});
|
||||||
|
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"label",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
|
interaction := ui.label(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"button",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
|
interaction := ui.button(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"advanced_button",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
flags, err := ui_flags(L, 3);
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 4);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 5);
|
||||||
|
|
||||||
|
interaction := ui.advanced_button(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, { semantic_width, semantic_height });
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"buffer",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
|
||||||
|
if ui_ctx != nil {
|
||||||
|
buffer_index := int(lua.L_checkinteger(L, 2));
|
||||||
|
|
||||||
|
if buffer_index != -2 && (buffer_index < 0 || buffer_index >= len(state.buffers)) {
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_file_buffer(ui_ctx, core.buffer_from_index(state, buffer_index));
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"log_buffer",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
|
||||||
|
if ui_ctx != nil {
|
||||||
|
ui_file_buffer(ui_ctx, &state.log_buffer);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: generate this from the plugin.Key enum
|
||||||
|
lua.newtable(state.L);
|
||||||
|
{
|
||||||
|
lua.newtable(state.L);
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.B));
|
||||||
|
lua.setfield(state.L, -2, "B");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.F));
|
||||||
|
lua.setfield(state.L, -2, "F");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.T));
|
||||||
|
lua.setfield(state.L, -2, "T");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.Y));
|
||||||
|
lua.setfield(state.L, -2, "Y");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.P));
|
||||||
|
lua.setfield(state.L, -2, "P");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.M));
|
||||||
|
lua.setfield(state.L, -2, "M");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.K));
|
||||||
|
lua.setfield(state.L, -2, "K");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.J));
|
||||||
|
lua.setfield(state.L, -2, "J");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.Q));
|
||||||
|
lua.setfield(state.L, -2, "Q");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.BACKQUOTE));
|
||||||
|
lua.setfield(state.L, -2, "Backtick");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.ESCAPE));
|
||||||
|
lua.setfield(state.L, -2, "Escape");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.ENTER));
|
||||||
|
lua.setfield(state.L, -2, "Enter");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(plugin.Key.SPACE));
|
||||||
|
lua.setfield(state.L, -2, "Space");
|
||||||
|
}
|
||||||
|
lua.setfield(state.L, -2, "Key");
|
||||||
|
|
||||||
|
{
|
||||||
|
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(state.L, -2, "Hook");
|
||||||
|
|
||||||
|
lua.L_setfuncs(state.L, bbb, 0);
|
||||||
|
lua.setglobal(state.L, "Editor");
|
||||||
|
|
||||||
|
lua.newtable(state.L);
|
||||||
|
{
|
||||||
|
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(state.L, raw_data(&ui_lib), 0);
|
||||||
|
lua.setglobal(state.L, "UI");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close :: proc(L: ^lua.State) {
|
||||||
|
lua.close(L)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
register_key_group ::proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TTABLE));
|
||||||
|
table_to_action(L, 1, state.current_input_map);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
table_to_action :: proc(L: ^lua.State, index: i32, input_map: ^core.InputActions) {
|
||||||
|
lua.len(L, index);
|
||||||
|
key_group_len := lua.tointeger(L, -1);
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
for i in 1..=key_group_len {
|
||||||
|
lua.rawgeti(L, index, i);
|
||||||
|
defer lua.pop(L, 1);
|
||||||
|
|
||||||
|
lua.rawgeti(L, -1, 1);
|
||||||
|
key:= plugin.Key(lua.tointeger(L, -1));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
lua.rawgeti(L, -1, 2);
|
||||||
|
desc := strings.clone(string(lua.tostring(L, -1)));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
switch lua.rawgeti(L, -1, 3) {
|
||||||
|
case i32(lua.TTABLE):
|
||||||
|
if action, exists := input_map.key_actions[key]; exists {
|
||||||
|
switch value in action.action {
|
||||||
|
case core.LuaEditorAction:
|
||||||
|
log.warn("Plugin attempted to register input group on existing key action (added from Lua)");
|
||||||
|
case core.PluginEditorAction:
|
||||||
|
log.warn("Plugin attempted to register input group on existing key action (added from Plugin)");
|
||||||
|
case core.EditorAction:
|
||||||
|
log.warn("Plugin attempted to register input group on existing key action");
|
||||||
|
case core.InputActions:
|
||||||
|
input_map := &(&input_map.key_actions[key]).action.(core.InputActions);
|
||||||
|
table_to_action(L, lua.gettop(L), input_map);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
core.register_key_action(input_map, key, core.new_input_actions(), desc);
|
||||||
|
table_to_action(L, lua.gettop(L), &((&input_map.key_actions[key]).action.(core.InputActions)));
|
||||||
|
}
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
case i32(lua.TFUNCTION):
|
||||||
|
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
||||||
|
|
||||||
|
if lua.rawgeti(L, -1, 4) == i32(lua.TTABLE) {
|
||||||
|
maybe_input_map := core.new_input_actions();
|
||||||
|
table_to_action(L, lua.gettop(L), &maybe_input_map);
|
||||||
|
|
||||||
|
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, maybe_input_map }, desc);
|
||||||
|
} else {
|
||||||
|
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, core.InputActions {} }, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
case:
|
||||||
|
lua.pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load_plugins :: proc(state: ^core.State, dir: string) {
|
||||||
|
filepath.walk(filepath.join({ os.get_current_directory(), dir }), walk_plugins, transmute(rawptr)state);
|
||||||
|
log.info("done walking")
|
||||||
|
|
||||||
|
for plugin in state.new_plugins {
|
||||||
|
// FIXME: check if the global actually exists
|
||||||
|
lua.getglobal(state.L, fmt.ctprintf("%s_%s", plugin.namespace, plugin.name));
|
||||||
|
|
||||||
|
lua.getfield(state.L, -1, "OnLoad");
|
||||||
|
if (lua.isnil(state.L, -1)) {
|
||||||
|
lua.pop(state.L, 2)
|
||||||
|
log.warn("plugin", plugin.name, "doesn't have an 'OnLoad' function")
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if lua.pcall(state.L, 0, 0, 0) == i32(lua.OK) {
|
||||||
|
lua.pop(state.L, lua.gettop(state.L));
|
||||||
|
} else {
|
||||||
|
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||||
|
lua.pop(state.L, lua.gettop(state.L));
|
||||||
|
lua.pop(state.L, 1);
|
||||||
|
|
||||||
|
log.error("failed to initialize plugin (OnLoad):", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_plugins :: proc(info: os.File_Info, in_err: os.Errno, state: rawptr) -> (err: os.Errno, skip_dir: bool) {
|
||||||
|
state := cast(^core.State)state;
|
||||||
|
|
||||||
|
relative_file_path, rel_error := filepath.rel(state.directory, info.fullpath);
|
||||||
|
extension := filepath.ext(info.fullpath);
|
||||||
|
|
||||||
|
if extension == ".lua" {
|
||||||
|
log.info("attempting to load", relative_file_path)
|
||||||
|
|
||||||
|
if plugin, ok := load_plugin(state, info.fullpath); ok {
|
||||||
|
append(&state.new_plugins, plugin);
|
||||||
|
|
||||||
|
if rel_error == .None {
|
||||||
|
log.info("Loaded", relative_file_path);
|
||||||
|
} else {
|
||||||
|
log.info("Loaded", info.fullpath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("failed to load")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_err, skip_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_plugin :: proc(state: ^core.State, path: string) -> (lua_plugin: plugin.NewInterface, ok: bool) {
|
||||||
|
if lua.L_dofile(state.L, strings.clone_to_cstring(path, allocator = context.temp_allocator)) != i32(lua.OK) {
|
||||||
|
err := lua.tostring(state.L, lua.gettop(state.L))
|
||||||
|
lua.pop(state.L, lua.gettop(state.L))
|
||||||
|
|
||||||
|
log.error("failed to load lua plugin:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lua.getfield(state.L, -1, "name");
|
||||||
|
if (lua.isnil(state.L, -1)) {
|
||||||
|
lua.pop(state.L, 2)
|
||||||
|
|
||||||
|
log.error("no name for lua plugin")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name := strings.clone(string(lua.tostring(state.L, -1)))
|
||||||
|
lua.pop(state.L, 1)
|
||||||
|
|
||||||
|
lua.getfield(state.L, -1, "version");
|
||||||
|
if (lua.isnil(state.L, -1)) {
|
||||||
|
lua.pop(state.L, 2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
version := strings.clone(string(lua.tostring(state.L, -1)))
|
||||||
|
lua.pop(state.L, 1)
|
||||||
|
|
||||||
|
lua.getfield(state.L, -1, "namespace");
|
||||||
|
if (lua.isnil(state.L, -1)) {
|
||||||
|
lua.pop(state.L, 2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
namespace := strings.clone(string(lua.tostring(state.L, -1)))
|
||||||
|
lua.pop(state.L, 1)
|
||||||
|
|
||||||
|
// Add plugin to lua globals
|
||||||
|
lua.setglobal(state.L, fmt.caprintf("%s_%s", namespace, name))
|
||||||
|
|
||||||
|
return plugin.NewInterface {
|
||||||
|
name = name,
|
||||||
|
version = version,
|
||||||
|
namespace = namespace,
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_flags :: proc(L: ^lua.State, index: i32) -> (bit_set[ui.Flag], bool) {
|
||||||
|
lua.L_checktype(L, index, i32(lua.TTABLE));
|
||||||
|
lua.len(L, index);
|
||||||
|
array_len := lua.tointeger(L, -1);
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
flags: bit_set[ui.Flag]
|
||||||
|
|
||||||
|
for i in 1..=array_len {
|
||||||
|
lua.rawgeti(L, index, i);
|
||||||
|
defer lua.pop(L, 1);
|
||||||
|
|
||||||
|
flag := lua.tostring(L, -1);
|
||||||
|
switch flag {
|
||||||
|
case "Clickable": flags |= {.Clickable}
|
||||||
|
case "Hoverable": flags |= {.Hoverable}
|
||||||
|
case "Scrollable": flags |= {.Scrollable}
|
||||||
|
case "DrawText": flags |= {.DrawText}
|
||||||
|
case "DrawBorder": flags |= {.DrawBorder}
|
||||||
|
case "DrawBackground": flags |= {.DrawBackground}
|
||||||
|
case "RoundedBorder": flags |= {.RoundedBorder}
|
||||||
|
case "Floating": flags |= {.Floating}
|
||||||
|
case "CustomDrawFunc": flags |= {.CustomDrawFunc}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags, true
|
||||||
|
}
|
||||||
|
|
||||||
|
run_editor_action :: proc(state: ^core.State, key: plugin.Key, action: core.LuaEditorAction) {
|
||||||
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(action.fn_ref));
|
||||||
|
if lua.pcall(state.L, 0, 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(state.L, lua.gettop(state.L));
|
||||||
|
}
|
||||||
|
|
||||||
|
if action.maybe_input_map.key_actions != nil {
|
||||||
|
ptr_action := &(&state.current_input_map.key_actions[key]).action.(core.LuaEditorAction)
|
||||||
|
state.current_input_map = (&ptr_action.maybe_input_map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run_ui_function :: proc(state: ^core.State, ui_context: ^ui.Context, fn_ref: i32) {
|
||||||
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(fn_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(state.L, lua.gettop(state.L));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: don't duplicate this procedure
|
||||||
|
ui_file_buffer :: proc(ctx: ^ui.Context, buffer: ^core.FileBuffer) -> ui.Interaction {
|
||||||
|
draw_func := proc(state: ^core.State, box: ^ui.Box, user_data: rawptr) {
|
||||||
|
buffer := transmute(^core.FileBuffer)user_data;
|
||||||
|
buffer.glyph_buffer_width = box.computed_size.x / state.source_font_width;
|
||||||
|
buffer.glyph_buffer_height = box.computed_size.y / state.source_font_height + 1;
|
||||||
|
|
||||||
|
core.draw_file_buffer(state, buffer, box.computed_pos.x, box.computed_pos.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
relative_file_path, _ := filepath.rel(state.directory, buffer.file_path, context.temp_allocator)
|
||||||
|
|
||||||
|
buffer_container, _ := ui.push_box(ctx, relative_file_path, {}, .Vertical, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Fill)});
|
||||||
|
ui.push_parent(ctx, buffer_container);
|
||||||
|
defer ui.pop_parent(ctx);
|
||||||
|
|
||||||
|
interaction := ui.custom(ctx, "buffer1", draw_func, transmute(rawptr)buffer);
|
||||||
|
|
||||||
|
{
|
||||||
|
info_box, _ := ui.push_box(ctx, "buffer info", {}, semantic_size = {ui.make_semantic_size(.Fill), ui.make_semantic_size(.Exact, state.source_font_height)});
|
||||||
|
ui.push_parent(ctx, info_box);
|
||||||
|
defer ui.pop_parent(ctx);
|
||||||
|
|
||||||
|
ui.label(ctx, fmt.tprintf("%s", state.mode))
|
||||||
|
if selection, exists := buffer.selection.?; exists {
|
||||||
|
ui.label(ctx, fmt.tprintf("sel: %d:%d", selection.end.line, selection.end.col));
|
||||||
|
}
|
||||||
|
ui.spacer(ctx, "spacer");
|
||||||
|
ui.label(ctx, relative_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interaction;
|
||||||
|
}
|
|
@ -0,0 +1,693 @@
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
|
import core "../core"
|
||||||
|
import ui "../ui"
|
||||||
|
|
||||||
|
import lua "vendor:lua/5.4"
|
||||||
|
|
||||||
|
state: ^core.State = nil
|
||||||
|
|
||||||
|
new_lua_state :: proc() -> ^lua.State {
|
||||||
|
L := lua.L_newstate();
|
||||||
|
lua.L_openlibs(L);
|
||||||
|
|
||||||
|
bbb: [^]lua.L_Reg;
|
||||||
|
editor_lib := [?]lua.L_Reg {
|
||||||
|
lua.L_Reg {
|
||||||
|
"quit",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
|
||||||
|
state.should_close = true;
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"log",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
text := string(lua.L_checkstring(L, 1));
|
||||||
|
log.info("[LUA]:", text);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"register_hook",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
hook := lua.L_checkinteger(L, 1);
|
||||||
|
|
||||||
|
lua.L_checktype(L, 2, i32(lua.TFUNCTION));
|
||||||
|
lua.pushvalue(L, 2);
|
||||||
|
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
||||||
|
|
||||||
|
core.add_lua_hook(&state, Hook(hook), fn_ref);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"register_key_group",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TTABLE));
|
||||||
|
|
||||||
|
table_to_action :: proc(L: ^lua.State, index: i32, input_map: ^core.InputActions) {
|
||||||
|
lua.len(L, index);
|
||||||
|
key_group_len := lua.tointeger(L, -1);
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
for i in 1..=key_group_len {
|
||||||
|
lua.rawgeti(L, index, i);
|
||||||
|
defer lua.pop(L, 1);
|
||||||
|
|
||||||
|
lua.rawgeti(L, -1, 1);
|
||||||
|
key:= Key(lua.tointeger(L, -1));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
lua.rawgeti(L, -1, 2);
|
||||||
|
desc := strings.clone(string(lua.tostring(L, -1)));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
switch lua.rawgeti(L, -1, 3) {
|
||||||
|
case i32(lua.TTABLE):
|
||||||
|
if action, exists := input_map.key_actions[key]; exists {
|
||||||
|
switch value in action.action {
|
||||||
|
case core.LuaEditorAction:
|
||||||
|
log.warn("Plugin attempted to register input group on existing key action (added from Lua)");
|
||||||
|
case core.PluginEditorAction:
|
||||||
|
log.warn("Plugin attempted to register input group on existing key action (added from Plugin)");
|
||||||
|
case core.EditorAction:
|
||||||
|
log.warn("Plugin attempted to register input group on existing key action");
|
||||||
|
case core.InputActions:
|
||||||
|
input_map := &(&input_map.key_actions[key]).action.(core.InputActions);
|
||||||
|
table_to_action(L, lua.gettop(L), input_map);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
core.register_key_action(input_map, key, core.new_input_actions(), desc);
|
||||||
|
table_to_action(L, lua.gettop(L), &((&input_map.key_actions[key]).action.(core.InputActions)));
|
||||||
|
}
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
case i32(lua.TFUNCTION):
|
||||||
|
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
||||||
|
|
||||||
|
if lua.rawgeti(L, -1, 4) == i32(lua.TTABLE) {
|
||||||
|
maybe_input_map := core.new_input_actions();
|
||||||
|
table_to_action(L, lua.gettop(L), &maybe_input_map);
|
||||||
|
|
||||||
|
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, maybe_input_map }, desc);
|
||||||
|
} else {
|
||||||
|
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, core.InputActions {} }, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
case:
|
||||||
|
lua.pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table_to_action(L, 1, state.current_input_map);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"request_window_close",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
core.request_window_close(&state);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"get_current_buffer_index",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(state.current_buffer));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"set_current_buffer_from_index",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
buffer_index := int(lua.L_checkinteger(L, 1));
|
||||||
|
if buffer_index != -2 && (buffer_index < 0 || buffer_index >= len(state.buffers)) {
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
} else {
|
||||||
|
state.current_buffer = buffer_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"buffer_info_from_index",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
buffer_index := int(lua.L_checkinteger(L, 1));
|
||||||
|
if buffer_index < 0 || buffer_index >= len(state.buffers) {
|
||||||
|
lua.pushnil(L);
|
||||||
|
} else {
|
||||||
|
push_lua_buffer_info :: proc(L: ^lua.State, buffer: ^FileBuffer) {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushlightuserdata(L, buffer);
|
||||||
|
lua.setfield(L, -2, "buffer");
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(buffer.cursor.col));
|
||||||
|
lua.setfield(L, -2, "col");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(buffer.cursor.line));
|
||||||
|
lua.setfield(L, -2, "line");
|
||||||
|
}
|
||||||
|
lua.setfield(L, -2, "cursor");
|
||||||
|
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(buffer.file_path, context.temp_allocator));
|
||||||
|
lua.setfield(L, -2, "full_file_path");
|
||||||
|
|
||||||
|
relative_file_path, _ := filepath.rel(state.directory, buffer.file_path, context.temp_allocator)
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(relative_file_path, context.temp_allocator));
|
||||||
|
lua.setfield(L, -2, "file_path");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_lua_buffer_info(L, core.buffer_from_index(&state, buffer_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"query_command_group",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
group := lua.L_checkstring(L, 1);
|
||||||
|
cmds := core.query_editor_commands_by_group(&state.commands, string(group), scratch_alloc);
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
for cmd, i in cmds {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(cmd.name, scratch_alloc));
|
||||||
|
lua.setfield(L, -2, "name");
|
||||||
|
|
||||||
|
lua.pushstring(L, strings.clone_to_cstring(cmd.description, scratch_alloc));
|
||||||
|
lua.setfield(L, -2, "description");
|
||||||
|
}
|
||||||
|
lua.rawseti(L, -2, lua.Integer(i+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"run_command",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
group := lua.L_checkstring(L, 1);
|
||||||
|
name := lua.L_checkstring(L, 2);
|
||||||
|
core.run_command(&state, string(group), string(name));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bbb = raw_data(editor_lib[:]);
|
||||||
|
|
||||||
|
get_lua_semantic_size :: proc(L: ^lua.State, index: i32) -> ui.SemanticSize {
|
||||||
|
if lua.istable(L, index) {
|
||||||
|
lua.rawgeti(L, index, 1);
|
||||||
|
semantic_kind := ui.SemanticSizeKind(lua.tointeger(L, -1));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
lua.rawgeti(L, index, 2);
|
||||||
|
semantic_value := int(lua.tointeger(L, -1));
|
||||||
|
lua.pop(L, 1);
|
||||||
|
|
||||||
|
return {semantic_kind, semantic_value};
|
||||||
|
} else {
|
||||||
|
semantic_kind := ui.SemanticSizeKind(lua.L_checkinteger(L, index));
|
||||||
|
return {semantic_kind, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_lua_semantic_size_table :: proc(L: ^lua.State, size: ui.SemanticSize) {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(i32(size.kind)));
|
||||||
|
lua.rawseti(L, -2, 1);
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(size.value));
|
||||||
|
lua.rawseti(L, -2, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push_lua_box_interaction :: proc(L: ^lua.State, interaction: ui.Interaction) {
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushboolean(L, b32(interaction.clicked));
|
||||||
|
lua.setfield(L, -2, "clicked");
|
||||||
|
|
||||||
|
lua.pushboolean(L, b32(interaction.hovering));
|
||||||
|
lua.setfield(L, -2, "hovering");
|
||||||
|
|
||||||
|
lua.pushboolean(L, b32(interaction.dragging));
|
||||||
|
lua.setfield(L, -2, "dragging");
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_pos.x));
|
||||||
|
lua.setfield(L, -2, "x");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_pos.y));
|
||||||
|
lua.setfield(L, -2, "y");
|
||||||
|
}
|
||||||
|
lua.setfield(L, -2, "box_pos");
|
||||||
|
|
||||||
|
lua.newtable(L);
|
||||||
|
{
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_size.x));
|
||||||
|
lua.setfield(L, -2, "x");
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(interaction.box_size.y));
|
||||||
|
lua.setfield(L, -2, "y");
|
||||||
|
}
|
||||||
|
lua.setfield(L, -2, "box_size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_lib := [?]lua.L_Reg {
|
||||||
|
lua.L_Reg {
|
||||||
|
"get_mouse_pos",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_x));
|
||||||
|
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_y));
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"Exact",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
value := lua.L_checknumber(L, 1);
|
||||||
|
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.Exact, int(value) });
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"PercentOfParent",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
value := lua.L_checknumber(L, 1);
|
||||||
|
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.PercentOfParent, int(value) });
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_parent",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
lua.L_checktype(L, 2, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 2);
|
||||||
|
box := transmute(^ui.Box)lua.touserdata(L, -1);
|
||||||
|
if box == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
ui.push_parent(ui_ctx, box);
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"pop_parent",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
ui.pop_parent(ui_ctx);
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_floating",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
x := int(lua.L_checkinteger(L, 3));
|
||||||
|
y := int(lua.L_checkinteger(L, 4));
|
||||||
|
|
||||||
|
box, interaction := ui.push_floating(ui_ctx, strings.clone(string(label), context.temp_allocator), {x,y});
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_box",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
flags, err := lua_ui_flags(L, 3);
|
||||||
|
axis := ui.Axis(lua.L_checkinteger(L, 4));
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 5);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 6);
|
||||||
|
|
||||||
|
box, interaction := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
||||||
|
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"_box_interaction",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
lua.L_checktype(L, 2, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 2);
|
||||||
|
box := transmute(^ui.Box)lua.touserdata(L, -1);
|
||||||
|
if box == nil { return i32(lua.ERRRUN); }
|
||||||
|
|
||||||
|
interaction := ui.test_box(ui_ctx, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_box",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
flags, err := lua_ui_flags(L, 3);
|
||||||
|
axis := ui.Axis(lua.L_checkinteger(L, 4));
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 5);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 6);
|
||||||
|
|
||||||
|
box, interaction := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"push_rect",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
background := bool(lua.toboolean(L, 3));
|
||||||
|
border := bool(lua.toboolean(L, 4));
|
||||||
|
axis := ui.Axis(lua.L_checkinteger(L, 5));
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 6);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 7);
|
||||||
|
|
||||||
|
box, interaction := ui.push_rect(ui_ctx, strings.clone(string(label), context.temp_allocator), background, border, axis, { semantic_width, semantic_height });
|
||||||
|
lua.pushlightuserdata(L, box);
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"spacer",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
|
interaction := ui.spacer(ui_ctx, strings.clone(string(label), context.temp_allocator), semantic_size = {{.Fill, 0}, {.Fill, 0}});
|
||||||
|
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"label",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
|
interaction := ui.label(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"button",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
|
||||||
|
interaction := ui.button(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"advanced_button",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
|
||||||
|
if ui_ctx != nil {
|
||||||
|
label := lua.L_checkstring(L, 2);
|
||||||
|
flags, err := lua_ui_flags(L, 3);
|
||||||
|
|
||||||
|
semantic_width := get_lua_semantic_size(L, 4);
|
||||||
|
semantic_height := get_lua_semantic_size(L, 5);
|
||||||
|
|
||||||
|
interaction := ui.advanced_button(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, { semantic_width, semantic_height });
|
||||||
|
push_lua_box_interaction(L, interaction)
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"buffer",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
|
||||||
|
if ui_ctx != nil {
|
||||||
|
buffer_index := int(lua.L_checkinteger(L, 2));
|
||||||
|
|
||||||
|
if buffer_index != -2 && (buffer_index < 0 || buffer_index >= len(state.buffers)) {
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_file_buffer(ui_ctx, core.buffer_from_index(&state, buffer_index));
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lua.L_Reg {
|
||||||
|
"log_buffer",
|
||||||
|
proc "c" (L: ^lua.State) -> i32 {
|
||||||
|
context = state.ctx;
|
||||||
|
|
||||||
|
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
||||||
|
lua.pushvalue(L, 1);
|
||||||
|
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
||||||
|
|
||||||
|
if ui_ctx != nil {
|
||||||
|
ui_file_buffer(ui_ctx, &state.log_buffer);
|
||||||
|
|
||||||
|
return i32(lua.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i32(lua.ERRRUN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: generate this from the plugin.Key enum
|
||||||
|
lua.newtable(state.L);
|
||||||
|
{
|
||||||
|
lua.newtable(state.L);
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.B));
|
||||||
|
lua.setfield(state.L, -2, "B");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.T));
|
||||||
|
lua.setfield(state.L, -2, "T");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.Y));
|
||||||
|
lua.setfield(state.L, -2, "Y");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.P));
|
||||||
|
lua.setfield(state.L, -2, "P");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.M));
|
||||||
|
lua.setfield(state.L, -2, "M");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.K));
|
||||||
|
lua.setfield(state.L, -2, "K");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.J));
|
||||||
|
lua.setfield(state.L, -2, "J");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.Q));
|
||||||
|
lua.setfield(state.L, -2, "Q");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.BACKQUOTE));
|
||||||
|
lua.setfield(state.L, -2, "Backtick");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.ESCAPE));
|
||||||
|
lua.setfield(state.L, -2, "Escape");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.ENTER));
|
||||||
|
lua.setfield(state.L, -2, "Enter");
|
||||||
|
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Key.SPACE));
|
||||||
|
lua.setfield(state.L, -2, "Space");
|
||||||
|
}
|
||||||
|
lua.setfield(state.L, -2, "Key");
|
||||||
|
|
||||||
|
{
|
||||||
|
lua.newtable(state.L);
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Hook.BufferInput));
|
||||||
|
lua.setfield(state.L, -2, "OnBufferInput");
|
||||||
|
lua.pushinteger(state.L, lua.Integer(Hook.Draw));
|
||||||
|
lua.setfield(state.L, -2, "OnDraw");
|
||||||
|
}
|
||||||
|
lua.setfield(state.L, -2, "Hook");
|
||||||
|
|
||||||
|
lua.L_setfuncs(state.L, bbb, 0);
|
||||||
|
lua.setglobal(state.L, "Editor");
|
||||||
|
|
||||||
|
lua.newtable(state.L);
|
||||||
|
{
|
||||||
|
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(state.L, raw_data(&ui_lib), 0);
|
||||||
|
lua.setglobal(state.L, "UI");
|
||||||
|
}
|
||||||
|
|
||||||
|
return L
|
||||||
|
}
|
851
src/main.odin
851
src/main.odin
|
@ -12,8 +12,8 @@ import "core:mem"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
import "vendor:sdl2"
|
import "vendor:sdl2"
|
||||||
import "vendor:sdl2/ttf"
|
import "vendor:sdl2/ttf"
|
||||||
import lua "vendor:lua/5.4"
|
|
||||||
|
|
||||||
|
import "lua"
|
||||||
import "core"
|
import "core"
|
||||||
import "theme"
|
import "theme"
|
||||||
import "ui"
|
import "ui"
|
||||||
|
@ -243,12 +243,24 @@ register_default_visual_actions :: proc(input_map: ^core.InputActions) {
|
||||||
sel_cur := &(core.current_buffer(state).selection.?);
|
sel_cur := &(core.current_buffer(state).selection.?);
|
||||||
|
|
||||||
core.delete_content(core.current_buffer(state), sel_cur);
|
core.delete_content(core.current_buffer(state), sel_cur);
|
||||||
|
core.current_buffer(state).selection = nil;
|
||||||
|
core.update_file_buffer_scroll(core.current_buffer(state))
|
||||||
|
|
||||||
state.mode = .Normal
|
state.mode = .Normal
|
||||||
state.current_input_map = &state.input_map.mode[.Normal];
|
state.current_input_map = &state.input_map.mode[.Normal];
|
||||||
|
}, "delete selection");
|
||||||
|
|
||||||
|
core.register_key_action(input_map, .C, proc(state: ^State) {
|
||||||
|
sel_cur := &(core.current_buffer(state).selection.?);
|
||||||
|
|
||||||
|
core.delete_content(core.current_buffer(state), sel_cur);
|
||||||
core.current_buffer(state).selection = nil;
|
core.current_buffer(state).selection = nil;
|
||||||
core.update_file_buffer_scroll(core.current_buffer(state))
|
core.update_file_buffer_scroll(core.current_buffer(state))
|
||||||
}, "delete selection");
|
|
||||||
|
state.mode = .Insert
|
||||||
|
state.current_input_map = &state.input_map.mode[.Normal];
|
||||||
|
sdl2.StartTextInput();
|
||||||
|
}, "change selection");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1007,35 +1019,6 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_ui_flags :: proc(L: ^lua.State, index: i32) -> (bit_set[ui.Flag], bool) {
|
|
||||||
lua.L_checktype(L, index, i32(lua.TTABLE));
|
|
||||||
lua.len(L, index);
|
|
||||||
array_len := lua.tointeger(L, -1);
|
|
||||||
lua.pop(L, 1);
|
|
||||||
|
|
||||||
flags: bit_set[ui.Flag]
|
|
||||||
|
|
||||||
for i in 1..=array_len {
|
|
||||||
lua.rawgeti(L, index, i);
|
|
||||||
defer lua.pop(L, 1);
|
|
||||||
|
|
||||||
flag := lua.tostring(L, -1);
|
|
||||||
switch flag {
|
|
||||||
case "Clickable": flags |= {.Clickable}
|
|
||||||
case "Hoverable": flags |= {.Hoverable}
|
|
||||||
case "Scrollable": flags |= {.Scrollable}
|
|
||||||
case "DrawText": flags |= {.DrawText}
|
|
||||||
case "DrawBorder": flags |= {.DrawBorder}
|
|
||||||
case "DrawBackground": flags |= {.DrawBackground}
|
|
||||||
case "RoundedBorder": flags |= {.RoundedBorder}
|
|
||||||
case "Floating": flags |= {.Floating}
|
|
||||||
case "CustomDrawFunc": flags |= {.CustomDrawFunc}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return flags, true
|
|
||||||
}
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
_command_arena: mem.Arena
|
_command_arena: mem.Arena
|
||||||
mem.arena_init(&_command_arena, make([]u8, 1024*1024));
|
mem.arena_init(&_command_arena, make([]u8, 1024*1024));
|
||||||
|
@ -1053,6 +1036,7 @@ main :: proc() {
|
||||||
window = nil,
|
window = nil,
|
||||||
directory = os.get_current_directory(),
|
directory = os.get_current_directory(),
|
||||||
plugins = make([dynamic]plugin.Interface),
|
plugins = make([dynamic]plugin.Interface),
|
||||||
|
new_plugins = make([dynamic]plugin.NewInterface),
|
||||||
highlighters = make(map[string]plugin.OnColorBufferProc),
|
highlighters = make(map[string]plugin.OnColorBufferProc),
|
||||||
hooks = make(map[plugin.Hook][dynamic]plugin.OnHookProc),
|
hooks = make(map[plugin.Hook][dynamic]plugin.OnHookProc),
|
||||||
lua_hooks = make(map[plugin.Hook][dynamic]core.LuaHookRef),
|
lua_hooks = make(map[plugin.Hook][dynamic]core.LuaHookRef),
|
||||||
|
@ -1078,7 +1062,8 @@ main :: proc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.logger = core.new_logger(&state.log_buffer);
|
// context.logger = core.new_logger(&state.log_buffer);
|
||||||
|
context.logger = log.create_console_logger();
|
||||||
state.ctx = context;
|
state.ctx = context;
|
||||||
|
|
||||||
// TODO: don't use this
|
// TODO: don't use this
|
||||||
|
@ -1228,729 +1213,8 @@ main :: proc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// **********************************************************************
|
lua.new_state(&state);
|
||||||
lua_allocator :: proc "c" (ud: rawptr, ptr: rawptr, osize, nsize: c.size_t) -> (buf: rawptr) {
|
lua.load_plugins(&state, "plugins/")
|
||||||
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 {
|
|
||||||
lua.L_Reg {
|
|
||||||
"quit",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
|
|
||||||
state.should_close = true;
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"log",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
text := string(lua.L_checkstring(L, 1));
|
|
||||||
log.info("[LUA]:", text);
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"register_hook",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
hook := lua.L_checkinteger(L, 1);
|
|
||||||
|
|
||||||
lua.L_checktype(L, 2, i32(lua.TFUNCTION));
|
|
||||||
lua.pushvalue(L, 2);
|
|
||||||
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
|
||||||
|
|
||||||
core.add_lua_hook(&state, plugin.Hook(hook), fn_ref);
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"register_key_group",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TTABLE));
|
|
||||||
|
|
||||||
table_to_action :: proc(L: ^lua.State, index: i32, input_map: ^core.InputActions) {
|
|
||||||
lua.len(L, index);
|
|
||||||
key_group_len := lua.tointeger(L, -1);
|
|
||||||
lua.pop(L, 1);
|
|
||||||
|
|
||||||
for i in 1..=key_group_len {
|
|
||||||
lua.rawgeti(L, index, i);
|
|
||||||
defer lua.pop(L, 1);
|
|
||||||
|
|
||||||
lua.rawgeti(L, -1, 1);
|
|
||||||
key:= plugin.Key(lua.tointeger(L, -1));
|
|
||||||
lua.pop(L, 1);
|
|
||||||
|
|
||||||
lua.rawgeti(L, -1, 2);
|
|
||||||
desc := strings.clone(string(lua.tostring(L, -1)));
|
|
||||||
lua.pop(L, 1);
|
|
||||||
|
|
||||||
switch lua.rawgeti(L, -1, 3) {
|
|
||||||
case i32(lua.TTABLE):
|
|
||||||
if action, exists := input_map.key_actions[key]; exists {
|
|
||||||
switch value in action.action {
|
|
||||||
case core.LuaEditorAction:
|
|
||||||
log.warn("Plugin attempted to register input group on existing key action (added from Lua)");
|
|
||||||
case core.PluginEditorAction:
|
|
||||||
log.warn("Plugin attempted to register input group on existing key action (added from Plugin)");
|
|
||||||
case core.EditorAction:
|
|
||||||
log.warn("Plugin attempted to register input group on existing key action");
|
|
||||||
case core.InputActions:
|
|
||||||
input_map := &(&input_map.key_actions[key]).action.(core.InputActions);
|
|
||||||
table_to_action(L, lua.gettop(L), input_map);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
core.register_key_action(input_map, key, core.new_input_actions(), desc);
|
|
||||||
table_to_action(L, lua.gettop(L), &((&input_map.key_actions[key]).action.(core.InputActions)));
|
|
||||||
}
|
|
||||||
lua.pop(L, 1);
|
|
||||||
|
|
||||||
case i32(lua.TFUNCTION):
|
|
||||||
fn_ref := lua.L_ref(L, i32(lua.REGISTRYINDEX));
|
|
||||||
|
|
||||||
if lua.rawgeti(L, -1, 4) == i32(lua.TTABLE) {
|
|
||||||
maybe_input_map := core.new_input_actions();
|
|
||||||
table_to_action(L, lua.gettop(L), &maybe_input_map);
|
|
||||||
|
|
||||||
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, maybe_input_map }, desc);
|
|
||||||
} else {
|
|
||||||
core.register_key_action_group(input_map, key, core.LuaEditorAction { fn_ref, core.InputActions {} }, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
case:
|
|
||||||
lua.pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table_to_action(L, 1, state.current_input_map);
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"request_window_close",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
core.request_window_close(&state);
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"get_current_buffer_index",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(state.current_buffer));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"set_current_buffer_from_index",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
buffer_index := int(lua.L_checkinteger(L, 1));
|
|
||||||
if buffer_index != -2 && (buffer_index < 0 || buffer_index >= len(state.buffers)) {
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
} else {
|
|
||||||
state.current_buffer = buffer_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"buffer_info_from_index",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
buffer_index := int(lua.L_checkinteger(L, 1));
|
|
||||||
if buffer_index < 0 || buffer_index >= len(state.buffers) {
|
|
||||||
lua.pushnil(L);
|
|
||||||
} else {
|
|
||||||
push_lua_buffer_info :: proc(L: ^lua.State, buffer: ^FileBuffer) {
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushlightuserdata(L, buffer);
|
|
||||||
lua.setfield(L, -2, "buffer");
|
|
||||||
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushinteger(L, lua.Integer(buffer.cursor.col));
|
|
||||||
lua.setfield(L, -2, "col");
|
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(buffer.cursor.line));
|
|
||||||
lua.setfield(L, -2, "line");
|
|
||||||
}
|
|
||||||
lua.setfield(L, -2, "cursor");
|
|
||||||
|
|
||||||
lua.pushstring(L, strings.clone_to_cstring(buffer.file_path, context.temp_allocator));
|
|
||||||
lua.setfield(L, -2, "full_file_path");
|
|
||||||
|
|
||||||
relative_file_path, _ := filepath.rel(state.directory, buffer.file_path, context.temp_allocator)
|
|
||||||
lua.pushstring(L, strings.clone_to_cstring(relative_file_path, context.temp_allocator));
|
|
||||||
lua.setfield(L, -2, "file_path");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push_lua_buffer_info(L, core.buffer_from_index(&state, buffer_index));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"query_command_group",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
group := lua.L_checkstring(L, 1);
|
|
||||||
cmds := core.query_editor_commands_by_group(&state.commands, string(group), scratch_alloc);
|
|
||||||
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
for cmd, i in cmds {
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushstring(L, strings.clone_to_cstring(cmd.name, scratch_alloc));
|
|
||||||
lua.setfield(L, -2, "name");
|
|
||||||
|
|
||||||
lua.pushstring(L, strings.clone_to_cstring(cmd.description, scratch_alloc));
|
|
||||||
lua.setfield(L, -2, "description");
|
|
||||||
}
|
|
||||||
lua.rawseti(L, -2, lua.Integer(i+1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"run_command",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
group := lua.L_checkstring(L, 1);
|
|
||||||
name := lua.L_checkstring(L, 2);
|
|
||||||
core.run_command(&state, string(group), string(name));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
bbb = raw_data(editor_lib[:]);
|
|
||||||
|
|
||||||
get_lua_semantic_size :: proc(L: ^lua.State, index: i32) -> ui.SemanticSize {
|
|
||||||
if lua.istable(L, index) {
|
|
||||||
lua.rawgeti(L, index, 1);
|
|
||||||
semantic_kind := ui.SemanticSizeKind(lua.tointeger(L, -1));
|
|
||||||
lua.pop(L, 1);
|
|
||||||
|
|
||||||
lua.rawgeti(L, index, 2);
|
|
||||||
semantic_value := int(lua.tointeger(L, -1));
|
|
||||||
lua.pop(L, 1);
|
|
||||||
|
|
||||||
return {semantic_kind, semantic_value};
|
|
||||||
} else {
|
|
||||||
semantic_kind := ui.SemanticSizeKind(lua.L_checkinteger(L, index));
|
|
||||||
return {semantic_kind, 0};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push_lua_semantic_size_table :: proc(L: ^lua.State, size: ui.SemanticSize) {
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushinteger(L, lua.Integer(i32(size.kind)));
|
|
||||||
lua.rawseti(L, -2, 1);
|
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(size.value));
|
|
||||||
lua.rawseti(L, -2, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push_lua_box_interaction :: proc(L: ^lua.State, interaction: ui.Interaction) {
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushboolean(L, b32(interaction.clicked));
|
|
||||||
lua.setfield(L, -2, "clicked");
|
|
||||||
|
|
||||||
lua.pushboolean(L, b32(interaction.hovering));
|
|
||||||
lua.setfield(L, -2, "hovering");
|
|
||||||
|
|
||||||
lua.pushboolean(L, b32(interaction.dragging));
|
|
||||||
lua.setfield(L, -2, "dragging");
|
|
||||||
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushinteger(L, lua.Integer(interaction.box_pos.x));
|
|
||||||
lua.setfield(L, -2, "x");
|
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(interaction.box_pos.y));
|
|
||||||
lua.setfield(L, -2, "y");
|
|
||||||
}
|
|
||||||
lua.setfield(L, -2, "box_pos");
|
|
||||||
|
|
||||||
lua.newtable(L);
|
|
||||||
{
|
|
||||||
lua.pushinteger(L, lua.Integer(interaction.box_size.x));
|
|
||||||
lua.setfield(L, -2, "x");
|
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(interaction.box_size.y));
|
|
||||||
lua.setfield(L, -2, "y");
|
|
||||||
}
|
|
||||||
lua.setfield(L, -2, "box_size");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_lib := [?]lua.L_Reg {
|
|
||||||
lua.L_Reg {
|
|
||||||
"get_mouse_pos",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
|
||||||
|
|
||||||
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_x));
|
|
||||||
lua.pushinteger(L, lua.Integer(ui_ctx.mouse_y));
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"Exact",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
value := lua.L_checknumber(L, 1);
|
|
||||||
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.Exact, int(value) });
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"PercentOfParent",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
value := lua.L_checknumber(L, 1);
|
|
||||||
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.PercentOfParent, int(value) });
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"push_parent",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
|
||||||
|
|
||||||
lua.L_checktype(L, 2, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 2);
|
|
||||||
box := transmute(^ui.Box)lua.touserdata(L, -1);
|
|
||||||
if box == nil { return i32(lua.ERRRUN); }
|
|
||||||
|
|
||||||
ui.push_parent(ui_ctx, box);
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"pop_parent",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
|
||||||
|
|
||||||
ui.pop_parent(ui_ctx);
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"push_floating",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
x := int(lua.L_checkinteger(L, 3));
|
|
||||||
y := int(lua.L_checkinteger(L, 4));
|
|
||||||
|
|
||||||
box, interaction := ui.push_floating(ui_ctx, strings.clone(string(label), context.temp_allocator), {x,y});
|
|
||||||
lua.pushlightuserdata(L, box);
|
|
||||||
push_lua_box_interaction(L, interaction);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"push_box",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
flags, err := lua_ui_flags(L, 3);
|
|
||||||
axis := ui.Axis(lua.L_checkinteger(L, 4));
|
|
||||||
|
|
||||||
semantic_width := get_lua_semantic_size(L, 5);
|
|
||||||
semantic_height := get_lua_semantic_size(L, 6);
|
|
||||||
|
|
||||||
box, interaction := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
|
||||||
|
|
||||||
lua.pushlightuserdata(L, box);
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"_box_interaction",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx == nil { return i32(lua.ERRRUN); }
|
|
||||||
|
|
||||||
lua.L_checktype(L, 2, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 2);
|
|
||||||
box := transmute(^ui.Box)lua.touserdata(L, -1);
|
|
||||||
if box == nil { return i32(lua.ERRRUN); }
|
|
||||||
|
|
||||||
interaction := ui.test_box(ui_ctx, box);
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"push_box",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
flags, err := lua_ui_flags(L, 3);
|
|
||||||
axis := ui.Axis(lua.L_checkinteger(L, 4));
|
|
||||||
|
|
||||||
semantic_width := get_lua_semantic_size(L, 5);
|
|
||||||
semantic_height := get_lua_semantic_size(L, 6);
|
|
||||||
|
|
||||||
box, interaction := ui.push_box(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, axis, { semantic_width, semantic_height });
|
|
||||||
lua.pushlightuserdata(L, box);
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"push_rect",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
background := bool(lua.toboolean(L, 3));
|
|
||||||
border := bool(lua.toboolean(L, 4));
|
|
||||||
axis := ui.Axis(lua.L_checkinteger(L, 5));
|
|
||||||
|
|
||||||
semantic_width := get_lua_semantic_size(L, 6);
|
|
||||||
semantic_height := get_lua_semantic_size(L, 7);
|
|
||||||
|
|
||||||
box, interaction := ui.push_rect(ui_ctx, strings.clone(string(label), context.temp_allocator), background, border, axis, { semantic_width, semantic_height });
|
|
||||||
lua.pushlightuserdata(L, box);
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"spacer",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
|
|
||||||
interaction := ui.spacer(ui_ctx, strings.clone(string(label), context.temp_allocator), semantic_size = {{.Fill, 0}, {.Fill, 0}});
|
|
||||||
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"label",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
|
|
||||||
interaction := ui.label(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"button",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
|
|
||||||
interaction := ui.button(ui_ctx, strings.clone(string(label), context.temp_allocator));
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"advanced_button",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
|
|
||||||
if ui_ctx != nil {
|
|
||||||
label := lua.L_checkstring(L, 2);
|
|
||||||
flags, err := lua_ui_flags(L, 3);
|
|
||||||
|
|
||||||
semantic_width := get_lua_semantic_size(L, 4);
|
|
||||||
semantic_height := get_lua_semantic_size(L, 5);
|
|
||||||
|
|
||||||
interaction := ui.advanced_button(ui_ctx, strings.clone(string(label), context.temp_allocator), flags, { semantic_width, semantic_height });
|
|
||||||
push_lua_box_interaction(L, interaction)
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"buffer",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
|
|
||||||
if ui_ctx != nil {
|
|
||||||
buffer_index := int(lua.L_checkinteger(L, 2));
|
|
||||||
|
|
||||||
if buffer_index != -2 && (buffer_index < 0 || buffer_index >= len(state.buffers)) {
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_file_buffer(ui_ctx, core.buffer_from_index(&state, buffer_index));
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
lua.L_Reg {
|
|
||||||
"log_buffer",
|
|
||||||
proc "c" (L: ^lua.State) -> i32 {
|
|
||||||
context = state.ctx;
|
|
||||||
|
|
||||||
lua.L_checktype(L, 1, i32(lua.TLIGHTUSERDATA));
|
|
||||||
lua.pushvalue(L, 1);
|
|
||||||
ui_ctx := transmute(^ui.Context)lua.touserdata(L, -1);
|
|
||||||
|
|
||||||
if ui_ctx != nil {
|
|
||||||
ui_file_buffer(ui_ctx, &state.log_buffer);
|
|
||||||
|
|
||||||
return i32(lua.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return i32(lua.ERRRUN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: generate this from the plugin.Key enum
|
|
||||||
lua.newtable(state.L);
|
|
||||||
{
|
|
||||||
lua.newtable(state.L);
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.B));
|
|
||||||
lua.setfield(state.L, -2, "B");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.T));
|
|
||||||
lua.setfield(state.L, -2, "T");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.Y));
|
|
||||||
lua.setfield(state.L, -2, "Y");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.P));
|
|
||||||
lua.setfield(state.L, -2, "P");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.M));
|
|
||||||
lua.setfield(state.L, -2, "M");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.K));
|
|
||||||
lua.setfield(state.L, -2, "K");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.J));
|
|
||||||
lua.setfield(state.L, -2, "J");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.Q));
|
|
||||||
lua.setfield(state.L, -2, "Q");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.BACKQUOTE));
|
|
||||||
lua.setfield(state.L, -2, "Backtick");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.ESCAPE));
|
|
||||||
lua.setfield(state.L, -2, "Escape");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.ENTER));
|
|
||||||
lua.setfield(state.L, -2, "Enter");
|
|
||||||
|
|
||||||
lua.pushinteger(state.L, lua.Integer(plugin.Key.SPACE));
|
|
||||||
lua.setfield(state.L, -2, "Space");
|
|
||||||
}
|
|
||||||
lua.setfield(state.L, -2, "Key");
|
|
||||||
|
|
||||||
{
|
|
||||||
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(state.L, -2, "Hook");
|
|
||||||
|
|
||||||
lua.L_setfuncs(state.L, bbb, 0);
|
|
||||||
lua.setglobal(state.L, "Editor");
|
|
||||||
|
|
||||||
lua.newtable(state.L);
|
|
||||||
{
|
|
||||||
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(state.L, raw_data(&ui_lib), 0);
|
|
||||||
lua.setglobal(state.L, "UI");
|
|
||||||
}
|
|
||||||
|
|
||||||
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(state.L, lua.gettop(state.L));
|
|
||||||
lua.pop(state.L, lua.gettop(state.L));
|
|
||||||
|
|
||||||
log.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize Lua Plugins
|
|
||||||
{
|
|
||||||
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(state.L, lua.gettop(state.L));
|
|
||||||
lua.pop(state.L, lua.gettop(state.L));
|
|
||||||
|
|
||||||
log.error("failed to initialize plugin (OnInit):", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// **********************************************************************
|
|
||||||
|
|
||||||
control_key_pressed: bool;
|
control_key_pressed: bool;
|
||||||
for !state.should_close {
|
for !state.should_close {
|
||||||
|
@ -2062,14 +1326,15 @@ main :: proc() {
|
||||||
// TODO: move this to view.lua
|
// TODO: move this to view.lua
|
||||||
// log_window, _ := ui.push_floating(&ui_context, "log", {0,0}, flags = {.Floating, .DrawBackground}, semantic_size = {ui.make_semantic_size(.PercentOfParent, 75), ui.make_semantic_size(.PercentOfParent, 75)});
|
// log_window, _ := ui.push_floating(&ui_context, "log", {0,0}, flags = {.Floating, .DrawBackground}, semantic_size = {ui.make_semantic_size(.PercentOfParent, 75), ui.make_semantic_size(.PercentOfParent, 75)});
|
||||||
// ui.push_parent(&ui_context, log_window);
|
// ui.push_parent(&ui_context, log_window);
|
||||||
// {
|
{
|
||||||
// defer ui.pop_parent(&ui_context);
|
// defer ui.pop_parent(&ui_context);
|
||||||
// ui_file_buffer(&ui_context, &state.log_buffer);
|
ui_file_buffer(&ui_context, &state.log_buffer);
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
if draw_hooks, ok := state.lua_hooks[plugin.Hook.Draw]; ok {
|
if draw_hooks, ok := state.lua_hooks[plugin.Hook.Draw]; ok {
|
||||||
for hook_ref in draw_hooks {
|
for hook_ref in draw_hooks {
|
||||||
|
/*
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
||||||
lua.pushlightuserdata(state.L, &ui_context);
|
lua.pushlightuserdata(state.L, &ui_context);
|
||||||
if lua.pcall(state.L, 1, 0, 0) != i32(lua.OK) {
|
if lua.pcall(state.L, 1, 0, 0) != i32(lua.OK) {
|
||||||
|
@ -2080,6 +1345,7 @@ main :: proc() {
|
||||||
} else {
|
} else {
|
||||||
lua.pop(state.L, lua.gettop(state.L));
|
lua.pop(state.L, lua.gettop(state.L));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2087,6 +1353,37 @@ main :: proc() {
|
||||||
state.window.draw(state.plugin_vtable, state.window.user_data);
|
state.window.draw(state.plugin_vtable, state.window.user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if window, ok := &state.new_window.(core.NewWindow); ok {
|
||||||
|
floating, interaction := ui.push_floating(&ui_context, "floating_window", {0,0})
|
||||||
|
ui.push_parent(&ui_context, floating)
|
||||||
|
{
|
||||||
|
canvas, _ := ui.push_rect(&ui_context, "canvas", false, false, .Horizontal, ui.Fill)
|
||||||
|
ui.push_parent(&ui_context, canvas)
|
||||||
|
{
|
||||||
|
ui.spacer(&ui_context, "left spacer")
|
||||||
|
|
||||||
|
halfway, _ := ui.push_rect(&ui_context, "halfway centered", false, false, .Vertical, {ui.SemanticSize{kind = .ChildrenSum}, ui.SemanticSize{kind = .Fill}})
|
||||||
|
ui.push_parent(&ui_context, halfway)
|
||||||
|
{
|
||||||
|
ui.spacer(&ui_context, "top spacer")
|
||||||
|
|
||||||
|
centered_container, _ := ui.push_rect(&ui_context, "centered container", true, true, .Horizontal, {ui.SemanticSize{kind = .ChildrenSum, value=state.screen_width-32}, ui.SemanticSize{kind = .ChildrenSum, value = state.screen_height-32}})
|
||||||
|
ui.push_parent(&ui_context, centered_container)
|
||||||
|
{
|
||||||
|
lua.run_ui_function(&state, &ui_context, window.lua_draw_proc);
|
||||||
|
}
|
||||||
|
ui.pop_parent(&ui_context)
|
||||||
|
ui.spacer(&ui_context, "bottom spacer")
|
||||||
|
}
|
||||||
|
ui.pop_parent(&ui_context)
|
||||||
|
ui.spacer(&ui_context, "right spacer")
|
||||||
|
}
|
||||||
|
ui.pop_parent(&ui_context)
|
||||||
|
}
|
||||||
|
ui.pop_parent(&ui_context)
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ui_context.last_mouse_left_down = ui_context.mouse_left_down;
|
ui_context.last_mouse_left_down = ui_context.mouse_left_down;
|
||||||
ui_context.last_mouse_right_down = ui_context.mouse_right_down;
|
ui_context.last_mouse_right_down = ui_context.mouse_right_down;
|
||||||
|
@ -2132,19 +1429,7 @@ main :: proc() {
|
||||||
if action, exists := state.current_input_map.ctrl_key_actions[key]; exists {
|
if action, exists := state.current_input_map.ctrl_key_actions[key]; exists {
|
||||||
switch value in action.action {
|
switch value in action.action {
|
||||||
case core.LuaEditorAction:
|
case core.LuaEditorAction:
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref));
|
lua.run_editor_action(&state, key, value)
|
||||||
if lua.pcall(state.L, 0, 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(state.L, lua.gettop(state.L));
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.maybe_input_map.ctrl_key_actions != nil {
|
|
||||||
|
|
||||||
}
|
|
||||||
case core.PluginEditorAction:
|
case core.PluginEditorAction:
|
||||||
value(state.plugin_vtable);
|
value(state.plugin_vtable);
|
||||||
case core.EditorAction:
|
case core.EditorAction:
|
||||||
|
@ -2157,20 +1442,7 @@ main :: proc() {
|
||||||
if action, exists := state.current_input_map.key_actions[key]; exists {
|
if action, exists := state.current_input_map.key_actions[key]; exists {
|
||||||
switch value in action.action {
|
switch value in action.action {
|
||||||
case core.LuaEditorAction:
|
case core.LuaEditorAction:
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref));
|
lua.run_editor_action(&state, key, value)
|
||||||
if lua.pcall(state.L, 0, 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(state.L, lua.gettop(state.L));
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.maybe_input_map.key_actions != nil {
|
|
||||||
ptr_action := &(&state.current_input_map.key_actions[key]).action.(core.LuaEditorAction)
|
|
||||||
state.current_input_map = (&ptr_action.maybe_input_map)
|
|
||||||
}
|
|
||||||
case core.PluginEditorAction:
|
case core.PluginEditorAction:
|
||||||
value(state.plugin_vtable);
|
value(state.plugin_vtable);
|
||||||
case core.EditorAction:
|
case core.EditorAction:
|
||||||
|
@ -2219,6 +1491,7 @@ main :: proc() {
|
||||||
hook_proc(state.plugin_vtable, buffer);
|
hook_proc(state.plugin_vtable, buffer);
|
||||||
}
|
}
|
||||||
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
|
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
|
||||||
|
/*
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
||||||
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
||||||
err := lua.tostring(state.L, lua.gettop(state.L));
|
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||||
|
@ -2228,6 +1501,7 @@ main :: proc() {
|
||||||
} else {
|
} else {
|
||||||
lua.pop(state.L, lua.gettop(state.L));
|
lua.pop(state.L, lua.gettop(state.L));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2238,6 +1512,7 @@ main :: proc() {
|
||||||
hook_proc(state.plugin_vtable, buffer);
|
hook_proc(state.plugin_vtable, buffer);
|
||||||
}
|
}
|
||||||
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
|
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
|
||||||
|
/*
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
||||||
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
||||||
err := lua.tostring(state.L, lua.gettop(state.L));
|
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||||
|
@ -2247,6 +1522,7 @@ main :: proc() {
|
||||||
} else {
|
} else {
|
||||||
lua.pop(state.L, lua.gettop(state.L));
|
lua.pop(state.L, lua.gettop(state.L));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .ENTER: {
|
case .ENTER: {
|
||||||
|
@ -2268,6 +1544,7 @@ main :: proc() {
|
||||||
hook_proc(state.plugin_vtable, buffer);
|
hook_proc(state.plugin_vtable, buffer);
|
||||||
}
|
}
|
||||||
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
|
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
|
||||||
|
/*
|
||||||
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
|
||||||
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
|
||||||
err := lua.tostring(state.L, lua.gettop(state.L));
|
err := lua.tostring(state.L, lua.gettop(state.L));
|
||||||
|
@ -2277,6 +1554,7 @@ main :: proc() {
|
||||||
} else {
|
} else {
|
||||||
lua.pop(state.L, lua.gettop(state.L));
|
lua.pop(state.L, lua.gettop(state.L));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2329,6 +1607,7 @@ main :: proc() {
|
||||||
plugin.on_exit();
|
plugin.on_exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lua.close(state.L);
|
lua.close(state.L);
|
||||||
|
|
||||||
sdl2.Quit();
|
sdl2.Quit();
|
||||||
|
|
|
@ -16,6 +16,12 @@ Interface :: struct {
|
||||||
on_draw: OnDrawProc,
|
on_draw: OnDrawProc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewInterface :: struct {
|
||||||
|
name: string,
|
||||||
|
version: string,
|
||||||
|
namespace: string,
|
||||||
|
}
|
||||||
|
|
||||||
BufferIndex :: struct {
|
BufferIndex :: struct {
|
||||||
slice_index: int,
|
slice_index: int,
|
||||||
content_index: int,
|
content_index: int,
|
||||||
|
|
16
todo.md
16
todo.md
|
@ -1,11 +1,16 @@
|
||||||
|
- Get input maps working with `spawn_floating_window`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- Save/Load files
|
||||||
- Undo/Redo
|
- Undo/Redo
|
||||||
- Edit History Tree
|
- Edit History Tree
|
||||||
- Finish selections
|
- Finish selections
|
||||||
- Guarantee that start and end are always ordered
|
- [x] Guarantee that start and end are always ordered
|
||||||
- Add in text actions
|
- Add in text actions
|
||||||
- Yank
|
- Yank
|
||||||
- [x] Delete
|
- [x] Delete
|
||||||
- Change
|
- [x] Change
|
||||||
- Virtual Whitespace
|
- Virtual Whitespace
|
||||||
- Allow any-sized tabs
|
- Allow any-sized tabs
|
||||||
- Modify input system to allow for keybinds that take input
|
- Modify input system to allow for keybinds that take input
|
||||||
|
@ -16,13 +21,16 @@
|
||||||
- [ ] Registering Plugin Commands that can be run in palette and via other plugins
|
- [ ] Registering Plugin Commands that can be run in palette and via other plugins
|
||||||
- [x] A way to query these commands by-plugin
|
- [x] A way to query these commands by-plugin
|
||||||
- Re-write the UI (again)
|
- Re-write the UI (again)
|
||||||
|
- Separate ui components from layout
|
||||||
- Re-do plugin system
|
- Re-do plugin system
|
||||||
- Potentially have a C# plugins system? Use it instead of Lua? (probably not)
|
- Potentially have a C# plugins system? Use it instead of Lua? (probably not)
|
||||||
- Re-do dylib plugin system
|
- Re-do dylib plugin system
|
||||||
- Re-do Lua plugin system
|
- Re-do Lua plugin system
|
||||||
- Define ultra-core common API
|
- Core Events ~Define ultra-core common API~
|
||||||
- 3rd-party core UI modifications must abide by this API (for example, another plugin must be able to open a file and have it be focused)
|
- ~3rd-party core UI modifications must abide by this API (for example, another plugin must be able to open a file and have it be focused)~
|
||||||
|
- e.g. Open File, currently focused UI panel recieves event
|
||||||
- Ability to probe core for installed plugins and their version
|
- Ability to probe core for installed plugins and their version
|
||||||
|
- Plugins can register to be UI components that the user can define where they are laid out
|
||||||
- Persist end of line cursor position
|
- Persist end of line cursor position
|
||||||
- Generate key mappings from the plugin.Key enum
|
- Generate key mappings from the plugin.Key enum
|
||||||
- Fix jumping forward a word jumping past consecutive brackets
|
- Fix jumping forward a word jumping past consecutive brackets
|
||||||
|
|
Loading…
Reference in New Issue