Some batch edit optimizations; next need to support batch cursor fixing
							parent
							
								
									14b71b8172
								
							
						
					
					
						commit
						529ef3928e
					
				
							
								
								
									
										116
									
								
								4ed_edit.cpp
								
								
								
								
							
							
						
						
									
										116
									
								
								4ed_edit.cpp
								
								
								
								
							| 
						 | 
				
			
			@ -10,10 +10,30 @@
 | 
			
		|||
// TOP
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
edit_pre_state_change(Models *models, Editing_File *file){
 | 
			
		||||
pre_edit_state_change(Models *models, Editing_File *file){
 | 
			
		||||
    file_add_dirty_flag(file, DirtyState_UnsavedChanges);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
pre_edit_history_prep(Editing_File *file, Edit_Behaviors behaviors){
 | 
			
		||||
    if (!behaviors.do_not_post_to_history){
 | 
			
		||||
        history_dump_records_after_index(&file->state.history,
 | 
			
		||||
                                         file->state.current_record_index);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
post_edit_call_hook(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		||||
                    Range_i64 new_range, umem original_size){
 | 
			
		||||
    // NOTE(allen): edit range hook
 | 
			
		||||
    if (models->buffer_edit_range != 0){
 | 
			
		||||
        Application_Links app = {};
 | 
			
		||||
        app.tctx = tctx;
 | 
			
		||||
        app.cmd_context = models;
 | 
			
		||||
        models->buffer_edit_range(&app, file->id, new_range, original_size);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
edit_fix_markers__write_workspace_markers(Dynamic_Workspace *workspace, Buffer_ID buffer_id,
 | 
			
		||||
                                          Cursor_With_Index *cursors, Cursor_With_Index *r_cursors,
 | 
			
		||||
| 
						 | 
				
			
			@ -138,8 +158,14 @@ edit_fix_markers(Thread_Context *tctx, Models *models, Editing_File *file, Edit
 | 
			
		|||
    if (cursor_count > 0 || r_cursor_count > 0){
 | 
			
		||||
        buffer_sort_cursors(  cursors,   cursor_count);
 | 
			
		||||
        buffer_sort_cursors(r_cursors, r_cursor_count);
 | 
			
		||||
        buffer_update_cursors(  cursors,   cursor_count, edit.range.first, edit.range.one_past_last, edit.text.size, false);
 | 
			
		||||
        buffer_update_cursors(r_cursors, r_cursor_count, edit.range.first, edit.range.one_past_last, edit.text.size, true);
 | 
			
		||||
        
 | 
			
		||||
        buffer_update_cursors(  cursors,   cursor_count,
 | 
			
		||||
                              edit.range.first, edit.range.one_past_last,
 | 
			
		||||
                              edit.text.size, false);
 | 
			
		||||
        buffer_update_cursors(r_cursors, r_cursor_count,
 | 
			
		||||
                              edit.range.first, edit.range.one_past_last,
 | 
			
		||||
                              edit.text.size, true);
 | 
			
		||||
        
 | 
			
		||||
        buffer_unsort_cursors(  cursors,   cursor_count);
 | 
			
		||||
        buffer_unsort_cursors(r_cursors, r_cursor_count);
 | 
			
		||||
        
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +204,20 @@ edit_fix_markers(Thread_Context *tctx, Models *models, Editing_File *file, Edit
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
edit_single(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		||||
file_end_file(Thread_Context *tctx, Models *models, Editing_File *file){
 | 
			
		||||
    if (models->end_buffer != 0){
 | 
			
		||||
        Application_Links app = {};
 | 
			
		||||
        app.tctx = tctx;
 | 
			
		||||
        app.cmd_context = models;
 | 
			
		||||
        models->end_buffer(&app, file->id);
 | 
			
		||||
    }
 | 
			
		||||
    Lifetime_Allocator *lifetime_allocator = &models->lifetime_allocator;
 | 
			
		||||
    lifetime_free_object(lifetime_allocator, file->lifetime_object);
 | 
			
		||||
    file->lifetime_object = lifetime_alloc_object(lifetime_allocator, DynamicWorkspace_Buffer, file);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
edit__apply(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		||||
            Interval_i64 range, String_Const_u8 string, Edit_Behaviors behaviors){
 | 
			
		||||
    Edit edit = {};
 | 
			
		||||
    edit.text = string;
 | 
			
		||||
| 
						 | 
				
			
			@ -193,21 +232,13 @@ edit_single(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		|||
    
 | 
			
		||||
    // 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(&models->global_history, &file->state.history, buffer, edit);
 | 
			
		||||
        file->state.current_record_index = history_get_record_count(&file->state.history);
 | 
			
		||||
        history_record_edit(&models->global_history, &file->state.history, buffer,
 | 
			
		||||
                            edit);
 | 
			
		||||
        file->state.current_record_index =
 | 
			
		||||
            history_get_record_count(&file->state.history);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // NOTE(allen): fixing stuff beforewards????
 | 
			
		||||
    edit_pre_state_change(models, file);
 | 
			
		||||
    
 | 
			
		||||
    // NOTE(allen): save the original text for the edit range hook.
 | 
			
		||||
    String_Const_u8 original_text = {};
 | 
			
		||||
    if (models->buffer_edit_range != 0){
 | 
			
		||||
        original_text = buffer_stringify(scratch, &file->state.buffer, edit.range);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // NOTE(allen): expand spec, compute shift
 | 
			
		||||
    // NOTE(allen): compute shift
 | 
			
		||||
    i64 shift_amount = replace_range_shift(edit.range, (i64)edit.text.size);
 | 
			
		||||
    
 | 
			
		||||
    // NOTE(allen): actual text replacement
 | 
			
		||||
| 
						 | 
				
			
			@ -225,28 +256,18 @@ edit_single(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		|||
    
 | 
			
		||||
    // NOTE(allen): cursor fixing
 | 
			
		||||
    edit_fix_markers(tctx, models, file, edit);
 | 
			
		||||
    
 | 
			
		||||
    // NOTE(allen): edit range hook
 | 
			
		||||
    if (models->buffer_edit_range != 0){
 | 
			
		||||
        Interval_i64 new_range = Ii64(edit.range.first, edit.range.first + edit.text.size);
 | 
			
		||||
        Application_Links app = {};
 | 
			
		||||
        app.tctx = tctx;;
 | 
			
		||||
        app.cmd_context = models;
 | 
			
		||||
        models->buffer_edit_range(&app, file->id, new_range, original_text);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
file_end_file(Thread_Context *tctx, Models *models, Editing_File *file){
 | 
			
		||||
    if (models->end_buffer != 0){
 | 
			
		||||
        Application_Links app = {};
 | 
			
		||||
        app.tctx = tctx;
 | 
			
		||||
        app.cmd_context = models;
 | 
			
		||||
        models->end_buffer(&app, file->id);
 | 
			
		||||
    }
 | 
			
		||||
    Lifetime_Allocator *lifetime_allocator = &models->lifetime_allocator;
 | 
			
		||||
    lifetime_free_object(lifetime_allocator, file->lifetime_object);
 | 
			
		||||
    file->lifetime_object = lifetime_alloc_object(lifetime_allocator, DynamicWorkspace_Buffer, file);
 | 
			
		||||
edit_single(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		||||
            Range_i64 range, String_Const_u8 string, Edit_Behaviors behaviors){
 | 
			
		||||
    pre_edit_state_change(models, file);
 | 
			
		||||
    pre_edit_history_prep(file, behaviors);
 | 
			
		||||
    
 | 
			
		||||
    edit__apply(tctx, models, file, range, string, behaviors);
 | 
			
		||||
    
 | 
			
		||||
    post_edit_call_hook(tctx, models, file,
 | 
			
		||||
                        Ii64_size(range.first, string.size), range_size(range));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void
 | 
			
		||||
| 
						 | 
				
			
			@ -395,25 +416,41 @@ internal b32
 | 
			
		|||
edit_batch(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		||||
           Batch_Edit *batch, Edit_Behaviors behaviors){
 | 
			
		||||
    b32 result = true;
 | 
			
		||||
    
 | 
			
		||||
    if (batch != 0){
 | 
			
		||||
        pre_edit_state_change(models, file);
 | 
			
		||||
        pre_edit_history_prep(file, behaviors);
 | 
			
		||||
        
 | 
			
		||||
        History_Record_Index start_index = 0;
 | 
			
		||||
        if (history_is_activated(&file->state.history)){
 | 
			
		||||
            start_index = file->state.current_record_index;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        Range_i64 old_range = Ii64_neg_inf;
 | 
			
		||||
        Range_i64 new_range = Ii64_neg_inf;
 | 
			
		||||
        
 | 
			
		||||
        i64 shift = 0;
 | 
			
		||||
        for (Batch_Edit *edit = batch;
 | 
			
		||||
             edit != 0;
 | 
			
		||||
             edit = edit->next){
 | 
			
		||||
            String_Const_u8 insert_string = edit->edit.text;
 | 
			
		||||
            Interval_i64 edit_range = edit->edit.range;
 | 
			
		||||
            
 | 
			
		||||
            Range_i64 edit_range = edit->edit.range;
 | 
			
		||||
            old_range.min = min(old_range.min, edit_range.min);
 | 
			
		||||
            old_range.max = max(old_range.max, edit_range.max);
 | 
			
		||||
            
 | 
			
		||||
            edit_range.first += shift;
 | 
			
		||||
            edit_range.one_past_last += shift;
 | 
			
		||||
            
 | 
			
		||||
            new_range.min = min(new_range.min, edit_range.min);
 | 
			
		||||
            i64 new_max = (i64)(edit_range.min + insert_string.size); 
 | 
			
		||||
            new_range.max = max(new_range.max, new_max);
 | 
			
		||||
            
 | 
			
		||||
            i64 size = buffer_size(&file->state.buffer);
 | 
			
		||||
            if (0 <= edit_range.first &&
 | 
			
		||||
                edit_range.first <= edit_range.one_past_last &&
 | 
			
		||||
                edit_range.one_past_last <= size){
 | 
			
		||||
                edit_single(tctx, models, file, edit_range, insert_string, behaviors);
 | 
			
		||||
                edit__apply(tctx, models, file, edit_range, insert_string, behaviors);
 | 
			
		||||
                shift += replace_range_shift(edit_range, insert_string.size);
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
| 
						 | 
				
			
			@ -428,7 +465,10 @@ edit_batch(Thread_Context *tctx, Models *models, Editing_File *file,
 | 
			
		|||
                edit_merge_history_range(tctx, models, file, start_index + 1, last_index, RecordMergeFlag_StateInRange_ErrorOut);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        post_edit_call_hook(tctx, models, file, new_range, range_size(old_range));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1797,6 +1797,11 @@ If32(){
 | 
			
		|||
    return(interval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
global Interval_i32 Ii32_neg_inf = {max_i32, min_i32};
 | 
			
		||||
global Interval_i64 Ii64_neg_inf = {max_i64, min_i64};
 | 
			
		||||
global Interval_u64 Iu64_neg_inf = {max_u64, 0};
 | 
			
		||||
global Interval_f32 If32_neg_inf = {max_f32, -max_f32};
 | 
			
		||||
 | 
			
		||||
internal b32
 | 
			
		||||
operator==(Interval_i32 a, Interval_i32 b){
 | 
			
		||||
    return(a.min == b.min && a.max == b.max);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -794,10 +794,10 @@ BUFFER_HOOK_SIG(default_file_save){
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
BUFFER_EDIT_RANGE_SIG(default_buffer_edit_range){
 | 
			
		||||
    // buffer_id, new_range, text
 | 
			
		||||
    // buffer_id, new_range, original_size
 | 
			
		||||
    ProfileScope(app, "default edit range");
 | 
			
		||||
    
 | 
			
		||||
    Interval_i64 old_range = Ii64(new_range.first, new_range.first + text.size);
 | 
			
		||||
    Interval_i64 old_range = Ii64(new_range.first, new_range.first + original_size);
 | 
			
		||||
    i64 insert_size = range_size(new_range);
 | 
			
		||||
    i64 text_shift = replace_range_shift(old_range, insert_size);
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -812,63 +812,81 @@ BUFFER_EDIT_RANGE_SIG(default_buffer_edit_range){
 | 
			
		|||
    else{
 | 
			
		||||
        Token_Array *ptr = scope_attachment(app, scope, attachment_tokens, Token_Array);
 | 
			
		||||
        if (ptr != 0 && ptr->tokens != 0){
 | 
			
		||||
            ProfileBlockNamed(app, "attempt resync", profile_attempt_resync);
 | 
			
		||||
            
 | 
			
		||||
            Base_Allocator *allocator = managed_scope_allocator(app, scope);
 | 
			
		||||
            
 | 
			
		||||
            b32 do_full_relex = false;
 | 
			
		||||
            i64 token_index_first = token_relex_first(ptr, old_range.first, 1);
 | 
			
		||||
            i64 token_index_resync_guess =
 | 
			
		||||
                token_relex_resync(ptr, old_range.one_past_last, 16);
 | 
			
		||||
            
 | 
			
		||||
            Token *token_first = ptr->tokens + token_index_first;
 | 
			
		||||
            Token *token_resync = ptr->tokens + token_index_resync_guess;
 | 
			
		||||
            
 | 
			
		||||
            Range_i64 relex_range =
 | 
			
		||||
                Ii64(token_first->pos,
 | 
			
		||||
                     token_resync->pos + token_resync->size + text_shift);
 | 
			
		||||
            String_Const_u8 partial_text = push_buffer_range(app, scratch, buffer_id,
 | 
			
		||||
                                                             relex_range);
 | 
			
		||||
            
 | 
			
		||||
            Token_List relex_list = lex_full_input_cpp(scratch, partial_text);
 | 
			
		||||
            if (relex_range.one_past_last < buffer_get_size(app, buffer_id)){
 | 
			
		||||
                token_drop_eof(&relex_list);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            Base_Allocator *allocator = managed_scope_allocator(app, scope);
 | 
			
		||||
            
 | 
			
		||||
            Token_Relex relex = token_relex(relex_list, relex_range.first - text_shift,
 | 
			
		||||
                                            ptr->tokens, token_index_first, token_index_resync_guess);
 | 
			
		||||
            
 | 
			
		||||
            if (relex.successful_resync){
 | 
			
		||||
                i64 token_index_resync = relex.first_resync_index;
 | 
			
		||||
                
 | 
			
		||||
                Interval_i64 head = Ii64(0, token_index_first);
 | 
			
		||||
                Interval_i64 replaced = Ii64(token_index_first, token_index_resync);
 | 
			
		||||
                Interval_i64 tail = Ii64(token_index_resync, ptr->count);
 | 
			
		||||
                i64 resynced_count = (token_index_resync_guess + 1) - token_index_resync;
 | 
			
		||||
                i64 relexed_count = relex_list.total_count - resynced_count;
 | 
			
		||||
                i64 tail_shift = relexed_count - (token_index_resync - token_index_first);
 | 
			
		||||
                
 | 
			
		||||
                i64 new_tokens_count = ptr->count + tail_shift;
 | 
			
		||||
                Token *new_tokens = base_array(allocator, Token, new_tokens_count);
 | 
			
		||||
                
 | 
			
		||||
                Token *old_tokens = ptr->tokens;
 | 
			
		||||
                block_copy_array_shift(new_tokens, old_tokens, head, 0);
 | 
			
		||||
                token_fill_memory_from_list(new_tokens + replaced.first, &relex_list, relexed_count);
 | 
			
		||||
                for (i64 i = 0, index = replaced.first; i < relexed_count; i += 1, index += 1){
 | 
			
		||||
                    new_tokens[index].pos += relex_range.first;
 | 
			
		||||
                }
 | 
			
		||||
                for (i64 i = tail.first; i < tail.one_past_last; i += 1){
 | 
			
		||||
                    old_tokens[i].pos += text_shift;
 | 
			
		||||
                }
 | 
			
		||||
                block_copy_array_shift(new_tokens, ptr->tokens, tail, tail_shift);
 | 
			
		||||
                
 | 
			
		||||
                base_free(allocator, ptr->tokens);
 | 
			
		||||
                
 | 
			
		||||
                ptr->tokens = new_tokens;
 | 
			
		||||
                ptr->count = new_tokens_count;
 | 
			
		||||
                ptr->max = new_tokens_count;
 | 
			
		||||
            if (token_index_resync_guess - token_index_first >= 4000){
 | 
			
		||||
                do_full_relex = true;
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
                Token *token_first = ptr->tokens + token_index_first;
 | 
			
		||||
                Token *token_resync = ptr->tokens + token_index_resync_guess;
 | 
			
		||||
                
 | 
			
		||||
                Range_i64 relex_range =
 | 
			
		||||
                    Ii64(token_first->pos,
 | 
			
		||||
                         token_resync->pos + token_resync->size + text_shift);
 | 
			
		||||
                String_Const_u8 partial_text = push_buffer_range(app, scratch,
 | 
			
		||||
                                                                 buffer_id,
 | 
			
		||||
                                                                 relex_range);
 | 
			
		||||
                
 | 
			
		||||
                Token_List relex_list = lex_full_input_cpp(scratch, partial_text);
 | 
			
		||||
                if (relex_range.one_past_last < buffer_get_size(app, buffer_id)){
 | 
			
		||||
                    token_drop_eof(&relex_list);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                Token_Relex relex = token_relex(relex_list, relex_range.first - text_shift,
 | 
			
		||||
                                                ptr->tokens, token_index_first, token_index_resync_guess);
 | 
			
		||||
                
 | 
			
		||||
                profile_attempt_resync.close_now();
 | 
			
		||||
                
 | 
			
		||||
                if (relex.successful_resync){
 | 
			
		||||
                    ProfileBlock(app, "apply resync");
 | 
			
		||||
                    
 | 
			
		||||
                    i64 token_index_resync = relex.first_resync_index;
 | 
			
		||||
                    
 | 
			
		||||
                    Interval_i64 head = Ii64(0, token_index_first);
 | 
			
		||||
                    Interval_i64 replaced = Ii64(token_index_first, token_index_resync);
 | 
			
		||||
                    Interval_i64 tail = Ii64(token_index_resync, ptr->count);
 | 
			
		||||
                    i64 resynced_count = (token_index_resync_guess + 1) - token_index_resync;
 | 
			
		||||
                    i64 relexed_count = relex_list.total_count - resynced_count;
 | 
			
		||||
                    i64 tail_shift = relexed_count - (token_index_resync - token_index_first);
 | 
			
		||||
                    
 | 
			
		||||
                    i64 new_tokens_count = ptr->count + tail_shift;
 | 
			
		||||
                    Token *new_tokens = base_array(allocator, Token, new_tokens_count);
 | 
			
		||||
                    
 | 
			
		||||
                    Token *old_tokens = ptr->tokens;
 | 
			
		||||
                    block_copy_array_shift(new_tokens, old_tokens, head, 0);
 | 
			
		||||
                    token_fill_memory_from_list(new_tokens + replaced.first, &relex_list, relexed_count);
 | 
			
		||||
                    for (i64 i = 0, index = replaced.first; i < relexed_count; i += 1, index += 1){
 | 
			
		||||
                        new_tokens[index].pos += relex_range.first;
 | 
			
		||||
                    }
 | 
			
		||||
                    for (i64 i = tail.first; i < tail.one_past_last; i += 1){
 | 
			
		||||
                        old_tokens[i].pos += text_shift;
 | 
			
		||||
                    }
 | 
			
		||||
                    block_copy_array_shift(new_tokens, ptr->tokens, tail, tail_shift);
 | 
			
		||||
                    
 | 
			
		||||
                    base_free(allocator, ptr->tokens);
 | 
			
		||||
                    
 | 
			
		||||
                    ptr->tokens = new_tokens;
 | 
			
		||||
                    ptr->count = new_tokens_count;
 | 
			
		||||
                    ptr->max = new_tokens_count;
 | 
			
		||||
                }
 | 
			
		||||
                else{
 | 
			
		||||
                    do_full_relex = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (do_full_relex){
 | 
			
		||||
                base_free(allocator, ptr->tokens);
 | 
			
		||||
                block_zero_struct(ptr);
 | 
			
		||||
                *lex_task_ptr = async_task_no_dep(&global_async_system, do_full_lex_async,
 | 
			
		||||
                *lex_task_ptr = async_task_no_dep(&global_async_system,
 | 
			
		||||
                                                  do_full_lex_async,
 | 
			
		||||
                                                  make_data_struct(&buffer_id));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ rewrite_lines_to_crlf(Application_Links *app, Buffer_ID buffer){
 | 
			
		|||
    Batch_Edit *first = 0;
 | 
			
		||||
    Batch_Edit *last = 0;
 | 
			
		||||
    
 | 
			
		||||
    ProfileBlockNamed(app, "build batch edit", profile_batch);
 | 
			
		||||
    i64 pos = -1;
 | 
			
		||||
    Character_Predicate pred_cr = character_predicate_from_character('\r');
 | 
			
		||||
    Character_Predicate pred_lf = character_predicate_from_character('\n');
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +47,7 @@ rewrite_lines_to_crlf(Application_Links *app, Buffer_ID buffer){
 | 
			
		|||
            edit->edit.range = Ii64(pos);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    profile_batch.close_now();
 | 
			
		||||
    
 | 
			
		||||
    buffer_batch_edit(app, buffer, first);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +60,7 @@ rewrite_lines_to_lf(Application_Links *app, Buffer_ID buffer){
 | 
			
		|||
    Batch_Edit *first = 0;
 | 
			
		||||
    Batch_Edit *last = 0;
 | 
			
		||||
    
 | 
			
		||||
    ProfileBlockNamed(app, "build batch edit", profile_batch);
 | 
			
		||||
    i64 pos = -1;
 | 
			
		||||
    Character_Predicate pred = character_predicate_from_character('\r');
 | 
			
		||||
    for (;;){
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +76,8 @@ rewrite_lines_to_lf(Application_Links *app, Buffer_ID buffer){
 | 
			
		|||
        edit->edit.text = string_u8_litexpr("");
 | 
			
		||||
        edit->edit.range = match.range;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    profile_batch.close_now();
 | 
			
		||||
    
 | 
			
		||||
	buffer_batch_edit(app, buffer, first);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -558,16 +558,17 @@ struct Buffer_Name_Conflict_Entry{
 | 
			
		|||
 | 
			
		||||
typedef void Buffer_Name_Resolver_Function(Application_Links *app, Buffer_Name_Conflict_Entry *conflicts, i32 conflict_count);
 | 
			
		||||
#define BUFFER_NAME_RESOLVER_SIG(n) \
 | 
			
		||||
void n(Application_Links *app, Buffer_Name_Conflict_Entry *conflicts, i32 conflict_count)
 | 
			
		||||
void n(Application_Links *app, Buffer_Name_Conflict_Entry *conflicts, \
 | 
			
		||||
       i32 conflict_count)
 | 
			
		||||
 | 
			
		||||
typedef i32 Buffer_Hook_Function(Application_Links *app, Buffer_ID buffer_id);
 | 
			
		||||
#define BUFFER_HOOK_SIG(name) i32 name(Application_Links *app, Buffer_ID buffer_id)
 | 
			
		||||
 | 
			
		||||
typedef i32 Buffer_Edit_Range_Function(Application_Links *app, Buffer_ID buffer_id,
 | 
			
		||||
                                       Range_i64 new_range, String_Const_u8 text);
 | 
			
		||||
                                       Range_i64 new_range, umem original_size);
 | 
			
		||||
#define BUFFER_EDIT_RANGE_SIG(name) \
 | 
			
		||||
i32 name(Application_Links *app, Buffer_ID buffer_id, \
 | 
			
		||||
Interval_i64 new_range, String_Const_u8 text)
 | 
			
		||||
         Interval_i64 new_range, umem original_size)
 | 
			
		||||
 | 
			
		||||
typedef Vec2_f32 Delta_Rule_Function(Vec2_f32 pending, b32 is_new_target, f32 dt, void *data);
 | 
			
		||||
#define DELTA_RULE_SIG(name) \
 | 
			
		||||
| 
						 | 
				
			
			@ -580,7 +581,8 @@ typedef void New_Clipboard_Contents_Function(Application_Links *app, String_Cons
 | 
			
		|||
void name(Application_Links *app, String_Const_u8 contents)
 | 
			
		||||
 | 
			
		||||
typedef void Render_Caller_Function(Application_Links *app, Frame_Info frame_info, View_ID view);
 | 
			
		||||
#define RENDER_CALLER_SIG(name) void name(Application_Links *app, Frame_Info frame_info, View_ID view)
 | 
			
		||||
#define RENDER_CALLER_SIG(name) \
 | 
			
		||||
void name(Application_Links *app, Frame_Info frame_info, View_ID view)
 | 
			
		||||
 | 
			
		||||
typedef i64 Command_Map_ID;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -354,10 +354,10 @@ static Command_Metadata fcoder_metacmd_table[213] = {
 | 
			
		|||
{ PROC_LINKS(redo_all_buffers, 0), false, "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1922 },
 | 
			
		||||
{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2023 },
 | 
			
		||||
{ PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2030 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_to_crlf, 0), false, "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 82 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_to_lf, 0), false, "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 93 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_to_binary, 0), false, "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 104 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_from_contents, 0), false, "set_eol_mode_from_contents", 26, "Sets the buffer's line ending mode to match the contents of the buffer.", 71, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 115 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_to_crlf, 0), false, "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 86 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_to_lf, 0), false, "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 97 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_to_binary, 0), false, "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 108 },
 | 
			
		||||
{ PROC_LINKS(set_eol_mode_from_contents, 0), false, "set_eol_mode_from_contents", 26, "Sets the buffer's line ending mode to match the contents of the buffer.", 71, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 119 },
 | 
			
		||||
{ PROC_LINKS(interactive_switch_buffer, 0), true, "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 416 },
 | 
			
		||||
{ PROC_LINKS(interactive_kill_buffer, 0), true, "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 426 },
 | 
			
		||||
{ PROC_LINKS(interactive_open_or_new, 0), true, "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 474 },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue