refactor name key lookups for which key is optional

find_string_opt, find_int_opt and find_string_list_opt returned ('a, load_error) result, not an option. By OCaml convention the _opt suffix means the function returns an option — List.find_opt, Sys.getenv_opt — so the names described the wrong thing: what is optional is the key, not the result. Rename to required_string/required_int for keys that must be present and optional_string/optional_int/optional_string_list for keys that fall back to a default, which states the distinction the two groups actually make.

Commit
8e3925b0490ef268cc352473abc660c64290ebb2
Author
Claude Sonnet 4 <claude@anthropic.invalid>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
lib/config.ml
index bdee7e3b..5ed48202 100644..100644
@@ -89,31 +89,42 @@
89 89 Out_channel.with_open_text file (fun channel ->
90 90 Printer.string_of_table table |> Printf.fprintf channel "%s\n")
91 91
92 Removed: let find_string table key =
92 Added: (* Key lookups come in two flavours. [required_*] fails when the key is absent,
93 Added: for settings with no sensible default; [optional_*] falls back to [~default].
94 Added: Both fail when the key is present but holds the wrong type, so a typo is
95 Added: never silently ignored.
96 Added:
97 Added: These are deliberately not named [*_opt]: by OCaml convention that suffix
98 Added: means the function returns an option, whereas here the optionality is the
99 Added: key's, not the result's. *)
100 Added:
101 Added: let required_string table key =
93 102 match Types.Table.find_opt (Min.key key) table with
94 103 | Some (Types.TString value) -> Ok value
95 104 | Some _ -> Error (Invalid_value ("expected string for key: " ^ key))
96 105 | None -> Error (Invalid_value ("missing key: " ^ key))
97 106
98 Removed: let find_int table key =
107 Added: let required_int table key =
99 108 match Types.Table.find_opt (Min.key key) table with
100 109 | Some (Types.TInt value) -> Ok value
101 110 | Some _ -> Error (Invalid_value ("expected int for key: " ^ key))
102 111 | None -> Error (Invalid_value ("missing key: " ^ key))
103 112
104 Removed: let find_string_opt table key ~default =
113 Added: let optional_string table key ~default =
105 114 match Types.Table.find_opt (Min.key key) table with
106 115 | Some (Types.TString value) -> Ok value
107 116 | Some _ -> Error (Invalid_value ("expected string for key: " ^ key))
108 117 | None -> Ok default
109 118
110 Removed: let find_int_opt table key ~default =
119 Added: let optional_int table key ~default =
111 120 match Types.Table.find_opt (Min.key key) table with
112 121 | Some (Types.TInt value) -> Ok value
113 122 | Some _ -> Error (Invalid_value ("expected int for key: " ^ key))
114 123 | None -> Ok default
115 124
116 Removed: let find_string_list_opt table key =
125 Added: (* An absent list and an empty list mean the same thing here, so this needs no
126 Added: [~default]. *)
127 Added: let optional_string_list table key =
117 128 match Types.Table.find_opt (Min.key key) table with
118 129 | Some (Types.TArray (Types.NodeString values)) -> Ok values
119 130 | Some (Types.TArray Types.NodeEmpty) -> Ok []
@@ -123,25 +134,25 @@
123 134
124 135 let of_table table =
125 136 let ( let* ) = Result.bind in
126 Removed: let* git_project_root = find_string table "git_project_root" in
137 Added: let* git_project_root = required_string table "git_project_root" in
127 138 let* user_name =
128 Removed: find_string_opt table "user_name" ~default:default.user_name
139 Added: optional_string table "user_name" ~default:default.user_name
129 140 in
130 Removed: let* default_branch = find_string table "default_branch" in
131 Removed: let* commits_max_displayed = find_int table "commits_max_displayed" in
141 Added: let* default_branch = required_string table "default_branch" in
142 Added: let* commits_max_displayed = required_int table "commits_max_displayed" in
132 143 let* title =
133 144 match Types.Table.find_opt (Min.key "ogit_root_title") table with
134 Removed: | Some _ -> find_string_opt table "ogit_root_title" ~default:default.title
135 Removed: | None -> find_string_opt table "title" ~default:default.title
145 Added: | Some _ -> optional_string table "ogit_root_title" ~default:default.title
146 Added: | None -> optional_string table "title" ~default:default.title
136 147 in
137 Removed: let* nav_logo = find_string_opt table "nav_logo" ~default:default.nav_logo in
138 Removed: let* host = find_string_opt table "host" ~default:default.host in
139 Removed: let* port = find_int_opt table "port" ~default:default.port in
148 Added: let* nav_logo = optional_string table "nav_logo" ~default:default.nav_logo in
149 Added: let* host = optional_string table "host" ~default:default.host in
150 Added: let* port = optional_int table "port" ~default:default.port in
140 151 let* favorite_repositories =
141 Removed: find_string_list_opt table "favorite_repositories"
152 Added: optional_string_list table "favorite_repositories"
142 153 in
143 154 let* archived_repositories =
144 Removed: find_string_list_opt table "archived_repositories"
155 Added: optional_string_list table "archived_repositories"
145 156 in
146 157 if commits_max_displayed <= 0 then
147 158 Error (Invalid_value "commits_max_displayed must be positive")