@@ -330,7 +330,7 @@ archiver_rep::confirm () {
330330 if (depth <= last_save) last_save= -1 ;
331331 if (depth <= last_autosave) last_autosave= -1 ;
332332 normalize ();
333- // show_all ();
333+ show_all ();
334334 }
335335 }
336336}
@@ -688,23 +688,131 @@ archiver_rep::reconstruct_from_state (tree old_state, tree new_state, path p, st
688688
689689 if (!trees_equal) {
690690 modification mod = compute_tree_diff (old_state, new_state, p, completion);
691+ cout << " modification: " << mod << LF;
692+
693+ // modification cursor_mod = compute_cursor_update(old_state, new_state, p, mod);
694+ // cout << "cursor modification: " << cursor_mod << LF;
695+
696+ the_et = old_state;
691697 add (mod);
692- } else {
698+ the_et = new_state;
699+ // if (cursor_mod != mod_insert(path(), 0, "")) { // Check if cursor update is needed
700+ // add (cursor_mod);
701+ // }
693702 }
694703 confirm ();
695704 simplify ();
696705}
697706
698707modification
699708archiver_rep::compute_tree_diff (tree old_tree, tree new_tree, path p, string completion) {
700- // TODO: refactor
701709 cout << " compute_tree_diff: path=" << p << " \n " ;
702- string old_s =as_string (subtree (old_tree, path_up (p, 1 )));
710+
711+ string old_s = as_string (subtree (old_tree, path_up (p, 1 )));
703712 string new_s = as_string (subtree (new_tree, path_up (p, 1 )));
713+
714+ SI i = 0 ;
715+ SI j = 0 ;
716+
717+ // Find common prefix
718+ while (i < N (old_s) && i < N (new_s) && old_s[i] == new_s[i]) {
719+ i++;
720+ }
721+
722+ // Find common suffix (but don't overlap with prefix)
723+ while (j < (N (old_s) - i) && j < (N (new_s) - i) &&
724+ old_s[N (old_s) - 1 - j] == new_s[N (new_s) - 1 - j]) {
725+ j++;
726+ }
727+
728+ // Calculate the different parts
729+ SI old_start = i;
730+ SI old_end = N (old_s) - j;
731+ SI new_start = i;
732+ SI new_end = N (new_s) - j;
733+
734+ string old_diff = (old_end > old_start) ? old_s (old_start, old_end) : " " ;
735+ string new_diff = (new_end > new_start) ? new_s (new_start, new_end) : " " ;
736+
737+ cout << " old_s=\" " << old_s << " \" , new_s=\" " << new_s << " \"\n " ;
738+ cout << " old_diff=\" " << old_diff << " \" , new_diff=\" " << new_diff << " \"\n " ;
739+ cout << " prefix_len=" << i << " , suffix_len=" << j << " \n " ;
740+
704741 int insert_pos = last_item (p);
705- string insert_content = completion;
706- // cout << "compute_tree_diff: old_s=\"" << old_s << "\", new_s=\"" << new_s
707- // << "\", insert_pos=" << insert_pos
708- // << ", insert_content=\"" << insert_content << "\"\n";
709- return mod_insert (path_up (p, 1 ), insert_pos, insert_content);
742+
743+ // Determine the operation based on the differences
744+ if (old_diff == " " && new_diff != " " ) {
745+ // Pure insertion
746+ cout << " Pure insertion detected\n " ;
747+ return mod_insert (path_up (p, 1 ), i, new_diff);
748+ }
749+ else if (old_diff != " " && new_diff == " " ) {
750+ // Pure deletion
751+ cout << " Pure deletion detected\n " ;
752+ // For deletion, the position should be relative to the new string
753+ // Since we deleted from old_start to old_end, the deletion position
754+ // in the context of the new string is at position i (common prefix length)
755+ return mod_remove (path_up (p, 1 ), i, N (old_diff));
756+ }
757+ else if (old_diff != " " && new_diff != " " ) {
758+ // Replacement (remove old, then insert new)
759+ // For simplicity, we'll use insert with the new content at position i
760+ cout << " Replacement detected, using insert\n " ;
761+ return mod_insert (path_up (p, 1 ), i, new_diff);
762+ }
763+ else {
764+ // No diff
765+ cout << " No difference detected\n " ;
766+ return mod_insert (path_up (p, 1 ), insert_pos, " " );
767+ }
768+ }
769+
770+ modification
771+ archiver_rep::compute_cursor_update (tree old_tree, tree new_tree, path p, modification content_mod) {
772+ cout << " compute_cursor_update: path=" << p << " , content_mod=" << content_mod << " \n " ;
773+ int current_pos = last_item (p);
774+ int new_cursor_pos = current_pos;
775+ switch (content_mod->k ) {
776+ case MOD_INSERT: {
777+ string inserted_text = as_string (content_mod->t );
778+ int insert_pos = last_item (content_mod->p );
779+
780+ if (current_pos >= insert_pos) {
781+ // Cursor was at or after the insertion point, move it forward
782+ new_cursor_pos = current_pos + N (inserted_text);
783+ }
784+ break ;
785+ }
786+
787+ case MOD_REMOVE: {
788+ int remove_pos = last_item (path_up (content_mod->p , 1 ));
789+ int remove_count = last_item (content_mod->p );
790+ cout << " remove_pos=" << remove_pos << " , remove_count=" << remove_count << " \n " ;
791+
792+ if (current_pos > remove_pos + remove_count) {
793+ // Cursor was after the removed content, move it back
794+ new_cursor_pos = current_pos - remove_count;
795+ }
796+ else if (current_pos > remove_pos) {
797+ // Cursor was within the removed content, place it at the removal point
798+ new_cursor_pos = remove_pos;
799+ }
800+ break ;
801+ }
802+
803+ default :
804+ break ;
805+ }
806+
807+ cout << " cursor position: " << current_pos << " -> " << new_cursor_pos << " \n " ;
808+
809+ if (new_cursor_pos != current_pos) {
810+ path cursor_path = path_up (p, 1 );
811+ // Create appropriate cursor data tree
812+ tree cursor_data = compound (" author" , " 1" );
813+ return mod_set_cursor (cursor_path, new_cursor_pos, cursor_data);
814+ }
815+
816+ // empty modification
817+ return mod_insert (path (), 0 , " " );
710818}
0 commit comments