yay, input mapping!
parent
c0e980f406
commit
2a5a5af40f
|
@ -1,5 +1,6 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
import "vendor:raylib"
|
import "vendor:raylib"
|
||||||
|
|
||||||
Mode :: enum {
|
Mode :: enum {
|
||||||
|
@ -17,6 +18,69 @@ State :: struct {
|
||||||
current_buffer: int,
|
current_buffer: int,
|
||||||
buffers: [dynamic]FileBuffer,
|
buffers: [dynamic]FileBuffer,
|
||||||
|
|
||||||
|
// TODO: replace this with generic pointer to floating window
|
||||||
buffer_list_window_is_visible: bool,
|
buffer_list_window_is_visible: bool,
|
||||||
buffer_list_window_selected_buffer: int,
|
buffer_list_window_selected_buffer: int,
|
||||||
|
buffer_list_window_input_map: InputMap,
|
||||||
|
|
||||||
|
input_map: InputMap,
|
||||||
|
current_input_map: ^InputMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EditorAction :: proc(state: ^State);
|
||||||
|
InputGroup :: union {EditorAction, InputMap}
|
||||||
|
InputMap :: struct {
|
||||||
|
key_actions: map[raylib.KeyboardKey]InputGroup,
|
||||||
|
ctrl_key_actions: map[raylib.KeyboardKey]InputGroup,
|
||||||
|
}
|
||||||
|
|
||||||
|
new_input_map :: proc() -> InputMap {
|
||||||
|
input_map := InputMap {
|
||||||
|
key_actions = make(map[raylib.KeyboardKey]InputGroup),
|
||||||
|
ctrl_key_actions = make(map[raylib.KeyboardKey]InputGroup),
|
||||||
|
}
|
||||||
|
|
||||||
|
return input_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction) {
|
||||||
|
if ok := key in input_map.key_actions; ok {
|
||||||
|
// TODO: log that key is already registered
|
||||||
|
fmt.println("key already registered with single action", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
input_map.key_actions[key] = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup) {
|
||||||
|
if ok := key in input_map.key_actions; ok {
|
||||||
|
// TODO: log that key is already registered
|
||||||
|
fmt.println("key already registered with single action", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
input_map.key_actions[key] = input_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_ctrl_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction) {
|
||||||
|
if ok := key in input_map.key_actions; ok {
|
||||||
|
// TODO: log that key is already registered
|
||||||
|
fmt.println("key already registered with single action", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
input_map.ctrl_key_actions[key] = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_ctrl_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup) {
|
||||||
|
if ok := key in input_map.key_actions; ok {
|
||||||
|
// TODO: log that key is already registered
|
||||||
|
fmt.println("key already registered with single action", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
input_map.ctrl_key_actions[key] = input_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_key_action :: proc{register_key_action_single, register_key_action_group};
|
||||||
|
register_ctrl_key_action :: proc{register_ctrl_key_action_single, register_ctrl_key_action_group};
|
||||||
|
|
123
src/main.odin
123
src/main.odin
|
@ -18,33 +18,30 @@ FileBuffer :: core.FileBuffer;
|
||||||
|
|
||||||
// TODO: use buffer list in state
|
// TODO: use buffer list in state
|
||||||
do_normal_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
do_normal_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||||
if raylib.IsKeyPressed(.I) {
|
if state.current_input_map != nil {
|
||||||
state.mode = .Insert;
|
if raylib.IsKeyDown(.LEFT_CONTROL) {
|
||||||
return;
|
for key, action in state.current_input_map.ctrl_key_actions {
|
||||||
}
|
if raylib.IsKeyPressed(key) {
|
||||||
|
switch value in action {
|
||||||
if raylib.IsKeyPressed(.W) {
|
case core.EditorAction:
|
||||||
core.move_cursor_forward_start_of_word(buffer);
|
value(state);
|
||||||
}
|
case core.InputMap:
|
||||||
|
// TODO: make this the current input map and display it
|
||||||
if raylib.IsKeyPressed(.K) {
|
}
|
||||||
core.move_cursor_up(buffer);
|
}
|
||||||
}
|
}
|
||||||
if raylib.IsKeyPressed(.J) {
|
} else {
|
||||||
core.move_cursor_down(buffer);
|
for key, action in state.current_input_map.key_actions {
|
||||||
}
|
if raylib.IsKeyPressed(key) {
|
||||||
if raylib.IsKeyPressed(.H) {
|
switch value in action {
|
||||||
core.move_cursor_left(buffer);
|
case core.EditorAction:
|
||||||
}
|
value(state);
|
||||||
if raylib.IsKeyPressed(.L) {
|
case core.InputMap:
|
||||||
core.move_cursor_right(buffer);
|
// TODO: make this the current input map and display it
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if raylib.IsKeyDown(.LEFT_CONTROL) && raylib.IsKeyDown(.U) {
|
}
|
||||||
core.scroll_file_buffer(buffer, .Up);
|
}
|
||||||
}
|
|
||||||
if raylib.IsKeyDown(.LEFT_CONTROL) && raylib.IsKeyDown(.D) {
|
|
||||||
core.scroll_file_buffer(buffer, .Down);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,10 +83,77 @@ switch_to_buffer :: proc(state: ^State, item: ^ui.MenuBarItem) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register_default_input_actions :: proc(input_map: ^core.InputMap) {
|
||||||
|
core.register_key_action(input_map, .W, proc(state: ^State) {
|
||||||
|
core.move_cursor_forward_start_of_word(&state.buffers[state.current_buffer]);
|
||||||
|
});
|
||||||
|
|
||||||
|
core.register_key_action(input_map, .K, proc(state: ^State) {
|
||||||
|
core.move_cursor_up(&state.buffers[state.current_buffer]);
|
||||||
|
});
|
||||||
|
core.register_key_action(input_map, .J, proc(state: ^State) {
|
||||||
|
core.move_cursor_down(&state.buffers[state.current_buffer]);
|
||||||
|
});
|
||||||
|
core.register_key_action(input_map, .H, proc(state: ^State) {
|
||||||
|
core.move_cursor_left(&state.buffers[state.current_buffer]);
|
||||||
|
});
|
||||||
|
core.register_key_action(input_map, .L, proc(state: ^State) {
|
||||||
|
core.move_cursor_right(&state.buffers[state.current_buffer]);
|
||||||
|
});
|
||||||
|
|
||||||
|
core.register_ctrl_key_action(input_map, .U, proc(state: ^State) {
|
||||||
|
core.scroll_file_buffer(&state.buffers[state.current_buffer], .Up);
|
||||||
|
});
|
||||||
|
core.register_ctrl_key_action(input_map, .D, proc(state: ^State) {
|
||||||
|
core.scroll_file_buffer(&state.buffers[state.current_buffer], .Down);
|
||||||
|
});
|
||||||
|
|
||||||
|
core.register_key_action(input_map, .B, proc(state: ^State) {
|
||||||
|
state.buffer_list_window_is_visible = true;
|
||||||
|
state.current_input_map = &state.buffer_list_window_input_map;
|
||||||
|
});
|
||||||
|
|
||||||
|
core.register_key_action(input_map, .I, proc(state: ^State) {
|
||||||
|
state.mode = .Insert;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
register_buffer_list_input_actions :: proc(input_map: ^core.InputMap) {
|
||||||
|
core.register_key_action(input_map, .K, proc(state: ^State) {
|
||||||
|
if state.buffer_list_window_selected_buffer > 0 {
|
||||||
|
state.buffer_list_window_selected_buffer -= 1;
|
||||||
|
} else {
|
||||||
|
state.buffer_list_window_selected_buffer = len(state.buffers)-1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
core.register_key_action(input_map, .J, proc(state: ^State) {
|
||||||
|
if state.buffer_list_window_selected_buffer >= len(state.buffers)-1 {
|
||||||
|
state.buffer_list_window_selected_buffer = 0;
|
||||||
|
} else {
|
||||||
|
state.buffer_list_window_selected_buffer += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
core.register_key_action(input_map, .ENTER, proc(state: ^State) {
|
||||||
|
state.current_buffer = state.buffer_list_window_selected_buffer;
|
||||||
|
|
||||||
|
state.buffer_list_window_is_visible = false;
|
||||||
|
state.current_input_map = &state.input_map;
|
||||||
|
});
|
||||||
|
|
||||||
|
core.register_key_action(input_map, .Q, proc(state: ^State) {
|
||||||
|
state.buffer_list_window_is_visible = false;
|
||||||
|
state.current_input_map = &state.input_map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
state := State {
|
state := State {
|
||||||
buffer_list_window_is_visible = true,
|
input_map = core.new_input_map(),
|
||||||
|
buffer_list_window_input_map = core.new_input_map(),
|
||||||
};
|
};
|
||||||
|
state.current_input_map = &state.input_map;
|
||||||
|
register_default_input_actions(&state.input_map);
|
||||||
|
register_buffer_list_input_actions(&state.buffer_list_window_input_map);
|
||||||
|
|
||||||
for arg in os.args[1:] {
|
for arg in os.args[1:] {
|
||||||
buffer, err := core.new_file_buffer(context.allocator, arg);
|
buffer, err := core.new_file_buffer(context.allocator, arg);
|
||||||
|
@ -133,7 +197,8 @@ main :: proc() {
|
||||||
|
|
||||||
buffer := &state.buffers[state.current_buffer];
|
buffer := &state.buffers[state.current_buffer];
|
||||||
|
|
||||||
buffer.glyph_buffer_height = math.min(256, int((state.screen_height - 32 - core.source_font_height) / core.source_font_height));
|
buffer.glyph_buffer_height = math.min(256, int((state.screen_height - core.source_font_height*2) / core.source_font_height)) + 1;
|
||||||
|
buffer.glyph_buffer_width = math.min(256, int((state.screen_width - core.source_font_width) / core.source_font_width));
|
||||||
|
|
||||||
{
|
{
|
||||||
raylib.BeginDrawing();
|
raylib.BeginDrawing();
|
||||||
|
|
Loading…
Reference in New Issue