New edit range hook

This commit is contained in:
Allen Webster 2019-03-21 18:27:28 -07:00
parent 5b65686785
commit 3f3a31b114
6 changed files with 62 additions and 133 deletions

View File

@ -1106,6 +1106,8 @@ ENUM(i32, Special_Hook_ID){
/* DOC(TODO) */ /* DOC(TODO) */
special_hook_end_file, special_hook_end_file,
/* DOC(TODO) */ /* DOC(TODO) */
special_hook_file_edit_range,
/* DOC(TODO) */
special_hook_file_edit_finished, special_hook_file_edit_finished,
/* DOC(TODO) */ /* DOC(TODO) */
special_hook_command_caller, special_hook_command_caller,
@ -1137,6 +1139,9 @@ TYPEDEF_FUNC i32 Hook_Function(struct Application_Links *app);
TYPEDEF_FUNC i32 Open_File_Hook_Function(struct Application_Links *app, Buffer_ID buffer_id); TYPEDEF_FUNC i32 Open_File_Hook_Function(struct Application_Links *app, Buffer_ID buffer_id);
#define OPEN_FILE_HOOK_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id) #define OPEN_FILE_HOOK_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id)
TYPEDEF_FUNC i32 File_Edit_Range_Function(struct Application_Links *app, Buffer_ID buffer_id, Range range, String text);
#define FILE_EDIT_RANGE_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id, Range range, String text)
TYPEDEF_FUNC i32 File_Edit_Finished_Function(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count); TYPEDEF_FUNC i32 File_Edit_Finished_Function(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count);
#define FILE_EDIT_FINISHED_SIG(name) i32 name(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count) #define FILE_EDIT_FINISHED_SIG(name) i32 name(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count)

View File

@ -1128,7 +1128,30 @@ OPEN_FILE_HOOK_SIG(default_file_save){
return(0); return(0);
} }
FILE_EDIT_FINISHED_SIG(default_file_edit){ FILE_EDIT_RANGE_SIG(default_file_edit_range){
Buffer_Summary buffer_summary = {};
if (get_buffer_summary(app, buffer_id, AccessAll, &buffer_summary)){
if (!match(make_string(buffer_summary.buffer_name, buffer_summary.buffer_name_len), make_lit_string("*messages*"))){
char space[1024];
String str = make_fixed_width_string(space);
append(&str, "'");
append(&str, make_string(buffer_summary.buffer_name, buffer_summary.buffer_name_len));
append(&str, "' [");
append_int_to_str(&str, range.first);
append(&str, ", ");
append_int_to_str(&str, range.one_past_last);
append(&str, ") '");
append(&str, substr(text, 0, 32));
append(&str, "'\n");
print_message(app, str.str, str.size);
}
}
// no meaning for return
return(0);
}
FILE_EDIT_FINISHED_SIG(default_file_edit_finished){
for (i32 i = 0; i < buffer_id_count; i += 1){ for (i32 i = 0; i < buffer_id_count; i += 1){
#if 0 #if 0
// NOTE(allen|4.0.31): This code is example usage, it's not a particularly nice feature to actually have. // NOTE(allen|4.0.31): This code is example usage, it's not a particularly nice feature to actually have.
@ -1269,7 +1292,9 @@ set_all_default_hooks(Bind_Helper *context){
set_open_file_hook(context, default_file_settings); set_open_file_hook(context, default_file_settings);
set_new_file_hook(context, default_new_file); set_new_file_hook(context, default_new_file);
set_save_file_hook(context, default_file_save); set_save_file_hook(context, default_file_save);
set_file_edit_finished_hook(context, default_file_edit); set_file_edit_range_hook(context, default_file_edit_range);
set_file_edit_finished_hook(context, default_file_edit_finished);
set_file_edit_range_hook(context, default_file_edit_range);
set_end_file_hook(context, end_file_close_jump_list); set_end_file_hook(context, end_file_close_jump_list);

View File

@ -206,6 +206,15 @@ set_end_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
write_unit(helper, unit); write_unit(helper, unit);
} }
static void
set_file_edit_range_hook(Bind_Helper *helper, File_Edit_Range_Function *func){
Binding_Unit unit = {};
unit.type = unit_hook;
unit.hook.hook_id = special_hook_file_edit_range;
unit.hook.func = (void*)func;
write_unit(helper, unit);
}
static void static void
set_file_edit_finished_hook(Bind_Helper *helper, File_Edit_Finished_Function *func){ set_file_edit_finished_hook(Bind_Helper *helper, File_Edit_Finished_Function *func){
Binding_Unit unit = {}; Binding_Unit unit = {};

View File

@ -166,6 +166,7 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){
models->hook_new_file = 0; models->hook_new_file = 0;
models->hook_save_file = 0; models->hook_save_file = 0;
models->hook_end_file = 0; models->hook_end_file = 0;
models->hook_file_edit_range = 0;
models->hook_file_edit_finished = 0; models->hook_file_edit_finished = 0;
models->command_caller = 0; models->command_caller = 0;
models->render_caller = 0; models->render_caller = 0;
@ -367,6 +368,11 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){
models->hook_end_file = (Open_File_Hook_Function*)unit->hook.func; models->hook_end_file = (Open_File_Hook_Function*)unit->hook.func;
}break; }break;
case special_hook_file_edit_range:
{
models->hook_file_edit_range = (File_Edit_Range_Function*)unit->hook.func;
}break;
case special_hook_file_edit_finished: case special_hook_file_edit_finished:
{ {
models->hook_file_edit_finished = (File_Edit_Finished_Function*)unit->hook.func; models->hook_file_edit_finished = (File_Edit_Finished_Function*)unit->hook.func;

View File

@ -50,6 +50,7 @@ struct Models{
Open_File_Hook_Function *hook_new_file; Open_File_Hook_Function *hook_new_file;
Open_File_Hook_Function *hook_save_file; Open_File_Hook_Function *hook_save_file;
Open_File_Hook_Function *hook_end_file; Open_File_Hook_Function *hook_end_file;
File_Edit_Range_Function *hook_file_edit_range;
File_Edit_Finished_Function *hook_file_edit_finished; File_Edit_Finished_Function *hook_file_edit_finished;
Command_Caller_Hook_Function *command_caller; Command_Caller_Hook_Function *command_caller;
Render_Caller_Function *render_caller; Render_Caller_Function *render_caller;

View File

@ -90,9 +90,7 @@ edit_fix_markers__compute_scroll_y(i32 line_height, i32 old_y_val, f32 new_y_val
} }
internal void internal void
edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit_Array edits){ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit edit){
Assert(edits.count > 0);
Partition *part = &models->mem.part; Partition *part = &models->mem.part;
Layout *layout = &models->layout; Layout *layout = &models->layout;
@ -162,15 +160,8 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E
if (cursor_count > 0 || r_cursor_count > 0){ if (cursor_count > 0 || r_cursor_count > 0){
buffer_sort_cursors( cursors, cursor_count); buffer_sort_cursors( cursors, cursor_count);
buffer_sort_cursors(r_cursors, r_cursor_count); buffer_sort_cursors(r_cursors, r_cursor_count);
if (edits.count > 1){
buffer_batch_edit_update_cursors( cursors, cursor_count, edits, false);
buffer_batch_edit_update_cursors(r_cursors, r_cursor_count, edits, true);
}
else{
Edit edit = edits.vals[0];
buffer_update_cursors( cursors, cursor_count, edit.range.first, edit.range.one_past_last, edit.length, false); buffer_update_cursors( cursors, cursor_count, edit.range.first, edit.range.one_past_last, edit.length, false);
buffer_update_cursors(r_cursors, r_cursor_count, edit.range.first, edit.range.one_past_last, edit.length, true); buffer_update_cursors(r_cursors, r_cursor_count, edit.range.first, edit.range.one_past_last, edit.length, true);
}
buffer_unsort_cursors( cursors, cursor_count); buffer_unsort_cursors( cursors, cursor_count);
buffer_unsort_cursors(r_cursors, r_cursor_count); buffer_unsort_cursors(r_cursors, r_cursor_count);
@ -238,14 +229,6 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E
end_temp_memory(cursor_temp); end_temp_memory(cursor_temp);
} }
internal void
edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit edit){
Edit_Array edits = {};
edits.vals = &edit;
edits.count = 1;
edit_fix_markers(system, models, file, edits);
}
internal void internal void
edit_single(System_Functions *system, Models *models, Editing_File *file, Edit edit, Edit_Behaviors behaviors){ edit_single(System_Functions *system, Models *models, Editing_File *file, Edit edit, Edit_Behaviors behaviors){
Mem_Options *mem = &models->mem; Mem_Options *mem = &models->mem;
@ -265,7 +248,12 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Edit e
} }
// NOTE(allen): fixing stuff beforewards???? // NOTE(allen): fixing stuff beforewards????
edit_pre_state_change(system, &mem->heap, models, file); edit_pre_state_change(system, heap, models, file);
// NOTE(allen): edit range hook
if (models->hook_file_edit_range != 0){
models->hook_file_edit_range(&models->app_links, file->id.id, edit.range, make_string(edit.str, edit.length));
}
// NOTE(allen): expand spec, compute shift // NOTE(allen): expand spec, compute shift
i32 shift_amount = buffer_replace_range_compute_shift(edit.range.first, edit.range.one_past_last, edit.length); i32 shift_amount = buffer_replace_range_compute_shift(edit.range.first, edit.range.one_past_last, edit.length);
@ -308,7 +296,7 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Edit e
} }
// NOTE(allen): wrap meta data // NOTE(allen): wrap meta data
file_measure_wraps(system, &models->mem, file, font); file_measure_wraps(system, mem, file, font);
// NOTE(allen): cursor fixing // NOTE(allen): cursor fixing
edit_fix_markers(system, models, file, edit); edit_fix_markers(system, models, file, edit);
@ -324,117 +312,12 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Edit e
} }
} }
// TODO(allen): this isn't "real" anymore, batch edits are now superseded a combination of other features, we should dump this someday
internal void internal void
edit_batch(System_Functions *system, Models *models, Editing_File *file, Edit_Array edits, Edit_Behaviors behaviors){ edit_batch(System_Functions *system, Models *models, Editing_File *file, Edit_Array edits, Edit_Behaviors behaviors){
Mem_Options *mem = &models->mem;
Heap *heap = &mem->heap;
Partition *part = &mem->part;
Gap_Buffer *buffer = &file->state.buffer;
Assert(edits.count > 0);
// NOTE(allen): history update
if (!behaviors.do_not_post_to_history){
history_dump_records_after_index(&file->state.history, file->state.current_record_index);
history_record_edit(heap, &models->global_history, &file->state.history, buffer, edits, behaviors.batch_type);
file->state.current_record_index = history_get_record_count(&file->state.history);
}
// NOTE(allen): fixing stuff "beforewards"???
edit_pre_state_change(system, &mem->heap, models, file);
// NOTE(allen): actual text replacement
void *scratch = push_array(part, u8, 0);
i32 scratch_size = part_remaining(part);
Buffer_Batch_State state = {};
i32 request_amount = 0;
for (;buffer_batch_edit_step(&state, buffer, edits, scratch, scratch_size, &request_amount);){
void *new_data = 0;
if (request_amount > 0){
new_data = heap_allocate(heap, request_amount);
}
void *old_data = buffer_edit_provide_memory(&file->state.buffer, new_data, request_amount);
if (old_data){
heap_free(heap, old_data);
}
}
i32 shift_total = state.shift_total;
// NOTE(allen): line meta data
// TODO(allen): Let's try to switch to remeasuring here moron!
file_measure_starts(heap, &file->state.buffer);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
Assert(font.valid);
file_allocate_character_starts_as_needed(heap, file);
buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
// NOTE(allen): token fixing
switch (behaviors.batch_type){
case BatchEdit_Normal:
{
if (file->settings.tokens_exist){
// TODO(allen): Write a smart fast one here someday.
i32 start = edits.vals[0].range.first;
i32 end = edits.vals[edits.count - 1].range.one_past_last;
file_relex(system, models, file, start, end, shift_total);
}
else{
file_mark_edit_finished(&models->working_set, file);
}
}break;
case BatchEdit_PreserveTokens:
{
if (file->state.tokens_complete){
Cpp_Token_Array tokens = file->state.token_array;
Cpp_Token *token = tokens.tokens;
Cpp_Token *end_token = tokens.tokens + tokens.count;
Cpp_Token original = {};
Edit *edit = edits.vals; Edit *edit = edits.vals;
Edit *one_past_last_edit = edits.vals + edits.count; for (i32 i = 0; i < edits.count; i += 1, edit += 1){
edit_single(system, models, file, *edit, behaviors);
i32 shift_amount = 0;
i32 local_shift = 0;
for (;token < end_token; ++token){
original = *token;
for (;edit < one_past_last_edit && edit->range.first <= original.start;
++edit){
local_shift = (edit->length - (edit->range.one_past_last - edit->range.first));
shift_amount += local_shift;
}
token->start += shift_amount;
local_shift = 0;
i32 original_end = original.start + original.size;
for (;edit < one_past_last_edit && edit->range.first < original_end;
++edit){
local_shift += (edit->length - (edit->range.one_past_last - edit->range.first));
}
token->size += local_shift;
shift_amount += local_shift;
}
file_mark_edit_finished(&models->working_set, file);
}
}break;
}
// NOTE(allen): wrap meta data
file_measure_wraps(system, &models->mem, file, font);
// NOTE(allen): cursor fixing
edit_fix_markers(system, models, file, edits);
// NOTE(allen): mark edit finished
if (file->settings.tokens_exist){
if (file->settings.virtual_white){
file_mark_edit_finished(&models->working_set, file);
}
}
else{
file_mark_edit_finished(&models->working_set, file);
} }
} }