Shells in OCaml
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