Shells in OCaml
at wip 172 lines 4.8 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 | Parent_redirect of 54 int * Eio_unix.Fd.t * Eio_unix.Private.Fork_action.blocking 55 | Child_redirect of 56 int * Eio_unix.Fd.t * Eio_unix.Private.Fork_action.blocking 57 | Close of Eio_unix.Fd.t 58 59let pp_redirect ppf = function 60 | Parent_redirect (i, fd, _) -> Fmt.pf ppf "%i <=p=> %a" i Eio_unix.Fd.pp fd 61 | Child_redirect (i, fd, _) -> Fmt.pf ppf "%i <=c=> %a" i Eio_unix.Fd.pp fd 62 | Close fd -> Fmt.pf ppf "close %a" Eio_unix.Fd.pp fd 63 64type exec_mode = 65 | Switched of Eio.Switch.t 66 | Async 67 (** How to execute a process. This mainly controls what happens at the end 68 of the running a script or some commands. When a process is 69 "switched", we use the same semantics as Eio, we sigkill the process 70 and cleanup. If the process is complete Async then we do not wait. 71 This allows us to exit before some of our child processes, which is a 72 requirement for implementing the semantics of a shell! *) 73 74module type Exec = sig 75 type t 76 (** An executor for commands *) 77 78 type process 79 80 val signal : process -> int -> unit 81 val pid : process -> int 82 83 val exec : 84 ?delay_reap:unit Eio.Promise.t -> 85 ?fork_actions:Eio_unix__.Fork_action.t list -> 86 ?fds:redirect list -> 87 ?stdin:_ Eio.Flow.source -> 88 ?stdout:_ Eio.Flow.sink -> 89 ?stderr:_ Eio.Flow.sink -> 90 ?env:(string * string) list -> 91 mode:exec_mode -> 92 pgid:int -> 93 cwd:Eio.Fs.dir_ty Eio.Path.t -> 94 executable:string -> 95 t -> 96 string list -> 97 (process, int * [ `Not_found ]) result 98 (** Run a command in a child process *) 99 100 val await : process -> unit Exit.t 101end 102 103module type Job = sig 104 type t 105 (** A job for job control *) 106 107 type process 108 109 val get_reaper : t -> unit Eio.Promise.t * unit Eio.Promise.u 110 111 val make : 112 int -> 113 [ `Built_in of unit Exit.t 114 | `Error of int 115 | `Exit of unit Exit.t 116 | `Process of process 117 | `Rdr of unit Exit.t ] 118 list -> 119 t 120 121 val get_id : t -> int 122 (** Get the ID of the job. *) 123 124 val set_id : int -> t -> t 125 (** Set the ID of the job. *) 126 127 val add_process : process -> t -> t 128 val add_built_in : unit Exit.t -> t -> t 129 val add_error : int -> t -> t 130 val add_rdr : unit Exit.t -> t -> t 131 val add_exit : unit Exit.t -> t -> t 132 133 val size : t -> int 134 (** Number of processes in this job *) 135 136 val await_exit : pipefail:bool -> interactive:bool -> t -> unit Exit.t 137 (** Given a job, [await_exit] will wait for the job to finish and return the 138 exit based on the various options passed in. *) 139end 140 141module type History = sig 142 type t 143 (** A history of commands *) 144 145 val empty : t 146 (** The empty history *) 147 148 type entry 149 (** A history entry, usually a command. *) 150 151 val make_entry : string -> entry 152 (** Construct an entry given a command. *) 153 154 val add : entry -> t -> t 155 (** Add an entry to the history. *) 156 157 val save : t -> _ Eio.Path.t -> unit 158 (** [save t path] should save history [t] to [path]. *) 159 160 val load : _ Eio.Path.t -> t 161 (** [load path] should try to read a history from [path]. *) 162 163 val history : command:string -> t -> t 164 (** [history ~command t] should return some subset of [t] (perhaps all of [t]) 165 based on the current [command] to be used for history searching. *) 166 167 val commands : t -> string list 168 (** Converts your (perhaps richer) history to just a series of commands. *) 169 170 val pp : t Fmt.t 171 (** A pretty printer for the commands *) 172end