From 198e314953f1961babc06acfaff7457ee2bd324a Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Sat, 6 Jan 2024 15:13:06 -0600 Subject: [PATCH] get started moving buffer search window to plugin --- Makefile | 4 +- plugins/buffer_search/plugin.odin | 34 ++++++++ plugins/highlighter/src/plugin.odin | 2 +- src/core/core.odin | 17 +++- src/main.odin | 65 +++++++++++++- src/plugin/plugin.odin | 128 +++++++++++++++++++++++++++- 6 files changed, 241 insertions(+), 9 deletions(-) create mode 100644 plugins/buffer_search/plugin.odin diff --git a/Makefile b/Makefile index 58238f1..de87d98 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ all: editor -editor: src/*.odin rg odin_highlighter +editor: src/*.odin rg odin_highlighter buffer_search odin build src/ -out:bin/editor -lld +buffer_search: + odin build plugins/buffer_search/ -build-mode:dll -no-entry-point -out:bin/buffer_search odin_highlighter: odin build plugins/highlighter/src/ -build-mode:dll -no-entry-point -out:bin/highlighter diff --git a/plugins/buffer_search/plugin.odin b/plugins/buffer_search/plugin.odin new file mode 100644 index 0000000..c5e6e65 --- /dev/null +++ b/plugins/buffer_search/plugin.odin @@ -0,0 +1,34 @@ +// A simple window to view/search open buffers +package buffer_search; + +import "core:runtime" +import "core:fmt" + +import p "../../src/plugin" + +Plugin :: p.Plugin; +Iterator :: p.Iterator; +BufferIter :: p.BufferIter; +BufferIndex :: p.BufferIndex; +Key :: p.Key; + +@export +OnInitialize :: proc "c" (plugin: Plugin) { + context = runtime.default_context(); + fmt.println("builtin buffer search plugin initialized!"); + + plugin.register_input_group(nil, .SPACE, proc "c" (plugin: Plugin, input_map: rawptr) { + plugin.register_input(input_map, .B, open_buffer_window, "show list of open buffers"); + }); +} + +@export +OnExit :: proc "c" (plugin: Plugin) { + context = runtime.default_context(); +} + +open_buffer_window :: proc "c" (plugin: Plugin) { + context = runtime.default_context(); + + fmt.println("Look you tried opening a window from a plugin!"); +} diff --git a/plugins/highlighter/src/plugin.odin b/plugins/highlighter/src/plugin.odin index 21ed6d8..c7288ff 100644 --- a/plugins/highlighter/src/plugin.odin +++ b/plugins/highlighter/src/plugin.odin @@ -1,4 +1,4 @@ -// The default syntax highlighter plugin for Odin +// The default syntax highlighter plugin for Odin & Rust package highlighter; import "core:runtime" diff --git a/src/core/core.odin b/src/core/core.odin index 2de55f1..cf0491f 100644 --- a/src/core/core.odin +++ b/src/core/core.odin @@ -70,8 +70,9 @@ State :: struct { highlighters: map[string]plugin.OnColorBufferProc } +PluginEditorAction :: proc "c" (plugin: plugin.Plugin); EditorAction :: proc(state: ^State); -InputGroup :: union {EditorAction, InputMap} +InputGroup :: union {PluginEditorAction, EditorAction, InputMap} Action :: struct { action: InputGroup, description: string, @@ -97,6 +98,18 @@ delete_input_map :: proc(input_map: ^InputMap) { // NOTE(pcleavelin): might be a bug in the compiler where it can't coerce // `EditorAction` to `InputGroup` when given as a proc parameter, that is why there // are two functions +register_plugin_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: PluginEditorAction, description: string = "") { + if ok := key in input_map.key_actions; ok { + // TODO: log that key is already registered + fmt.eprintln("plugin key already registered with single action", key); + } + + input_map.key_actions[key] = Action { + action = action, + description = description, + }; +} + register_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction, description: string = "") { if ok := key in input_map.key_actions; ok { // TODO: log that key is already registered @@ -145,5 +158,5 @@ register_ctrl_key_action_group :: proc(input_map: ^InputMap, key: raylib.Keyboar }; } -register_key_action :: proc{register_key_action_single, register_key_action_group}; +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}; diff --git a/src/main.odin b/src/main.odin index 4c18187..c611d5d 100644 --- a/src/main.odin +++ b/src/main.odin @@ -29,6 +29,8 @@ do_normal_mode :: proc(state: ^State, buffer: ^FileBuffer) { for key, action in &state.current_input_map.ctrl_key_actions { if raylib.IsKeyPressed(key) { switch value in action.action { + case core.PluginEditorAction: + value(state.plugin_vtable); case core.EditorAction: value(state); case core.InputMap: @@ -40,6 +42,8 @@ do_normal_mode :: proc(state: ^State, buffer: ^FileBuffer) { for key, action in state.current_input_map.key_actions { if raylib.IsKeyPressed(key) { switch value in action.action { + case core.PluginEditorAction: + value(state.plugin_vtable); case core.EditorAction: value(state); case core.InputMap: @@ -90,10 +94,10 @@ switch_to_buffer :: proc(state: ^State, item: ^ui.MenuBarItem) { } register_default_leader_actions :: proc(input_map: ^core.InputMap) { - core.register_key_action(input_map, .B, proc(state: ^State) { - state.window = ui.create_buffer_list_window(); - state.current_input_map = &state.window.input_map; - }, "show list of open buffers"); + // core.register_key_action(input_map, .B, proc(state: ^State) { + // state.window = ui.create_buffer_list_window(); + // state.current_input_map = &state.window.input_map; + // }, "show list of open buffers"); core.register_key_action(input_map, .R, proc(state: ^State) { state.window = ui.create_grep_window(); state.current_input_map = &state.window.input_map; @@ -233,6 +237,59 @@ main :: proc() { state.highlighters[extension] = on_color_buffer; } }, + register_input_group = proc "c" (input_map: rawptr, key: plugin.Key, register_group: plugin.InputGroupProc) { + context = state.ctx; + + to_be_edited_map: ^core.InputMap = nil; + key := raylib.KeyboardKey(int(key)); + + if input_map != nil { + to_be_edited_map = transmute(^core.InputMap)input_map; + } else { + to_be_edited_map = state.current_input_map; + } + + if action, exists := to_be_edited_map.key_actions[key]; exists { + switch value in action.action { + case core.PluginEditorAction: + fmt.eprintln("Plugin attempted to register input group on existing key action (added from Plugin)"); + case core.EditorAction: + fmt.eprintln("Plugin attempted to register input group on existing key action"); + case core.InputMap: + input_map := &(&to_be_edited_map.key_actions[key]).action.(core.InputMap); + register_group(state.plugin_vtable, transmute(rawptr)input_map); + } + } else { + core.register_key_action(to_be_edited_map, key, core.new_input_map(), "PLUGIN INPUT GROUP"); + register_group(state.plugin_vtable, &(&to_be_edited_map.key_actions[key]).action.(core.InputMap)); + } + }, + register_input = proc "c" (input_map: rawptr, key: plugin.Key, input_action: plugin.InputActionProc, description: cstring) { + context = state.ctx; + + to_be_edited_map: ^core.InputMap = nil; + key := raylib.KeyboardKey(int(key)); + description := strings.clone(string(description)); + + if input_map != nil { + to_be_edited_map = transmute(^core.InputMap)input_map; + } else { + to_be_edited_map = state.current_input_map; + } + + if action, exists := to_be_edited_map.key_actions[key]; exists { + switch value in action.action { + case core.PluginEditorAction: + fmt.eprintln("Plugin attempted to register key action on existing key action (added from Plugin)"); + case core.EditorAction: + fmt.eprintln("Plugin attempted to register input key action on existing key action"); + case core.InputMap: + fmt.eprintln("Plugin attempted to register input key action on existing input group"); + } + } else { + core.register_key_action(to_be_edited_map, key, input_action, description); + } + }, iter = plugin.Iterator { get_current_buffer_iterator = proc "c" () -> plugin.BufferIter { context = state.ctx; diff --git a/src/plugin/plugin.odin b/src/plugin/plugin.odin index 6db24b0..19ab51f 100644 --- a/src/plugin/plugin.odin +++ b/src/plugin/plugin.odin @@ -7,7 +7,6 @@ import "core:fmt" OnInitializeProc :: proc "c" (plugin: Plugin); OnExitProc :: proc "c" (/* probably needs some state eventually */); OnDrawProc :: proc "c" (plugin: Plugin); -OnColorBufferProc :: proc "c" (plugin: Plugin, buffer: rawptr); Interface :: struct { on_initialize: OnInitializeProc, on_exit: OnExitProc, @@ -64,12 +63,139 @@ Iterator :: struct { until_end_of_word: rawptr, } +Key :: enum { + KEY_NULL = 0, // Key: NULL, used for no key pressed + // Alphanumeric keys + APOSTROPHE = 39, // Key: ' + COMMA = 44, // Key: , + MINUS = 45, // Key: - + PERIOD = 46, // Key: . + SLASH = 47, // Key: / + ZERO = 48, // Key: 0 + ONE = 49, // Key: 1 + TWO = 50, // Key: 2 + THREE = 51, // Key: 3 + FOUR = 52, // Key: 4 + FIVE = 53, // Key: 5 + SIX = 54, // Key: 6 + SEVEN = 55, // Key: 7 + EIGHT = 56, // Key: 8 + NINE = 57, // Key: 9 + SEMICOLON = 59, // Key: ; + EQUAL = 61, // Key: = + A = 65, // Key: A | a + B = 66, // Key: B | b + C = 67, // Key: C | c + D = 68, // Key: D | d + E = 69, // Key: E | e + F = 70, // Key: F | f + G = 71, // Key: G | g + H = 72, // Key: H | h + I = 73, // Key: I | i + J = 74, // Key: J | j + K = 75, // Key: K | k + L = 76, // Key: L | l + M = 77, // Key: M | m + N = 78, // Key: N | n + O = 79, // Key: O | o + P = 80, // Key: P | p + Q = 81, // Key: Q | q + R = 82, // Key: R | r + S = 83, // Key: S | s + T = 84, // Key: T | t + U = 85, // Key: U | u + V = 86, // Key: V | v + W = 87, // Key: W | w + X = 88, // Key: X | x + Y = 89, // Key: Y | y + Z = 90, // Key: Z | z + LEFT_BRACKET = 91, // Key: [ + BACKSLASH = 92, // Key: '\' + RIGHT_BRACKET = 93, // Key: ] + GRAVE = 96, // Key: ` + // Function keys + SPACE = 32, // Key: Space + ESCAPE = 256, // Key: Esc + ENTER = 257, // Key: Enter + TAB = 258, // Key: Tab + BACKSPACE = 259, // Key: Backspace + INSERT = 260, // Key: Ins + DELETE = 261, // Key: Del + RIGHT = 262, // Key: Cursor right + LEFT = 263, // Key: Cursor left + DOWN = 264, // Key: Cursor down + UP = 265, // Key: Cursor up + PAGE_UP = 266, // Key: Page up + PAGE_DOWN = 267, // Key: Page down + HOME = 268, // Key: Home + END = 269, // Key: End + CAPS_LOCK = 280, // Key: Caps lock + SCROLL_LOCK = 281, // Key: Scroll down + NUM_LOCK = 282, // Key: Num lock + PRINT_SCREEN = 283, // Key: Print screen + PAUSE = 284, // Key: Pause + F1 = 290, // Key: F1 + F2 = 291, // Key: F2 + F3 = 292, // Key: F3 + F4 = 293, // Key: F4 + F5 = 294, // Key: F5 + F6 = 295, // Key: F6 + F7 = 296, // Key: F7 + F8 = 297, // Key: F8 + F9 = 298, // Key: F9 + F10 = 299, // Key: F10 + F11 = 300, // Key: F11 + F12 = 301, // Key: F12 + LEFT_SHIFT = 340, // Key: Shift left + LEFT_CONTROL = 341, // Key: Control left + LEFT_ALT = 342, // Key: Alt left + LEFT_SUPER = 343, // Key: Super left + RIGHT_SHIFT = 344, // Key: Shift right + RIGHT_CONTROL = 345, // Key: Control right + RIGHT_ALT = 346, // Key: Alt right + RIGHT_SUPER = 347, // Key: Super right + KB_MENU = 348, // Key: KB menu + // Keypad keys + KP_0 = 320, // Key: Keypad 0 + KP_1 = 321, // Key: Keypad 1 + KP_2 = 322, // Key: Keypad 2 + KP_3 = 323, // Key: Keypad 3 + KP_4 = 324, // Key: Keypad 4 + KP_5 = 325, // Key: Keypad 5 + KP_6 = 326, // Key: Keypad 6 + KP_7 = 327, // Key: Keypad 7 + KP_8 = 328, // Key: Keypad 8 + KP_9 = 329, // Key: Keypad 9 + KP_DECIMAL = 330, // Key: Keypad . + KP_DIVIDE = 331, // Key: Keypad / + KP_MULTIPLY = 332, // Key: Keypad * + KP_SUBTRACT = 333, // Key: Keypad - + KP_ADD = 334, // Key: Keypad + + KP_ENTER = 335, // Key: Keypad Enter + KP_EQUAL = 336, // Key: Keypad = + // Android key buttons + BACK = 4, // Key: Android back button + MENU = 82, // Key: Android menu button + VOLUME_UP = 24, // Key: Android volume up button + VOLUME_DOWN = 25, // Key: Android volume down button +} + + +OnColorBufferProc :: proc "c" (plugin: Plugin, buffer: rawptr); +InputGroupProc :: proc "c" (plugin: Plugin, input_map: rawptr); +InputActionProc :: proc "c" (plugin: Plugin); +WindowInputProc :: proc "c" (plugin: Plugin, window: rawptr); Plugin :: struct { state: rawptr, iter: Iterator, buffer: Buffer, register_highlighter: proc "c" (extension: cstring, on_color_buffer: OnColorBufferProc), + + register_input_group: proc "c" (input_map: rawptr, key: Key, register_group: InputGroupProc), + register_input: proc "c" (input_map: rawptr, key: Key, input_action: InputActionProc, description: cstring), + + create_window: proc "c" (register_group: InputGroupProc) -> rawptr, } load_proc_address :: proc(lib_path: string, library: dynlib.Library, symbol: string, $ProcType: typeid) -> ProcType