JustBash.Interpreter.Executor.Redirection (JustBash v0.4.0)
View SourceHandles file redirections for bash commands.
Supports:
- Output redirection:
>,>> - Error redirection:
2>,2>> - Input redirection:
< - Here-strings:
<<< - Combined redirection:
&> - Stream duplication:
>&,2>&1,1>&2 - /dev/null handling
Summary
Types
A redirection whose target has already been expanded, resolved, and opened
by preflight/2.
Functions
Apply preflighted redirections to the result, writing each stream to the
target preflight/2 already opened.
Extract heredoc, here-string or < file content as stdin.
Expand, resolve, and open every redirection target, left to right, before the command body runs.
Types
@type prepared() :: {redir_type(), String.t() | nil}
A redirection whose target has already been expanded, resolved, and opened
by preflight/2.
The path is nil for redirections that touch no file (/dev/null, stream
duplication, <). Carrying the resolved path forward is what keeps a
target containing a command substitution from being expanded a second
time when the output is finally written.
@type redir_type() ::
:stdout_dev_null
| :stderr_dev_null
| :combined_dev_null
| :stdout_write
| :stdout_append
| :stderr_write
| :stderr_append
| :stdout_to_stderr
| :stderr_to_stdout
| :combined_write
| :combined_append
| :stdin_read
| :close_fd
| :noop
@type result() :: %{ stdout: String.t(), stderr: String.t(), exit_code: non_neg_integer() }
Functions
@spec apply_redirections(result(), JustBash.t(), [prepared()]) :: {result(), JustBash.t()}
Apply preflighted redirections to the result, writing each stream to the
target preflight/2 already opened.
@spec extract_heredoc_stdin(JustBash.t(), [JustBash.AST.Redirection.t()]) :: {:ok, String.t() | nil, [JustBash.AST.Redirection.t()]} | {:error, result()}
Extract heredoc, here-string or < file content as stdin.
Returns {:ok, stdin_content, non_heredoc_redirections}, or {:error, result} when a < file target cannot be opened. The shell opens that
target itself, so — like the write side in preflight/2 — a failure is the
shell's to report and the command never runs.
@spec preflight(JustBash.t(), [JustBash.AST.Redirection.t()]) :: {:ok, [prepared()], JustBash.t()} | {:error, result(), JustBash.t()}
Expand, resolve, and open every redirection target, left to right, before the command body runs.
bash opens redirect targets before forking the command, so a target it
cannot open means the command never runs — none of its side effects happen.
On {:error, result, bash} the caller must return result without
executing the body; on {:ok, prepared, bash} it runs the body and hands
prepared to apply_redirections/3.
Opening follows the open/2 flags bash uses: >, 2> and &> create or
truncate (O_CREAT | O_TRUNC), >> and &>> create only if missing
(O_CREAT | O_APPEND). Redirections that touch no file — the
special-file table's null device (/dev/null, /dev/./null), >&,
< — are classified and passed through untouched.
Targets to the left of a failing one are still created or truncated, and targets to its right are never expanded, so a command substitution in one of them does not run. Both match bash.