command stuff?
parent
bd01fa6cfb
commit
111f2f8a70
4
Makefile
4
Makefile
|
@ -3,10 +3,10 @@ all: editor
|
|||
editor: src/*.odin # grep odin_highlighter
|
||||
# odin build src/ -out:bin/editor.o -build-mode:obj -debug -lld
|
||||
# dsymutil bin/editor.o -o bin/editor.dSYM
|
||||
odin build src/ -out:bin/editor -lld
|
||||
../Odin/odin build src/ -out:bin/editor -debug -lld -extra-linker-flags:"-L./"
|
||||
|
||||
odin_highlighter: plugins/highlighter/src/*.odin
|
||||
odin build plugins/highlighter/src/ -build-mode:dll -no-entry-point -out:bin/highlighter
|
||||
../Odin/odin build plugins/highlighter/src/ -build-mode:dll -no-entry-point -out:bin/highlighter
|
||||
|
||||
grep: plugins/grep/src/*.rs
|
||||
nightly-cargo b --manifest-path=plugins/grep/Cargo.toml
|
||||
|
|
|
@ -63,13 +63,17 @@
|
|||
{
|
||||
devShell = pkgs.mkShell {
|
||||
buildInputs = with pkgs; (if pkgs.system == "aarch64-darwin" || pkgs.system == "x86_64-darwin" then [
|
||||
fixed-odin
|
||||
# fixed-odin
|
||||
llvmPackages_17.bintools
|
||||
llvmPackages_17.lld
|
||||
llvmPackages_17.clang
|
||||
local-rust
|
||||
nightly-cargo
|
||||
rust-analyzer
|
||||
lua54Packages.stdlib
|
||||
SDL2
|
||||
SDL2_ttf
|
||||
darwin.apple_sdk.frameworks.System
|
||||
darwin.apple_sdk.frameworks.CoreData
|
||||
darwin.apple_sdk.frameworks.Kernel
|
||||
darwin.apple_sdk.frameworks.CoreVideo
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
local BufferSearchOpen = false
|
||||
local BufferSearchOpenElapsed = 0
|
||||
|
||||
local CommandSearchOpen = false
|
||||
local CommandSearchOpenElapsed = 0
|
||||
local CommandList = {}
|
||||
|
||||
local LogWindowOpen = false
|
||||
local LogWindowOpenElapsed = 0
|
||||
|
||||
|
@ -280,6 +284,7 @@ function render_ui_window(ctx)
|
|||
end
|
||||
|
||||
render_buffer_search(ctx)
|
||||
render_command_search(ctx)
|
||||
render_log_window(ctx)
|
||||
|
||||
LastMouseX = x
|
||||
|
@ -323,6 +328,45 @@ function render_buffer_search(ctx)
|
|||
end
|
||||
end
|
||||
|
||||
function render_command_search(ctx)
|
||||
if CommandSearchOpen or CommandSearchOpenElapsed > 0 then
|
||||
if CommandSearchOpen and CommandSearchOpenElapsed < numFrames then
|
||||
CommandSearchOpenElapsed = CommandSearchOpenElapsed + 1
|
||||
elseif not CommandSearchOpen and CommandSearchOpenElapsed > 0 then
|
||||
CommandSearchOpenElapsed = CommandSearchOpenElapsed - 1
|
||||
end
|
||||
end
|
||||
|
||||
if CommandSearchOpen or CommandSearchOpenElapsed > 0 then
|
||||
window_percent_width = 75
|
||||
window_percent_height = 25
|
||||
if CommandSearchOpenElapsed > 0 then
|
||||
window_percent_width = ((CommandSearchOpenElapsed/numFrames) * 75)
|
||||
window_percent_height = ((CommandSearchOpenElapsed/numFrames) * 25)
|
||||
end
|
||||
|
||||
UI.push_parent(ctx, UI.push_floating(ctx, "buffer search canvas", 0, 0))
|
||||
centered(ctx, "command search window", UI.Horizontal, UI.PercentOfParent(window_percent_width), UI.PercentOfParent(window_percent_height), (
|
||||
function ()
|
||||
UI.push_parent(ctx, UI.push_rect(ctx, "window", true, true, UI.Horizontal, UI.Fill, UI.Fill))
|
||||
UI.push_parent(ctx, UI.push_rect(ctx, "command list", false, false, UI.Vertical, UI.Fill, UI.Fill))
|
||||
-- local commands = Editor.query_command_group("nl.spacegirl.editor.core")
|
||||
for i, cmd in ipairs(CommandList) do
|
||||
flags = {"DrawText"}
|
||||
|
||||
if i == CommandSearchIndex then
|
||||
table.insert(flags, 1, "DrawBorder")
|
||||
end
|
||||
interaction = UI.advanced_button(ctx, " "..cmd.name..": "..cmd.description.." ", flags, UI.Fill, UI.FitText)
|
||||
end
|
||||
UI.pop_parent(ctx)
|
||||
UI.pop_parent(ctx)
|
||||
end
|
||||
))
|
||||
UI.pop_parent(ctx)
|
||||
end
|
||||
end
|
||||
|
||||
function render_log_window(ctx)
|
||||
if Editor.get_current_buffer_index() ~= -2 then
|
||||
LogWindowOpen = false
|
||||
|
@ -372,6 +416,36 @@ function OnInit()
|
|||
end
|
||||
end)},
|
||||
{Editor.Key.Space, "", {
|
||||
{Editor.Key.Backtick, "Command Palette",
|
||||
(function ()
|
||||
CommandSearchOpen = true
|
||||
CommandSearchIndex = 1
|
||||
|
||||
CommandList = Editor.query_command_group("nl.spacegirl.editor.core")
|
||||
end),
|
||||
{
|
||||
{Editor.Key.Escape, "Close Window", (
|
||||
function ()
|
||||
Editor.request_window_close()
|
||||
CommandSearchOpen = false
|
||||
end
|
||||
)},
|
||||
{Editor.Key.Enter, "Run Command", (
|
||||
function ()
|
||||
if CommandList[CommandSearchIndex] ~= nil then
|
||||
Editor.run_command("nl.spacegirl.editor.core", CommandList[CommandSearchIndex]["name"])
|
||||
CommandList = {}
|
||||
|
||||
Editor.request_window_close()
|
||||
CommandSearchOpen = false
|
||||
end
|
||||
end
|
||||
)},
|
||||
-- TODO: don't scroll past selections
|
||||
{Editor.Key.K, "Move Selection Up", (function () CommandSearchIndex = CommandSearchIndex - 1 end)},
|
||||
{Editor.Key.J, "Move Selection Down", (function () CommandSearchIndex = CommandSearchIndex + 1 end)},
|
||||
}
|
||||
},
|
||||
{Editor.Key.B, "Buffer Search", (
|
||||
function ()
|
||||
BufferSearchOpen = true
|
||||
|
|
|
@ -46,6 +46,7 @@ close_window_and_free :: proc(state: ^State) {
|
|||
}
|
||||
|
||||
LuaHookRef :: i32;
|
||||
EditorCommandList :: map[string][dynamic]EditorCommand;
|
||||
State :: struct {
|
||||
ctx: runtime.Context,
|
||||
L: ^lua.State,
|
||||
|
@ -76,6 +77,8 @@ State :: struct {
|
|||
input_map: InputMap,
|
||||
current_input_map: ^InputActions,
|
||||
|
||||
commands: EditorCommandList,
|
||||
|
||||
plugins: [dynamic]plugin.Interface,
|
||||
plugin_vtable: plugin.Plugin,
|
||||
highlighters: map[string]plugin.OnColorBufferProc,
|
||||
|
@ -83,6 +86,12 @@ State :: struct {
|
|||
lua_hooks: map[plugin.Hook][dynamic]LuaHookRef,
|
||||
}
|
||||
|
||||
EditorCommand :: struct {
|
||||
name: string,
|
||||
description: string,
|
||||
action: EditorAction,
|
||||
}
|
||||
|
||||
current_buffer :: proc(state: ^State) -> ^FileBuffer {
|
||||
if state.current_buffer == -2 {
|
||||
return &state.log_buffer;
|
||||
|
@ -142,7 +151,7 @@ new_input_map :: proc() -> InputMap {
|
|||
ti := runtime.type_info_base(type_info_of(Mode));
|
||||
if v, ok := ti.variant.(runtime.Type_Info_Enum); ok {
|
||||
for i in &v.values {
|
||||
input_map.mode[(cast(^Mode)(&i))^] = new_input_actions();
|
||||
input_map.mode[cast(Mode)i] = new_input_actions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +167,7 @@ new_input_actions :: proc() -> InputActions {
|
|||
return input_actions;
|
||||
}
|
||||
delete_input_map :: proc(input_map: ^InputMap) {
|
||||
for _, actions in &input_map.mode {
|
||||
for _, &actions in &input_map.mode {
|
||||
delete_input_actions(&actions);
|
||||
}
|
||||
delete(input_map.mode);
|
||||
|
@ -233,3 +242,59 @@ register_ctrl_key_action_group :: proc(input_map: ^InputActions, key: plugin.Key
|
|||
|
||||
register_key_action :: proc{register_plugin_key_action_single, register_key_action_single, register_key_action_group};
|
||||
register_ctrl_key_action :: proc{register_ctrl_key_action_single, register_ctrl_key_action_group};
|
||||
|
||||
register_editor_command :: proc(command_list: ^EditorCommandList, command_group, name, description: string, action: EditorAction) {
|
||||
if _, ok := command_list[command_group]; !ok {
|
||||
command_list[command_group] = make([dynamic]EditorCommand);
|
||||
}
|
||||
|
||||
runtime.append(&command_list[command_group], EditorCommand {
|
||||
name = name,
|
||||
description = description,
|
||||
action = action,
|
||||
});
|
||||
}
|
||||
|
||||
query_editor_commands_by_name :: proc(command_list: ^EditorCommandList, name: string, allocator: runtime.Allocator) -> []EditorCommand {
|
||||
context.allocator = allocator;
|
||||
commands := make([dynamic]EditorCommand)
|
||||
|
||||
for group, list in command_list {
|
||||
for cmd in list {
|
||||
if cmd.name == name {
|
||||
append(&commands, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return commands[:];
|
||||
}
|
||||
|
||||
query_editor_commands_by_group :: proc(command_list: ^EditorCommandList, name: string, allocator: runtime.Allocator) -> []EditorCommand {
|
||||
context.allocator = allocator;
|
||||
commands := make([dynamic]EditorCommand)
|
||||
|
||||
for group, list in command_list {
|
||||
if group == name {
|
||||
for cmd in list {
|
||||
append(&commands, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return commands[:];
|
||||
}
|
||||
|
||||
run_command :: proc(state: ^State, group: string, name: string) {
|
||||
if cmds, ok := state.commands[group]; ok {
|
||||
for cmd in cmds {
|
||||
if cmd.name == name {
|
||||
log.info("Running command", group, name);
|
||||
cmd.action(state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.error("no command", group, name);
|
||||
}
|
||||
|
|
|
@ -679,7 +679,7 @@ new_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: s
|
|||
defer os.close(fd);
|
||||
|
||||
fi, fstat_err := os.fstat(fd);
|
||||
if fstat_err > 0 {
|
||||
if fstat_err != nil {
|
||||
return FileBuffer{}, make_error(ErrorType.FileIOError, fmt.aprintf("failed to get file info: errno=%x", fstat_err));
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ import "plugin"
|
|||
State :: core.State;
|
||||
FileBuffer :: core.FileBuffer;
|
||||
|
||||
// TODO: should probably go into state
|
||||
scratch: mem.Scratch;
|
||||
scratch_alloc: runtime.Allocator;
|
||||
state := core.State {};
|
||||
|
||||
StateWithUi :: struct {
|
||||
|
@ -1022,6 +1025,8 @@ main :: proc() {
|
|||
source_font_width = 8,
|
||||
source_font_height = 16,
|
||||
input_map = core.new_input_map(),
|
||||
commands = make(core.EditorCommandList),
|
||||
|
||||
window = nil,
|
||||
directory = os.get_current_directory(),
|
||||
plugins = make([dynamic]plugin.Interface),
|
||||
|
@ -1035,19 +1040,55 @@ main :: proc() {
|
|||
context.logger = core.new_logger(&state.log_buffer);
|
||||
state.ctx = context;
|
||||
|
||||
mem.scratch_allocator_init(&scratch, 1024*1024);
|
||||
scratch_alloc = mem.scratch_allocator(&scratch);
|
||||
|
||||
state.current_input_map = &state.input_map.mode[.Normal];
|
||||
register_default_input_actions(&state.input_map.mode[.Normal]);
|
||||
register_default_visual_actions(&state.input_map.mode[.Visual]);
|
||||
|
||||
register_default_text_input_actions(&state.input_map.mode[.Normal]);
|
||||
|
||||
for arg in os.args[1:] {
|
||||
buffer, err := core.new_file_buffer(context.allocator, arg, state.directory);
|
||||
if err.type != .None {
|
||||
log.error("Failed to create file buffer:", err);
|
||||
continue;
|
||||
core.register_editor_command(
|
||||
&state.commands,
|
||||
"nl.spacegirl.editor.core",
|
||||
"New Scratch Buffer",
|
||||
"Opens a new scratch buffer",
|
||||
proc(state: ^State) {
|
||||
buffer := core.new_virtual_file_buffer(context.allocator);
|
||||
runtime.append(&state.buffers, buffer);
|
||||
}
|
||||
)
|
||||
core.register_editor_command(
|
||||
&state.commands,
|
||||
"nl.spacegirl.editor.core",
|
||||
"Quit",
|
||||
"Quits the application",
|
||||
proc(state: ^State) {
|
||||
state.should_close = true
|
||||
}
|
||||
)
|
||||
|
||||
{
|
||||
cmds := core.query_editor_commands_by_group(&state.commands, "nl.spacegirl.editor.core", scratch_alloc);
|
||||
log.info("List of commands:");
|
||||
for cmd in cmds {
|
||||
log.info(cmd.name, ":", cmd.description);
|
||||
}
|
||||
}
|
||||
|
||||
if len(os.args) > 1 {
|
||||
for arg in os.args[1:] {
|
||||
buffer, err := core.new_file_buffer(context.allocator, arg, state.directory);
|
||||
if err.type != .None {
|
||||
log.error("Failed to create file buffer:", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
runtime.append(&state.buffers, buffer);
|
||||
}
|
||||
} else {
|
||||
buffer := core.new_virtual_file_buffer(context.allocator);
|
||||
runtime.append(&state.buffers, buffer);
|
||||
}
|
||||
|
||||
|
@ -1314,6 +1355,44 @@ main :: proc() {
|
|||
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[:]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue