pub struct StepCtx<'a, P>where
P: ProcessManager,{ /* private fields */ }Expand description
Per-step execution context handed to every command handler.
Host-registered functions receive this context: read script state through
the public accessors (get_var, get_env, cwd) and return a Value.
The fields stay crate-private so execution invariants hold for hosts.
Output contract (load-bearing for LET-capture, pipes, and stream assertions):
handlers must emit stdout/stderr ONLY through out/err — via
write_stdout or StreamHandle::to_stdout/to_stderr — and never write
to host stdout directly. The step runner swaps these handles per context:
LET $x: STRING = <command> installs a spillable capture sink, WITH_IO
installs named-pipe endpoints, and the root installs the assertion tee. A handler that bypasses its context handles silently breaks all three.
Implementations§
Source§impl<'a, P> StepCtx<'a, P>where
P: ProcessManager,
impl<'a, P> StepCtx<'a, P>where
P: ProcessManager,
Sourcepub fn get_var(&self, key: &str) -> Option<Value>
pub fn get_var(&self, key: &str) -> Option<Value>
Look up a script variable by name (innermost scope first).
Sourcepub fn get_env(&self, key: &str) -> Option<String>
pub fn get_env(&self, key: &str) -> Option<String>
Look up an environment variable visible to the script.
Sourcepub fn env_snapshot(&self) -> HashMap<String, String>
pub fn env_snapshot(&self) -> HashMap<String, String>
Snapshot of the script-visible environment: ENV assignments
layered over inherited entries, as currently scoped. Hosts staging
child processes layer this over the host environment (the same
contract RUN honors through CommandContext), so block-scoped
ENV reaches the child and reverts at scope exit with no extra
machinery.
Sourcepub fn cwd(&self) -> &GuardedPath
pub fn cwd(&self) -> &GuardedPath
Current working directory (guarded; stays inside the workspace).
Sourcepub fn new_pipe(&self) -> Value
pub fn new_pipe(&self) -> Value
Mint a fresh unbound pipe handle, like bare LET $p: PIPE. The
backend materializes lazily on first binding; return it from a
host function to hand the DSL a pipe it can bind. Tagged with the
current task so promotion checks see the declaration origin.
Sourcepub fn pipe_reader(
&self,
value: &Value,
) -> Result<Arc<Mutex<dyn Read + Send>>, Error>
pub fn pipe_reader( &self, value: &Value, ) -> Result<Arc<Mutex<dyn Read + Send>>, Error>
Borrow the read half of a PIPE value for byte streaming (see
PipeStream). Unbound handles materialize as script pipes —
hosts cannot spawn RUN, so script is the only sensible kind,
and a later RUN binding adapts through the shared path. DSL,
bridge, and host bindings on an OS-materialized handle resolve
through the single-take bridge: the first call takes, repeats bail
loudly (same contract as DSL consumers; use script-backed pipes
for repeat or multi access).
Sourcepub fn pipe_writer(
&self,
value: &Value,
) -> Result<Arc<Mutex<dyn Write + Send>>, Error>
pub fn pipe_writer( &self, value: &Value, ) -> Result<Arc<Mutex<dyn Write + Send>>, Error>
Borrow the write half of a PIPE value for byte streaming (see
PipeStream). Same materialization and take-once contract as
StepCtx::pipe_reader.
Sourcepub fn close_pipe(&self, value: &Value) -> Result<(), Error>
pub fn close_pipe(&self, value: &Value) -> Result<(), Error>
Explicitly close a script pipe: readers drain buffered bytes, then observe EOF regardless of live writers or keeper pins. Unbound handles bail (closing a never-bound pipe is a caller bug), and OS-materialized handles bail (kernel pairs close by dropping their taken halves — drop the value instead).
Sourcepub fn is_cancelled(&self) -> bool
pub fn is_cancelled(&self) -> bool
Whether the current task was cancelled (CANCEL/TIMEOUT). For
external host modules running blocking pumps: poll each tick so
silent-but-open pipes cannot strand the task thread.
Sourcepub fn is_async_task(&self) -> bool
pub fn is_async_task(&self) -> bool
Whether this step runs on an ASYNC task thread. Blocking pumps
must refuse the main sequential flow.
Sourcepub fn pipe_backend(&self, value: &Value) -> Option<Arc<PipeInner>>
pub fn pipe_backend(&self, value: &Value) -> Option<Arc<PipeInner>>
Resolve an explicitly passed PIPE value to its script backend for
timeout-bounded reads (read_into_timeout). This is value-based on
purpose: the ambient out_pipe/stdin_pipe fields only populate via
engine-level WITH_IO resolution, which never runs for host function
calls. Returns None for unbound and OS-materialized handles, which
fall back to blocking reads.