use anyhow::Result;
use super::make_sentinel;
use super::subprocess::{spawn_script, SubprocessSession};
const SH_BOOTSTRAP: &str = r#"
_calepin_tmpfile=$(mktemp)
trap 'rm -f "$_calepin_tmpfile"' EXIT
while IFS= read -r _line; do
case "$_line" in
*_BEGIN)
_sentinel="${_line%_BEGIN}"
_code=""
while IFS= read -r _line; do
case "$_line" in
"${_sentinel}_END") break ;;
*) _code="${_code}${_line}
" ;;
esac
done
_exit=0
eval "$_code" > "$_calepin_tmpfile" 2>&1 || _exit=$?
_output=$(cat "$_calepin_tmpfile")
if [ "$_exit" -ne 0 ]; then
printf '%s' "${_sentinel}_ERROR:${_output}"
printf '\n'
elif [ -n "$_output" ]; then
printf '%s' "${_sentinel}_OUTPUT:${_output}"
printf '\n'
fi
printf '%s' "${_sentinel}_DONE"
printf '\n'
;;
esac
done
"#;
pub struct ShSession {
session: SubprocessSession,
_bootstrap_file: tempfile::NamedTempFile,
}
impl ShSession {
pub fn init_with_program(
program: &str,
cwd: Option<&std::path::Path>,
timeout: Option<std::time::Duration>,
) -> Result<Self> {
let (session, bootstrap_file) =
spawn_script(program, &[], SH_BOOTSTRAP, "sh", cwd, timeout)?;
Ok(ShSession {
session,
_bootstrap_file: bootstrap_file,
})
}
pub fn capture(&mut self, code: &str) -> Result<String> {
let sentinel = make_sentinel();
self.session.execute(&sentinel, code)
}
}