(*********************************************************************************)
(*                Chamo                                                          *)
(*                                                                               *)
(*    Copyright (C) 2003-2021 Institut National de Recherche en Informatique     *)
(*    et en Automatique. All rights reserved.                                    *)
(*                                                                               *)
(*    This program is free software; you can redistribute it and/or modify       *)
(*    it under the terms of the GNU Lesser General Public License version        *)
(*    3 as published by the Free Software Foundation.                            *)
(*                                                                               *)
(*    This program is distributed in the hope that it will be useful,            *)
(*    but WITHOUT ANY WARRANTY; without even the implied warranty of             *)
(*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *)
(*    GNU General Public License for more details.                               *)
(*                                                                               *)
(*    You should have received a copy of the GNU General Public License          *)
(*    along with this program; if not, write to the Free Software                *)
(*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                   *)
(*    02111-1307  USA                                                            *)
(*                                                                               *)
(*    Contact: Maxence.Guesdon@inria.fr                                          *)
(*                                                                               *)
(*********************************************************************************)

(** Misc functions. *)

val map_opt : ('a -> 'b) -> 'a option -> 'b option

(** Same as [int_of_string] but support strings beginning with '+'. *)
val my_int_of_string : string -> int

val add_shortcut : Stk.Widget.widget ->
  (string * ((unit -> bool) option * (unit -> unit))) list ->
  Stk.Key.keystate * string -> unit

(** [remove_char s c] returns a copy of the given string [s] without character [c]. *)
val remove_char : string -> char -> string

(** [line_of_char file char] gets the line number (0-based)
   in a file from a character number. *)
val line_of_char : string -> int -> int

(** [char_of_line file line] returns the offset of the first character
     of the given [line] of the give [file]. Line number are zero-based,
     as the returned character number. *)
val char_of_line : string -> int -> int

(** [escape_menu_label string] returns a the string where all '_' have
   been escaped to be displayed correctly in Lablgtk menus.*)
val escape_menu_label : string -> string

(** [mod_date_of_file file] returns the Unix last modification date of the given file,
   or 0.0 if the date could not be obtained. *)
val mod_date_of_file : string -> float

val string_of_bool : bool -> string
val bool_of_string : string -> bool

(** [date_of_file file] returns the unix date of the last modification
     of the file, is the file can be accessed. *)
val date_of_file : string -> float option

(** [catch_print_exception f v] applies [f] to [v] and
     catch and print any raised exception to stderr. *)
