Skip to content

Commit df23221

Browse files
authored
feat: add shellExec and shellSpawn for running shell commands (#160)
1 parent bad20ce commit df23221

33 files changed

+2553
-818
lines changed

Cargo.lock

Lines changed: 1045 additions & 786 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
[workspace]
22
resolver = "2"
3-
members = ["packages/desktop"]
3+
members = ["packages/desktop", "crates/*"]
4+
5+
[workspace.dependencies]
6+
serde = { version = "1", features = ["derive"] }
7+
serde_json = { version = "1", features = ["raw_value"] }
8+
tokio = { version = "1", features = ["full"] }
9+
tracing = "0.1"
10+
thiserror = "2"

crates/shell-util/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "shell-util"
3+
version = "0.0.0"
4+
authors = ["you"]
5+
license = ""
6+
repository = ""
7+
edition = "2021"
8+
9+
[dependencies]
10+
serde = { workspace = true }
11+
serde_json = { workspace = true }
12+
tokio = { workspace = true }
13+
tracing = { workspace = true }
14+
thiserror = { workspace = true }
15+
shared_child = "1"
16+
regex = "1"
17+
encoding_rs = "0.8"
18+
os_pipe = "1"

crates/shell-util/src/encoding.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
use crate::shell::Buffer;
4+
5+
#[derive(Debug, Clone, Deserialize, Eq, PartialEq, Serialize)]
6+
pub enum Encoding {
7+
#[serde(rename = "raw")]
8+
Raw,
9+
#[serde(rename = "utf-8")]
10+
Utf8,
11+
#[serde(rename = "utf-16")]
12+
Utf16,
13+
#[serde(rename = "gbk")]
14+
Gbk,
15+
#[serde(rename = "gb18030")]
16+
Gb18030,
17+
#[serde(rename = "big5")]
18+
Big5,
19+
#[serde(rename = "euc-jp")]
20+
EucJp,
21+
#[serde(rename = "euc-kr")]
22+
EucKr,
23+
#[serde(rename = "iso-2022-jp")]
24+
Iso2022Jp,
25+
#[serde(rename = "shift-jis")]
26+
ShiftJis,
27+
}
28+
29+
impl Encoding {
30+
pub fn decode(&self, line: Vec<u8>) -> Buffer {
31+
match <&Encoding as TryInto<&'static encoding_rs::Encoding>>::try_into(
32+
self,
33+
) {
34+
Ok(encoding) => {
35+
let encoding = encoding.decode_with_bom_removal(&line).0;
36+
Buffer::Text(encoding.into())
37+
}
38+
Err(_) => Buffer::Raw(line),
39+
}
40+
}
41+
}
42+
43+
impl TryInto<&'static encoding_rs::Encoding> for &Encoding {
44+
type Error = ();
45+
46+
fn try_into(
47+
self,
48+
) -> Result<&'static encoding_rs::Encoding, Self::Error> {
49+
match self {
50+
Encoding::Raw => Err(()),
51+
Encoding::Utf8 => Ok(encoding_rs::UTF_8),
52+
Encoding::Gbk => Ok(encoding_rs::GBK),
53+
Encoding::Gb18030 => Ok(encoding_rs::GB18030),
54+
Encoding::Big5 => Ok(encoding_rs::BIG5),
55+
Encoding::EucJp => Ok(encoding_rs::EUC_JP),
56+
Encoding::Iso2022Jp => Ok(encoding_rs::ISO_2022_JP),
57+
Encoding::ShiftJis => Ok(encoding_rs::SHIFT_JIS),
58+
Encoding::EucKr => Ok(encoding_rs::EUC_KR),
59+
Encoding::Utf16 => Ok(encoding_rs::UTF_16LE),
60+
}
61+
}
62+
}

crates/shell-util/src/error.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use serde::{Serialize, Serializer};
2+
3+
#[derive(Debug, thiserror::Error)]
4+
pub enum Error {
5+
#[error(transparent)]
6+
Io(#[from] std::io::Error),
7+
8+
#[error("Invalid buffer")]
9+
InvalidBuffer,
10+
}
11+
12+
impl Serialize for Error {
13+
fn serialize<S>(
14+
&self,
15+
serializer: S,
16+
) -> std::result::Result<S::Ok, S::Error>
17+
where
18+
S: Serializer,
19+
{
20+
serializer.serialize_str(&self.to_string())
21+
}
22+
}

crates/shell-util/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(slice_internals)]
2+
3+
mod encoding;
4+
mod error;
5+
mod options;
6+
mod shell;
7+
mod stdout_reader;
8+
9+
pub use encoding::*;
10+
pub use error::*;
11+
pub use options::*;
12+
pub use shell::*;
13+
pub(crate) use stdout_reader::*;
14+
15+
pub type Result<T> = std::result::Result<T, Error>;

crates/shell-util/src/options.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::{collections::HashMap, path::PathBuf};
2+
3+
use serde::{Deserialize, Serialize};
4+
5+
use crate::encoding::Encoding;
6+
7+
#[derive(Debug, Clone, Deserialize, Eq, PartialEq, Serialize)]
8+
#[serde(default, rename_all = "camelCase")]
9+
pub struct CommandOptions {
10+
pub cwd: Option<PathBuf>,
11+
12+
pub env: HashMap<String, String>,
13+
14+
/// Clear the environment variables of the spawned process.
15+
pub clear_env: bool,
16+
17+
/// Character encoding for stdout/stderr.
18+
pub encoding: Encoding,
19+
}
20+
21+
impl Default for CommandOptions {
22+
fn default() -> Self {
23+
Self {
24+
cwd: None,
25+
env: HashMap::default(),
26+
clear_env: false,
27+
encoding: Encoding::Utf8,
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)