package shell
Yet another implementation of fork&exec and related functionality
Install
Dune Dependency
Authors
Maintainers
Sources
shell-v0.15.0.tar.gz
sha256=7b992e214e6ecdbffb1d3726ac649558f2799957da12db145e1bbd08688db2d0
doc/src/shell.filename_extended/filename_extended.ml.html
Source file filename_extended.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
open Core open Filename open Poly module Unix = Core_unix (** Path *) let explode path = let rec aux = function | "" | "." -> [] | "/" -> ["/"] | path -> let dirname, basename = split path in basename :: aux dirname in List.rev (aux path) let implode = function | [] -> "." | "/"::rest -> "/" ^ (String.concat ~sep:"/" rest) | l -> String.concat ~sep:"/" l (* Takes out all "../" and "./" in a path, except that if it's a relative path it may start with some "../../" stuff at the front. *) let normalize_path p = List.fold p ~init:[] ~f:(fun acc path_element -> match path_element, acc with (* parent of root is root, and root can only appear as first part of path *) | "..", ["/"] -> ["/"] (* just pop the stack, e.g. /foo/bar/../ becomes just /foo/ *) | "..", h::rest when h <> ".." -> rest | ".", v -> v | _ -> path_element :: acc (* accumulate regular dirs or chains of ... at the beginning of a relative path*)) |> List.rev let make_relative ?to_ f = if to_ = None && is_relative f then f else let to_ = match to_ with | Some dir -> if is_relative f <> is_relative dir then failwithf "make_relative ~to_:%s %s: cannot work on an absolute path and a \ relative one" dir f (); dir | None -> Sys_unix.getcwd () in let rec aux = function | (h :: t), (h' :: t') when String.equal h h' -> aux (t,t') | ".."::_, _ -> failwithf "make_relative ~to_:%s %s: negative lookahead (ie goes \"above\" the current directory)" to_ f () | p, p' -> (List.map ~f:(fun _ -> parent_dir_name) p) @ p' in let to_ = normalize_path (explode to_) and f = normalize_path (explode f) in implode (aux (to_,f)) let%test_module "make_relative" = (module struct let make_relative ~to_ f = try Some (make_relative ~to_ f) with Failure _ -> None let%test _ = make_relative ~to_:".." "a" = None let%test _ = make_relative ~to_:".." "../a"= Some "a" let%test _ = make_relative ~to_:"c" "a/b" = Some "../a/b" let%test _ = make_relative ~to_:"/" "a/b" = None end) let normalize p = implode (normalize_path (explode p)) let%test_module "normalize" = (module struct let%test "id" = normalize "/mnt/local" ="/mnt/local" let%test "dot_dotdot" = normalize "/mnt/./../local" = "/local" let%test _ = normalize "/mnt/local/../global/foo" = "/mnt/global/foo" let%test "beyond_root" = normalize "/mnt/local/../../.." = "/" let%test "negative_lookahead" = normalize "../a/../../b" = "../../b" end) let (//) src p = if is_absolute p then p else concat src p let make_absolute p = Sys_unix.getcwd () // p let user_home username = match Unix.Passwd.getbyname username with | Some user -> let pw_dir = user.Unix.Passwd.dir in if String.length pw_dir = 0 then failwithf "user's \"%s\"'s home is an empty string" username () else pw_dir | None -> failwithf "user \"%s\" not found" username () let expand_user s = let expand_home = function | "~" -> user_home (Shell_internal.whoami ()) | s -> user_home (String.chop_prefix_exn s ~prefix:"~") in if (String.is_prefix ~prefix:"~" s) then match String.lsplit2 ~on:'/' s with | Some (base,rest) -> expand_home base ^ "/" ^ rest | None -> expand_home s else s let expand ?(from=".") p = normalize (Sys_unix.getcwd () // from // expand_user p) let rec is_parent_path p1 p2 = match p1, p2 with | ["/"], _ -> true | ((h1 :: p1) as l), (h2 :: p2) -> (h1 = h2 && is_parent_path p1 p2) || (h2 <> ".." && h2 <> "/" && List.for_all l ~f:((=) parent_dir_name)) | l, [] -> List.for_all l ~f:((=) parent_dir_name) | [], (h :: _) -> h <> ".." && h <> "/" let is_parent f1 f2 = is_parent_path (normalize_path (explode f1)) (normalize_path (explode f2)) (** Filename comparison *) (* Extension comparison: We have a list of lists of extension that should appear consecutive to one another. Our comparison function works by mapping extensions to (extension*int) couples, for instance "c" is mapped to "h,1" meaning it should come right after h. *) let create_extension_map l = List.fold l ~f:(fun init l -> match l with | [] -> init | idx::_ -> List.foldi l ~f:(fun pos map v -> if Core.Map.mem map v then failwithf "Extension %s is defined twice" v (); Core.Map.set map ~key:v ~data:(idx,pos) ) ~init ) ~init:Map.empty let extension_cmp map h1 h2 = let lookup e = Option.value (Map.find map e) ~default:(e,0) in Tuple2.compare (lookup h1) (lookup h2) ~cmp1:(String_extended.collate) ~cmp2:(Int.compare) let basename_compare map f1 f2 = let ext_split s = Option.value (String.lsplit2 ~on:'.' s) ~default:(s,"") in Tuple2.compare (ext_split f1) (ext_split f2) ~cmp1:(String_extended.collate) ~cmp2:(extension_cmp map) let filename_compare map v1 v2 = let v1 = explode v1 and v2 = explode v2 in List.compare (basename_compare map) v1 v2 let parent p = normalize (concat p parent_dir_name) let%test_module "parent" = (module struct let%test _ = parent "/mnt/local" = "/mnt" let%test _ = parent "/mnt/local/../global/foo" = "/mnt/global" let%test _ = parent "/mnt/local/../../global" = "/" end) let extension_map = create_extension_map [["h";"c"];["mli";"ml"]] let compare = filename_compare extension_map let with_open_temp_file ?in_dir ?(write=ignore) ~f prefix suffix = protectx (Filename_unix.open_temp_file ?in_dir prefix suffix) ~f:(fun (fname,oc) -> protectx oc ~f:write ~finally:Out_channel.close; f fname) ~finally:(fun (fname,_) -> Unix.unlink fname) let with_temp_dir ?in_dir prefix suffix ~f = protectx (Filename_unix.temp_dir ?in_dir prefix suffix) ~f ~finally:(fun dirname -> ignore (Sys_unix.command (sprintf "rm -rf '%s'" dirname)))
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>