terminal user interface to jujutsu. Focused on speed and clarity
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactored to allow better testing and fixed bug in graph rendering

+330 -252
+1 -9
jj_tui/bin/global_vars.ml
··· 2 2 open Nottui 3 3 open Eio.Std 4 4 open Lwd_infix 5 + open Jj_tui.Process 5 6 6 7 type cmd_args = string list 7 - 8 - type rev_id = { 9 - change_id : string 10 - ; commit_id : string 11 - } 12 - 13 - type 'a maybe_unique = 14 - | Unique of 'a 15 - | Duplicate of 'a 16 8 17 9 type ui_state_t = { 18 10 view :
+7 -6
jj_tui/bin/graph_view.ml
··· 1 1 module Make (Vars : Global_vars.Vars) = struct 2 2 open Lwd_infix 3 3 open Vars 4 - open Jj_process.Make (Vars) 5 4 open Notty 6 5 open Jj_tui 7 6 open Nottui 8 7 open! Jj_tui.Util 9 8 open Jj_commands.Make (Vars) 10 9 open Jj_widgets.Make (Vars) 10 + module Process =Jj_process.Make (Vars) 11 + open Process 12 + open Jj_tui.Process_wrappers.Make(Process) 11 13 12 14 let branch_select_prompt get_branch_list name func = 13 15 Selection_prompt ··· 71 73 let rev = Vars.get_selected_rev () in 72 74 let source_msg, dest_msg = get_messages rev (rev ^ "-") in 73 75 let new_msg = 74 - [ dest_msg;source_msg ] |> String.concat_non_empty "\n" 76 + [ dest_msg; source_msg ] |> String.concat_non_empty "\n" 75 77 in 76 78 jj [ "squash"; "--quiet"; "-r"; rev; "-m"; new_msg ] |> ignore) 77 79 } ··· 86 88 (fun rev -> 87 89 let src_msg, dest_msg = get_messages rev target in 88 90 let new_msg = 89 - [ dest_msg;src_msg ] |> String.concat_non_empty "\n" 91 + [ dest_msg; src_msg ] |> String.concat_non_empty "\n" 90 92 in 91 93 Cmd 92 94 [ ··· 134 136 } 135 137 ; { 136 138 key = 'D' 137 - ; cmd = 138 - Dynamic_r (fun rev -> Cmd_I[ "describe"; "-r"; rev; ]) 139 + ; cmd = Dynamic_r (fun rev -> Cmd_I [ "describe"; "-r"; rev ]) 139 140 ; description = "Describe this revision using an editor" 140 141 } 141 142 ; { ··· 210 211 ] 211 212 in 212 213 let log = 213 - jj_no_log ~get_stderr:true [ "git"; "push"; "--dry-run" ] 214 + jj_no_log ~get_stderr:true [ "git"; "push"; "--dry-run" ] 214 215 |> AnsiReverse.colored_string 215 216 |> Ui.atom 216 217 |> Lwd.pure
-237
jj_tui/bin/jj_widgets.ml
··· 11 11 open Global_vars 12 12 open Jj_process.Make (Vars) 13 13 14 - exception FoundStart 15 - exception FoundFiller 16 - 17 - let make_uchar str = 18 - let a = String.get_utf_8_uchar str 0 in 19 - if a |> Uchar.utf_decode_is_valid 20 - then a |> Uchar.utf_decode_uchar 21 - else failwith "not a unicode string" 22 - ;; 23 - 24 - let elieded_symbol = make_uchar "◌" 25 - let rev_symbol = make_uchar "◉" 26 - let merge_symbol = make_uchar "◆" 27 - 28 - let is_whitespace_char (code_point : int) : bool = 29 - match code_point with 30 - | 0x0009 (* Tab *) 31 - | 0x000A (* Line Feed *) 32 - | 0x000B (* Vertical Tab *) 33 - | 0x000C (* Form Feed *) 34 - | 0x000D (* Carriage Return *) 35 - | 0x0020 (* Space *) 36 - | 0x0085 (* Next Line *) 37 - | 0x00A0 (* No-Break Space *) 38 - | 0x1680 (* Ogham Space Mark *) 39 - | 0x2000 (* En Quad *) 40 - | 0x2001 (* Em Quad *) 41 - | 0x2002 (* En Space *) 42 - | 0x2003 (* Em Space *) 43 - | 0x2004 (* Three-Per-Em Space *) 44 - | 0x2005 (* Four-Per-Em Space *) 45 - | 0x2006 (* Six-Per-Em Space *) 46 - | 0x2007 (* Figure Space *) 47 - | 0x2008 (* Punctuation Space *) 48 - | 0x2009 (* Thin Space *) 49 - | 0x200A (* Hair Space *) 50 - | 0x2028 (* Line Separator *) 51 - | 0x2029 (* Paragraph Separator *) 52 - | 0x202F (* Narrow No-Break Space *) 53 - | 0x205F (* Medium Mathematical Space *) 54 - | 0x3000 (* Ideographic Space *) -> 55 - true 56 - | _ -> 57 - false 58 - ;; 59 - 60 - let is_graph_start_char char = 61 - let i = Uchar.to_int char in 62 - (*chars like these: ├─╮*) 63 - let is_pipe = i > 0x2500 && i < 0x259f in 64 - let is_whitespace = is_whitespace_char i in 65 - is_pipe || is_whitespace 66 - ;; 67 - 68 - let test_data = 69 - {|◉ yzquvpvl eli.jambu@gmail.com 2024-05-23 15:04:24 3565237c 70 - ├─╮ merger 71 - ◉ │ wttqrrwo eli.jambu@gmail.com 2024-05-23 14:36:43 ui-update* 7e46fdef 72 - │ │ border_box working 73 - │ │ ◉ skwqmzmt eli.jambu@gmail.com 2024-05-25 01:07:57 7e358c79 74 - │ ├─╯ test old size scaling 75 - │ ◉ nuptyuws eli.jambu@gmail.com 2024-05-22 18:58:31 master 7b156964 76 - │ │ Update README.md 77 - │ ◌ (elided revisions) 78 - │ │ ◉ kmslutyl eli.jambu@gmail.com 2024-05-22 18:07:36 7b10ea4f conflict 79 - │ │ │ (no description set) 80 - │ │ ◉ nqyzyups eli.jambu@gmail.com 2024-05-22 18:07:36 519c664f conflict 81 - │ ├─╯ progress 82 - │ ◉ tutrxvzs eli.jambu@gmail.com 2024-05-22 18:07:36 af8620df 83 - │ │ flakes working 84 - │ ◌ (elided revisions) 85 - │ │ ◉ vlkxvssz eli.jambu@gmail.com 2024-05-15 19:40:28 79fb16f1 86 - │ ├─╯ (no description set) 87 - │ ◉ vtkpsqlr eli.jambu@gmail.com 2024-05-15 16:44:09 1974cc7d 88 - │ │ switch to pkgsStatic 89 - │ ◌ (elided revisions) 90 - │ │ ◉ zpvnoqkm eli.jambu@gmail.com 2024-05-15 09:47:41 c9f95816 91 - ├───╯ (no description set) 92 - ◉ │ unspmqrw eli.jambu@gmail.com 2024-05-15 09:47:41 83aafe3c 93 - ├─╯ update to nottui 94 - │ ◉ smvuxtrv eli.jambu@gmail.com 2024-05-15 09:47:41 d0ce4665 95 - ├─╯ (empty) bup 96 - ◉ yqytskyk eli.jambu@gmail.com 2024-05-15 09:47:41 0a89ce77 97 - │ test reorganise 98 - ◌ (elided revisions) 99 - │ ◉ qpqzkuss eli.jambu@gmail.com 2024-05-15 09:46:18 fdd16b26 conflict 100 - │ │ (no description set) 101 - │ ◉ xpqmtrmp eli.jambu@gmail.com 2024-05-15 09:46:18 555a5355 102 - ├─╯ remove old nix file 103 - ◉ zxpskuop eli.jambu@gmail.com 2024-05-15 09:46:18 dac0f8bb 104 - │ Update README.md|} 105 - ;; 106 - 107 - let root_test = {|◆ zzzzzzzz root() 00000000|} 108 - 109 - let rec list_to_pairs lst = 110 - match lst with 111 - | [] | [ _ ] -> 112 - [] (* If list is empty or has only one element, return empty list *) 113 - | x :: y :: rest -> 114 - (x, y) :: list_to_pairs rest 115 - ;; 116 - 117 - let rec pairwise f ~f_last lst = 118 - match lst with 119 - | [ single ] -> 120 - f_last single 121 - | x :: y :: rest -> 122 - ((x, y) |> f) :: pairwise f ~f_last rest 123 - | [] -> 124 - [] (* If list is empty or has only one element, return empty list *) 125 - ;; 126 - 127 - (* 128 - 1. Make the graph 129 - *) 130 - let is_line_filler line = 131 - if line |> Base.String.is_substring ~substring:"root()" 132 - then raise FoundStart 133 - else 134 - line 135 - (* We will iterate through skipping any chars like pipes and whitespace untill we find either: 136 - a) A rev start char,which would make the line a rev. 137 - b) Nothing, which would make the the line filler 138 - *) 139 - |> String.iteri (fun i char -> 140 - let uchar = String.get_utf_8_uchar line i |> Uchar.utf_decode_uchar in 141 - (*I've removed the part that tries to precisely skip all the start chars. this is becasue it gets all stuffed up by the terminal escape codes 142 - FIXME currently this will get stuffed up if a line has that rev symbol in it 143 - *) 144 - if uchar |> Uchar.equal merge_symbol 145 - || uchar |> Uchar.equal rev_symbol 146 - || char == '@' 147 - then raise FoundStart) 148 - ;; 149 - 150 - (** Function to tag duplicated items in a list *) 151 - let tag_duplicates lst = 152 - (* Create a frequency map to count occurrences of each element *) 153 - let freq_map = 154 - List.fold_left 155 - (fun acc { change_id; _ } -> 156 - let count = try List.assoc change_id acc with Not_found -> 0 in 157 - (change_id, count + 1) :: List.remove_assoc change_id acc) 158 - [] 159 - lst 160 - in 161 - (* Tag each item in the list based on the frequency map *) 162 - List.map 163 - (fun ({ change_id; _ } as x) -> 164 - if List.assoc change_id freq_map > 1 then Duplicate x else Unique x) 165 - lst 166 - ;; 167 - 168 - (**Returns a list of revs with both the change_id and commit_id*) 169 - let get_revs ?revset () = 170 - let revset_arg = match revset with Some revset -> [ "-r"; revset ] | None -> [] in 171 - jj_no_log 172 - ~color:false 173 - ([ "log"; "-T"; {|"|"++change_id++"|"++commit_id++"\n"|} ] @ revset_arg) 174 - |> String.split_on_char '\n' 175 - |> List.filter_map (fun x -> 176 - let items = x |> String.split_on_char '|' in 177 - match items with 178 - | [ _graph; change_id; commit_id ] -> 179 - Some { change_id; commit_id } 180 - | _ -> 181 - None) 182 - |> tag_duplicates 183 - |> Array.of_list 184 - ;; 185 - 186 - let find_selectable_from_graph str = 187 - let selectable_count = ref 0 in 188 - let processLine new_list previous_line this_line = 189 - match previous_line with 190 - | Some previous_line -> 191 - selectable_count := !selectable_count + 1; 192 - `Selectable (String.concat "\n" [ previous_line; this_line ]) :: new_list, None 193 - | None -> 194 - (try 195 - is_line_filler this_line; 196 - `Filler this_line :: new_list, None 197 - with 198 - | FoundStart -> 199 - new_list, Some this_line 200 - | FoundFiller -> 201 - `Filler this_line :: new_list, None) 202 - in 203 - let graph = 204 - str 205 - |> String.split_on_char '\n' 206 - (* filter out any lines that contain *) 207 - |> Base.List.fold ~init:([], None) ~f:(fun (new_list, previous) x -> 208 - (*there is generally a final newline and we should just skip that *) 209 - if String.length x = 0 210 - then new_list, previous 211 - else if String.length x <= 1 212 - then `Filler x :: new_list, None 213 - else processLine new_list previous x) 214 - (*the root() commit only has one line and will always be last, so we will try to process the final line*) 215 - |> (fun (list, final_line) -> 216 - match final_line with 217 - | Some line -> 218 - selectable_count := !selectable_count + 1; 219 - `Selectable line :: list 220 - | None -> 221 - list) 222 - |> List.rev 223 - |> Array.of_list 224 - in 225 - !selectable_count, graph 226 - ;; 227 - 228 - (* let test= *) 229 - (* let count,graph=find_selectable_from_graph root_test *) 230 - (* in *) 231 - (* if count<=0 then failwith "no process root" *) 232 - (* ;; *) 233 - 234 - (** returns the graph and a list of revs within that graph*) 235 - let graph_and_revs ?revset () = 236 - let selectable_count, graph = 237 - let revset_arg = match revset with Some revset -> [ "-r"; revset ] | None -> [] in 238 - let output = jj_no_log ([ "log" ] @ revset_arg) in 239 - output |> find_selectable_from_graph 240 - in 241 - let revs = get_revs ?revset () in 242 - (*The graph should never have selectable items that don't also have a rev*) 243 - 244 - (* TODO: remove this becasue it's just for debugging*) 245 - let revs_len = revs |> Array.length in 246 - if selectable_count <> revs_len 247 - then failwith (Printf.sprintf "selectable:%d revs:%d" selectable_count revs_len); 248 - graph, revs 249 - ;; 250 - 251 14 (*We use this sepcial char as the seperator because it seems very unlikely anyone will ever use it in a branch name: 252 15 \u{1c} 253 16 *)
+9
jj_tui/lib/process.ml
··· 1 + 2 + type rev_id = { 3 + change_id : string 4 + ; commit_id : string 5 + } 6 + 7 + type 'a maybe_unique = 8 + | Unique of 'a 9 + | Duplicate of 'a
+313
jj_tui/lib/process_wrappers.ml
··· 1 + (** Collection of JJ specific widgets*) 2 + 3 + open Notty 4 + open Nottui 5 + open Lwd_infix 6 + open! Util 7 + open Process 8 + 9 + exception FoundStart 10 + exception FoundFiller 11 + 12 + let make_uchar str = 13 + let a = String.get_utf_8_uchar str 0 in 14 + if a |> Uchar.utf_decode_is_valid 15 + then a |> Uchar.utf_decode_uchar 16 + else failwith "not a unicode string" 17 + ;; 18 + 19 + let elieded_symbol = make_uchar "◌" 20 + let elieded_symbol_alt = make_uchar "○" 21 + let rev_symbol = make_uchar "◉" 22 + let merge_symbol = make_uchar "◆" 23 + 24 + let is_whitespace_char (code_point : int) : bool = 25 + match code_point with 26 + | 0x0009 (* Tab *) 27 + | 0x000A (* Line Feed *) 28 + | 0x000B (* Vertical Tab *) 29 + | 0x000C (* Form Feed *) 30 + | 0x000D (* Carriage Return *) 31 + | 0x0020 (* Space *) 32 + | 0x0085 (* Next Line *) 33 + | 0x00A0 (* No-Break Space *) 34 + | 0x1680 (* Ogham Space Mark *) 35 + | 0x2000 (* En Quad *) 36 + | 0x2001 (* Em Quad *) 37 + | 0x2002 (* En Space *) 38 + | 0x2003 (* Em Space *) 39 + | 0x2004 (* Three-Per-Em Space *) 40 + | 0x2005 (* Four-Per-Em Space *) 41 + | 0x2006 (* Six-Per-Em Space *) 42 + | 0x2007 (* Figure Space *) 43 + | 0x2008 (* Punctuation Space *) 44 + | 0x2009 (* Thin Space *) 45 + | 0x200A (* Hair Space *) 46 + | 0x2028 (* Line Separator *) 47 + | 0x2029 (* Paragraph Separator *) 48 + | 0x202F (* Narrow No-Break Space *) 49 + | 0x205F (* Medium Mathematical Space *) 50 + | 0x3000 (* Ideographic Space *) -> 51 + true 52 + | _ -> 53 + false 54 + ;; 55 + 56 + let is_graph_start_char char = 57 + let i = Uchar.to_int char in 58 + (*chars like these: ├─╮*) 59 + let is_pipe = i > 0x2500 && i < 0x259f in 60 + let is_whitespace = is_whitespace_char i in 61 + is_pipe || is_whitespace 62 + ;; 63 + 64 + let rec list_to_pairs lst = 65 + match lst with 66 + | [] | [ _ ] -> 67 + [] (* If list is empty or has only one element, return empty list *) 68 + | x :: y :: rest -> 69 + (x, y) :: list_to_pairs rest 70 + ;; 71 + 72 + let rec pairwise f ~f_last lst = 73 + match lst with 74 + | [ single ] -> 75 + f_last single 76 + | x :: y :: rest -> 77 + ((x, y) |> f) :: pairwise f ~f_last rest 78 + | [] -> 79 + [] (* If list is empty or has only one element, return empty list *) 80 + ;; 81 + 82 + (* 83 + 1. Make the graph 84 + *) 85 + let is_line_filler line = 86 + if line |> Base.String.is_substring ~substring:"root()" 87 + then raise FoundStart 88 + else 89 + line 90 + (* We will iterate through skipping any chars like pipes and whitespace untill we find either: 91 + a) A rev start char,which would make the line a rev. 92 + b) Nothing, which would make the the line filler 93 + *) 94 + |> String.iteri (fun i char -> 95 + let uchar = String.get_utf_8_uchar line i |> Uchar.utf_decode_uchar in 96 + (*I've removed the part that tries to precisely skip all the start chars. this is becasue it gets all stuffed up by the terminal escape codes 97 + FIXME currently this will get stuffed up if a line has that rev symbol in it 98 + *) 99 + (* TODO: Overhaul the default graph template to include a special token at the end of selectable revisions *) 100 + if (uchar |> Uchar.equal merge_symbol 101 + || uchar |> Uchar.equal rev_symbol 102 + || uchar |> Uchar.equal elieded_symbol 103 + || uchar |> Uchar.equal elieded_symbol_alt 104 + || char == '@') 105 + && not (line |> Base.String.is_substring ~substring:"(elided revisions)") 106 + then raise FoundStart) 107 + ;; 108 + 109 + (** Function to tag duplicated items in a list *) 110 + let tag_duplicates lst = 111 + (* Create a frequency map to count occurrences of each element *) 112 + let freq_map = 113 + List.fold_left 114 + (fun acc { change_id; _ } -> 115 + let count = try List.assoc change_id acc with Not_found -> 0 in 116 + (change_id, count + 1) :: List.remove_assoc change_id acc) 117 + [] 118 + lst 119 + in 120 + (* Tag each item in the list based on the frequency map *) 121 + List.map 122 + (fun ({ change_id; _ } as x) -> 123 + if List.assoc change_id freq_map > 1 then Duplicate x else Unique x) 124 + lst 125 + ;; 126 + 127 + let find_selectable_from_graph str = 128 + let selectable_count = ref 0 in 129 + let processLine new_list previous_line this_line = 130 + match previous_line with 131 + | Some previous_line -> 132 + selectable_count := !selectable_count + 1; 133 + `Selectable (String.concat "\n" [ previous_line; this_line ]) :: new_list, None 134 + | None -> 135 + (try 136 + is_line_filler this_line; 137 + `Filler this_line :: new_list, None 138 + with 139 + | FoundStart -> 140 + new_list, Some this_line 141 + | FoundFiller -> 142 + `Filler this_line :: new_list, None) 143 + in 144 + let graph = 145 + str 146 + |> String.split_on_char '\n' 147 + (* filter out any lines that contain *) 148 + |> Base.List.fold ~init:([], None) ~f:(fun (new_list, previous) x -> 149 + (*there is generally a final newline and we should just skip that *) 150 + if String.length x = 0 151 + then new_list, previous 152 + else if String.length x <= 1 153 + then `Filler x :: new_list, None 154 + else processLine new_list previous x) 155 + (*the root() commit only has one line and will always be last, so we will try to process the final line*) 156 + |> (fun (list, final_line) -> 157 + match final_line with 158 + | Some line -> 159 + selectable_count := !selectable_count + 1; 160 + `Selectable line :: list 161 + | None -> 162 + list) 163 + |> List.rev 164 + |> Array.of_list 165 + in 166 + !selectable_count, graph 167 + ;; 168 + 169 + (** retrieve revs from jj log of jj_tui*) 170 + let revs_from_log log = 171 + log 172 + |> String.split_on_char '\n' 173 + |> List.filter_map (fun x -> 174 + let items = x |> String.split_on_char '|' in 175 + match items with 176 + | [ _graph; change_id; commit_id ] -> 177 + Some { change_id; commit_id } 178 + | _ -> 179 + None) 180 + |> tag_duplicates 181 + |> Array.of_list 182 + ;; 183 + 184 + module Make (Process : sig 185 + val jj_no_log : 186 + ?get_stderr:bool 187 + -> ?snapshot:bool 188 + -> ?color:bool 189 + -> string list 190 + -> string 191 + end) = 192 + struct 193 + open Process 194 + 195 + (**Returns a list of revs with both the change_id and commit_id*) 196 + let get_revs ?revset () = 197 + let revset_arg = match revset with Some revset -> [ "-r"; revset ] | None -> [] in 198 + jj_no_log 199 + ~color:false 200 + ([ "log"; "-T"; {|"|"++change_id++"|"++commit_id++"\n"|} ] @ revset_arg) 201 + |> revs_from_log 202 + ;; 203 + 204 + (* let test= *) 205 + (* let count,graph=find_selectable_from_graph root_test *) 206 + (* in *) 207 + (* if count<=0 then failwith "no process root" *) 208 + (* ;; *) 209 + 210 + (** returns the graph and a list of revs within that graph*) 211 + let graph_and_revs ?revset () = 212 + let selectable_count, graph = 213 + let revset_arg = match revset with Some revset -> [ "-r"; revset ] | None -> [] in 214 + let output = jj_no_log ([ "log" ] @ revset_arg) in 215 + output |> find_selectable_from_graph 216 + in 217 + let revs = get_revs ?revset () in 218 + (*The graph should never have selectable items that don't also have a rev*) 219 + 220 + (* TODO: remove this becasue it's just for debugging*) 221 + let revs_len = revs |> Array.length in 222 + if selectable_count <> revs_len 223 + then failwith (Printf.sprintf "selectable:%d revs:%d" selectable_count revs_len); 224 + graph, revs 225 + ;; 226 + end 227 + 228 + (*========Tests======*) 229 + 230 + let test_data = 231 + {|◉ yzquvpvl eli.jambu@gmail.com 2024-05-23 15:04:24 3565237c 232 + ├─╮ merger 233 + ◉ │ wttqrrwo eli.jambu@gmail.com 2024-05-23 14:36:43 ui-update* 7e46fdef 234 + │ │ border_box working 235 + │ │ ◉ skwqmzmt eli.jambu@gmail.com 2024-05-25 01:07:57 7e358c79 236 + │ ├─╯ test old size scaling 237 + │ ◉ nuptyuws eli.jambu@gmail.com 2024-05-22 18:58:31 master 7b156964 238 + │ │ Update README.md 239 + │ ◌ (elided revisions) 240 + │ │ ◉ kmslutyl eli.jambu@gmail.com 2024-05-22 18:07:36 7b10ea4f conflict 241 + │ │ │ (no description set) 242 + │ │ ◉ nqyzyups eli.jambu@gmail.com 2024-05-22 18:07:36 519c664f conflict 243 + │ ├─╯ progress 244 + │ ◉ tutrxvzs eli.jambu@gmail.com 2024-05-22 18:07:36 af8620df 245 + │ │ flakes working 246 + │ ◌ (elided revisions) 247 + │ │ ◉ vlkxvssz eli.jambu@gmail.com 2024-05-15 19:40:28 79fb16f1 248 + │ ├─╯ (no description set) 249 + │ ◉ vtkpsqlr eli.jambu@gmail.com 2024-05-15 16:44:09 1974cc7d 250 + │ │ switch to pkgsStatic 251 + │ ◌ (elided revisions) 252 + │ │ ◉ zpvnoqkm eli.jambu@gmail.com 2024-05-15 09:47:41 c9f95816 253 + ├───╯ (no description set) 254 + ◉ │ unspmqrw eli.jambu@gmail.com 2024-05-15 09:47:41 83aafe3c 255 + ├─╯ update to nottui 256 + │ ◉ smvuxtrv eli.jambu@gmail.com 2024-05-15 09:47:41 d0ce4665 257 + ├─╯ (empty) bup 258 + ◉ yqytskyk eli.jambu@gmail.com 2024-05-15 09:47:41 0a89ce77 259 + │ test reorganise 260 + ◌ (elided revisions) 261 + │ ◉ qpqzkuss eli.jambu@gmail.com 2024-05-15 09:46:18 fdd16b26 conflict 262 + │ │ (no description set) 263 + │ ◉ xpqmtrmp eli.jambu@gmail.com 2024-05-15 09:46:18 555a5355 264 + ├─╯ remove old nix file 265 + ◉ zxpskuop eli.jambu@gmail.com 2024-05-15 09:46:18 dac0f8bb 266 + │ Update README.md|} 267 + ;; 268 + 269 + let root_test = {|◆ zzzzzzzz root() 00000000|} 270 + 271 + let test_data_2 = 272 + {|@ qpnrvwyl ethanboxx 13 seconds ago 48829167 273 + │ (no description set) 274 + ◆ pqvkrmkw ethanboxx 3 months ago main v0.1.10 HEAD@git 931019c4 275 + │ (empty) Merge pull request #63 from eopb/release-plz-2024-05-11T09-14-47Z 276 + ~ (elided revisions) 277 + │ ○ xnyvmlur ethanboxx 5 months ago push-znvwmrtqnnlq 0deaa0aa 278 + ├─┘ feat: impl `Deref` and `DerefMut` without exposing `Secret` 279 + ◆ kkzuqwxo ethanboxx 5 months ago 9aa340cc 280 + │ (empty) Merge pull request #56 from eopb/push-smksztlxprww 281 + ~|} 282 + ;; 283 + 284 + let%expect_test "revs_graph_parsing" = 285 + let selectable, graph = find_selectable_from_graph test_data_2 in 286 + graph 287 + |> Array.iter (fun x -> 288 + match x with 289 + | `Filler x -> 290 + "F:" |> print_endline; 291 + x |> print_endline 292 + | `Selectable x -> 293 + "S:" |> print_endline; 294 + x |> print_endline); 295 + [%expect 296 + {| 297 + S: 298 + @ qpnrvwyl ethanboxx 13 seconds ago 48829167 299 + │ (no description set) 300 + S: 301 + ◆ pqvkrmkw ethanboxx 3 months ago main v0.1.10 HEAD@git 931019c4 302 + │ (empty) Merge pull request #63 from eopb/release-plz-2024-05-11T09-14-47Z 303 + F: 304 + ~ (elided revisions) 305 + S: 306 + │ ○ xnyvmlur ethanboxx 5 months ago push-znvwmrtqnnlq 0deaa0aa 307 + ├─┘ feat: impl `Deref` and `DerefMut` without exposing `Secret` 308 + S: 309 + ◆ kkzuqwxo ethanboxx 5 months ago 9aa340cc 310 + │ (empty) Merge pull request #56 from eopb/push-smksztlxprww 311 + F: 312 + ~ |}] 313 + ;;