Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions lib/fs/fs.ml
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
module Filec = Filec

type tree =
| File of string * Filec.t Lazy.t * Filec.file_type Lazy.t
| Dir of string * tree array Lazy.t
| File of {
name : string;
contents : Filec.t Lazy.t;
file_type : Filec.file_type Lazy.t;
}
| Dir of {
name : string;
children : tree array Lazy.t;
}

type dir_cursor = {
pos : int;
Expand All @@ -15,8 +22,8 @@ type cursor =

(* Extracts the file name from a tree node *)
let file_name = function
| File (name, _, _) -> name
| Dir (name, _) -> name
| File { name; _ } -> name
| Dir { name; _ } -> name
Comment on lines +25 to +26
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was actually the main motivation behind doing this minor refactoring.

The internal contents of constructors like File and Dir might change by adding and removing some fields (I already expect a few possible changes). But these changes will be decoupled from functions that don't affect them, so it'll be easier to perform them.

Even such minor things matter when a project grows.


(* A files comparison:

Expand All @@ -30,10 +37,10 @@ let order_files t1 t2 =
| _, _ -> String.compare (file_name t1) (file_name t2)

let rec sort_tree = function
| File (name, contents, ft) -> File (name, contents, ft)
| Dir (name, (lazy children)) ->
| File _ as f -> f
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice usage of alias patterns 💯

| Dir { name; children = (lazy children) } ->
Array.sort order_files children;
Dir (name, lazy (Array.map sort_tree children))
Dir { name; children = lazy (Array.map sort_tree children) }

(* Recursively reads a directory tree *)
let rec to_tree path =
Expand All @@ -44,13 +51,15 @@ let rec to_tree path =
(fun child_name -> to_tree (Filename.concat path child_name))
(Sys.readdir path))
in
let dirname = Filename.basename path in
Dir (dirname, children)
let name = Filename.basename path in
Dir { name; children }
else
File
( Filename.basename path,
lazy (Filec.read path),
lazy (Filec.type_of_path path) )
{
name = Filename.basename path;
contents = lazy (Filec.read path);
file_type = lazy (Filec.type_of_path path);
}

let read_tree path = path |> to_tree |> sort_tree
let file_at cursor = cursor.files.(cursor.pos)
Expand Down Expand Up @@ -100,12 +109,12 @@ let go_next zipper =
| Dir_cursor cursor -> (
let next = file_at cursor in
match next with
| File (_name, contents, _) ->
| File { contents; _ } ->
{
parents = cursor :: zipper.parents;
current = File_cursor (Lazy.force contents);
}
| Dir (_, (lazy next)) ->
| Dir { children = (lazy next); _ } ->
if Array.length next = 0 then zipper
else
{
Expand Down
14 changes: 12 additions & 2 deletions lib/fs/fs.mli
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@
and current offsets. *)
module Filec = Filec

(* NOTE: contents and file_type are stored separately so we can know the file
type and assign a proper icon without reading the contents *)

(** A definition of a file tree. *)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor addition while we're on this: let's improve docs by adding a note saying something like that contents and file_type are stored separately as two lazy values so we can quickly understand the file type and use a proper icon without reading the whole contents.

Just a note for future selves so we don't forget the motivation 😅

type tree =
| File of string * Filec.t Lazy.t * Filec.file_type Lazy.t
| Dir of string * tree array Lazy.t
| File of {
name : string;
contents : Filec.t Lazy.t;
file_type : Filec.file_type Lazy.t;
}
| Dir of {
name : string;
children : tree array Lazy.t;
}

(** Return the name of a given tree node. *)
val file_name : tree -> string
Expand Down
6 changes: 3 additions & 3 deletions lib/tui/tui.ml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ let read_root_tree ~root_dir_path =
let tree = Fs.read_tree root_dir_path in
let files =
match tree with
| Fs.File (path, _, _) ->
Printf.eprintf "Given path '%s' is not a directory!" path;
| Fs.File { name; _ } ->
Printf.eprintf "Given path '%s' is not a directory!" name;
exit 1
| Fs.Dir (_, files) -> files
| Fs.Dir { children = files; _ } -> files
in
files

Expand Down
8 changes: 4 additions & 4 deletions lib/tui/widget/code.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ let max_file_name_len files =
let fmt_file ~max_name_len (tree : Fs.tree) =
let pad = Extra.String.fill_right max_name_len in
match tree with
| File (name, _, file_type) -> (
| File { name; file_type; _ } -> (
match Lazy.force file_type with
| Fs.Filec.Text -> Pretty.Icon.file_char ^ " " ^ pad name
| Fs.Filec.Binary -> Pretty.Icon.bin_char ^ " " ^ pad name)
| Dir (name, (lazy children)) -> (
| Dir { name; children = (lazy children) } -> (
match children with
| [||] -> Pretty.Icon.empty_dir_char ^ " " ^ pad name
| _ -> Pretty.Icon.dir_char ^ " " ^ pad name)
Expand Down Expand Up @@ -189,8 +189,8 @@ let fs_to_view (fs : Fs.zipper) =
| File_cursor contents, parent :: _ -> (parent, File_selected contents)
| Dir_cursor cursor, _ -> (
match Fs.file_at cursor with
| File (_, contents, _) -> (cursor, File_selected (Lazy.force contents))
| Dir (_, children) ->
| File { contents; _ } -> (cursor, File_selected (Lazy.force contents))
| Dir { children; _ } ->
( cursor,
Dir_selected
{
Expand Down