Skip to content
Closed
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
1 change: 1 addition & 0 deletions lib/pretty/dune
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
(libraries
ansifmt
shell
str
;; Internal dependencies
extra))
104 changes: 93 additions & 11 deletions lib/pretty/icon.ml
Original file line number Diff line number Diff line change
@@ -1,11 +1,93 @@
let closed_char = "\u{ebda}"
let open_char = "\u{ea64}"
let merged_char = "\u{e725}"
let arrow_left_char = "\u{f0a8}"
let pwd_char = "\u{e5fd}"
let dir_char = "\u{f4d4}"
let empty_dir_char = "\u{f413}"
let file_char = "\u{f4a5}"
let bin_char = "\u{eae8}"
let warning = "\u{26A0}"
let issue_char = "\u{f41b}"
type t = {
closed_char : string;
open_char : string;
merged_char : string;
arrow_left_char : string;
pwd_char : string;
dir_char : string;
empty_dir_char : string;
file_char : string;
bin_char : string;
warning : string;
issue_char : string;
}

let hack_nerd_font = "HackNerdFontMono"
let fc_list_cmd = Printf.sprintf "fc-list | grep '%s'" hack_nerd_font
let uname_cmd = {| uname |}

type os_name =
| Linux
| MacOS

let uname_result =
Shell.proc_stdout uname_cmd |> String.trim |> function
| "Linux" -> Some Linux
| "Darwin" -> Some MacOS
| _ -> None

