Add run_cmd

This commit is contained in:
mo8it 2026-04-06 16:12:49 +02:00
parent c9ccedcff6
commit dace3e3953
2 changed files with 47 additions and 61 deletions

View File

@ -8,6 +8,25 @@ use anyhow::{Context, Result, bail};
mod zellij; mod zellij;
fn run_cmd(cmd: &mut Command) -> Result<Vec<u8>> {
let output = cmd
.stdin(Stdio::null())
.output()
.with_context(|| format!("Failed to run the command {cmd:?}"))?;
if !output.status.success() {
bail!(
"The command {cmd:?} didn't run successfully\n\n\
stdout:\n{}\n\n\
stderr:\n{}",
str::from_utf8(&output.stdout).unwrap_or_default(),
str::from_utf8(&output.stderr).unwrap_or_default(),
);
}
Ok(output.stdout)
}
pub enum Editor { pub enum Editor {
VSCode, VSCode,
Cmd(String, Vec<String>), Cmd(String, Vec<String>),
@ -39,32 +58,12 @@ impl Editor {
let handle = thread::Builder::new() let handle = thread::Builder::new()
.spawn(move || match self { .spawn(move || match self {
Editor::VSCode => { Editor::VSCode => {
if !Command::new("code") run_cmd(Command::new("code").arg(exercise_path))?;
.arg(exercise_path)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.context("Failed to run `code` to open the current exercise file")?
.success()
{
bail!("Failed to run `code PATH` to open the current exercise file");
}
Ok(Self::VSCode) Ok(Self::VSCode)
} }
Editor::Cmd(program, args) => { Editor::Cmd(program, args) => {
if !Command::new("code") run_cmd(Command::new(&program).args(&args).arg(exercise_path))?;
.arg(exercise_path)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.context("Failed to run the command from `--edit-cmd`")
.is_ok_and(|status| status.success())
{
bail!("Failed to run the command from `--edit-cmd`");
}
Ok(Self::Cmd(program, args)) Ok(Self::Cmd(program, args))
} }
@ -83,20 +82,14 @@ impl Editor {
} }
} }
let output = Command::new("zellij") let stdout = run_cmd(
.arg("action") Command::new("zellij")
.arg("edit") .arg("action")
.arg(exercise_path) .arg("edit")
.stdin(Stdio::null()) .arg(exercise_path),
.stderr(Stdio::null()) )?;
.output()
.context("Failed to run `zellij`")?;
if !output.status.success() { let (pane_id_str, pane_id) = zellij::parse_pane_id(&stdout)
bail!("Failed to open a new Zellij editor pane");
}
let (pane_id_str, pane_id) = zellij::parse_pane_id(&output.stdout)
.context("Failed to parse the ID of the new Zellij pane")?; .context("Failed to parse the ID of the new Zellij pane")?;
Ok(Self::Zellij(Some((pane_id_str, pane_id, exercise_ind)))) Ok(Self::Zellij(Some((pane_id_str, pane_id, exercise_ind))))

View File

@ -1,8 +1,10 @@
use std::process::{Command, Stdio}; use std::process::Command;
use anyhow::{Context, Result, bail}; use anyhow::{Context, Result};
use serde::Deserialize; use serde::Deserialize;
use crate::editor::run_cmd;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Pane { struct Pane {
id: u32, id: u32,
@ -24,39 +26,30 @@ pub fn parse_pane_id(b: &[u8]) -> Option<(String, u32)> {
} }
pub fn pane_open(pane_id: u32) -> Result<bool> { pub fn pane_open(pane_id: u32) -> Result<bool> {
let mut output = Command::new("zellij") let mut stdout = run_cmd(
.arg("action") Command::new("zellij")
.arg("list-panes") .arg("action")
.arg("-j") .arg("list-panes")
.stdin(Stdio::null()) .arg("-j"),
.stderr(Stdio::null()) )?;
.output()
.context("Failed to run `zellij action list-panes -j`")?;
if !output.status.success() {
bail!("`zellij action list-panes -j` didn't exit successfully");
}
// Remove newline // Remove newline
output.stdout.pop(); stdout.pop();
let panes = serde_json::de::from_slice::<Vec<Pane>>(&output.stdout) let panes = serde_json::de::from_slice::<Vec<Pane>>(&stdout)
.context("Failed to parse the output of `zellij action list-panes -j`")?; .context("Failed to parse the output of `zellij action list-panes -j`")?;
Ok(panes.iter().any(|pane| pane.id == pane_id)) Ok(panes.iter().any(|pane| pane.id == pane_id))
} }
pub fn close_pane(pane_id: &str) -> Result<()> { pub fn close_pane(pane_id: &str) -> Result<()> {
Command::new("zellij") run_cmd(
.arg("action") Command::new("zellij")
.arg("close-pane") .arg("action")
.arg("-p") .arg("close-pane")
.arg(pane_id) .arg("-p")
.stdin(Stdio::null()) .arg(pane_id),
.stdout(Stdio::null()) )?;
.stderr(Stdio::null())
.status()
.context("Failed to run `zellij action close-pane -p ID`")?;
Ok(()) Ok(())
} }