QOL jump stack

This commit is contained in:
Peter Slattery 2025-07-07 14:47:14 -07:00
parent 322f690afc
commit 50c53649a2
3 changed files with 166 additions and 0 deletions

View File

@ -123,6 +123,9 @@ CUSTOM_COMMAND_SIG(cmd_alt_enter_behavior)
}
}
//////////////////////////////////////////////////////////////////
// Column Alignment
function i64
qol_seek_char(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 start_pos, u8 target_char){
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
bindings_cmd_misc(Mapping* m, Command_Map* map)
@ -310,11 +464,16 @@ custom_keyboard_bindings()
Bind(unindent_range, KeyCode_Tab, KeyCode_Shift);
Bind(indent_range, KeyCode_Tab);
// Column Alignment
Bind(qol_column_toggle, KeyCode_BackwardSlash, key_alt);
Bind(qol_write_space, KeyCode_Space, key_alt, KeyCode_Shift);
Bind(qol_char_forward, KeyCode_L, key_alt);
Bind(qol_char_backward, KeyCode_J, key_alt);
// Jumping
Bind(qol_jump_down, KeyCode_LeftBracket);
Bind(qol_jump_up, KeyCode_RightBracket);
// Macros
Bind(keyboard_macro_start_recording, KeyCode_1, key_alt);
Bind(keyboard_macro_finish_recording, KeyCode_2, key_alt);

View File

@ -140,11 +140,13 @@ CUSTOM_DOC("Input consumption loop for default view behavior")
}
// NOTE(allen): Run the command and pre/post command stuff
qol_pre_command_inner(app, scope);
default_pre_command(app, scope);
ProfileCloseNow(view_input_profile);
map_result.command(app);
ProfileScope(app, "after view input");
default_post_command(app, scope);
qol_post_command_inner(app, scope);
}
}

View File

@ -6,4 +6,9 @@
global u8 qol_target_char;
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