(* Based on the list of possible folders here: https://github.com/adrg/xdg/blob/master/README.md#other-directories*)
let mac_font_dirs =
[
Unix.getenv "HOME" ^ "/Library/Fonts";
"/Library/Fonts";
"/System/Library/Fonts";
"/Network/Library/Fonts";
]

let string_contains str substr =
let re = Str.regexp_string substr in
try
ignore (Str.search_forward re str 0);
true
with Not_found -> false

let rec font_exists_in_dirs font_name = function
| [] -> false
| dir :: dirs ->
if Sys.file_exists dir then
let files = Sys.readdir dir in
if Array.exists (fun file -> string_contains file font_name) files then
true
else font_exists_in_dirs font_name dirs
else font_exists_in_dirs font_name dirs

(* We only support mac and linux right now - if the system is unix based and
it's linux, we can use the fc-list cmd, otherwise on mac we look in common
directories manually for our font *)
let nerd_font_installed =
match uname_result with
| Some Linux ->
Shell.proc_stdout fc_list_cmd |> String.trim |> String.length > 0
| Some MacOS -> font_exists_in_dirs hack_nerd_font mac_font_dirs
| None -> false (* do we want this be false or true if we can't tell? *)

let icons =
if nerd_font_installed then
{
closed_char = "\u{ebda}";
open_char = "\u{ea64}";
merged_char = "\u{e725}";
arrow_left_char = "\u{f0a8}";
pwd_char = "\u{e5fd}";
dir_char = "\u{f4d4}";
empty_dir_char = "\u{f413}";
file_char = "\u{f4a5}";
bin_char = "\u{eae8}";
warning = "\u{26A0}";
issue_char = "\u{f41b}";
}
else
{
closed_char = "x";
open_char = "o";
merged_char = "m";
arrow_left_char = "<-";
pwd_char = "*";
dir_char = "/";
empty_dir_char = "/";
file_char = "f";
bin_char = "b";
warning = "!";
issue_char = "i";
}
18 changes: 18 additions & 0 deletions lib/pretty/icon.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(** A record representing the icon set **)
type t = {
closed_char : string;
open_char : string;
merged_char : string;
arrow_left_char : string;
pwd_char : string;
dir_char : string;
empty_dir_char : string;
file_char : string;
bin_char : string;
warning : string;
issue_char : string;
}
Comment on lines +2 to +14
Copy link
Owner

Choose a reason for hiding this comment

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

Idea to use a record is really good!


(** Populated with the current icon set based on if Nerd Font is available or or
not**)
val icons : t
3 changes: 2 additions & 1 deletion lib/pretty/pretty.ml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module Doc = Doc
module Layout = Layout
module Style = Style
module Icon = Icon

let icons = Icon.icons

let render ~width ~height doc =
doc |> Doc.render ~width ~height |> Layout.to_lines |> Extra.String.unlines
7 changes: 4 additions & 3 deletions lib/pretty/pretty.mli
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ module Doc = Doc
{!Layout.t} is the output of {!Doc.render} with all the sizes calculated. *)
module Layout = Layout

(** Icons and symbols used for identifying different parts. Symbols from Hack
Nerd Font Mono are used when it's available. Symbols list:
(** A record representign the Icons and symbols used for identifying different
parts. Symbols from Hack Nerd Font Mono are used when it's available.
Symbols list:

- https://www.nerdfonts.com/cheat-sheet *)
module Icon = Icon
val icons : Icon.t

(** Render a document into the final string

Expand Down
4 changes: 2 additions & 2 deletions lib/tui/render/render.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ type 'a t = {

let fmt_issue_state (state : Gh.Issue.state) =
match state with
| Open -> Layout.(fmt Style.issue_open Pretty.Icon.issue_char)
| Closed -> Layout.(fmt Style.issue_closed Pretty.Icon.issue_char)
| Open -> Layout.(fmt Style.issue_open Pretty.icons.issue_char)
| Closed -> Layout.(fmt Style.issue_closed Pretty.icons.issue_char)

let fmt_title (issue : Gh.Issue.t) =
let open Layout in
Expand Down
10 changes: 5 additions & 5 deletions lib/tui/widget/code.ml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let pwd root_dir_path (fs : Fs.zipper) =
let pwd_path = parents_path parents in
let root_dir_name = Filename.basename root_dir_path in
let full_path =
Pretty.Icon.pwd_char ^ " " ^ Filename.concat root_dir_name pwd_path
Pretty.icons.pwd_char ^ " " ^ Filename.concat root_dir_name pwd_path
in
Pretty.Doc.(fmt Style.directory full_path)

Expand Down Expand Up @@ -52,12 +52,12 @@ let fmt_file ~max_name_len (tree : Fs.tree) =
match tree with
| 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)
| Fs.Filec.Text -> Pretty.icons.file_char ^ " " ^ pad name
| Fs.Filec.Binary -> Pretty.icons.bin_char ^ " " ^ pad name)
| Dir { name; children = (lazy children) } -> (
match children with
| [||] -> Pretty.Icon.empty_dir_char ^ " " ^ pad name
| _ -> Pretty.Icon.dir_char ^ " " ^ pad name)
| [||] -> Pretty.icons.empty_dir_char ^ " " ^ pad name
| _ -> Pretty.icons.dir_char ^ " " ^ pad name)

let current_level_to_doc (cursor : Fs.dir_cursor) ~has_next ~is_file_chosen =
let open Pretty.Doc in
Expand Down
6 changes: 3 additions & 3 deletions lib/tui/widget/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ let fmt_error (error : Gh.Client.error) =
| No_github_token ->
[
str
(Pretty.Icon.warning
(Pretty.icons.warning
^ " GITHUB_TOKEN not found. Make sure it's configured in your \
environment.");
str "";
Expand All @@ -13,15 +13,15 @@ let fmt_error (error : Gh.Client.error) =
]
| Bad_credentials { msg; doc_url; code } ->
[
str (Format.sprintf "%s [%d] %s" Pretty.Icon.warning code msg);
str (Format.sprintf "%s [%d] %s" Pretty.icons.warning code msg);
str "";
str ("Documentation url: " ^ doc_url);
]
| Curl_error { code; msg } ->
[
str
(Format.sprintf "%s GitHub API returned error code: %d"
Pretty.Icon.warning code);
Pretty.icons.warning code);
str "";
str msg;
]
4 changes: 3 additions & 1 deletion lib/tui/widget/generic.ml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ let vlist_border ~scroll_start ~selected items =
let first_line =
Doc.(
horizontal
[ fmt_selected_line hd; str " "; str Pretty.Icon.arrow_left_char ])
[
fmt_selected_line hd; str " "; str Pretty.icons.arrow_left_char;
])
in
let other_lines = List.map fmt_selected_line tl in
first_line :: other_lines
Expand Down
6 changes: 3 additions & 3 deletions lib/tui/widget/pr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ let section (tab : Model.Pr.t) =
| None ->
let fmt_state = function
| None -> str ""
| Some Gh.Pr.Merged -> fmt Style.pr_merged Pretty.Icon.merged_char
| Some Gh.Pr.Open -> fmt Style.pr_open Pretty.Icon.open_char
| Some Gh.Pr.Closed -> fmt Style.pr_closed Pretty.Icon.closed_char
| Some Gh.Pr.Merged -> fmt Style.pr_merged Pretty.icons.merged_char
| Some Gh.Pr.Open -> fmt Style.pr_open Pretty.icons.open_char
| Some Gh.Pr.Closed -> fmt Style.pr_closed Pretty.icons.closed_char
in
let fmt_pr (pr : Gh.Pr.t) =
Pretty.Doc.(
Expand Down