Shells in OCaml
at main 168 lines 4.6 kB view raw
1module Parameter = struct 2 type t = 3 | String of string 4 | Number of string 5 | Special of string 6 | Null (** Possible shell parameters *) 7end 8 9module type State = sig 10 type t 11 (** State for the shell and operating system that is carried from one 12 evaluation step to the next. *) 13 14 val cwd : t -> Fpath.t 15 (** The current working directory *) 16 17 val set_cwd : t -> Fpath.t -> t 18 (** Update the cwd *) 19 20 val expand : t -> [ `Tilde ] -> string 21 (** Expansions *) 22 23 val lookup : t -> param:string -> string option 24 (** Parameter lookup. [None] means [unset]. *) 25 26 val update : 27 ?export:bool -> 28 ?readonly:bool -> 29 t -> 30 param:string -> 31 string -> 32 (t, string) result 33 (** Update the state with a new parameter mapping and whether or not it should 34 exported to the environment (default false), if it is readonly (default 35 false). *) 36 37 val remove : param:string -> t -> bool * t 38 (** [remove ~param t] removes [param] from [t] if it exists. [bool] is [true] 39 if a removal took place. *) 40 41 val exports : t -> (string * string) list 42 (** All of the variables that must be exported to the environment *) 43 44 val readonly : t -> (string * string) list 45 (** All of the variables that must be exported to the environment *) 46 47 val pp_readonly : t Fmt.t 48 val pp_export : t Fmt.t 49 val dump : t Fmt.t 50end 51 52type redirect = 53 | Redirect of int * Eio_unix.Fd.t * Eio_unix.Private.Fork_action.blocking 54 | Close of Eio_unix.Fd.t 55 56let pp_redirect ppf = function 57 | Redirect (i, fd, _) -> Fmt.pf ppf "%i <-> %a" i Eio_unix.Fd.pp fd 58 | Close fd -> Fmt.pf ppf "close %a" Eio_unix.Fd.pp fd 59 60type exec_mode = 61 | Switched of Eio.Switch.t 62 | Async 63 (** How to execute a process. This mainly controls what happens at the end 64 of the running a script or some commands. When a process is 65 "switched", we use the same semantics as Eio, we sigkill the process 66 and cleanup. If the process is complete Async then we do not wait. 67 This allows us to exit before some of our child processes, which is a 68 requirement for implementing the semantics of a shell! *) 69 70module type Exec = sig 71 type t 72 (** An executor for commands *) 73 74 type process 75 76 val signal : process -> int -> unit 77 val pid : process -> int 78 79 val exec : 80 ?delay_reap:unit Eio.Promise.t -> 81 ?fork_actions:Eio_unix__.Fork_action.t list -> 82 ?fds:redirect list -> 83 ?stdin:_ Eio.Flow.source -> 84 ?stdout:_ Eio.Flow.sink -> 85 ?stderr:_ Eio.Flow.sink -> 86 ?env:(string * string) list -> 87 mode:exec_mode -> 88 pgid:int -> 89 cwd:Eio.Fs.dir_ty Eio.Path.t -> 90 executable:string -> 91 t -> 92 string list -> 93 (process, int * [ `Not_found ]) result 94 (** Run a command in a child process *) 95 96 val await : process -> unit Exit.t 97end 98 99module type Job = sig 100 type t 101 (** A job for job control *) 102 103 type process 104 105 val get_reaper : t -> unit Eio.Promise.t * unit Eio.Promise.u 106 107 val make : 108 int -> 109 [ `Built_in of unit Exit.t 110 | `Error of int 111 | `Exit of unit Exit.t 112 | `Process of process 113 | `Rdr of unit Exit.t ] 114 list -> 115 t 116 117 val get_id : t -> int 118 (** Get the ID of the job. *) 119 120 val set_id : int -> t -> t 121 (** Set the ID of the job. *) 122 123 val add_process : process -> t -> t 124 val add_built_in : unit Exit.t -> t -> t 125 val add_error : int -> t -> t 126 val add_rdr : unit Exit.t -> t -> t 127 val add_exit : unit Exit.t -> t -> t 128 129 val size : t -> int 130 (** Number of processes in this job *) 131 132 val await_exit : pipefail:bool -> interactive:bool -> t -> unit Exit.t 133 (** Given a job, [await_exit] will wait for the job to finish and return the 134 exit based on the various options passed in. *) 135end 136 137module type History = sig 138 type t 139 (** A history of commands *) 140 141 val empty : t 142 (** The empty history *) 143 144 type entry 145 (** A history entry, usually a command. *) 146 147 val make_entry : string -> entry 148 (** Construct an entry given a command. *) 149 150 val add : entry -> t -> t 151 (** Add an entry to the history. *) 152 153 val save : t -> _ Eio.Path.t -> unit 154 (** [save t path] should save history [t] to [path]. *) 155 156 val load : _ Eio.Path.t -> t 157 (** [load path] should try to read a history from [path]. *) 158 159 val history : command:string -> t -> t 160 (** [history ~command t] should return some subset of [t] (perhaps all of [t]) 161 based on the current [command] to be used for history searching. *) 162 163 val commands : t -> string list 164 (** Converts your (perhaps richer) history to just a series of commands. *) 165 166 val pp : t Fmt.t 167 (** A pretty printer for the commands *) 168end