module Parameter = struct type t = | String of string | Number of string | Special of string | Null (** Possible shell parameters *) end module type State = sig type t (** State for the shell and operating system that is carried from one evaluation step to the next. *) val cwd : t -> Fpath.t (** The current working directory *) val set_cwd : t -> Fpath.t -> t (** Update the cwd *) val expand : t -> [ `Tilde ] -> string (** Expansions *) val lookup : t -> param:string -> Ast.word_cst option (** Parameter lookup. [None] means [unset]. *) val update : ?export:bool -> ?readonly:bool -> t -> param:string -> Ast.word_cst -> (t, string) result (** Update the state with a new parameter mapping and whether or not it should exported to the environment (default false). *) val remove : param:string -> t -> bool * t (** [remove ~param t] removes [param] from [t] if it exists. [bool] is [true] if a removal took place. *) val exports : t -> (string * Ast.word_cst) list (** All of the variables that must be exported to the environment *) val readonly : t -> (string * Ast.word_cst) list (** All of the variables that must be exported to the environment *) val pp_readonly : t Fmt.t val pp_export : t Fmt.t val dump : t Fmt.t end type redirect = | Redirect of int * Eio_unix.Fd.t * Eio_unix.Private.Fork_action.blocking | Close of Eio_unix.Fd.t type exec_mode = | Switched of Eio.Switch.t | Async (** How to execute a process. This mainly controls what happens at the end of the running a script or some commands. When a process is "switched", we use the same semantics as Eio, we sigkill the process and cleanup. If the process is complete Async then we do not wait. This allows us to exit before some of our child processes, which is a requirement for implementing the semantics of a shell! *) module type Exec = sig type t (** An executor for commands *) type process val signal : process -> int -> unit val pid : process -> int val exec : ?delay_reap:unit Eio.Promise.t -> ?fork_actions:Eio_unix__.Fork_action.t list -> ?fds:redirect list -> ?stdin:_ Eio.Flow.source -> ?stdout:_ Eio.Flow.sink -> ?stderr:_ Eio.Flow.sink -> ?env:(string * string) list -> mode:exec_mode -> pgid:int -> cwd:Eio.Fs.dir_ty Eio.Path.t -> executable:string -> t -> string list -> (process, int * [ `Not_found ]) result (** Run a command in a child process *) val await : process -> unit Exit.t end module type Job = sig type t (** A job for job control *) type process val get_reaper : t -> unit Eio.Promise.t * unit Eio.Promise.u val make : int -> [ `Built_in of unit Exit.t | `Error of int | `Exit of unit Exit.t | `Process of process | `Rdr of unit Exit.t ] list -> t val get_id : t -> int (** Get the ID of the job. *) val set_id : int -> t -> t (** Set the ID of the job. *) val add_process : process -> t -> t val add_built_in : unit Exit.t -> t -> t val add_error : int -> t -> t val add_rdr : unit Exit.t -> t -> t val add_exit : unit Exit.t -> t -> t val size : t -> int (** Number of processes in this job *) val await_exit : pipefail:bool -> interactive:bool -> t -> unit Exit.t (** Given a job, [await_exit] will wait for the job to finish and return the exit based on the various options passed in. *) end module type History = sig type t (** A history of commands *) val empty : t (** The empty history *) type entry (** A history entry, usually a command. *) val make_entry : string -> entry (** Construct an entry given a command. *) val add : entry -> t -> t (** Add an entry to the history. *) val save : t -> _ Eio.Path.t -> unit (** [save t path] should save history [t] to [path]. *) val load : _ Eio.Path.t -> t (** [load path] should try to read a history from [path]. *) val history : command:string -> t -> t (** [history ~command t] should return some subset of [t] (perhaps all of [t]) based on the current [command] to be used for history searching. *) val commands : t -> string list (** Converts your (perhaps richer) history to just a series of commands. *) val pp : t Fmt.t (** A pretty printer for the commands *) end