Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command support for specified character encoding, closes #4644 #4772

Merged
merged 2 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/shell-encoding-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"api": minor
---

Added the `encoding` option to the `Command` options.
5 changes: 5 additions & 0 deletions .changes/shell-encoding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri": minor
---

Add `api::Command::encoding` method to set the stdout/stderr encoding.
1 change: 1 addition & 0 deletions core/tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ serialize-to-javascript = "=0.1.1"
infer = { version = "0.8", optional = true }
png = { version = "0.17", optional = true }
ico = { version = "0.1", optional = true }
encoding_rs = "0.8.31"

[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
gtk = { version = "0.15", features = [ "v3_20" ] }
Expand Down
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.js

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion core/tauri/src/api/process/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::os::windows::process::CommandExt;
const CREATE_NO_WINDOW: u32 = 0x0800_0000;

use crate::async_runtime::{block_on as block_on_task, channel, Receiver, Sender};
pub use encoding_rs::Encoding;
use os_pipe::{pipe, PipeReader, PipeWriter};
use serde::Serialize;
use shared_child::SharedChild;
Expand Down Expand Up @@ -95,6 +96,7 @@ pub struct Command {
env_clear: bool,
env: HashMap<String, String>,
current_dir: Option<PathBuf>,
encoding: Option<&'static Encoding>,
}

/// Spawned child process.
Expand Down Expand Up @@ -171,6 +173,7 @@ impl Command {
env_clear: false,
env: Default::default(),
current_dir: None,
encoding: None,
}
}

Expand Down Expand Up @@ -216,6 +219,13 @@ impl Command {
self
}

/// Sets the character encoding for stdout/stderr.
#[must_use]
pub fn encoding(mut self, encoding: &'static Encoding) -> Self {
self.encoding.replace(encoding);
self
}

/// Spawns the command.
///
/// # Examples
Expand Down Expand Up @@ -264,12 +274,14 @@ impl Command {
guard.clone(),
stdout_reader,
CommandEvent::Stdout,
self.encoding,
);
spawn_pipe_reader(
tx.clone(),
guard.clone(),
stderr_reader,
CommandEvent::Stderr,
self.encoding,
);

spawn(move || {
Expand Down Expand Up @@ -378,6 +390,7 @@ fn spawn_pipe_reader<F: Fn(String) -> CommandEvent + Send + Copy + 'static>(
guard: Arc<RwLock<()>>,
pipe_reader: PipeReader,
wrapper: F,
character_encoding: Option<&'static Encoding>,
) {
spawn(move || {
let _lock = guard.read().unwrap();
Expand All @@ -392,7 +405,10 @@ fn spawn_pipe_reader<F: Fn(String) -> CommandEvent + Send + Copy + 'static>(
break;
}
let tx_ = tx.clone();
let line = String::from_utf8(buf.clone());
let line = match character_encoding {
Some(encoding) => Ok(encoding.decode_with_bom_removal(&buf).0.into()),
None => String::from_utf8(buf.clone()),
};
block_on_task(async move {
let _ = match line {
Ok(line) => tx_.send(wrapper(line)).await,
Expand Down
10 changes: 10 additions & 0 deletions core/tauri/src/endpoints/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub struct CommandOptions {
// but the env is an `Option` so when it's `None` we clear the env.
#[serde(default = "default_env")]
env: Option<HashMap<String, String>>,
// Character encoding for stdout/stderr
encoding: Option<String>,
}

/// The API descriptor.
Expand Down Expand Up @@ -148,6 +150,13 @@ impl Cmd {
} else {
command = command.env_clear();
}
if let Some(encoding) = options.encoding {
if let Some(encoding) = crate::api::process::Encoding::for_label(encoding.as_bytes()) {
command = command.encoding(encoding);
} else {
return Err(anyhow::anyhow!(format!("unknown encoding {}", encoding)));
}
}
let (mut rx, child) = command.spawn()?;

let pid = child.pid();
Expand Down Expand Up @@ -229,6 +238,7 @@ mod tests {
sidecar: false,
cwd: Option::arbitrary(g),
env: Option::arbitrary(g),
encoding: Option::arbitrary(g),
}
}
}
Expand Down
15 changes: 8 additions & 7 deletions examples/api/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion examples/api/src/views/Shell.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script>
import { Command } from '@tauri-apps/api/shell'

const windows = navigator.userAgent.includes('Windows')
let cmd = windows ? 'cmd' : 'sh'
let args = windows ? ['/C'] : ['-c']
Expand All @@ -9,6 +10,7 @@
let script = 'echo "hello world"'
let cwd = null
let env = 'SOMETHING=value ANOTHER=2'
let encoding = ''
let stdin = ''
let child

Expand All @@ -26,7 +28,8 @@
child = null
const command = new Command(cmd, [...args, script], {
cwd: cwd || null,
env: _getEnv()
env: _getEnv(),
encoding,
})

command.on('close', (data) => {
Expand Down Expand Up @@ -65,6 +68,10 @@
Script:
<input class="grow input" bind:value={script} />
</div>
<div class="flex items-center gap-1">
Encoding:
<input class="grow input" bind:value={encoding} />
</div>
<div class="flex items-center gap-1">
Working directory:
<input
Expand Down
2 changes: 2 additions & 0 deletions tooling/api/src/shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ interface SpawnOptions {
cwd?: string
/** Environment variables. set to `null` to clear the process env. */
env?: { [name: string]: string }
/** Character encoding for stdout/stderr */
encoding?: string
}

/** @ignore */
Expand Down