Skip to main content

pmpx_plugin/
spec.rs

1//! What a plugin answers with: one command, still unexecuted.
2
3use std::ffi::OsString;
4use std::path::PathBuf;
5
6/// One command waiting to be executed, pure data -- a plugin only describes "what to run" and the
7/// actual spawn is done by the host, so stdio, environment, and exit-code handling have exactly
8/// one implementation. Construction is a consuming chain (`self` -> `Self`), so it can produce a
9/// value directly:
10/// ```ignore
11/// let spec = CommandSpec::new("cargo").arg("add").args(args.iter()).cwd("/somewhere");
12/// ```
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct CommandSpec {
15    /// Executable. The host resolves it to a real path with `which` and decides per platform
16    /// whether to wrap it in `cmd /C` (on Windows `pnpm` is really `pnpm.cmd`, and spawning it
17    /// directly fails).
18    pub program: OsString,
19
20    /// Arguments, in order.
21    pub args: Vec<OsString>,
22
23    /// Working-directory override. `None` = use the project root given by the host.
24    pub cwd: Option<PathBuf>,
25}
26
27impl CommandSpec {
28    /// Specify the executable.
29    pub fn new(program: impl Into<OsString>) -> Self {
30        Self {
31            program: program.into(),
32            args: Vec::new(),
33            cwd: None,
34        }
35    }
36
37    /// Append one argument.
38    pub fn arg(mut self, arg: impl Into<OsString>) -> Self {
39        self.args.push(arg.into());
40        self
41    }
42
43    /// Append a batch of arguments; `args.iter()` can be passed straight in and stays lossless
44    /// (`&OsString: Into<OsString>`), unlike `String`, which would corrupt non-UTF-8 arguments on
45    /// Unix.
46    pub fn args<I, S>(mut self, args: I) -> Self
47    where
48        I: IntoIterator<Item = S>,
49        S: Into<OsString>,
50    {
51        self.args.extend(args.into_iter().map(Into::into));
52        self
53    }
54
55    /// Override the working directory.
56    pub fn cwd(mut self, dir: impl Into<PathBuf>) -> Self {
57        self.cwd = Some(dir.into());
58        self
59    }
60}