support ctrl modified inputs, display keybind helper in sub-commands
parent
2a5a5af40f
commit
8160038fd3
|
@ -29,15 +29,19 @@ State :: struct {
|
|||
|
||||
EditorAction :: proc(state: ^State);
|
||||
InputGroup :: union {EditorAction, InputMap}
|
||||
Action :: struct {
|
||||
action: InputGroup,
|
||||
description: string,
|
||||
}
|
||||
InputMap :: struct {
|
||||
key_actions: map[raylib.KeyboardKey]InputGroup,
|
||||
ctrl_key_actions: map[raylib.KeyboardKey]InputGroup,
|
||||
key_actions: map[raylib.KeyboardKey]Action,
|
||||
ctrl_key_actions: map[raylib.KeyboardKey]Action,
|
||||
}
|
||||
|
||||
new_input_map :: proc() -> InputMap {
|
||||
input_map := InputMap {
|
||||
key_actions = make(map[raylib.KeyboardKey]InputGroup),
|
||||
ctrl_key_actions = make(map[raylib.KeyboardKey]InputGroup),
|
||||
key_actions = make(map[raylib.KeyboardKey]Action),
|
||||
ctrl_key_actions = make(map[raylib.KeyboardKey]Action),
|
||||
}
|
||||
|
||||
return input_map;
|
||||
|
@ -46,40 +50,52 @@ new_input_map :: proc() -> 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_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction) {
|
||||
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
|
||||
fmt.println("key already registered with single action", key);
|
||||
fmt.eprintln("key already registered with single action", key);
|
||||
}
|
||||
|
||||
input_map.key_actions[key] = action;
|
||||
input_map.key_actions[key] = Action {
|
||||
action = action,
|
||||
description = description,
|
||||
};
|
||||
}
|
||||
|
||||
register_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup) {
|
||||
register_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup, description: string = "") {
|
||||
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);
|
||||
fmt.eprintln("key already registered with single action", key);
|
||||
}
|
||||
|
||||
input_map.key_actions[key] = input_group;
|
||||
input_map.key_actions[key] = Action {
|
||||
action = input_group,
|
||||
description = description,
|
||||
};
|
||||
}
|
||||
|
||||
register_ctrl_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction) {
|
||||
register_ctrl_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
|
||||
fmt.println("key already registered with single action", key);
|
||||
fmt.eprintln("key already registered with single action", key);
|
||||
}
|
||||
|
||||
input_map.ctrl_key_actions[key] = action;
|
||||
input_map.ctrl_key_actions[key] = Action {
|
||||
action = action,
|
||||
description = description,
|
||||
};
|
||||
}
|
||||
|
||||
register_ctrl_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup) {
|
||||
register_ctrl_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup, description: string = "") {
|
||||
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);
|
||||
fmt.eprintln("key already registered with single action", key);
|
||||
}
|
||||
|
||||
input_map.ctrl_key_actions[key] = input_group;
|
||||
input_map.ctrl_key_actions[key] = Action {
|
||||
action = input_group,
|
||||
description = description,
|
||||
};
|
||||
}
|
||||
|
||||
register_key_action :: proc{register_key_action_single, register_key_action_group};
|
||||
|
|
169
src/main.odin
169
src/main.odin
|
@ -20,24 +20,24 @@ FileBuffer :: core.FileBuffer;
|
|||
do_normal_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||
if state.current_input_map != nil {
|
||||
if raylib.IsKeyDown(.LEFT_CONTROL) {
|
||||
for key, action in state.current_input_map.ctrl_key_actions {
|
||||
for key, action in &state.current_input_map.ctrl_key_actions {
|
||||
if raylib.IsKeyPressed(key) {
|
||||
switch value in action {
|
||||
switch value in action.action {
|
||||
case core.EditorAction:
|
||||
value(state);
|
||||
value(state);
|
||||
case core.InputMap:
|
||||
// TODO: make this the current input map and display it
|
||||
state.current_input_map = &(&state.current_input_map.ctrl_key_actions[key]).action.(core.InputMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for key, action in state.current_input_map.key_actions {
|
||||
if raylib.IsKeyPressed(key) {
|
||||
switch value in action {
|
||||
switch value in action.action {
|
||||
case core.EditorAction:
|
||||
value(state);
|
||||
value(state);
|
||||
case core.InputMap:
|
||||
// TODO: make this the current input map and display it
|
||||
state.current_input_map = &(&state.current_input_map.key_actions[key]).action.(core.InputMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,39 +83,44 @@ 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);
|
||||
});
|
||||
|
||||
register_default_leader_actions :: proc(input_map: ^core.InputMap) {
|
||||
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;
|
||||
});
|
||||
}, "show list of open buffers");
|
||||
}
|
||||
|
||||
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]);
|
||||
}, "move forward one word");
|
||||
|
||||
core.register_key_action(input_map, .K, proc(state: ^State) {
|
||||
core.move_cursor_up(&state.buffers[state.current_buffer]);
|
||||
}, "move up one line");
|
||||
core.register_key_action(input_map, .J, proc(state: ^State) {
|
||||
core.move_cursor_down(&state.buffers[state.current_buffer]);
|
||||
}, "move down one line");
|
||||
core.register_key_action(input_map, .H, proc(state: ^State) {
|
||||
core.move_cursor_left(&state.buffers[state.current_buffer]);
|
||||
}, "move left one char");
|
||||
core.register_key_action(input_map, .L, proc(state: ^State) {
|
||||
core.move_cursor_right(&state.buffers[state.current_buffer]);
|
||||
}, "move right one char");
|
||||
|
||||
core.register_ctrl_key_action(input_map, .U, proc(state: ^State) {
|
||||
core.scroll_file_buffer(&state.buffers[state.current_buffer], .Up);
|
||||
}, "scroll buffer up");
|
||||
core.register_ctrl_key_action(input_map, .D, proc(state: ^State) {
|
||||
core.scroll_file_buffer(&state.buffers[state.current_buffer], .Down);
|
||||
}, "scroll buffer up");
|
||||
|
||||
core.register_key_action(input_map, .I, proc(state: ^State) {
|
||||
state.mode = .Insert;
|
||||
});
|
||||
}, "enter insert mode");
|
||||
|
||||
core.register_key_action(input_map, .SPACE, core.new_input_map(), "leader commands");
|
||||
register_default_leader_actions(&(&input_map.key_actions[.SPACE]).action.(core.InputMap));
|
||||
}
|
||||
|
||||
register_buffer_list_input_actions :: proc(input_map: ^core.InputMap) {
|
||||
|
@ -125,25 +130,25 @@ register_buffer_list_input_actions :: proc(input_map: ^core.InputMap) {
|
|||
} else {
|
||||
state.buffer_list_window_selected_buffer = len(state.buffers)-1;
|
||||
}
|
||||
});
|
||||
}, "move selection up");
|
||||
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;
|
||||
}
|
||||
});
|
||||
}, "move selection down");
|
||||
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;
|
||||
});
|
||||
}, "switch to file");
|
||||
|
||||
core.register_key_action(input_map, .Q, proc(state: ^State) {
|
||||
state.buffer_list_window_is_visible = false;
|
||||
state.current_input_map = &state.input_map;
|
||||
});
|
||||
}, "close window");
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
|
@ -210,27 +215,95 @@ main :: proc() {
|
|||
|
||||
raylib.DrawRectangle(0, state.screen_height - core.source_font_height, state.screen_width, core.source_font_height, theme.get_palette_raylib_color(.Background2));
|
||||
|
||||
line_info_text := raylib.TextFormat("Line: %d, Col: %d --- Slice Index: %d, Content Index: %d", buffer.cursor.line + 1, buffer.cursor.col + 1, buffer.cursor.index.slice_index, buffer.cursor.index.content_index);
|
||||
line_info_text := raylib.TextFormat(
|
||||
"Line: %d, Col: %d --- Slice Index: %d, Content Index: %d",
|
||||
buffer.cursor.line + 1,
|
||||
buffer.cursor.col + 1,
|
||||
buffer.cursor.index.slice_index,
|
||||
buffer.cursor.index.content_index);
|
||||
line_info_width := raylib.MeasureTextEx(font, line_info_text, core.source_font_height, 0).x;
|
||||
|
||||
switch state.mode {
|
||||
case .Normal:
|
||||
raylib.DrawRectangle(0, state.screen_height - core.source_font_height, 8 + len("NORMAL")*core.source_font_width, core.source_font_height, theme.get_palette_raylib_color(.Foreground4));
|
||||
raylib.DrawRectangleV(raylib.Vector2 { f32(state.screen_width) - line_info_width - 8 , f32(state.screen_height - core.source_font_height) }, raylib.Vector2 { 8 + line_info_width, f32(core.source_font_height) }, theme.get_palette_raylib_color(.Foreground4));
|
||||
|
||||
raylib.DrawTextEx(font, "NORMAL", raylib.Vector2 { 4, f32(state.screen_height - core.source_font_height) }, core.source_font_height, 0, theme.get_palette_raylib_color(.Background1));
|
||||
raylib.DrawRectangle(
|
||||
0,
|
||||
state.screen_height - core.source_font_height,
|
||||
8 + len("NORMAL")*core.source_font_width,
|
||||
core.source_font_height,
|
||||
theme.get_palette_raylib_color(.Foreground4));
|
||||
raylib.DrawRectangleV(
|
||||
raylib.Vector2 { f32(state.screen_width) - line_info_width - 8, f32(state.screen_height - core.source_font_height) },
|
||||
raylib.Vector2 { 8 + line_info_width, f32(core.source_font_height) },
|
||||
theme.get_palette_raylib_color(.Foreground4));
|
||||
raylib.DrawTextEx(
|
||||
font,
|
||||
"NORMAL",
|
||||
raylib.Vector2 { 4, f32(state.screen_height - core.source_font_height) },
|
||||
core.source_font_height,
|
||||
0,
|
||||
theme.get_palette_raylib_color(.Background1));
|
||||
case .Insert:
|
||||
raylib.DrawRectangle(0, state.screen_height - core.source_font_height, 8 + len("INSERT")*core.source_font_width, core.source_font_height, theme.get_palette_raylib_color(.Foreground2));
|
||||
raylib.DrawRectangleV(raylib.Vector2 { f32(state.screen_width) - line_info_width - 8 , f32(state.screen_height - core.source_font_height) }, raylib.Vector2 { 8 + line_info_width, f32(core.source_font_height) }, theme.get_palette_raylib_color(.Foreground2));
|
||||
|
||||
raylib.DrawTextEx(font, "INSERT", raylib.Vector2 { 4, f32(state.screen_height - core.source_font_height) }, core.source_font_height, 0, theme.get_palette_raylib_color(.Background1));
|
||||
raylib.DrawRectangle(
|
||||
0,
|
||||
state.screen_height - core.source_font_height,
|
||||
8 + len("INSERT")*core.source_font_width,
|
||||
core.source_font_height,
|
||||
theme.get_palette_raylib_color(.Foreground2));
|
||||
raylib.DrawRectangleV(
|
||||
raylib.Vector2 { f32(state.screen_width) - line_info_width - 8, f32(state.screen_height - core.source_font_height) },
|
||||
raylib.Vector2 { 8 + line_info_width, f32(core.source_font_height) },
|
||||
theme.get_palette_raylib_color(.Foreground2));
|
||||
raylib.DrawTextEx(
|
||||
font,
|
||||
"INSERT",
|
||||
raylib.Vector2 { 4, f32(state.screen_height - core.source_font_height) },
|
||||
core.source_font_height,
|
||||
0,
|
||||
theme.get_palette_raylib_color(.Background1));
|
||||
}
|
||||
|
||||
raylib.DrawTextEx(font, line_info_text, raylib.Vector2 { f32(state.screen_width) - line_info_width - 4, f32(state.screen_height - core.source_font_height) }, core.source_font_height, 0, theme.get_palette_raylib_color(.Background1));
|
||||
raylib.DrawTextEx(
|
||||
font,
|
||||
line_info_text,
|
||||
raylib.Vector2 { f32(state.screen_width) - line_info_width - 4, f32(state.screen_height - core.source_font_height) },
|
||||
core.source_font_height,
|
||||
0,
|
||||
theme.get_palette_raylib_color(.Background1));
|
||||
|
||||
if state.buffer_list_window_is_visible {
|
||||
ui.draw_buffer_list_window(&state);
|
||||
}
|
||||
|
||||
if state.current_input_map != &state.input_map {
|
||||
longest_description := 0;
|
||||
for key, action in state.current_input_map.key_actions {
|
||||
if len(action.description) > longest_description {
|
||||
longest_description = len(action.description);
|
||||
}
|
||||
}
|
||||
longest_description += 4;
|
||||
|
||||
helper_height := i32(core.source_font_height * len(state.current_input_map.key_actions));
|
||||
|
||||
raylib.DrawRectangle(
|
||||
state.screen_width - i32(longest_description * core.source_font_width),
|
||||
state.screen_height - helper_height - 20,
|
||||
i32(longest_description*core.source_font_width),
|
||||
helper_height,
|
||||
theme.get_palette_raylib_color(.Background2));
|
||||
|
||||
index := 0;
|
||||
for key, action in state.current_input_map.key_actions {
|
||||
raylib.DrawTextEx(
|
||||
font,
|
||||
raylib.TextFormat("%s - %s", key, action.description),
|
||||
raylib.Vector2 { f32(state.screen_width - i32(longest_description * core.source_font_width)), f32(state.screen_height - helper_height + i32((index) * core.source_font_height) - 20) },
|
||||
core.source_font_height,
|
||||
0,
|
||||
theme.get_palette_raylib_color(.Foreground1));
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch state.mode {
|
||||
|
|
|
@ -37,8 +37,6 @@ draw_menu_bar_item :: proc(item: ^MenuBarItem, x, y: i32, parent_width, parent_h
|
|||
raylib.DrawRectangle(x, y, parent_width, i32(font_height), theme.get_palette_raylib_color(foreground_color));
|
||||
raylib.DrawTextEx(font, item_text, raylib.Vector2 { f32(x + text_padding), f32(y) }, f32(font_height), 0, theme.get_palette_raylib_color(.Background1));
|
||||
|
||||
//raylib.DrawRectangle(x, y, i32(item_width) + text_padding*2, i32(1 * font_height), theme.get_palette_raylib_color(.Foreground3));
|
||||
|
||||
if item.selected {
|
||||
// TODO: change to parent_width
|
||||
largest_sub_item: int
|
||||
|
@ -49,7 +47,6 @@ draw_menu_bar_item :: proc(item: ^MenuBarItem, x, y: i32, parent_width, parent_h
|
|||
this_width := i32(largest_sub_item) * 8 + text_padding*2;
|
||||
sub_list_x := x;
|
||||
if horizontal {
|
||||
//sub_list_x += i32(largest_sub_item) * 8;
|
||||
sub_list_x += parent_width;
|
||||
}
|
||||
for _, index in item.sub_items {
|
||||
|
|
Loading…
Reference in New Issue