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.

fix some ansi colour parsing bugs and optimize joined ansi codes

+87 -22
+4 -3
forks/notty/src/notty.ml
··· 195 195 and lightmagenta = 0x0100000d 196 196 and lightcyan = 0x0100000e 197 197 and lightwhite = 0x0100000f 198 - and no_color = 0x01000010 198 + and color_reset = 0x01000010 199 199 200 200 let tag c = (c land 0x03000000) lsr 24 201 201 ··· 240 240 241 241 let (--) a1 a2 = 242 242 if a1 == empty then a2 else if a2 == empty then a1 else 243 - { fg = (match a2.fg with no_color -> 0 | _ -> a1.fg) 244 - ; bg = (match a2.bg with no_color -> 0 | _ -> a1.bg) 243 + (* 0x01000010 is the color reset color defined above*) 244 + { fg = (match a2.fg with 0x01000010-> 0 | _ -> if a1.fg==a2.fg then 0 else a1.fg) 245 + ; bg = (match a2.bg with 0x01000010-> 0 | _ -> if a1.bg==a2.bg then 0 else a1.bg) 245 246 ; st = a1.st land (lnot a2.st) } 246 247 247 248 let fg fg = { empty with fg }
+2 -5
forks/notty/src/notty.mli
··· 104 104 val lightmagenta : color 105 105 val lightcyan : color 106 106 val lightwhite : color 107 - val no_color : color 107 + val color_reset : color 108 108 109 109 (** {2 Extended 256-color palette} *) 110 110 ··· 169 169 [++] is left-associative, and forms a monoid with [empty]. *) 170 170 171 171 val (--) : attr -> attr -> attr 172 - (** [a1 -- a2] is the difference of [a1] and [a2], the attribute that has 173 - [a1]'s foreground (resp. background), unless {e unset}, in which case it 174 - is [a2]'s, and the difference of both style sets. 175 - 172 + (** [a1 -- a2] removes a2 from a1 176 173 [--] is left-associative, and forms a monoid with [empty]. *) 177 174 178 175 val fg : color -> attr
+81 -14
jj_tui/lib/ansiReverse.ml
··· 33 33 let print_attr img = 34 34 print_endline "attr:"; 35 35 img |> Notty.Render.pp_attr @@ Format.str_formatter; 36 - print_endline (Format.flush_str_formatter ()|>Str.global_replace (Str.regexp "\027") "\\e") 36 + print_endline 37 + (Format.flush_str_formatter () |> Str.global_replace (Str.regexp "\027") "\\e") 37 38 ;; 38 39 39 40 (** Like fold left except we run the first element through init to get the state*) ··· 54 55 | Apply of A.t 55 56 | Reset of A.t 56 57 | FullyReset 58 + 57 59 let parse_escape_seq = 58 60 let open A in 59 61 let open Angstrom in ··· 63 65 let param = digits <* option ' ' (char ';') in 64 66 let params = many (param >>| int_of_string) in 65 67 let escape_sequence = char '\027' *> char '[' *> params <* char 'm' in 68 + let full_seq=many1 escape_sequence in 66 69 let attr_of_params = function 67 70 | [] -> 68 71 Apply empty ··· 91 94 | 23 :: _ -> 92 95 Reset (st italic) (* Reset italic *) 93 96 | 24 :: _ -> 94 - Reset (st underline ) (* Reset underline *) 97 + Reset (st underline) (* Reset underline *) 95 98 | 25 :: _ -> 96 99 Reset (st blink) (* Reset blink *) 97 100 | 27 :: _ -> ··· 121 124 | 38 :: 2 :: r :: g :: b :: _ -> 122 125 Apply (fg (rgb_888 ~r ~g ~b)) 123 126 | 39 :: _ -> 124 - Reset (fg no_color) (* Default foreground color *) 127 + Reset (fg color_reset) (* Default foreground color *) 125 128 | 40 :: _ -> 126 129 Apply (bg black) 127 130 | 41 :: _ -> ··· 143 146 | 48 :: 2 :: r :: g :: b :: _ -> 144 147 Apply (bg (rgb_888 ~r ~g ~b)) 145 148 | 49 :: _ -> 146 - Reset (bg no_color) (* Default background color *) 149 + Reset (bg color_reset) (* Default background color *) 147 150 | 90 :: _ -> 148 151 Apply (fg lightblack) (* Bright black (gray) *) 149 152 | 91 :: _ -> ··· 179 182 | _ -> 180 183 Apply empty 181 184 in 182 - escape_sequence >>| attr_of_params 185 + full_seq>>| List.map attr_of_params 183 186 ;; 184 187 185 188 let%expect_test "escape_parser" = ··· 187 190 let res = 188 191 Angstrom.parse_string ~consume:All parse_escape_seq test_str |> Result.get_ok 189 192 in 193 + res|>List.iter(fun res-> 190 194 (match res with 191 195 | Apply attr -> 192 196 print_attr attr ··· 194 198 print_endline "Reset attribute" 195 199 | FullyReset -> 196 200 print_endline "Fully reset attribute"); 197 - 201 + ); 202 + [%expect 203 + {| 204 + attr: 205 + \e[0m<\e[0;32mATTR\e[0m\e[K\e[0m>\e[0m 206 + |}] 207 + ;; 208 + let%expect_test "escape_parser_2" = 209 + let test_str = "\027[32m" in 210 + let res = 211 + Angstrom.parse_string ~consume:All parse_escape_seq test_str |> Result.get_ok 212 + in 213 + res|>List.iter(fun res-> 214 + (match res with 215 + | Apply attr -> 216 + print_attr attr 217 + | Reset _ -> 218 + print_endline "Reset attribute" 219 + | FullyReset -> 220 + print_endline "Fully reset attribute"); 221 + ); 198 222 [%expect 199 223 {| 200 224 attr: ··· 208 232 let attr = parse_escape_seq in 209 233 let substring = take_while (fun c -> c <> '\027') in 210 234 let pair = 211 - attr >>= fun action -> 235 + attr >>= fun actions -> 212 236 substring >>= fun s -> 213 - (match action with 237 + actions|>List.iter(fun action-> 238 + match action with 214 239 | Apply a -> 215 240 attr_state := A.( ++ ) !attr_state a 216 241 | Reset a -> ··· 264 289 Text: "rest" 265 290 |}] 266 291 ;; 292 + 267 293 let%expect_test "parse_ansi_strikethrough_test" = 268 - let open A in 294 + let open A in 269 295 print_attr (A.st A.strike); 270 296 print_attr (A.st A.strike ++ A.fg A.red); 271 297 print_attr (A.st A.blink); ··· 275 301 print_attr (A.st A.bold); 276 302 print_attr (A.st A.reverse ++ A.fg A.red); 277 303 print_attr (A.st A.hidden); 278 - 279 304 [%expect 280 305 {| 281 306 attr: ··· 299 324 |}] 300 325 ;; 301 326 302 - 303 327 let%expect_test "attribute_removal_test" = 304 328 let open A in 305 329 (* Test removing styles *) 306 - let base_attr = st bold ++ st underline ++ st italic in 330 + let base_attr = st bold ++ st underline ++ st italic in 307 331 let result = base_attr -- st italic in 308 332 Internal.print_attr result; 309 333 [%expect ··· 321 345 |}]; 322 346 (* Test removing foreground color *) 323 347 let colored = base_attr ++ fg red in 324 - let no_color = colored -- fg no_color in 325 - Internal.print_attr no_color; 348 + let color_reset = colored -- fg color_reset in 349 + Internal.print_attr color_reset; 326 350 [%expect 327 351 {| 328 352 attr: 329 353 \e[0m<\e[0;1;3;4mATTR\e[0m\e[K\e[0m>\e[0m 354 + |}]; 355 + (* Test removing a style from colored *) 356 + let no_underline = colored -- st underline in 357 + Internal.print_attr no_underline; 358 + [%expect 359 + {| 360 + attr: 361 + \e[0m<\e[0;1;3mATTR\e[0m\e[K\e[0m>\e[0m 330 362 |}]; 331 363 (* Test removing background color *) 332 364 let bg_colored = base_attr ++ bg blue in ··· 345 377 {| 346 378 attr: 347 379 \e[0m<\e[0mATTR\e[0m\e[K\e[0m>\e[0m 380 + |}] 381 + ;; 382 + 383 + let%expect_test "edge_case_1" = 384 + let test_str = 385 + {| 145: onescript10|} 386 + in 387 + (match parse_ansi_escape_codes test_str with 388 + | Error err -> 389 + Printf.printf "Error: %s\n" err 390 + | Ok result -> 391 + Printf.printf "Parsed %d segments:\n" (List.length result); 392 + List.iter 393 + (fun (attr, text) -> 394 + print_attr attr; 395 + Printf.printf "Text: %s" (String.escaped text)) 396 + result); 397 + [%expect 398 + {| 399 + Parsed 7 segments: 400 + attr: 401 + \e[0m<\e[0mATTR\e[0m\e[K\e[0m>\e[0m 402 + Text: attr: 403 + \e[0m<\e[0;32mATTR\e[0m\e[K\e[0m>\e[0m 404 + Text: 145attr: 405 + \e[0m<\e[0mATTR\e[0m\e[K\e[0m>\e[0m 406 + Text: : attr: 407 + \e[0m<\e[0;4mATTR\e[0m\e[K\e[0m>\e[0m 408 + Text: attr: 409 + \e[0m<\e[0;32;4mATTR\e[0m\e[K\e[0m>\e[0m 410 + Text: oneattr: 411 + \e[0m<\e[0mATTR\e[0m\e[K\e[0m>\e[0m 412 + Text: scriptattr: 413 + \e[0m<\e[0;4mATTR\e[0m\e[K\e[0m>\e[0m 414 + Text: 10 348 415 |}] 349 416 ;; 350 417 end