val catch_print_exceptions : ('a -> unit) -> 'a -> unit

(** Encode the given string to UTF-8, using the default charset
  {!Core_rc.encoding} or the given [coding].*)
val to_utf8 : ?coding:string -> string -> string

val pp_to_utf8 : Format.formatter -> string -> unit

(** Decode the given string from UTF-8, using the default charset
  {!Core_rc.encoding} or the given [coding].*)
val of_utf8 : ?coding:string -> string -> string

(** Convert filename from locale encoding to UTF-8. *)
val filename_to_utf8 : string -> string

(** Convert filename from UTF-8 to locale encoding. *)
val filename_from_utf8 : string -> string

(** Return whether the two given filename identifies the same file
     (same device and inode).
     @raise Failure if information about a file cannot be accessed. *)
val same_files : string -> string -> bool

(** Same as {!same_files} but returns [false] instead of raising an exception
     if information about one file could not be retrieved. *)
val safe_same_files : string -> string -> bool

(** This function calls the "set_active_state_message" command with
     the given utf-8 string. *)
val set_active_state_message : string -> unit

(** This function calls the "set_active_action_message" command with
     the given utf-8 string. *)
val set_active_action_message : string -> unit

(** This function displays the given message with {!Log.app}
    and calls the "set_active_action_message" command with the given utf-8 string. *)
val display_message : string -> unit

(** This function displays the given message with {!Log.warn}
    and calls the "set_active_action_message" command with the given utf-8 string. *)
val warning_message : string -> unit

(** This function displays the given message with {!Log.err}
    and calls the "set_active_action_message" command with the given utf-8 string. *)
val error_message : string -> unit

(** [fail_if_unix_error f x] applies [f] to [x] and catches only exception
     [Unix.Unix_error]. If such an exception is raised by [f], create
     a message string and raise [Failure message]. *)
val fail_if_unix_error : ('a -> 'b) -> 'a -> 'b

(** [is_prefix s1 s2] returns whether [s2] is a prefix of [s1]. *)
val is_prefix : string -> string -> bool

(** [dir_entries dir] return the list of entries in directory [dir].
     @param prefix can be used to filter only entries with the given
     prefix. *)
val dir_entries : ?prefix:string -> string -> string list

(** [max_common strings] return the longest string common to all
     the given strings or None if [strings] is the empty list. *)
val max_common : string list -> string option


(** [chop_n_char n s] returns the given string where characters after position n
   are replaced by ["..."].
*)
val chop_n_char : int -> string -> string

(** [list_remove_doubles ?pred l] remove doubles in the given list [l], according
   to the optional equality function [pred]. Default equality function is [(=)].
*)
val list_remove_doubles : ?pred:('k -> 'k -> bool) -> 'k list -> 'k list

(** [subdirs path] returns the list of subdirectories of the given directory name.
   Returned names are relative to the given path.
  Raises [Unix_error] if an error occurs.*)
val subdirs : string -> string list

(** [replace_in_string ~pat ~subs ~s] replaces all occurences of
   pattern [pat] by [subs] in string [s].*)
val replace_in_string : pat:string -> subs:string -> s:string -> string

(** [string_of_file filename] returns the content of [filename]
   in the form of one string.
     Raises [Sys_error] if the file could not be open.*)
val string_of_file : string -> string

(** [file_of_string ~file str] creates a file named
   [filename] whose content is [str].
  Raises [Sys_error] if the file could not be open.*)
val file_of_string : file:string -> string -> unit

(** Separate the given string according to the given list of characters.
[keep_empty] is [false] by default. If set to [true],
   the empty strings between separators are kept.*)
val split_string : ?keep_empty:bool -> string -> char list -> string list

(** Remove the given file, and ignore the error if
   the file does not exist (catch [Sys_error]).*)
val safe_remove_file : string -> unit

(** [make_list n ele] builds a list of [n] elements [ele].*)
val make_list : int -> 'i -> 'i list

(** [no_blanks s] returns the given string without any blank
   characters, i.e. '\n' '\r' ' ' '\t'.*)
val no_blanks : string -> string

(** [try_finalize f x g y] applies [f] to [x] and return
   the result or raises an exception, but in all cases
   [g] is applied to [y] before returning or raising the exception.*)
val try_finalize : ('l -> 'm) -> 'l -> ('n -> unit) -> 'n -> 'm

(** {2 Input functions}

     The strings given in parameter to the following input functions
     must be utf-8 encoded; the strings passed to the given callback function
     is decoded from utf-8 before. *)

(** The minibuffer history used in function {!select_file}. *)
val select_file_history : Minibuffer.minibuffer_history

(** [select_file mb ~title default_text f] makes the user select a file
     in the minibuffer and calls [f] with the selected file when
     user validates. *)
val select_file :
  Minibuffer.minibuffer ->
  title:string -> string -> (string -> unit Lwt.t) -> unit Lwt.t

(** [select_string mb ~title ~choice default_text f] makes the user
       choose a string among the given choices and then calls [f]
       with the choices when the user validates.
       @param a minibuffer history can be given to use.*)
val select_string :
  ?history:Minibuffer.minibuffer_history ->
  Minibuffer.minibuffer ->
  title:string -> choices:string list -> string -> (string -> unit Lwt.t) ->
      unit Lwt.t

(** [input_string mb ~title default_text f] makes the user enter a
       text and calls [f] on that text when the user validates. *)
val input_string :
  ?history:Minibuffer.minibuffer_history ->
  Minibuffer.minibuffer ->
  title:string -> string -> (string -> unit Lwt.t) -> unit Lwt.t

(** FIXME: explain this *)
val input_command_arg :
  Minibuffer.minibuffer ->
  ?history:Minibuffer.minibuffer_history ->
  title:string -> (string -> unit Lwt.t) -> string -> string array -> unit Lwt.t

(** [confirm mb question f] makes the user answer to the given question
       and calls [f] if the response is "yes" *)
val confirm : Minibuffer.minibuffer -> string -> (unit -> unit Lwt.t) ->
  unit Lwt.t

