let execution_directory = Sys.getenv_opt "STICH_DIRECTORY" |> Option.value ~default:"/home/mccd/notes-example" let grep_cmd = Sys.getenv_opt "STICH_GREP_CMD" |> Option.value ~default:"ugrep" let tag_pattern = Sys.getenv_opt "STITCH_TAG_PATTERN" |> Option.value ~default:":[a-z_-]+:" let headline_pattern = Sys.getenv_opt "STITCH_HEADLINE_PATTERN" |> Option.value ~default:"^\\* " let run_print ~dir args = let open Shexp_process in let open Shexp_process.Infix in eval (chdir dir (call args |- read_all)) let headline_args = [ grep_cmd; "^\\*"; "-H"; "-r"; "-n"; "--separator=|"; "--no-messages" ] let get_headlines () = run_print ~dir:execution_directory headline_args let get_tagged_headlines tag () = let open Shexp_process in let open Shexp_process.Infix in eval (chdir execution_directory (call headline_args |- call [ grep_cmd; "-E"; "--no-messages"; tag ] |- read_all)) let get_tags () = let open Shexp_process in let open Shexp_process.Infix in eval (chdir execution_directory (call headline_args |- call [ grep_cmd; "-E"; tag_pattern; "-o" ] |- read_all)) exception Not_A_Tuple of string * string (** Returns a tuple of file name and Content *) let parse_headlines s = String.split_on_char '\n' s (* Testing in utop it seems like there is maybe a bug with bounded_split, 1 doesn't work for ':'. Therefore using a slower implementation. *) |> List.filter_map (fun message -> if String.equal message "" then None else ( let split = Str.bounded_split (Str.regexp "|") message 3 in match split with (* file, line, content *) | [ file_name; _; content ] -> Some (file_name, content) | _ -> raise (Not_A_Tuple (String.concat " SPLIT " split, message)))) |> Array.of_list (** Used for pretty printing *) let get_padding list = Array.fold_left (fun n (file_name, _) -> Int.max n (String.length file_name)) 0 list let pad str n = let padding = n - String.length str in String.concat "" [ str; String.make padding ' ' ] (** Turns "2024-03-05.org:* Hello world" into "2024-03-05 | * Hello world" *) let pretty_format parsed_headlines = let padding = get_padding parsed_headlines in Array.map (fun (file_name, content) -> String.concat " | " [ pad file_name padding; content ]) parsed_headlines (** Full body parsing *) let get_full_content () = run_print ~dir:execution_directory [ grep_cmd; "^\\*"; "-h"; "-r"; "-n"; "-C"; "9999"; "--separator='|'" ] (* let parse_file_headline collection full = *) (* match full with *) (* | s :: r -> *) (* let split = Str.bounded_split (Str.regexp ":1:") s 1 in *) (* (match split with *) (* (\* file, line, content *\) *) (* | [ file_name; content ] -> file_name, content *) (* | rest -> *)