aboutsummaryrefslogtreecommitdiff
path: root/lib/grep.ml
blob: 9638c3720f0b89d10adc65fb397c33ea3aeffe4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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 find_sort_modification () =
  let open Shexp_process in
  let open Shexp_process.Infix in
  call [ "find"; "."; "-printf"; "%Ts/%f\\n" ]
  |- call [ "sort"; "-n" ]
  |- call [ "cut"; "-c12-" ]
  |- call [ "sed"; "/^\\./d" ]


let find_sort_name () =
  let open Shexp_process in
  let open Shexp_process.Infix in
  call [ "find"; "." ] |- call [ "sort"; "-n" ] |- call [ "cut"; "-c3-" ]


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 = [ "xargs"; grep_cmd; "^\\*"; "-H"; "-r"; "-n"; "--no-messages" ]

(* type sort = *)
(*   | Name *)
(*   | LastModified *)

(* let sort_to_cmd = function *)
(*   | Name -> find_sort_name () *)
(*   | LastModified -> find_sort_modification () *)

let get_headlines () =
  let open Shexp_process in
  let open Shexp_process.Infix in
  eval (chdir execution_directory (find_sort_name () |- call headline_args |- read_all))


let get_tagged_headlines tag () =
  let open Shexp_process in
  let open Shexp_process.Infix in
  eval
    (chdir
       execution_directory
       (find_sort_name ()
        |- 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 ":[0-9]+:") message 2 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 ->  *)