aboutsummaryrefslogtreecommitdiff
path: root/src/cli.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli.rs')
-rw-r--r--src/cli.rs75
1 files changed, 73 insertions, 2 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 276462b7..3facba8b 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -4,20 +4,34 @@ use serde::Serialize;
use crate::api::client::{ApiClient, ApiClientError};
use crate::api::schema::{
- AgentStatus, Method, OutputMatch, PaneAgentState, PaneWaitForOutputParams, ReadFormat,
- ReadSource, Request, SplitDirection, Subscription,
+ AgentStatus, ClientWindowTitleSetParams, EmptyParams, Method, OutputMatch, PaneAgentState,
+ PaneWaitForOutputParams, ReadFormat, ReadSource, Request, SplitDirection, Subscription,
};
mod agent;
mod integration;
mod notification;
mod pane;
+mod plugin;
mod server;
mod status;
mod tab;
mod workspace;
mod worktree;
+pub(crate) fn parse_env_assignment(raw: &str) -> Result<(String, String), String> {
+ let Some((key, value)) = raw.split_once('=') else {
+ return Err("env must use KEY=VALUE".into());
+ };
+ if key.is_empty() {
+ return Err("env key must not be empty".into());
+ }
+ if key.contains('\0') || value.contains('\0') {
+ return Err("env must not contain NUL bytes".into());
+ }
+ Ok((key.to_string(), value.to_string()))
+}
+
pub enum CommandOutcome {
Handled(i32),
NotCli,
@@ -45,6 +59,7 @@ pub fn maybe_run(args: &[String]) -> std::io::Result<CommandOutcome> {
"agent" => agent::run_agent_command(&args[2..])?,
"terminal" => run_terminal_command(&args[2..])?,
"pane" => pane::run_pane_command(&args[2..])?,
+ "plugin" => plugin::run_plugin_command(&args[2..])?,
"wait" => run_wait_command(&args[2..])?,
"integration" => integration::run_integration_command(&args[2..])?,
"session" => run_session_command(&args[2..])?,
@@ -305,6 +320,7 @@ fn run_terminal_command(args: &[String]) -> std::io::Result<i32> {
match subcommand {
"attach" => terminal_attach(&args[1..]),
+ "title" => terminal_title(&args[1..]),
"help" | "--help" | "-h" => {
print_terminal_help();
Ok(0)
@@ -458,6 +474,43 @@ fn terminal_attach(args: &[String]) -> std::io::Result<i32> {
Ok(0)
}
+fn terminal_title(args: &[String]) -> std::io::Result<i32> {
+ match args.first().map(|arg| arg.as_str()) {
+ Some("set") => {
+ if args.len() != 2 {
+ eprintln!("usage: herdr terminal title set <title>");
+ return Ok(2);
+ }
+ print_response(&send_request(&Request {
+ id: "cli:terminal:title:set".into(),
+ method: Method::ClientWindowTitleSet(ClientWindowTitleSetParams {
+ title: args[1].clone(),
+ }),
+ })?)
+ }
+ Some("clear") => {
+ if args.len() != 1 {
+ eprintln!("usage: herdr terminal title clear");
+ return Ok(2);
+ }
+ print_response(&send_request(&Request {
+ id: "cli:terminal:title:clear".into(),
+ method: Method::ClientWindowTitleClear(EmptyParams::default()),
+ })?)
+ }
+ Some("help" | "--help" | "-h") => {
+ eprintln!("usage: herdr terminal title set <title>");
+ eprintln!(" herdr terminal title clear");
+ Ok(0)
+ }
+ _ => {
+ eprintln!("usage: herdr terminal title set <title>");
+ eprintln!(" herdr terminal title clear");
+ Ok(2)
+ }
+ }
+}
+
pub(super) fn parse_attach_target(args: &[String], usage: &str) -> Result<(String, bool), i32> {
let Some(target) = args.first() else {
eprintln!("{usage}");
@@ -861,6 +914,8 @@ fn print_config_help() {
fn print_terminal_help() {
eprintln!("herdr terminal commands:");
eprintln!(" herdr terminal attach <terminal_id> [--takeover]");
+ eprintln!(" herdr terminal title set <title>");
+ eprintln!(" herdr terminal title clear");
eprintln!(" detach from direct attach with ctrl+b q; send literal ctrl+b with ctrl+b ctrl+b");
}
@@ -948,4 +1003,20 @@ mod tests {
super::ChannelSetInstallAction::RunSelfUpdate
);
}
+
+ #[test]
+ fn parse_env_assignment_accepts_empty_values() {
+ assert_eq!(
+ super::parse_env_assignment("HERDR_ROLE=").unwrap(),
+ ("HERDR_ROLE".to_string(), String::new())
+ );
+ }
+
+ #[test]
+ fn parse_env_assignment_requires_key_value_separator() {
+ assert_eq!(
+ super::parse_env_assignment("HERDR_ROLE").unwrap_err(),
+ "env must use KEY=VALUE"
+ );
+ }
}