let left, right = find_left 0, find_right (s_len - 1) in
String.sub s left (right - left + 1)
+(** {2 Char processing} *)
+
+let is_alpha c =
+ let code = Char.code c in
+ (code >= 65 && code <= 90) || (code >= 97 && code <= 122)
+
+let is_digit c =
+ let code = Char.code c in
+ code >= 48 && code <= 57
+
+let is_blank c =
+ let code = Char.code c in
+ code = 9 || code = 10 || code = 13 || code = 32
+
+let is_alphanum c = is_alpha c || is_digit c
+
(** {2 List processing} *)
let rec list_uniq = function
let oc = open_out filename in
output_string oc text;
close_out oc
+
+let blank_split s =
+ let len = String.length s in
+ let buf = Buffer.create 0 in
+ let rec aux acc i =
+ if i >= len
+ then begin
+ if Buffer.length buf > 0
+ then List.rev (Buffer.contents buf :: acc)
+ else List.rev acc
+ end else begin
+ if is_blank s.[i] then
+ if Buffer.length buf > 0 then begin
+ let s = Buffer.contents buf in
+ Buffer.clear buf;
+ aux (s :: acc) (i + 1)
+ end else
+ aux acc (i + 1)
+ else begin
+ Buffer.add_char buf s.[i];
+ aux acc (i + 1)
+ end
+ end
+ in
+ aux [] 0
+
+ (* Rules: * "~name" -> home dir of "name"
+ * "~" -> value of $HOME if defined, home dir of the current user otherwise *)
+let tilde_expand s =
+ let get_home login = (Unix.getpwnam login).Unix.pw_dir in
+ let expand_one s =
+ let len = String.length s in
+ if len > 0 && s.[0] = '~' then begin
+ let login_len = ref 1 in
+ while !login_len < len && is_alphanum (s.[!login_len]) do
+ incr login_len
+ done;
+ let login = String.sub s 1 (!login_len - 1) in
+ try
+ let home =
+ if login = "" then
+ try Sys.getenv "HOME" with Not_found -> get_home (Unix.getlogin ())
+ else
+ get_home login
+ in
+ home ^ String.sub s !login_len (len - !login_len)
+ with Not_found | Invalid_argument _ -> s
+ end else
+ s
+ in
+ String.concat " " (List.map expand_one (blank_split s))
let find ?(test = fun _ -> true) path =
let rec aux acc todo =
val is_dir: string -> bool (** @return true if file is a directory *)
val is_regular: string -> bool (** @return true if file is a regular file *)
val mkdir: string -> unit (** create dir and parents. @raise Failure *)
+val tilde_expand: string -> string (** bash-like (head) tilde expansion *)
(** find all _files_ matching test under a filesystem root *)
val find: ?test:(string -> bool) -> string -> string list
val finally: (unit -> unit) -> ('a -> 'b) -> 'a -> 'b
+(** {2 Char processing} *)
+
+val is_alpha: char -> bool
+val is_digit: char -> bool
+val is_alphanum: char -> bool (** is_alpha || is_digit *)
+
(** {2 String processing} *)
val split: ?sep:char -> string -> string list (** @param sep defaults to ' ' *)