use anyhow::Result;
use bmux_cli_schema::{
AccessCommand, AuthCommand, Command, ConfigCommand, ConfigProfilesCommand, ConfigScopeCommand,
DiagnosticsCommand, KeymapCommand, KioskCommand, LogsCommand, LogsProfilesCommand, PerfCommand,
PlaybookCommand, RecordingEventKindArg, RemoteCommand, RemoteCompleteCommand,
RemoteTrustCommand, SandboxCommand, SandboxEnvModeArg, SandboxSourceArg, SandboxStatusArg,
ServerAutostartCommand, ServerCommand, SessionCommand, SlotCommand, TerminalCommand,
};
use bmux_config::{BmuxConfig, SandboxCleanupSource};
use bmux_recording_protocol::{RecordingEventKind, RecordingRollingStartOptions};
use super::{
BuiltInHandlerId, BundleIncludeOptions, BundleSandboxOptions, ConnectionContext,
InspectTargetOptions, RerunSandboxOptions, RunSandboxOptions, TriageBundleOptions,
TriageSandboxOptions, built_in_command_by_handler, run_access_add, run_access_disable,
run_access_enable, run_access_init, run_access_list, run_access_remove, run_access_status,
run_auth_login, run_auth_logout, run_auth_status, run_client_list, run_config_get,
run_config_path, run_config_profiles_diff, run_config_profiles_evaluate,
run_config_profiles_explain, run_config_profiles_lint, run_config_profiles_list,
run_config_profiles_resolve, run_config_profiles_show, run_config_profiles_switch,
run_config_scope_explain, run_config_set, run_config_show, run_connect, run_device_seal_broker,
run_diagnostics_watch, run_doctor, run_external_plugin_command, run_follow, run_host,
run_hosts, run_join, run_keymap_doctor, run_keymap_explain, run_kiosk_attach, run_kiosk_init,
run_kiosk_issue_token, run_kiosk_revoke_token, run_kiosk_ssh_print_config, run_kiosk_status,
run_logs_level, run_logs_path, run_logs_profiles_delete, run_logs_profiles_list,
run_logs_profiles_rename, run_logs_profiles_show, run_logs_tail, run_logs_watch, run_perf_off,
run_perf_on, run_perf_status, run_playbook_cleanup, run_playbook_diff, run_playbook_dry_run,
run_playbook_interactive, run_playbook_run, run_playbook_validate,
run_remote_complete_sessions, run_remote_complete_targets, run_remote_doctor, run_remote_init,
run_remote_install_server, run_remote_list, run_remote_test, run_remote_trust_add,
run_remote_trust_list, run_remote_trust_remove, run_remote_upgrade, run_sandbox_bundle,
run_sandbox_cleanup, run_sandbox_doctor, run_sandbox_inspect, run_sandbox_list,
run_sandbox_open, run_sandbox_rebuild_index, run_sandbox_rerun, run_sandbox_run,
run_sandbox_status, run_sandbox_tail, run_sandbox_triage, run_sandbox_verify_bundle,
run_server_bridge, run_server_gateway, run_server_restore, run_server_save, run_server_start,
run_server_status, run_server_stop, run_server_whoami_principal, run_session_attach,
run_session_detach, run_session_kill, run_session_kill_all, run_session_list, run_session_new,
run_setup, run_share, run_terminal_doctor, run_terminal_install_terminfo, run_unfollow,
run_unshare,
server_autostart::{
run_server_autostart_install, run_server_autostart_print, run_server_autostart_status,
run_server_autostart_uninstall,
},
};
pub(super) async fn run_command(
command: &Command,
connection_context: ConnectionContext<'_>,
) -> Result<u8> {
match command {
Command::External(args) => run_external_plugin_command(args).await,
_ => Box::pin(dispatch_built_in_command(command, connection_context)).await,
}
}
#[allow(clippy::too_many_lines)]
pub(super) fn built_in_handler_for_command(command: &Command) -> BuiltInHandlerId {
match command {
Command::Setup { .. } => BuiltInHandlerId::Setup,
Command::Host { .. } => BuiltInHandlerId::Host,
Command::Join { .. } => BuiltInHandlerId::Join,
Command::Hosts { .. } => BuiltInHandlerId::Hosts,
Command::Auth { command } => match command {
AuthCommand::Login { .. } => BuiltInHandlerId::AuthLogin,
AuthCommand::Status => BuiltInHandlerId::AuthStatus,
AuthCommand::Logout => BuiltInHandlerId::AuthLogout,
},
Command::Access { .. } => BuiltInHandlerId::Access,
Command::Kiosk { command } => match command {
KioskCommand::Status { .. } => BuiltInHandlerId::KioskStatus,
KioskCommand::Init { .. } => BuiltInHandlerId::KioskInit,
KioskCommand::IssueToken { .. } => BuiltInHandlerId::KioskIssueToken,
KioskCommand::RevokeToken { .. } => BuiltInHandlerId::KioskRevokeToken,
KioskCommand::Attach { .. } => BuiltInHandlerId::KioskAttach,
KioskCommand::SshPrintConfig { .. } => BuiltInHandlerId::KioskSshPrintConfig,
},
Command::Share { .. } => BuiltInHandlerId::Share,
Command::Unshare { .. } => BuiltInHandlerId::Unshare,
Command::Connect { .. } => BuiltInHandlerId::Connect,
Command::NewSession { .. } => BuiltInHandlerId::NewSession,
Command::ListSessions { .. } => BuiltInHandlerId::ListSessions,
Command::ListClients { .. } => BuiltInHandlerId::ListClients,
Command::KillSession { .. } => BuiltInHandlerId::KillSession,
Command::KillAllSessions { .. } => BuiltInHandlerId::KillAllSessions,
Command::Attach { .. } => BuiltInHandlerId::Attach,
Command::Detach => BuiltInHandlerId::Detach,
Command::Follow { .. } => BuiltInHandlerId::Follow,
Command::Unfollow => BuiltInHandlerId::Unfollow,
Command::Session { command } => match command {
SessionCommand::New { .. } => BuiltInHandlerId::SessionNew,
SessionCommand::List { .. } => BuiltInHandlerId::SessionList,
SessionCommand::Clients { .. } => BuiltInHandlerId::SessionClients,
SessionCommand::Kill { .. } => BuiltInHandlerId::SessionKill,
SessionCommand::KillAll { .. } => BuiltInHandlerId::SessionKillAll,
SessionCommand::Attach { .. } => BuiltInHandlerId::SessionAttach,
SessionCommand::Detach => BuiltInHandlerId::SessionDetach,
SessionCommand::Follow { .. } => BuiltInHandlerId::SessionFollow,
SessionCommand::Unfollow => BuiltInHandlerId::SessionUnfollow,
},
Command::Remote { command } => match command {
RemoteCommand::List { .. } => BuiltInHandlerId::RemoteList,
RemoteCommand::Test { .. } => BuiltInHandlerId::RemoteTest,
RemoteCommand::Doctor { .. } => BuiltInHandlerId::RemoteDoctor,
RemoteCommand::Init { .. } => BuiltInHandlerId::RemoteInit,
RemoteCommand::InstallServer { .. } => BuiltInHandlerId::RemoteInstallServer,
RemoteCommand::Upgrade { .. } => BuiltInHandlerId::RemoteUpgrade,
RemoteCommand::Trust { command } => match command {
RemoteTrustCommand::List => BuiltInHandlerId::RemoteTrustList,
RemoteTrustCommand::Add { .. } => BuiltInHandlerId::RemoteTrustAdd,
RemoteTrustCommand::Remove { .. } => BuiltInHandlerId::RemoteTrustRemove,
},
RemoteCommand::Complete { command } => match command {
RemoteCompleteCommand::Targets => BuiltInHandlerId::RemoteCompleteTargets,
RemoteCompleteCommand::Sessions { .. } => BuiltInHandlerId::RemoteCompleteSessions,
},
},
Command::Server { command } => match command {
ServerCommand::Start { .. } => BuiltInHandlerId::ServerStart,
ServerCommand::Status { .. } => BuiltInHandlerId::ServerStatus,
ServerCommand::WhoamiPrincipal { .. } => BuiltInHandlerId::ServerWhoamiPrincipal,
ServerCommand::Save => BuiltInHandlerId::ServerSave,
ServerCommand::Restore { .. } => BuiltInHandlerId::ServerRestore,
ServerCommand::Stop => BuiltInHandlerId::ServerStop,
ServerCommand::Autostart { command } => match command {
ServerAutostartCommand::Install { .. } => BuiltInHandlerId::ServerAutostartInstall,
ServerAutostartCommand::Uninstall => BuiltInHandlerId::ServerAutostartUninstall,
ServerAutostartCommand::Status { .. } => BuiltInHandlerId::ServerAutostartStatus,
ServerAutostartCommand::Print { .. } => BuiltInHandlerId::ServerAutostartPrint,
},
ServerCommand::Gateway { .. } => BuiltInHandlerId::ServerGateway,
ServerCommand::Bridge { .. } => BuiltInHandlerId::ServerBridge,
},
Command::Logs { command } => match command {
LogsCommand::Path { .. } => BuiltInHandlerId::LogsPath,
LogsCommand::Level { .. } => BuiltInHandlerId::LogsLevel,
LogsCommand::Tail { .. } => BuiltInHandlerId::LogsTail,
LogsCommand::Watch { .. } => BuiltInHandlerId::LogsWatch,
LogsCommand::Profiles { command } => match command {
LogsProfilesCommand::List { .. } => BuiltInHandlerId::LogsProfilesList,
LogsProfilesCommand::Show { .. } => BuiltInHandlerId::LogsProfilesShow,
LogsProfilesCommand::Delete { .. } => BuiltInHandlerId::LogsProfilesDelete,
LogsProfilesCommand::Rename { .. } => BuiltInHandlerId::LogsProfilesRename,
},
},
Command::Diagnostics { command } => match command {
DiagnosticsCommand::Watch { .. } | DiagnosticsCommand::View { .. } => {
BuiltInHandlerId::DiagnosticsWatch
}
},
Command::Config { command } => match command {
ConfigCommand::Path { .. } => BuiltInHandlerId::ConfigPath,
ConfigCommand::Show { .. } => BuiltInHandlerId::ConfigShow,
ConfigCommand::Get { .. } => BuiltInHandlerId::ConfigGet,
ConfigCommand::Set { .. } => BuiltInHandlerId::ConfigSet,
ConfigCommand::Profiles { command } => match command {
ConfigProfilesCommand::List { .. } => BuiltInHandlerId::ConfigProfilesList,
ConfigProfilesCommand::Show { .. } => BuiltInHandlerId::ConfigProfilesShow,
ConfigProfilesCommand::Resolve { .. } => BuiltInHandlerId::ConfigProfilesResolve,
ConfigProfilesCommand::Explain { .. } => BuiltInHandlerId::ConfigProfilesExplain,
ConfigProfilesCommand::Switch { .. } => BuiltInHandlerId::ConfigProfilesSwitch,
ConfigProfilesCommand::Diff { .. } => BuiltInHandlerId::ConfigProfilesDiff,
ConfigProfilesCommand::Lint { .. } => BuiltInHandlerId::ConfigProfilesLint,
ConfigProfilesCommand::Evaluate { .. } => BuiltInHandlerId::ConfigProfilesEvaluate,
},
ConfigCommand::Scope { command } => match command {
ConfigScopeCommand::Explain { .. } => BuiltInHandlerId::ConfigScopeExplain,
},
},
Command::Perf { command } => match command {
PerfCommand::Status { .. } => BuiltInHandlerId::PerfStatus,
PerfCommand::On { .. } => BuiltInHandlerId::PerfOn,
PerfCommand::Off { .. } => BuiltInHandlerId::PerfOff,
},
Command::Doctor { .. } => BuiltInHandlerId::Doctor,
Command::Keymap { command } => match command {
KeymapCommand::Doctor { .. } => BuiltInHandlerId::KeymapDoctor,
KeymapCommand::Explain { .. } => BuiltInHandlerId::KeymapExplain,
},
Command::Terminal { command } => match command {
TerminalCommand::Doctor { .. } => BuiltInHandlerId::TerminalDoctor,
TerminalCommand::InstallTerminfo { .. } => BuiltInHandlerId::TerminalInstallTerminfo,
},
Command::Playbook { command } => match command {
PlaybookCommand::Run { .. } => BuiltInHandlerId::PlaybookRun,
PlaybookCommand::Validate { .. } => BuiltInHandlerId::PlaybookValidate,
PlaybookCommand::Interactive { .. } => BuiltInHandlerId::PlaybookInteractive,
PlaybookCommand::DryRun { .. } => BuiltInHandlerId::PlaybookDryRun,
PlaybookCommand::Diff { .. } => BuiltInHandlerId::PlaybookDiff,
PlaybookCommand::Cleanup { .. } => BuiltInHandlerId::PlaybookCleanup,
},
Command::Sandbox { command } => match command {
SandboxCommand::Dev { .. } => BuiltInHandlerId::SandboxDev,
SandboxCommand::Attach { .. } => BuiltInHandlerId::SandboxAttach,
SandboxCommand::Stop { .. } => BuiltInHandlerId::SandboxStop,
SandboxCommand::Run { .. } => BuiltInHandlerId::SandboxRun,
SandboxCommand::List { .. } => BuiltInHandlerId::SandboxList,
SandboxCommand::Status { .. } => BuiltInHandlerId::SandboxStatus,
SandboxCommand::Inspect { .. } => BuiltInHandlerId::SandboxInspect,
SandboxCommand::Tail { .. } => BuiltInHandlerId::SandboxTail,
SandboxCommand::Open { .. } => BuiltInHandlerId::SandboxOpen,
SandboxCommand::Rerun { .. } => BuiltInHandlerId::SandboxRerun,
SandboxCommand::Triage { .. } => BuiltInHandlerId::SandboxTriage,
SandboxCommand::Doctor { .. } => BuiltInHandlerId::SandboxDoctor,
SandboxCommand::Bundle { .. } => BuiltInHandlerId::SandboxBundle,
SandboxCommand::VerifyBundle { .. } => BuiltInHandlerId::SandboxVerifyBundle,
SandboxCommand::Cleanup { .. } => BuiltInHandlerId::SandboxCleanup,
SandboxCommand::Clean { .. } => BuiltInHandlerId::SandboxClean,
SandboxCommand::RebuildIndex { .. } => BuiltInHandlerId::SandboxRebuildIndex,
},
Command::DeviceSealBroker => BuiltInHandlerId::DeviceSealBroker,
Command::Slot { command } | Command::Env { command } => match command {
SlotCommand::List { .. } => BuiltInHandlerId::SlotList,
SlotCommand::Show { .. } => BuiltInHandlerId::SlotShow,
SlotCommand::Paths { .. } => BuiltInHandlerId::SlotPaths,
SlotCommand::Doctor => BuiltInHandlerId::SlotDoctor,
SlotCommand::Install { .. } => BuiltInHandlerId::SlotInstall,
SlotCommand::Uninstall { .. } => BuiltInHandlerId::SlotUninstall,
SlotCommand::Shell { .. } => BuiltInHandlerId::SlotShell,
SlotCommand::Exec { .. } => BuiltInHandlerId::SlotExec,
SlotCommand::Print { .. } => BuiltInHandlerId::SlotPrint,
},
Command::External(_) => unreachable!("external commands are dispatched separately"),
}
}
#[allow(
clippy::match_same_arms,
clippy::too_many_lines,
clippy::large_stack_frames
)] pub(super) async fn dispatch_built_in_command(
command: &Command,
connection_context: ConnectionContext<'_>,
) -> Result<u8> {
let handler = built_in_handler_for_command(command);
let _descriptor = built_in_command_by_handler(handler);
match (handler, command) {
(BuiltInHandlerId::Setup, Command::Setup { check, mode }) => run_setup(*check, *mode).await,
(
BuiltInHandlerId::Host,
Command::Host {
listen,
name,
copy,
daemon,
status,
stop,
restart,
mode,
},
) => {
Box::pin(run_host(
listen,
name.as_deref(),
*copy,
*daemon,
*status,
*stop,
*restart,
*mode,
false,
))
.await
}
(BuiltInHandlerId::Join, Command::Join { link, session }) => {
Box::pin(run_join(link.as_deref(), session.as_deref())).await
}
(BuiltInHandlerId::Hosts, Command::Hosts { verbose }) => run_hosts(*verbose),
(
BuiltInHandlerId::AuthLogin,
Command::Auth {
command: AuthCommand::Login { no_browser },
},
) => run_auth_login(*no_browser).await,
(
BuiltInHandlerId::AuthStatus,
Command::Auth {
command: AuthCommand::Status,
},
) => run_auth_status(),
(
BuiltInHandlerId::AuthLogout,
Command::Auth {
command: AuthCommand::Logout,
},
) => run_auth_logout(),
(
BuiltInHandlerId::Access,
Command::Access {
command: AccessCommand::Status,
},
) => run_access_status(),
(
BuiltInHandlerId::Access,
Command::Access {
command:
AccessCommand::Init {
agent,
key_file,
public_key,
github_user,
yes,
},
},
) => run_access_init(*agent, key_file, public_key, github_user, *yes),
(
BuiltInHandlerId::Access,
Command::Access {
command:
AccessCommand::Add {
agent,
key_file,
public_key,
github_user,
},
},
) => run_access_add(*agent, key_file, public_key, github_user),
(
BuiltInHandlerId::Access,
Command::Access {
command: AccessCommand::List { json },
},
) => run_access_list(*json),
(
BuiltInHandlerId::Access,
Command::Access {
command: AccessCommand::Remove { fingerprint, yes },
},
) => run_access_remove(fingerprint, *yes),
(
BuiltInHandlerId::Access,
Command::Access {
command: AccessCommand::Enable,
},
) => run_access_enable(),
(
BuiltInHandlerId::Access,
Command::Access {
command: AccessCommand::Disable,
},
) => run_access_disable(),
(
BuiltInHandlerId::KioskStatus,
Command::Kiosk {
command: KioskCommand::Status { json },
},
) => run_kiosk_status(*json),
(
BuiltInHandlerId::KioskInit,
Command::Kiosk {
command:
KioskCommand::Init {
profile,
all_profiles,
dry_run,
yes,
},
},
) => run_kiosk_init(profile, *all_profiles, *dry_run, *yes),
(
BuiltInHandlerId::KioskIssueToken,
Command::Kiosk {
command:
KioskCommand::IssueToken {
profile,
session,
ttl_secs,
one_shot,
multi_use,
},
},
) => run_kiosk_issue_token(
profile,
session.as_deref(),
*ttl_secs,
*one_shot,
*multi_use,
),
(
BuiltInHandlerId::KioskRevokeToken,
Command::Kiosk {
command: KioskCommand::RevokeToken { token_id },
},
) => run_kiosk_revoke_token(token_id),
(
BuiltInHandlerId::KioskAttach,
Command::Kiosk {
command: KioskCommand::Attach { profile, token },
},
) => run_kiosk_attach(profile, token, connection_context).await,
(
BuiltInHandlerId::KioskSshPrintConfig,
Command::Kiosk {
command:
KioskCommand::SshPrintConfig {
profile,
all_profiles,
},
},
) => run_kiosk_ssh_print_config(profile, *all_profiles),
(
BuiltInHandlerId::Share,
Command::Share {
target,
secondary,
name,
role,
ttl,
one_time,
copy,
qr,
},
) => {
run_share(
target.as_deref(),
secondary.as_deref(),
name.as_deref(),
role,
ttl.as_deref(),
*one_time,
*copy,
*qr,
)
.await
}
(BuiltInHandlerId::Unshare, Command::Unshare { name }) => run_unshare(name).await,
(
BuiltInHandlerId::Connect,
Command::Connect {
target,
session,
follow,
global,
reconnect_forever,
},
) => {
Box::pin(run_connect(
target.as_deref(),
session.as_deref(),
follow.as_deref(),
*global,
*reconnect_forever,
))
.await
}
(BuiltInHandlerId::NewSession, Command::NewSession { name }) => {
run_session_new(name.clone(), connection_context).await
}
(BuiltInHandlerId::ListSessions, Command::ListSessions { json }) => {
run_session_list(*json, connection_context).await
}
(BuiltInHandlerId::ListClients, Command::ListClients { json }) => {
run_client_list(*json, connection_context).await
}
(
BuiltInHandlerId::KillSession,
Command::KillSession {
target,
force_local,
},
) => run_session_kill(target, *force_local, connection_context).await,
(BuiltInHandlerId::KillAllSessions, Command::KillAllSessions { force_local }) => {
run_session_kill_all(*force_local, connection_context).await
}
(
BuiltInHandlerId::Attach,
Command::Attach {
target,
follow,
global,
observer_socket,
observer_cols,
observer_rows,
web,
web_assets,
web_only,
web_port,
web_auth,
web_host,
web_public_host,
web_allowed_hosts,
},
) => {
if let Some(socket) = observer_socket {
let session_id = target
.as_deref()
.ok_or_else(|| anyhow::anyhow!("observer requires a session UUID"))?
.parse::<uuid::Uuid>()?;
let client = super::connect_with_context(
super::ConnectionPolicyScope::Normal,
"bmux-retained-observer",
connection_context,
)
.await?;
#[cfg(unix)]
return super::attach::observer::transport::run_private_worker(
client,
session_id,
socket,
*observer_cols,
*observer_rows,
)
.await;
#[cfg(not(unix))]
{
let _ = (client, session_id, socket, observer_cols, observer_rows);
anyhow::bail!("private attachment observation requires Unix sockets");
}
}
if *web || *web_only || web_assets.is_some() {
return Box::pin(super::web_attach::run(
target.as_deref(),
follow.as_deref(),
*global,
web_assets.as_deref(),
*web_only,
super::web_attach::WebOptions {
port: *web_port,
auth: web_auth.as_deref(),
host: *web_host,
public_host: *web_public_host,
allowed_hosts: web_allowed_hosts.as_deref(),
},
connection_context,
))
.await;
}
Box::pin(run_session_attach(
target.as_deref(),
follow.as_deref(),
*global,
connection_context,
))
.await
}
(BuiltInHandlerId::Detach, Command::Detach) => run_session_detach(connection_context).await,
(
BuiltInHandlerId::Follow,
Command::Follow {
target_client_id,
global,
},
) => run_follow(target_client_id, *global, connection_context).await,
(BuiltInHandlerId::Unfollow, Command::Unfollow) => run_unfollow(connection_context).await,
(
BuiltInHandlerId::SessionNew,
Command::Session {
command: SessionCommand::New { name },
},
) => run_session_new(name.clone(), connection_context).await,
(
BuiltInHandlerId::SessionList,
Command::Session {
command: SessionCommand::List { json },
},
) => run_session_list(*json, connection_context).await,
(
BuiltInHandlerId::SessionClients,
Command::Session {
command: SessionCommand::Clients { json },
},
) => run_client_list(*json, connection_context).await,
(
BuiltInHandlerId::SessionKill,
Command::Session {
command:
SessionCommand::Kill {
target,
force_local,
},
},
) => run_session_kill(target, *force_local, connection_context).await,
(
BuiltInHandlerId::SessionKillAll,
Command::Session {
command: SessionCommand::KillAll { force_local },
},
) => run_session_kill_all(*force_local, connection_context).await,
(
BuiltInHandlerId::SessionAttach,
Command::Session {
command:
SessionCommand::Attach {
target,
follow,
global,
},
},
) => {
Box::pin(run_session_attach(
target.as_deref(),
follow.as_deref(),
*global,
connection_context,
))
.await
}
(
BuiltInHandlerId::SessionDetach,
Command::Session {
command: SessionCommand::Detach,
},
) => run_session_detach(connection_context).await,
(
BuiltInHandlerId::SessionFollow,
Command::Session {
command:
SessionCommand::Follow {
target_client_id,
global,
},
},
) => run_follow(target_client_id, *global, connection_context).await,
(
BuiltInHandlerId::SessionUnfollow,
Command::Session {
command: SessionCommand::Unfollow,
},
) => run_unfollow(connection_context).await,
(
BuiltInHandlerId::RemoteList,
Command::Remote {
command: RemoteCommand::List { json },
},
) => run_remote_list(*json),
(
BuiltInHandlerId::RemoteTest,
Command::Remote {
command: RemoteCommand::Test { target },
},
) => run_remote_test(target).await,
(
BuiltInHandlerId::RemoteDoctor,
Command::Remote {
command: RemoteCommand::Doctor { target, fix },
},
) => run_remote_doctor(target, *fix).await,
(
BuiltInHandlerId::RemoteInit,
Command::Remote {
command:
RemoteCommand::Init {
name,
ssh,
tls,
iroh,
user,
port,
set_default,
},
},
) => {
run_remote_init(
name,
ssh.as_deref(),
tls.as_deref(),
iroh.as_deref(),
user.as_deref(),
*port,
*set_default,
)
.await
}
(
BuiltInHandlerId::RemoteInstallServer,
Command::Remote {
command: RemoteCommand::InstallServer { target },
},
) => run_remote_install_server(target).await,
(
BuiltInHandlerId::RemoteUpgrade,
Command::Remote {
command: RemoteCommand::Upgrade { target },
},
) => run_remote_upgrade(target.as_deref()).await,
(
BuiltInHandlerId::RemoteTrustList,
Command::Remote {
command:
RemoteCommand::Trust {
command: RemoteTrustCommand::List,
},
},
) => run_remote_trust_list(),
(
BuiltInHandlerId::RemoteTrustAdd,
Command::Remote {
command:
RemoteCommand::Trust {
command: RemoteTrustCommand::Add { target, yes },
},
},
) => run_remote_trust_add(target, *yes).await,
(
BuiltInHandlerId::RemoteTrustRemove,
Command::Remote {
command:
RemoteCommand::Trust {
command: RemoteTrustCommand::Remove { endpoint },
},
},
) => run_remote_trust_remove(endpoint),
(
BuiltInHandlerId::RemoteCompleteTargets,
Command::Remote {
command:
RemoteCommand::Complete {
command: RemoteCompleteCommand::Targets,
},
},
) => run_remote_complete_targets(),
(
BuiltInHandlerId::RemoteCompleteSessions,
Command::Remote {
command:
RemoteCommand::Complete {
command: RemoteCompleteCommand::Sessions { target },
},
},
) => run_remote_complete_sessions(target).await,
(
BuiltInHandlerId::ServerStart,
Command::Server {
command:
ServerCommand::Start {
daemon,
foreground_internal,
pane_shell_integration,
no_pane_shell_integration,
rolling_recording,
no_rolling_recording,
rolling_window_secs,
rolling_event_kind_all,
rolling_event_kind,
rolling_capture_input,
no_rolling_capture_input,
rolling_capture_output,
no_rolling_capture_output,
rolling_capture_events,
no_rolling_capture_events,
rolling_capture_protocol_replies,
no_rolling_capture_protocol_replies,
rolling_capture_images,
no_rolling_capture_images,
},
},
) => {
let rolling_enabled_override = if *rolling_recording {
Some(true)
} else if *no_rolling_recording {
Some(false)
} else {
None
};
let pane_shell_integration_override =
bool_override(*pane_shell_integration, *no_pane_shell_integration);
let rolling_options = RecordingRollingStartOptions {
window_secs: *rolling_window_secs,
name: None,
event_kinds: if *rolling_event_kind_all {
Some(all_recording_event_kinds())
} else if rolling_event_kind.is_empty() {
None
} else {
Some(
rolling_event_kind
.iter()
.copied()
.map(recording_event_kind_arg_to_ipc)
.collect(),
)
},
capture_input: bool_override(*rolling_capture_input, *no_rolling_capture_input),
capture_output: bool_override(*rolling_capture_output, *no_rolling_capture_output),
capture_events: bool_override(*rolling_capture_events, *no_rolling_capture_events),
capture_protocol_replies: bool_override(
*rolling_capture_protocol_replies,
*no_rolling_capture_protocol_replies,
),
capture_images: bool_override(*rolling_capture_images, *no_rolling_capture_images),
};
run_server_start(
*daemon,
*foreground_internal,
rolling_enabled_override,
rolling_options,
pane_shell_integration_override,
None,
)
.await
}
(
BuiltInHandlerId::ServerStatus,
Command::Server {
command: ServerCommand::Status { json },
},
) => run_server_status(*json, connection_context).await,
(
BuiltInHandlerId::ServerWhoamiPrincipal,
Command::Server {
command: ServerCommand::WhoamiPrincipal { json },
},
) => run_server_whoami_principal(*json, connection_context).await,
(
BuiltInHandlerId::ServerSave,
Command::Server {
command: ServerCommand::Save,
},
) => run_server_save(connection_context).await,
(
BuiltInHandlerId::ServerRestore,
Command::Server {
command: ServerCommand::Restore { dry_run, yes },
},
) => run_server_restore(*dry_run, *yes, connection_context).await,
(
BuiltInHandlerId::ServerStop,
Command::Server {
command: ServerCommand::Stop,
},
) => run_server_stop(connection_context).await,
(
BuiltInHandlerId::ServerAutostartInstall,
Command::Server {
command:
ServerCommand::Autostart {
command:
ServerAutostartCommand::Install {
no_start,
executable,
},
},
},
) => {
run_server_autostart_install(*no_start, executable.as_deref(), connection_context).await
}
(
BuiltInHandlerId::ServerAutostartUninstall,
Command::Server {
command:
ServerCommand::Autostart {
command: ServerAutostartCommand::Uninstall,
},
},
) => run_server_autostart_uninstall(connection_context),
(
BuiltInHandlerId::ServerAutostartStatus,
Command::Server {
command:
ServerCommand::Autostart {
command: ServerAutostartCommand::Status { json },
},
},
) => run_server_autostart_status(*json, connection_context).await,
(
BuiltInHandlerId::ServerAutostartPrint,
Command::Server {
command:
ServerCommand::Autostart {
command: ServerAutostartCommand::Print { executable },
},
},
) => run_server_autostart_print(executable.as_deref(), connection_context),
(
BuiltInHandlerId::ServerGateway,
Command::Server {
command:
ServerCommand::Gateway {
listen,
host,
host_mode,
host_relay,
quick,
cert_file,
key_file,
},
},
) => {
run_server_gateway(
listen,
*host,
*host_mode,
host_relay,
*quick,
cert_file.as_deref(),
key_file.as_deref(),
)
.await
}
(
BuiltInHandlerId::ServerBridge,
Command::Server {
command: ServerCommand::Bridge { stdio, preflight },
},
) => run_server_bridge(*stdio, *preflight).await,
(
BuiltInHandlerId::LogsPath,
Command::Logs {
command: LogsCommand::Path { json },
},
) => run_logs_path(*json),
(
BuiltInHandlerId::LogsLevel,
Command::Logs {
command: LogsCommand::Level { json },
},
) => run_logs_level(*json),
(
BuiltInHandlerId::LogsTail,
Command::Logs {
command:
LogsCommand::Tail {
lines,
since,
no_follow,
},
},
) => run_logs_tail(*lines, since.as_deref(), !*no_follow),
(
BuiltInHandlerId::LogsWatch,
Command::Logs {
command:
LogsCommand::Watch {
lines,
since,
profile,
include,
include_i,
exclude,
exclude_i,
},
},
) => run_logs_watch(
*lines,
since.as_deref(),
profile.as_deref(),
include,
include_i,
exclude,
exclude_i,
),
(
BuiltInHandlerId::DiagnosticsWatch,
Command::Diagnostics {
command:
DiagnosticsCommand::Watch {
lines,
since,
profile,
include,
include_i,
exclude,
exclude_i,
}
| DiagnosticsCommand::View {
lines,
since,
profile,
include,
include_i,
exclude,
exclude_i,
},
},
) => run_diagnostics_watch(
*lines,
since.as_deref(),
profile.as_deref(),
include,
include_i,
exclude,
exclude_i,
),
(
BuiltInHandlerId::LogsProfilesList,
Command::Logs {
command:
LogsCommand::Profiles {
command: LogsProfilesCommand::List { json },
},
},
) => run_logs_profiles_list(*json),
(
BuiltInHandlerId::LogsProfilesShow,
Command::Logs {
command:
LogsCommand::Profiles {
command: LogsProfilesCommand::Show { profile, json },
},
},
) => run_logs_profiles_show(profile.as_deref(), *json),
(
BuiltInHandlerId::LogsProfilesDelete,
Command::Logs {
command:
LogsCommand::Profiles {
command: LogsProfilesCommand::Delete { profile },
},
},
) => run_logs_profiles_delete(profile),
(
BuiltInHandlerId::LogsProfilesRename,
Command::Logs {
command:
LogsCommand::Profiles {
command: LogsProfilesCommand::Rename { from, to },
},
},
) => run_logs_profiles_rename(from, to),
(
BuiltInHandlerId::ConfigPath,
Command::Config {
command: ConfigCommand::Path { json },
},
) => run_config_path(*json),
(
BuiltInHandlerId::ConfigShow,
Command::Config {
command: ConfigCommand::Show { json },
},
) => run_config_show(*json),
(
BuiltInHandlerId::ConfigGet,
Command::Config {
command: ConfigCommand::Get { key, json },
},
) => run_config_get(key, *json),
(
BuiltInHandlerId::ConfigSet,
Command::Config {
command: ConfigCommand::Set { key, value },
},
) => run_config_set(key, value),
(
BuiltInHandlerId::ConfigScopeExplain,
Command::Config {
command:
ConfigCommand::Scope {
command: ConfigScopeCommand::Explain { scope, cwd, json },
},
},
) => run_config_scope_explain(scope, cwd.as_deref(), *json),
(
BuiltInHandlerId::ConfigProfilesList,
Command::Config {
command:
ConfigCommand::Profiles {
command: ConfigProfilesCommand::List { json },
},
},
) => run_config_profiles_list(*json),
(
BuiltInHandlerId::ConfigProfilesShow,
Command::Config {
command:
ConfigCommand::Profiles {
command: ConfigProfilesCommand::Show { profile, json },
},
},
) => run_config_profiles_show(profile, *json),
(
BuiltInHandlerId::ConfigProfilesResolve,
Command::Config {
command:
ConfigCommand::Profiles {
command: ConfigProfilesCommand::Resolve { profile, json },
},
},
) => run_config_profiles_resolve(profile.as_deref(), *json),
(
BuiltInHandlerId::ConfigProfilesExplain,
Command::Config {
command:
ConfigCommand::Profiles {
command: ConfigProfilesCommand::Explain { profile, json },
},
},
) => run_config_profiles_explain(profile.as_deref(), *json),
(
BuiltInHandlerId::ConfigProfilesSwitch,
Command::Config {
command:
ConfigCommand::Profiles {
command:
ConfigProfilesCommand::Switch {
profile,
dry_run,
json,
},
},
},
) => run_config_profiles_switch(profile, *dry_run, *json),
(
BuiltInHandlerId::ConfigProfilesDiff,
Command::Config {
command:
ConfigCommand::Profiles {
command: ConfigProfilesCommand::Diff { from, to, json },
},
},
) => run_config_profiles_diff(from, to, *json),
(
BuiltInHandlerId::ConfigProfilesLint,
Command::Config {
command:
ConfigCommand::Profiles {
command: ConfigProfilesCommand::Lint { json },
},
},
) => run_config_profiles_lint(*json),
(
BuiltInHandlerId::ConfigProfilesEvaluate,
Command::Config {
command:
ConfigCommand::Profiles {
command: ConfigProfilesCommand::Evaluate { json },
},
},
) => run_config_profiles_evaluate(*json),
(
BuiltInHandlerId::PerfStatus,
Command::Perf {
command: PerfCommand::Status { json },
},
) => run_perf_status(*json, connection_context).await,
(
BuiltInHandlerId::PerfOn,
Command::Perf {
command: PerfCommand::On { profile, json },
},
) => run_perf_on(*profile, *json, connection_context).await,
(
BuiltInHandlerId::PerfOff,
Command::Perf {
command: PerfCommand::Off { json },
},
) => run_perf_off(*json, connection_context).await,
(BuiltInHandlerId::Doctor, Command::Doctor { json, hosted }) => {
run_doctor(*json, *hosted).await
}
(
BuiltInHandlerId::KeymapDoctor,
Command::Keymap {
command: KeymapCommand::Doctor { json },
},
) => run_keymap_doctor(*json),
(
BuiltInHandlerId::KeymapExplain,
Command::Keymap {
command: KeymapCommand::Explain { key, mode, json },
},
) => run_keymap_explain(key, mode.as_deref(), *json),
(
BuiltInHandlerId::TerminalDoctor,
Command::Terminal {
command:
TerminalCommand::Doctor {
json,
trace,
trace_limit,
trace_family,
trace_pane,
},
},
) => run_terminal_doctor(*json, *trace, *trace_limit, *trace_family, *trace_pane),
(
BuiltInHandlerId::TerminalInstallTerminfo,
Command::Terminal {
command: TerminalCommand::InstallTerminfo { yes, check },
},
) => run_terminal_install_terminfo(*yes, *check),
(
BuiltInHandlerId::PlaybookRun,
Command::Playbook {
command:
PlaybookCommand::Run {
source,
json,
interactive,
playback_speed,
target_server,
record,
export_gif,
viewport,
timeout,
shell,
vars,
verbose,
},
},
) => {
run_playbook_run(
source,
*json,
*interactive,
playback_speed,
*target_server,
*record,
export_gif.as_deref(),
viewport.as_deref(),
*timeout,
shell.as_deref(),
vars,
*verbose,
)
.await
}
(
BuiltInHandlerId::PlaybookValidate,
Command::Playbook {
command: PlaybookCommand::Validate { source, json },
},
) => run_playbook_validate(source, *json),
(
BuiltInHandlerId::PlaybookInteractive,
Command::Playbook {
command:
PlaybookCommand::Interactive {
socket,
record,
viewport,
shell,
timeout,
},
},
) => {
run_playbook_interactive(
socket.as_deref(),
*record,
viewport,
shell.as_deref(),
*timeout,
)
.await
}
(
BuiltInHandlerId::PlaybookDryRun,
Command::Playbook {
command: PlaybookCommand::DryRun { source, json },
},
) => run_playbook_dry_run(source, *json),
(
BuiltInHandlerId::PlaybookDiff,
Command::Playbook {
command:
PlaybookCommand::Diff {
left,
right,
json,
timing_threshold,
},
},
) => run_playbook_diff(left, right, *json, *timing_threshold),
(
BuiltInHandlerId::PlaybookCleanup,
Command::Playbook {
command: PlaybookCommand::Cleanup { dry_run, json },
},
) => run_playbook_cleanup(*dry_run, *json),
(
BuiltInHandlerId::SandboxDev,
Command::Sandbox {
command:
SandboxCommand::Dev {
inherit_config,
bmux_bin,
env_mode,
json,
print_env,
timeout,
name,
command,
},
},
) => {
let options = RunSandboxOptions {
bmux_bin: bmux_bin.as_deref(),
env_mode: *env_mode,
keep: true,
json: *json,
print_env: *print_env,
timeout_secs: *timeout,
name: name.as_deref(),
};
if *inherit_config {
super::sandbox_cli::run_inherited_sandbox(options, command).await
} else {
run_sandbox_run(options, command).await
}
}
(
BuiltInHandlerId::SandboxAttach,
Command::Sandbox {
command: SandboxCommand::Attach { sandbox },
},
) => super::sandbox_cli::run_inherited_sandbox_control(sandbox, false).await,
(
BuiltInHandlerId::SandboxStop,
Command::Sandbox {
command: SandboxCommand::Stop { sandbox },
},
) => super::sandbox_cli::run_inherited_sandbox_control(sandbox, true).await,
(
BuiltInHandlerId::SandboxRun,
Command::Sandbox {
command:
SandboxCommand::Run {
bmux_bin,
env_mode,
keep,
json,
print_env,
timeout,
name,
command,
},
},
) => {
let options = RunSandboxOptions {
bmux_bin: bmux_bin.as_deref(),
env_mode: *env_mode,
keep: *keep,
json: *json,
print_env: *print_env,
timeout_secs: *timeout,
name: name.as_deref(),
};
run_sandbox_run(options, command).await
}
(
BuiltInHandlerId::SandboxList,
Command::Sandbox {
command:
SandboxCommand::List {
status,
source,
limit,
json,
},
},
) => {
let status_filter = match status {
SandboxStatusArg::Running => Some("running"),
SandboxStatusArg::Stopped => Some("stopped"),
SandboxStatusArg::Failed => Some("failed"),
SandboxStatusArg::All => None,
};
let source_filter = match source {
SandboxSourceArg::SandboxCli => Some("sandbox-cli"),
SandboxSourceArg::Playbook => Some("playbook"),
SandboxSourceArg::RecordingVerify => Some("recording-verify"),
SandboxSourceArg::All => None,
};
run_sandbox_list(status_filter, source_filter, *limit, *json)
}
(
BuiltInHandlerId::SandboxStatus,
Command::Sandbox {
command: SandboxCommand::Status { json },
},
) => run_sandbox_status(*json),
(
BuiltInHandlerId::SandboxInspect,
Command::Sandbox {
command:
SandboxCommand::Inspect {
sandbox,
latest,
latest_failed,
source,
tail,
json,
},
},
) => {
let source_filter = sandbox_source_filter(*source);
run_sandbox_inspect(
sandbox.as_deref(),
*latest,
*latest_failed,
source_filter,
*tail,
*json,
)
}
(
BuiltInHandlerId::SandboxTail,
Command::Sandbox {
command:
SandboxCommand::Tail {
sandbox,
latest,
latest_failed,
source,
tail,
json,
},
},
) => {
let source_filter = sandbox_source_filter(*source);
run_sandbox_tail(
sandbox.as_deref(),
*latest,
*latest_failed,
source_filter,
*tail,
*json,
)
}
(
BuiltInHandlerId::SandboxOpen,
Command::Sandbox {
command:
SandboxCommand::Open {
sandbox,
latest,
latest_failed,
source,
json,
},
},
) => {
let source_filter = sandbox_source_filter(*source);
run_sandbox_open(
sandbox.as_deref(),
*latest,
*latest_failed,
source_filter,
*json,
)
}
(
BuiltInHandlerId::SandboxRerun,
Command::Sandbox {
command:
SandboxCommand::Rerun {
sandbox,
latest,
latest_failed,
source,
bmux_bin,
env_mode,
keep,
json,
print_env,
timeout,
name,
},
},
) => {
let source_filter = sandbox_source_filter(*source);
run_sandbox_rerun(RerunSandboxOptions {
inspect: InspectTargetOptions {
target: sandbox.as_deref(),
latest: *latest,
latest_failed: *latest_failed,
source_filter,
},
run: RunSandboxOptions {
bmux_bin: None,
env_mode: SandboxEnvModeArg::Inherit,
keep: *keep,
json: *json,
print_env: *print_env,
timeout_secs: *timeout,
name: name.as_deref(),
},
bmux_bin_override: bmux_bin.as_deref(),
env_mode_override: *env_mode,
})
.await
}
(
BuiltInHandlerId::SandboxTriage,
Command::Sandbox {
command:
SandboxCommand::Triage {
sandbox,
latest,
latest_failed,
source,
tail,
rerun,
bmux_bin,
env_mode,
keep,
print_env,
timeout,
name,
bundle,
bundle_output,
bundle_strict_verify,
json,
},
},
) => {
let source_filter = sandbox_source_filter(*source);
run_sandbox_triage(TriageSandboxOptions {
inspect: InspectTargetOptions {
target: sandbox.as_deref(),
latest: *latest,
latest_failed: *latest_failed,
source_filter,
},
tail: *tail,
rerun: *rerun,
run: RunSandboxOptions {
bmux_bin: None,
env_mode: SandboxEnvModeArg::Inherit,
keep: *keep,
json: false,
print_env: *print_env,
timeout_secs: *timeout,
name: name.as_deref(),
},
bmux_bin_override: bmux_bin.as_deref(),
env_mode_override: *env_mode,
bundle: bundle.then_some(TriageBundleOptions {
output: bundle_output.as_deref(),
strict_verify: *bundle_strict_verify,
}),
json: *json,
})
.await
}
(
BuiltInHandlerId::SandboxDoctor,
Command::Sandbox {
command:
SandboxCommand::Doctor {
id,
fix,
dry_run,
json,
},
},
) => run_sandbox_doctor(id.as_deref(), *fix, *dry_run, *json),
(
BuiltInHandlerId::SandboxBundle,
Command::Sandbox {
command:
SandboxCommand::Bundle {
sandbox,
output,
include_env,
include_index_state,
include_doctor,
verify,
json,
},
},
) => run_sandbox_bundle(&BundleSandboxOptions {
target: sandbox,
output: output.as_deref(),
include: BundleIncludeOptions {
env: *include_env,
index_state: *include_index_state,
doctor: *include_doctor,
},
verify: *verify,
json: *json,
}),
(
BuiltInHandlerId::SandboxCleanup,
Command::Sandbox {
command:
SandboxCommand::Cleanup {
dry_run,
failed_only,
all_status,
older_than,
source,
json,
},
},
) => {
let config = BmuxConfig::load().unwrap_or_default();
let defaults = config.sandbox.cleanup;
let resolved_failed_only =
bool_override(*failed_only, *all_status).unwrap_or(defaults.failed_only);
let resolved_older_than = older_than.unwrap_or(defaults.older_than_secs);
let source_arg = source.as_ref().copied().unwrap_or(match defaults.source {
SandboxCleanupSource::SandboxCli => SandboxSourceArg::SandboxCli,
SandboxCleanupSource::Playbook => SandboxSourceArg::Playbook,
SandboxCleanupSource::RecordingVerify => SandboxSourceArg::RecordingVerify,
SandboxCleanupSource::All => SandboxSourceArg::All,
});
let source_filter = sandbox_source_filter(source_arg);
run_sandbox_cleanup(
*dry_run,
resolved_failed_only,
Some(resolved_older_than),
source_filter,
*json,
)
}
(
BuiltInHandlerId::SandboxVerifyBundle,
Command::Sandbox {
command:
SandboxCommand::VerifyBundle {
bundle_dir,
strict,
json,
},
},
) => run_sandbox_verify_bundle(bundle_dir, *strict, *json),
(
BuiltInHandlerId::SandboxRebuildIndex,
Command::Sandbox {
command: SandboxCommand::RebuildIndex { json },
},
) => run_sandbox_rebuild_index(*json),
(
BuiltInHandlerId::SandboxClean,
Command::Sandbox {
command:
SandboxCommand::Clean {
dry_run,
all_status,
older_than,
source,
json,
},
},
) => {
let source_filter =
sandbox_source_filter(source.as_ref().copied().unwrap_or(SandboxSourceArg::All));
let resolved_failed_only = !all_status;
let resolved_older_than = older_than.unwrap_or(600);
run_sandbox_cleanup(
*dry_run,
resolved_failed_only,
Some(resolved_older_than),
source_filter,
*json,
)
}
(BuiltInHandlerId::DeviceSealBroker, Command::DeviceSealBroker) => {
run_device_seal_broker(connection_context).await
}
(
BuiltInHandlerId::SlotList,
Command::Slot {
command: SlotCommand::List { format },
}
| Command::Env {
command: SlotCommand::List { format },
},
) => super::slot_cli::run_slot_list(*format),
(
BuiltInHandlerId::SlotShow,
Command::Slot {
command: SlotCommand::Show { name, format },
}
| Command::Env {
command: SlotCommand::Show { name, format },
},
) => super::slot_cli::run_slot_show(name.as_deref(), *format),
(
BuiltInHandlerId::SlotPaths,
Command::Slot {
command: SlotCommand::Paths { name },
}
| Command::Env {
command: SlotCommand::Paths { name },
},
) => super::slot_cli::run_slot_paths(name.as_deref()),
(
BuiltInHandlerId::SlotDoctor,
Command::Slot {
command: SlotCommand::Doctor,
}
| Command::Env {
command: SlotCommand::Doctor,
},
) => super::slot_cli::run_slot_doctor(),
(
BuiltInHandlerId::SlotInstall,
Command::Slot {
command:
SlotCommand::Install {
name,
binary,
no_inherit_base,
mode,
bin_dir,
format,
dry_run,
overwrite,
yes,
},
}
| Command::Env {
command:
SlotCommand::Install {
name,
binary,
no_inherit_base,
mode,
bin_dir,
format,
dry_run,
overwrite,
yes,
},
},
) => super::slot_cli::run_slot_install(super::slot_cli::SlotInstallOptions {
name,
binary,
inherit_base: !*no_inherit_base,
mode: *mode,
bin_dir: bin_dir.as_deref(),
format: *format,
dry_run: *dry_run,
overwrite: *overwrite,
yes: *yes,
}),
(
BuiltInHandlerId::SlotUninstall,
Command::Slot {
command:
SlotCommand::Uninstall {
name,
purge,
bin_dir,
},
}
| Command::Env {
command:
SlotCommand::Uninstall {
name,
purge,
bin_dir,
},
},
) => super::slot_cli::run_slot_uninstall(name, *purge, bin_dir.as_deref()),
(
BuiltInHandlerId::SlotShell,
Command::Slot {
command: SlotCommand::Shell { shell },
}
| Command::Env {
command: SlotCommand::Shell { shell },
},
) => super::slot_cli::run_slot_shell(*shell),
(
BuiltInHandlerId::SlotExec,
Command::Slot {
command: SlotCommand::Exec { slot, argv },
}
| Command::Env {
command: SlotCommand::Exec { slot, argv },
},
) => super::slot_cli::run_slot_exec(slot, argv),
(
BuiltInHandlerId::SlotPrint,
Command::Slot {
command: SlotCommand::Print { format },
}
| Command::Env {
command: SlotCommand::Print { format },
},
) => super::slot_cli::run_slot_print(*format),
_ => unreachable!("built-in command handler and command variant should stay in sync"),
}
}
const fn bool_override(positive: bool, negative: bool) -> Option<bool> {
if positive {
Some(true)
} else if negative {
Some(false)
} else {
None
}
}
const fn sandbox_source_filter(source: SandboxSourceArg) -> Option<&'static str> {
match source {
SandboxSourceArg::SandboxCli => Some("sandbox-cli"),
SandboxSourceArg::Playbook => Some("playbook"),
SandboxSourceArg::RecordingVerify => Some("recording-verify"),
SandboxSourceArg::All => None,
}
}
fn all_recording_event_kinds() -> Vec<RecordingEventKind> {
vec![
RecordingEventKind::PaneInputRaw,
RecordingEventKind::PaneOutputRaw,
RecordingEventKind::ProtocolReplyRaw,
RecordingEventKind::PaneImage,
RecordingEventKind::ServerEvent,
RecordingEventKind::RequestStart,
RecordingEventKind::RequestDone,
RecordingEventKind::RequestError,
RecordingEventKind::Custom,
]
}
const fn recording_event_kind_arg_to_ipc(kind: RecordingEventKindArg) -> RecordingEventKind {
match kind {
RecordingEventKindArg::PaneInputRaw => RecordingEventKind::PaneInputRaw,
RecordingEventKindArg::PaneOutputRaw => RecordingEventKind::PaneOutputRaw,
RecordingEventKindArg::ProtocolReplyRaw => RecordingEventKind::ProtocolReplyRaw,
RecordingEventKindArg::PaneImage => RecordingEventKind::PaneImage,
RecordingEventKindArg::ServerEvent => RecordingEventKind::ServerEvent,
RecordingEventKindArg::RequestStart => RecordingEventKind::RequestStart,
RecordingEventKindArg::RequestDone => RecordingEventKind::RequestDone,
RecordingEventKindArg::RequestError => RecordingEventKind::RequestError,
RecordingEventKindArg::Custom => RecordingEventKind::Custom,
}
}
#[cfg(test)]
mod tests {
#[allow(clippy::wildcard_imports)]
use super::*;
#[test]
fn built_in_handler_maps_config_profiles_explain() {
let command = Command::Config {
command: ConfigCommand::Profiles {
command: ConfigProfilesCommand::Explain {
profile: Some("vim".to_string()),
json: false,
},
},
};
assert_eq!(
built_in_handler_for_command(&command),
BuiltInHandlerId::ConfigProfilesExplain
);
}
#[test]
fn built_in_handler_maps_config_profiles_switch_with_dry_run() {
let command = Command::Config {
command: ConfigCommand::Profiles {
command: ConfigProfilesCommand::Switch {
profile: "tmux_compat".to_string(),
dry_run: true,
json: true,
},
},
};
assert_eq!(
built_in_handler_for_command(&command),
BuiltInHandlerId::ConfigProfilesSwitch
);
}
#[test]
fn built_in_handler_maps_keymap_explain() {
let command = Command::Keymap {
command: KeymapCommand::Explain {
key: "ctrl+b n".to_string(),
mode: Some("normal".to_string()),
json: true,
},
};
assert_eq!(
built_in_handler_for_command(&command),
BuiltInHandlerId::KeymapExplain
);
}
}