get started moving buffer search window to plugin

plugins
Patrick Cleavelin 2024-01-06 15:13:06 -06:00
parent 5b9b7889c6
commit 198e314953
6 changed files with 241 additions and 9 deletions

View File

@ -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

View File

@ -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!");
}

View File

@ -1,4 +1,4 @@
// The default syntax highlighter plugin for Odin
// The default syntax highlighter plugin for Odin & Rust
package highlighter;
import "core:runtime"

View File

@ -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};

View File

@ -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;

View File

@ -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