Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numbered lines for side by side view #63

Merged
merged 8 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 79 additions & 25 deletions lib/interactive_viewer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -115,44 +115,98 @@ let toggle_view_mode () =
| Normal -> Lwd.set view_mode SideBySide
| SideBySide -> Lwd.set view_mode Normal

type line = Change of string | Common of string | Empty

let rec split_and_align_hunk hunks mine_acc their_acc =
let rec buffer_changes temp_mine temp_their hunks =
match hunks with
| [] -> (temp_mine, temp_their, hunks)
| `Common _ :: _ -> (temp_mine, temp_their, hunks)
| `Mine line :: t -> buffer_changes (Change line :: temp_mine) temp_their t
| `Their line :: t -> buffer_changes temp_mine (Change line :: temp_their) t
in
let append_balanced temp_mine temp_their =
let mine_len = List.length temp_mine in
let their_len = List.length temp_their in
let fill_empty n = List.init n (fun _ -> Empty) in

let diff = mine_len - their_len in
let empty_list = fill_empty (abs diff) in

if diff > 0 then (temp_mine, empty_list @ temp_their)
else if diff < 0 then (empty_list @ temp_mine, temp_their)
else (temp_mine, temp_their)
in

match hunks with
| [] -> (List.rev mine_acc, List.rev their_acc)
| (`Common _ as common) :: t ->
split_and_align_hunk t (common :: mine_acc) (common :: their_acc)
| `Mine s :: `Their s' :: t ->
split_and_align_hunk t (`Mine s :: mine_acc) (`Their s' :: their_acc)
| `Mine s :: t ->
split_and_align_hunk t (`Mine s :: mine_acc) (`Common "" :: their_acc)
| `Their s :: t ->
split_and_align_hunk t (`Common "" :: mine_acc) (`Their s :: their_acc)

let lines_to_ui lines attr_change =
List.map
(fun line ->
let content, attr =
match line with
| `Common s -> (s, Notty.A.empty)
| `Mine s -> (s, attr_change)
| `Their s -> (s, attr_change)
| _ -> (
let temp_mine, temp_their, remaining_hunks = buffer_changes [] [] hunks in
let balanced_mine, balanced_their =
append_balanced temp_mine temp_their
in
W.string ~attr content)
lines
let updated_mine_acc = balanced_mine @ mine_acc in
let updated_their_acc = balanced_their @ their_acc in
match remaining_hunks with
| `Common line :: t ->
let common_mine_acc = Common line :: updated_mine_acc in
let common_their_acc = Common line :: updated_their_acc in
split_and_align_hunk t common_mine_acc common_their_acc
| _ ->
split_and_align_hunk remaining_hunks updated_mine_acc
updated_their_acc)

let ui_of_hunk_side_by_side hunk =
let mine_lines, their_lines = split_and_align_hunk hunk.Patch.lines [] [] in
let lines_with_numbers lines attr_change prefix =
let line_num = ref 0 in
List.fold_left
(fun acc line ->
match line with
| Common s ->
incr line_num;
let content = Printf.sprintf "%3d %s" !line_num s in
(content, Notty.A.empty) :: acc
| Change s ->
incr line_num;
let content = Printf.sprintf "%3d %s %s" !line_num prefix s in
(content, attr_change) :: acc
| Empty ->
let content = Printf.sprintf " " in
(content, Notty.A.empty) :: acc)
[] lines
|> List.rev
|> List.map (fun (content, attr) -> W.string ~attr content)

let create_summary start_line_num hunk_length attr change_type =
yokurang marked this conversation as resolved.
Show resolved Hide resolved
let sign = match change_type with `Add -> "+" | `Remove -> "-" in
if hunk_length > 0 then
W.string ~attr
(Printf.sprintf "@@ %s%d,%d @@" sign start_line_num hunk_length)
else W.string ~attr (Printf.sprintf "@@ %s0,0 @@" sign)

let ui_of_hunk_side_by_side hunk =
let attr_mine = Notty.A.(fg red ++ st bold) in
let attr_their = Notty.A.(fg green ++ st bold) in

let mine_ui = lines_to_ui mine_lines attr_mine in
let their_ui = lines_to_ui their_lines attr_their in
let mine_lines, their_lines = split_and_align_hunk hunk.Patch.lines [] [] in

let content_mine = lines_with_numbers mine_lines attr_mine "-" in
let content_their = lines_with_numbers their_lines attr_their "+" in
let summary_mine =
create_summary
(hunk.Patch.mine_start + 1)
hunk.Patch.mine_len attr_mine `Remove
in
let summary_their =
create_summary
(hunk.Patch.their_start + 1)
hunk.Patch.their_len attr_their `Add
in
let space = Ui.space 1 0 in
Ui.hcat
[
Ui.resize ~w:0 ~sw:2 (Ui.vcat mine_ui);
Ui.resize ~w:0 ~sw:2 (Ui.vcat (summary_mine :: content_mine));
space;
Ui.resize ~w:0 ~sw:2 (Ui.vcat their_ui);
Ui.resize ~w:0 ~sw:2 (Ui.vcat (summary_their :: content_their));
]

let current_hunks_side_by_side z_patches : ui Lwd.t =
Expand Down
205 changes: 195 additions & 10 deletions test/cram/test.t
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ This is a cram test for the new executable.
Operation 1 of 2, 1 hunk
2 additions, 1 removal
Modification of file.txt
Hi everyone! Hello World!
This is the diffcessible project.

@@ -2,1 @@ @@ +2,2 @@
1 - Hi everyone! 1 + Hello World!
2 + This is the diffcessible project.



Expand All @@ -160,14 +160,36 @@ This is a cram test for the new executable.
Operation 2 of 2, 1 hunk
2 additions, 1 removal
Modification of file.txt
This file starts at line 3. This file starts at line 5.
This is the second test case in this file.
@@ -3,1 @@ @@ +5,2 @@
1 - This file starts at line 3. 1 + This file starts at line 5.
2 + This is the second test case in this file.













Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.

$ dummy_terminal example.diff n n t
Operation 3 of 14, 1 hunk
1 addition, 1 removal
Modification of lib/dune
@@ -1,3 @@ @@ +1,3 @@
1 (library 1 (library
2 (name diffcessible) 2 (name diffcessible)
3 - (libraries notty nottui lwd)) 3 + (libraries notty nottui lwd patch))







Expand All @@ -178,12 +200,169 @@ This is a cram test for the new executable.

Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.

$ dummy_terminal more-examples.diff n n t
Operation 2 of 2, 1 hunk
$ dummy_terminal example.diff n n n t
Operation 4 of 14, 1 hunk
6 additions, 20 removals
Modification of lib/interactive_viewer.ml
@@ -1,39 @@ @@ +1,25 @@
1 open Nottui 1 open Nottui
2 module W = Nottui_widgets 2 module W = Nottui_widgets
3 - open Lwd_infix 3 + (* open Lwd_infix *)
4 -
5 - type patch = unit
6 4
7 let pure_str s = Lwd.pure (W.string s) 5 let pure_str s = Lwd.pure (W.string s)
8 -
9 - let string_of_counter c =
10 - let$ c = c in
11 - W.string (string_of_int c)
12 -
13 let quit = Lwd.var false 6 let quit = Lwd.var false
14 - let counter = Lwd.var 0 7 + let string_of_operation = Format.asprintf "%a" (Patch.pp_operation ~
15 - let counter_d = Lwd.get counter
Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.


$ dummy_terminal example.diff n n n n t
Operation 5 of 14, 1 hunk
1 addition, 3 removals
Modification of lib/interactive_viewer.mli
@@ -1,5 @@ @@ +1,3 @@
1 (** Render and navigate through a diff. *) 1 (** Render and navigate through a diff. *)
2 2
3 - type patch = unit 3 + val start : Patch.t list -> unit
4 -
5 - val start : patch -> unit










Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.


$ dummy_terminal example.diff n n n n n t
Operation 6 of 14, 1 hunk
1 addition, 1 removal
Rename with modifications dir1/file.txt to dir2/file.txt
@@ -1,1 @@ @@ +1,1 @@
1 - This is the original content. 1 + This is the modified content.














Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.

$ dummy_terminal example.diff n n n n n n n t
Operation 8 of 14, 1 hunk
2 additions, 1 removal
Modification of file.txt
This file starts at line 3. This file starts at line 5.
This is the second test case in this file.
Rename with modifications dir1/file.txt to dir2/file.txt
@@ -1,1 @@ @@ +1,2 @@
1 - This is the original content. 1 + Here is some additional line.
2 + Deleted line 1 and added this.













Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.

$ dummy_terminal example.diff n n n n n n n n n t
Operation 10 of 14, 1 hunk
0 additions, 1 removal
Deletion of dir1/file.txt
@@ -1,1 @@ @@ +0,0 @@
1 - some text














Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.

$ dummy_terminal example.diff n n n n n n n n n n n n t
Operation 13 of 14, 1 hunk
2 additions, 0 removals
Creation of dir2/sample.txt
@@ -0,0 @@ @@ +1,2 @@
1 + some text
2 + lorem ipsum













Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.

$ dummy_terminal example.diff n n n n n n n n n n n n n n n t
Operation 14 of 14, 1 hunk
1 addition, 0 removals
Rename with modifications dir1/file.txt to dir2/file.txt
@@ -0,0 @@ @@ +1,1 @@
1 + new text














Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.


$ dummy_terminal example.diff n n n n n n n n n n n n n n n n t
Operation 14 of 14, 1 hunk
1 addition, 0 removals
Rename with modifications dir1/file.txt to dir2/file.txt
@@ -0,0 @@ @@ +1,1 @@
1 + new text



Expand All @@ -200,3 +379,9 @@ This is a cram test for the new executable.

Type 'h' to go to the help panel, 'q' to quit, 'n' to go to the next operation, 'p' to go to the previous operation. Press 't' to toggle view mode.