QOL jump stack
This commit is contained in:
parent
322f690afc
commit
50c53649a2
|
@ -123,6 +123,9 @@ CUSTOM_COMMAND_SIG(cmd_alt_enter_behavior)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// Column Alignment
|
||||||
|
|
||||||
function i64
|
function i64
|
||||||
qol_seek_char(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 start_pos, u8 target_char){
|
qol_seek_char(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 start_pos, u8 target_char){
|
||||||
Scratch_Block scratch(app);
|
Scratch_Block scratch(app);
|
||||||
|
@ -202,6 +205,157 @@ CUSTOM_DOC("[QOL] Writes as many spaces needed for bumping to column")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// Jumping
|
||||||
|
|
||||||
|
struct QOL_Point
|
||||||
|
{
|
||||||
|
Buffer_ID buffer;
|
||||||
|
i64 pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QOL_View_Jumps
|
||||||
|
{
|
||||||
|
b32 check;
|
||||||
|
QOL_Point point;
|
||||||
|
i64 bot, pos, top;
|
||||||
|
Point_Stack_Slot ring[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
function QOL_View_Jumps*
|
||||||
|
qol_jumps(Application_Links *app, View_ID view)
|
||||||
|
{
|
||||||
|
Managed_Scope scope = view_get_managed_scope(app, view);
|
||||||
|
return scope_attachment(app, scope, qol_view_jumps, QOL_View_Jumps);
|
||||||
|
}
|
||||||
|
|
||||||
|
function QOL_Point
|
||||||
|
qol_current_point(Application_Links *app)
|
||||||
|
{
|
||||||
|
QOL_Point point = {};
|
||||||
|
View_ID view = get_active_view(app, Access_ReadVisible);
|
||||||
|
point.buffer = view_get_buffer(app, view, Access_ReadVisible);
|
||||||
|
point.pos = view_get_cursor_pos(app, view);
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
function QOL_Point
|
||||||
|
qol_point_from_slot(Application_Links *app, Point_Stack_Slot slot)
|
||||||
|
{
|
||||||
|
Marker *marker = (Marker*)managed_object_get_pointer(app, slot.object);
|
||||||
|
return marker == 0 ? QOL_Point{-1,-1} : QOL_Point{slot.buffer, marker->pos};
|
||||||
|
}
|
||||||
|
|
||||||
|
function Point_Stack_Slot
|
||||||
|
qol_alloc_slot_from_point(Application_Links *app, QOL_Point point)
|
||||||
|
{
|
||||||
|
Point_Stack_Slot slot = {};
|
||||||
|
Managed_Object object = alloc_buffer_markers_on_buffer(app, point.buffer, 1, 0);
|
||||||
|
Marker *marker = (Marker*)managed_object_get_pointer(app, object);
|
||||||
|
marker->pos = point.pos;
|
||||||
|
marker->lean_right = false;
|
||||||
|
slot.buffer = point.buffer;
|
||||||
|
slot.object = object;
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
qol_free_slot(Application_Links *app, Point_Stack_Slot slot)
|
||||||
|
{
|
||||||
|
managed_object_free(app, slot.object);
|
||||||
|
}
|
||||||
|
|
||||||
|
function b32
|
||||||
|
qol_is_jump(Application_Links *app, QOL_Point a, QOL_Point b)
|
||||||
|
{
|
||||||
|
if (!buffer_exists(app, a.buffer)){ return false; }
|
||||||
|
return a.buffer != b.buffer || 1 < range_size(get_line_range_from_pos_range(app, a.buffer, Ii64(a.pos, b.pos)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
qol_pre_command_inner(Application_Links *app, Managed_Scope scope)
|
||||||
|
{
|
||||||
|
QOL_View_Jumps *jumps = scope_attachment(app, scope, qol_view_jumps, QOL_View_Jumps);
|
||||||
|
jumps->check = true;
|
||||||
|
jumps->point = qol_current_point(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
qol_post_command_inner(Application_Links *app, Managed_Scope scope)
|
||||||
|
{
|
||||||
|
QOL_View_Jumps *jumps = scope_attachment(app, scope, qol_view_jumps, QOL_View_Jumps);
|
||||||
|
QOL_Point point = qol_current_point(app);
|
||||||
|
if (jumps != 0 && jumps->check && qol_is_jump(app, jumps->point, point))
|
||||||
|
{
|
||||||
|
i64 cap = ArrayCount(jumps->ring);
|
||||||
|
if (jumps->pos - jumps->bot == cap-1)
|
||||||
|
{
|
||||||
|
qol_free_slot(app, jumps->ring[jumps->bot++ % cap]);
|
||||||
|
}
|
||||||
|
if (2*cap <= jumps->pos)
|
||||||
|
{
|
||||||
|
jumps->top -= cap;
|
||||||
|
jumps->bot -= cap;
|
||||||
|
}
|
||||||
|
jumps->ring[jumps->pos++ % cap] = qol_alloc_slot_from_point(app, jumps->point);
|
||||||
|
jumps->top = jumps->pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
qol_jump_to_point(Application_Links *app, View_ID view, QOL_Point point)
|
||||||
|
{
|
||||||
|
if (point.buffer != view_get_buffer(app, view, Access_Always))
|
||||||
|
{
|
||||||
|
view_set_buffer(app, view, point.buffer, 0);
|
||||||
|
view_set_cursor(app, view, seek_pos(point.pos));
|
||||||
|
center_view(app);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Range_i64 range = Ii64(view_get_cursor_pos(app, view), point.pos);
|
||||||
|
Range_i64 lines = get_line_range_from_pos_range(app, point.buffer, range);
|
||||||
|
f32 y_diff = view_line_y_difference(app, view, lines.max, lines.min);
|
||||||
|
view_set_cursor(app, view, seek_pos(point.pos));
|
||||||
|
if (rect_height(view_get_buffer_region(app, view)) < y_diff)
|
||||||
|
{
|
||||||
|
center_view(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(qol_jump_down)
|
||||||
|
CUSTOM_DOC("[QOL] Jump down the view's jump stack")
|
||||||
|
{
|
||||||
|
View_ID view = get_active_view(app, Access_ReadVisible);
|
||||||
|
QOL_View_Jumps *jumps = qol_jumps(app, view);
|
||||||
|
jumps->check = false;
|
||||||
|
|
||||||
|
if (jumps->pos == jumps->bot){ return; }
|
||||||
|
QOL_Point point = qol_point_from_slot(app, ArraySafe(jumps->ring, --jumps->pos));
|
||||||
|
if (!buffer_exists(app, point.buffer)){ return; }
|
||||||
|
|
||||||
|
if (jumps->pos+1 == jumps->top){
|
||||||
|
ArraySafe(jumps->ring, jumps->top++) = qol_alloc_slot_from_point(app, qol_current_point(app));
|
||||||
|
}
|
||||||
|
qol_jump_to_point(app, view, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(qol_jump_up)
|
||||||
|
CUSTOM_DOC("[QOL] Jump back up the view's jump stack")
|
||||||
|
{
|
||||||
|
View_ID view = get_active_view(app, Access_ReadVisible);
|
||||||
|
QOL_View_Jumps *jumps = qol_jumps(app, view);
|
||||||
|
jumps->check = false;
|
||||||
|
|
||||||
|
if (jumps->top <= jumps->pos+1){ return; }
|
||||||
|
QOL_Point point = qol_point_from_slot(app, ArraySafe(jumps->ring, ++jumps->pos));
|
||||||
|
if (!buffer_exists(app, point.buffer)){ return; }
|
||||||
|
qol_jump_to_point(app, view, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// Bindings
|
||||||
|
|
||||||
function void
|
function void
|
||||||
bindings_cmd_misc(Mapping* m, Command_Map* map)
|
bindings_cmd_misc(Mapping* m, Command_Map* map)
|
||||||
|
@ -310,11 +464,16 @@ custom_keyboard_bindings()
|
||||||
Bind(unindent_range, KeyCode_Tab, KeyCode_Shift);
|
Bind(unindent_range, KeyCode_Tab, KeyCode_Shift);
|
||||||
Bind(indent_range, KeyCode_Tab);
|
Bind(indent_range, KeyCode_Tab);
|
||||||
|
|
||||||
|
// Column Alignment
|
||||||
Bind(qol_column_toggle, KeyCode_BackwardSlash, key_alt);
|
Bind(qol_column_toggle, KeyCode_BackwardSlash, key_alt);
|
||||||
Bind(qol_write_space, KeyCode_Space, key_alt, KeyCode_Shift);
|
Bind(qol_write_space, KeyCode_Space, key_alt, KeyCode_Shift);
|
||||||
Bind(qol_char_forward, KeyCode_L, key_alt);
|
Bind(qol_char_forward, KeyCode_L, key_alt);
|
||||||
Bind(qol_char_backward, KeyCode_J, key_alt);
|
Bind(qol_char_backward, KeyCode_J, key_alt);
|
||||||
|
|
||||||
|
// Jumping
|
||||||
|
Bind(qol_jump_down, KeyCode_LeftBracket);
|
||||||
|
Bind(qol_jump_up, KeyCode_RightBracket);
|
||||||
|
|
||||||
// Macros
|
// Macros
|
||||||
Bind(keyboard_macro_start_recording, KeyCode_1, key_alt);
|
Bind(keyboard_macro_start_recording, KeyCode_1, key_alt);
|
||||||
Bind(keyboard_macro_finish_recording, KeyCode_2, key_alt);
|
Bind(keyboard_macro_finish_recording, KeyCode_2, key_alt);
|
||||||
|
|
|
@ -140,11 +140,13 @@ CUSTOM_DOC("Input consumption loop for default view behavior")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): Run the command and pre/post command stuff
|
// NOTE(allen): Run the command and pre/post command stuff
|
||||||
|
qol_pre_command_inner(app, scope);
|
||||||
default_pre_command(app, scope);
|
default_pre_command(app, scope);
|
||||||
ProfileCloseNow(view_input_profile);
|
ProfileCloseNow(view_input_profile);
|
||||||
map_result.command(app);
|
map_result.command(app);
|
||||||
ProfileScope(app, "after view input");
|
ProfileScope(app, "after view input");
|
||||||
default_post_command(app, scope);
|
default_post_command(app, scope);
|
||||||
|
qol_post_command_inner(app, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,9 @@
|
||||||
global u8 qol_target_char;
|
global u8 qol_target_char;
|
||||||
global Buffer_Cursor qol_col_cursor = {-1};
|
global Buffer_Cursor qol_col_cursor = {-1};
|
||||||
|
|
||||||
|
CUSTOM_ID(attachment, qol_view_jumps);
|
||||||
|
|
||||||
|
function void qol_pre_command_inner(Application_Links *app, Managed_Scope scope);
|
||||||
|
function void qol_post_command_inner(Application_Links *app, Managed_Scope scope);
|
||||||
|
|
||||||
#endif //FCODER_QOL_H
|
#endif //FCODER_QOL_H
|
||||||
|
|
Loading…
Reference in New Issue