14
14
15
15
open Local_store
16
16
17
- module STbl = Misc.Stdlib.String. Tbl
17
+ module Dir : sig
18
+ type t
18
19
19
- (* Mapping from basenames to full filenames *)
20
- type registry = string STbl .t
20
+ val path : t -> string
21
+ val files : t -> string list
22
+ val hidden : t -> bool
21
23
22
- let visible_files : registry ref = s_table STbl. create 42
23
- let visible_files_uncap : registry ref = s_table STbl. create 42
24
+ val create : hidden :bool -> string -> t
24
25
25
- let hidden_files : registry ref = s_table STbl. create 42
26
- let hidden_files_uncap : registry ref = s_table STbl. create 42
27
-
28
- module Dir = struct
26
+ val find : t -> string -> string option
27
+ val find_uncap : t -> string -> string option
28
+ end = struct
29
29
type t = {
30
30
path : string ;
31
31
files : string list ;
@@ -65,6 +65,81 @@ module Dir = struct
65
65
{ path; files = Array. to_list (readdir_compat path); hidden }
66
66
end
67
67
68
+ type visibility = Visible | Hidden
69
+
70
+ (* * Stores cached paths to files *)
71
+ module Path_cache : sig
72
+ (* Clear cache *)
73
+ val reset : unit -> unit
74
+
75
+ (* Same as [add] below, but will replace existing entries.
76
+
77
+ [prepend_add] is faster than [add] and intended for use in [init] and [remove_dir]:
78
+ since we are starting from an empty cache, we can avoid checking whether a unit name
79
+ already exists in the cache simply by adding entries in reverse order. *)
80
+ val prepend_add : Dir .t -> unit
81
+
82
+ (* Add path to cache. If path with same basename is already in cache, skip adding. *)
83
+ val add : Dir .t -> unit
84
+
85
+ (* Search for a basename in cache. Ignore case if [uncap] is true *)
86
+ val find : uncap :bool -> string -> string * visibility
87
+ end = struct
88
+ module STbl = Misc.Stdlib.String. Tbl
89
+
90
+ (* Mapping from basenames to full filenames *)
91
+ type registry = string STbl .t
92
+
93
+ let visible_files : registry ref = s_table STbl. create 42
94
+ let visible_files_uncap : registry ref = s_table STbl. create 42
95
+
96
+ let hidden_files : registry ref = s_table STbl. create 42
97
+ let hidden_files_uncap : registry ref = s_table STbl. create 42
98
+
99
+ let reset () =
100
+ STbl. clear ! hidden_files;
101
+ STbl. clear ! hidden_files_uncap;
102
+ STbl. clear ! visible_files;
103
+ STbl. clear ! visible_files_uncap
104
+
105
+ let prepend_add dir =
106
+ List. iter (fun base ->
107
+ let fn = Filename. concat (Dir. path dir) base in
108
+ if Dir. hidden dir then begin
109
+ STbl. replace ! hidden_files base fn;
110
+ STbl. replace ! hidden_files_uncap (String. uncapitalize_ascii base) fn
111
+ end else begin
112
+ STbl. replace ! visible_files base fn;
113
+ STbl. replace ! visible_files_uncap (String. uncapitalize_ascii base) fn
114
+ end
115
+ ) (Dir. files dir)
116
+
117
+ let add dir =
118
+ let update base fn visible_files hidden_files =
119
+ if (Dir. hidden dir) && not (STbl. mem ! hidden_files base) then
120
+ STbl. replace ! hidden_files base fn
121
+ else if not (STbl. mem ! visible_files base) then
122
+ STbl. replace ! visible_files base fn
123
+ in
124
+ List. iter
125
+ (fun base ->
126
+ let fn = Filename. concat (Dir. path dir) base in
127
+ update base fn visible_files hidden_files;
128
+ let ubase = String. uncapitalize_ascii base in
129
+ update ubase fn visible_files_uncap hidden_files_uncap)
130
+ (Dir. files dir)
131
+
132
+ let find fn visible_files hidden_files =
133
+ try (STbl. find ! visible_files fn, Visible ) with
134
+ | Not_found -> (STbl. find ! hidden_files fn, Hidden )
135
+
136
+ let find ~uncap fn =
137
+ if uncap then
138
+ find (String. uncapitalize_ascii fn) visible_files_uncap hidden_files_uncap
139
+ else
140
+ find fn visible_files hidden_files
141
+ end
142
+
68
143
type auto_include_callback =
69
144
(Dir .t -> string -> string option ) -> string -> string
70
145
@@ -75,10 +150,7 @@ let auto_include_callback = ref no_auto_include
75
150
76
151
let reset () =
77
152
assert (not Config. merlin || Local_store. is_bound () );
78
- STbl. clear ! hidden_files;
79
- STbl. clear ! hidden_files_uncap;
80
- STbl. clear ! visible_files;
81
- STbl. clear ! visible_files_uncap;
153
+ Path_cache. reset () ;
82
154
hidden_dirs := [] ;
83
155
visible_dirs := [] ;
84
156
auto_include_callback := no_auto_include
@@ -99,28 +171,12 @@ let get_paths () =
99
171
let get_visible_path_list () = List. rev_map Dir. path ! visible_dirs
100
172
let get_hidden_path_list () = List. rev_map Dir. path ! hidden_dirs
101
173
102
- (* Optimized version of [add] below, for use in [init] and [remove_dir]: since
103
- we are starting from an empty cache, we can avoid checking whether a unit
104
- name already exists in the cache simply by adding entries in reverse
105
- order. *)
106
- let prepend_add dir =
107
- List. iter (fun base ->
108
- let fn = Filename. concat dir.Dir. path base in
109
- if dir.Dir. hidden then begin
110
- STbl. replace ! hidden_files base fn;
111
- STbl. replace ! hidden_files_uncap (String. uncapitalize_ascii base) fn
112
- end else begin
113
- STbl. replace ! visible_files base fn;
114
- STbl. replace ! visible_files_uncap (String. uncapitalize_ascii base) fn
115
- end
116
- ) dir.Dir. files
117
-
118
174
let init ~auto_include ~visible ~hidden =
119
175
reset () ;
120
176
visible_dirs := List. rev_map (Dir. create ~hidden: false ) visible;
121
177
hidden_dirs := List. rev_map (Dir. create ~hidden: true ) hidden;
122
- List. iter prepend_add ! hidden_dirs;
123
- List. iter prepend_add ! visible_dirs;
178
+ List. iter Path_cache. prepend_add ! hidden_dirs;
179
+ List. iter Path_cache. prepend_add ! visible_dirs;
124
180
auto_include_callback := auto_include
125
181
126
182
let remove_dir dir =
@@ -132,29 +188,17 @@ let remove_dir dir =
132
188
reset () ;
133
189
visible_dirs := visible;
134
190
hidden_dirs := hidden;
135
- List. iter prepend_add hidden;
136
- List. iter prepend_add visible
191
+ List. iter Path_cache. prepend_add hidden;
192
+ List. iter Path_cache. prepend_add visible
137
193
end
138
194
139
195
(* General purpose version of function to add a new entry to load path: We only
140
196
add a basename to the cache if it is not already present, in order to enforce
141
197
left-to-right precedence. *)
142
198
let add (dir : Dir.t ) =
143
199
assert (not Config. merlin || Local_store. is_bound () );
144
- let update base fn visible_files hidden_files =
145
- if dir.hidden && not (STbl. mem ! hidden_files base) then
146
- STbl. replace ! hidden_files base fn
147
- else if not (STbl. mem ! visible_files base) then
148
- STbl. replace ! visible_files base fn
149
- in
150
- List. iter
151
- (fun base ->
152
- let fn = Filename. concat dir.Dir. path base in
153
- update base fn visible_files hidden_files;
154
- let ubase = String. uncapitalize_ascii base in
155
- update ubase fn visible_files_uncap hidden_files_uncap)
156
- dir.files;
157
- if dir.hidden then
200
+ Path_cache. add dir;
201
+ if (Dir. hidden dir) then
158
202
hidden_dirs := dir :: ! hidden_dirs
159
203
else
160
204
visible_dirs := dir :: ! visible_dirs
@@ -167,8 +211,8 @@ let add_dir ~hidden dir = add (Dir.create ~hidden dir)
167
211
unconditionally added. *)
168
212
let prepend_dir (dir : Dir.t ) =
169
213
assert (not Config. merlin || Local_store. is_bound () );
170
- prepend_add dir;
171
- if dir .hidden then
214
+ Path_cache. prepend_add dir;
215
+ if ( Dir . hidden dir) then
172
216
hidden_dirs := ! hidden_dirs @ [dir]
173
217
else
174
218
visible_dirs := ! visible_dirs @ [dir]
@@ -197,17 +241,11 @@ let auto_include_otherlibs =
197
241
List. map (fun lib -> (lib, read_lib lib)) [" dynlink" ; " str" ; " unix" ] in
198
242
auto_include_libs otherlibs
199
243
200
- type visibility = Visible | Hidden
201
-
202
- let find_file_in_cache fn visible_files hidden_files =
203
- try (STbl. find ! visible_files fn, Visible ) with
204
- | Not_found -> (STbl. find ! hidden_files fn, Hidden )
205
-
206
244
let find fn =
207
245
assert (not Config. merlin || Local_store. is_bound () );
208
246
try
209
247
if is_basename fn && not ! Sys. interactive then
210
- fst (find_file_in_cache fn visible_files hidden_files )
248
+ fst (Path_cache. find ~uncap: false fn )
211
249
else
212
250
Misc. find_in_path (get_path_list () ) fn
213
251
with Not_found ->
@@ -217,8 +255,7 @@ let find_uncap_with_visibility fn =
217
255
assert (not Config. merlin || Local_store. is_bound () );
218
256
try
219
257
if is_basename fn && not ! Sys. interactive then
220
- find_file_in_cache (String. uncapitalize_ascii fn)
221
- visible_files_uncap hidden_files_uncap
258
+ Path_cache. find ~uncap: true fn
222
259
else
223
260
try
224
261
(Misc. find_in_path_uncap (get_visible_path_list () ) fn, Visible )
0 commit comments