diff --git a/lib/cli.ml b/lib/cli.ml index 7633d00..93f31da 100644 --- a/lib/cli.ml +++ b/lib/cli.ml @@ -23,7 +23,7 @@ let ignore_size_warning_arg = Arg.(value & flag & info [ "i"; "ignore-size-warning" ] ~doc) let run owner_repo local_path log_file ignore_size_warning = - Tui.start ~owner_repo ~local_path ~log_file ~ignore_size_warning + Tui.start { owner_repo; local_path; log_file; ignore_size_warning } let gh_tui_term = Term.( diff --git a/lib/tui/dune b/lib/tui/dune index dfaff8b..d88ea5e 100644 --- a/lib/tui/dune +++ b/lib/tui/dune @@ -6,6 +6,7 @@ extra fs gh + init log model pretty diff --git a/lib/tui/init/dune b/lib/tui/init/dune new file mode 100644 index 0000000..9d38c72 --- /dev/null +++ b/lib/tui/init/dune @@ -0,0 +1,7 @@ +(library + (name init) + (libraries + terminal_size + ;; Internal dependencies + model + fs)) diff --git a/lib/tui/init/init.ml b/lib/tui/init/init.ml new file mode 100644 index 0000000..80f942a --- /dev/null +++ b/lib/tui/init/init.ml @@ -0,0 +1,78 @@ +type owner_repo = { + owner : string; + repo : string; +} + +let parse_owner_repo owner_repo = + match String.split_on_char '/' owner_repo with + | [ owner; repo ] -> { owner; repo } + | _ -> + Printf.eprintf "❌ Expected / but got: '%s'\n" owner_repo; + exit 1 + +let clone_repo ~owner_repo ~local_path = + match local_path with + | Some path -> path + | None -> + let { owner; repo } = owner_repo in + let temp_dir = + Filename.temp_dir "github-tui-" (Printf.sprintf "%s-%s" owner repo) + in + let cmd = + Printf.sprintf "git clone git@github.com:%s/%s.git %s" owner repo + temp_dir + in + Shell.proc cmd; + temp_dir + +let read_root_tree ~root_dir_path = + let tree = Fs.read_tree root_dir_path in + let files = + match tree with + | Fs.File { name; _ } -> + Printf.eprintf "Given path '%s' is not a directory!" name; + exit 1 + | Fs.Dir { children = files; _ } -> files + in + files + +type terminal = { + height : int; + width : int; +} + +let min_height, min_width = (40, 140) + +let get_terminal_dimensions ignore_size_warning = + match (Terminal_size.get_rows (), Terminal_size.get_columns ()) with + | Some height, Some width -> + if (not ignore_size_warning) && (height < min_height || width < min_width) + then ( + Printf.eprintf + {|⚠️ Terminal size is too small! GitHub TUI works better on bigger terminals. + Expected size: %3d width x %3d height + But got: %3d width x %3d height + + Pass the --ignore-size-warning flag to run anyway. +|} + min_width min_height width height; + exit 1); + { height; width } + | _ -> + Printf.eprintf "⚠️ Not able to get the terminal size.\n"; + exit 1 + +type t = { + owner_repo : string; + local_path : string option; + log_file : string option; + ignore_size_warning : bool; +} + +let init { owner_repo; local_path; ignore_size_warning; log_file = _ } : + Model.initial_data = + let ({ owner; repo } as owner_repo) = parse_owner_repo owner_repo in + let root_dir_path = clone_repo ~owner_repo ~local_path in + let files = Lazy.force (read_root_tree ~root_dir_path) in + let { height; width } = get_terminal_dimensions ignore_size_warning in + { owner; repo; root_dir_path; files; width; height } diff --git a/lib/tui/init/init.mli b/lib/tui/init/init.mli new file mode 100644 index 0000000..efdcecb --- /dev/null +++ b/lib/tui/init/init.mli @@ -0,0 +1,8 @@ +type t = { + owner_repo : string; + local_path : string option; + log_file : string option; + ignore_size_warning : bool; +} + +val init : t -> Model.initial_data diff --git a/lib/tui/tui.ml b/lib/tui/tui.ml index 2eaeb0d..e333bdd 100644 --- a/lib/tui/tui.ml +++ b/lib/tui/tui.ml @@ -1,76 +1,5 @@ -type owner_repo = { - owner : string; - repo : string; -} - -let parse_owner_repo owner_repo = - match String.split_on_char '/' owner_repo with - | [ owner; repo ] -> { owner; repo } - | _ -> - Printf.eprintf "❌ Expected / but got: '%s'\n" owner_repo; - exit 1 - -let clone_repo ~owner_repo ~local_path = - match local_path with - | Some path -> path - | None -> - let { owner; repo } = owner_repo in - let temp_dir = - Filename.temp_dir "github-tui-" (Printf.sprintf "%s-%s" owner repo) - in - let cmd = - Printf.sprintf "git clone git@github.com:%s/%s.git %s" owner repo - temp_dir - in - Shell.proc cmd; - temp_dir - -let read_root_tree ~root_dir_path = - let tree = Fs.read_tree root_dir_path in - let files = - match tree with - | Fs.File { name; _ } -> - Printf.eprintf "Given path '%s' is not a directory!" name; - exit 1 - | Fs.Dir { children = files; _ } -> files - in - files - -type terminal = { - height : int; - width : int; -} - -let min_height, min_width = (40, 140) - -let get_terminal_dimensions ignore_size_warning = - match (Terminal_size.get_rows (), Terminal_size.get_columns ()) with - | Some height, Some width -> - if (not ignore_size_warning) && (height < min_height || width < min_width) - then ( - Printf.eprintf - {|⚠️ Terminal size is too small! GitHub TUI works better on bigger terminals. - Expected size: %3d width x %3d height - But got: %3d width x %3d height - - Pass the --ignore-size-warning flag to run anyway. -|} - min_width min_height width height; - exit 1); - { height; width } - | _ -> - Printf.eprintf "⚠️ Not able to get the terminal size.\n"; - exit 1 - -let init ~owner_repo ~local_path ~ignore_size_warning : Model.initial_data = - let ({ owner; repo } as owner_repo) = parse_owner_repo owner_repo in - let root_dir_path = clone_repo ~owner_repo ~local_path in - let files = Lazy.force (read_root_tree ~root_dir_path) in - let { height; width } = get_terminal_dimensions ignore_size_warning in - { owner; repo; root_dir_path; files; width; height } - -let start ~owner_repo ~local_path ~log_file ~ignore_size_warning = - let initial_data = init ~owner_repo ~local_path ~ignore_size_warning in +let start args = + let initial_data = Init.init args in let init = Model.initial_model initial_data in let app = Tea.make ~init ~update:Update.update ~view:View.view in - Tea.run ?path:log_file app + Tea.run ?path:args.log_file app diff --git a/lib/tui/tui.mli b/lib/tui/tui.mli index cbeb368..ed5990e 100644 --- a/lib/tui/tui.mli +++ b/lib/tui/tui.mli @@ -1,6 +1 @@ -val start : - owner_repo:string -> - local_path:string option -> - log_file:string option -> - ignore_size_warning:bool -> - unit +val start : Init.t -> unit