Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 28 additions & 26 deletions crates/tui/src/commands/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::config_persistence::{
persist_tui_integer_key,
};
use crate::config_ui::{ConfigUiMode, parse_mode};
use crate::localization::resolve_locale;
use crate::localization::{MessageId, resolve_locale, tr};
use crate::settings::Settings;
use crate::tui::app::{
App, AppAction, AppMode, OnboardingState, ReasoningEffort, SidebarFocus, VimMode,
Expand Down Expand Up @@ -969,20 +969,18 @@ pub fn trust(app: &mut App, arg: Option<&str>) -> CommandResult {
"" | "status" | "list" => trust_status(&workspace, app, sub == "list"),
"on" | "enable" | "yes" | "y" => {
app.trust_mode = true;
CommandResult::message(
"Workspace trust mode enabled — agent file tools can now read/write any path. \
Use `/trust off` to revert; prefer `/trust add <path>` for a narrower opt-in.",
)
CommandResult::message(tr(app.ui_locale, MessageId::CmdTrustEnabled))
}
"off" | "disable" | "no" | "n" => {
app.trust_mode = false;
CommandResult::message("Workspace trust mode disabled.")
CommandResult::message(tr(app.ui_locale, MessageId::CmdTrustDisabled))
}
"add" => trust_add(&workspace, rest),
"remove" | "rm" | "del" | "delete" => trust_remove(&workspace, rest),
other => CommandResult::error(format!(
"Unknown /trust action `{other}`. Use `/trust`, `/trust on|off`, `/trust add <path>`, or `/trust remove <path>`."
)),
other => CommandResult::error_localized(
app.ui_locale,
tr(app.ui_locale, MessageId::CmdTrustUnknownAction).replace("{action}", other),
),
}
}

Expand Down Expand Up @@ -1072,27 +1070,24 @@ pub fn lsp_command(app: &mut App, arg: Option<&str>) -> CommandResult {
// Access lsp_manager config through the App's engine handle
let current_enabled = app.lsp_enabled;

let locale = app.ui_locale;
match raw {
"" | "status" => {
let status = if current_enabled { "on" } else { "off" };
CommandResult::message(format!(
"LSP diagnostics are currently **{status}**.\n\n\
Use `/lsp on` to enable or `/lsp off` to disable inline diagnostics after file edits."
))
CommandResult::message(tr(locale, MessageId::CmdLspStatus).replace("{status}", status))
}
"on" | "enable" | "1" | "true" => {
app.lsp_enabled = true;
CommandResult::message(
"LSP diagnostics enabled — file edit results will include compiler errors and warnings when available.",
)
CommandResult::message(tr(locale, MessageId::CmdLspEnabled))
}
"off" | "disable" | "0" | "false" => {
app.lsp_enabled = false;
CommandResult::message("LSP diagnostics disabled.")
CommandResult::message(tr(locale, MessageId::CmdLspDisabled))
}
other => CommandResult::error(format!(
"Unknown /lsp argument `{other}`. Use `/lsp on`, `/lsp off`, or `/lsp status`."
)),
other => CommandResult::error_localized(
locale,
tr(locale, MessageId::CmdLspUnknownArg).replace("{arg}", other),
),
}
}

Expand All @@ -1102,26 +1097,32 @@ pub fn lsp_command(app: &mut App, arg: Option<&str>) -> CommandResult {
/// `codewhale auth clear --provider <id>` and
/// `codewhale auth set --provider <id>`.
pub fn logout(app: &mut App) -> CommandResult {
let locale = app.ui_locale;
let provider_name = app.api_provider.as_str();
match clear_active_provider_api_key(provider_name) {
Ok(()) => {
app.onboarding = OnboardingState::ApiKey;
app.onboarding_needs_api_key = true;
app.api_key_input.clear();
app.api_key_cursor = 0;
CommandResult::message(format!(
"Cleared API key for {provider_name}. \
Use `codewhale auth clear --provider <id>` to clear a different provider."
))
CommandResult::message(
tr(locale, MessageId::CmdLogoutSuccess).replace("{provider}", provider_name),
)
}
Err(e) => CommandResult::error(format!("Failed to clear API key for {provider_name}: {e}")),
Err(e) => CommandResult::error_localized(
locale,
tr(locale, MessageId::CmdLogoutFailed)
.replace("{provider}", provider_name)
.replace("{error}", &e.to_string()),
),
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::config::Config;
use crate::localization::Locale;
use crate::test_support::lock_test_env;
use crate::tui::app::{App, TuiOptions};
use crate::tui::approval::ApprovalMode;
Expand Down Expand Up @@ -1251,6 +1252,7 @@ mod tests {
app.auto_model = false;
app.api_provider = crate::config::ApiProvider::Deepseek;
app.model_ids_passthrough = false;
app.ui_locale = Locale::En;
app
}

Expand Down Expand Up @@ -1892,7 +1894,7 @@ mod tests {
app.trust_mode = false;
let result = trust(&mut app, Some("on"));
let msg = result.message.expect("message");
assert!(msg.contains("Workspace trust mode enabled"));
assert!(msg.contains(tr(Locale::En, MessageId::CmdTrustEnabled)));
assert!(app.trust_mode);
}

Expand Down
13 changes: 13 additions & 0 deletions crates/tui/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,19 @@ impl CommandResult {
is_error: true,
}
}

/// Create an error message result with a localized "Error:" prefix
pub fn error_localized(locale: Locale, msg: impl Into<String>) -> Self {
Self {
message: Some(format!(
"{} {}",
tr(locale, MessageId::CmdErrorPrefix),
msg.into()
)),
action: None,
is_error: true,
}
}
}

/// Command metadata for help and autocomplete.
Expand Down
2 changes: 1 addition & 1 deletion crates/tui/src/commands/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn list_queue(app: &mut App) -> CommandResult {
let queued = app.queued_message_count();

if let Some(draft) = app.queued_draft.as_ref() {
lines.push("Editing queued message:".to_string());
lines.push(tr(locale, MessageId::CmdEditingQueuedDraft).to_string());
lines.push(format!("- {}", truncate_preview(&draft.display)));
}

Expand Down
21 changes: 16 additions & 5 deletions crates/tui/src/commands/task.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//! Task commands: add/list/show/cancel

use crate::localization::{MessageId, tr};
use crate::tui::app::{App, AppAction};

use super::CommandResult;

pub fn task(_app: &mut App, args: Option<&str>) -> CommandResult {
pub fn task(app: &mut App, args: Option<&str>) -> CommandResult {
let raw = args.unwrap_or("").trim();
if raw.is_empty() || raw.eq_ignore_ascii_case("list") {
return CommandResult::action(AppAction::TaskList);
Expand All @@ -14,10 +15,14 @@ pub fn task(_app: &mut App, args: Option<&str>) -> CommandResult {
let action = parts.next().unwrap_or("").to_ascii_lowercase();
let remainder = parts.next().map(str::trim).filter(|s| !s.is_empty());

let locale = app.ui_locale;
match action.as_str() {
"add" => {
let Some(prompt) = remainder else {
return CommandResult::error("Usage: /task add <prompt>");
return CommandResult::error_localized(
locale,
tr(locale, MessageId::CmdTaskUsageAdd),
);
};
CommandResult::action(AppAction::TaskAdd {
prompt: prompt.to_string(),
Expand All @@ -26,17 +31,23 @@ pub fn task(_app: &mut App, args: Option<&str>) -> CommandResult {
"list" => CommandResult::action(AppAction::TaskList),
"show" => {
let Some(id) = remainder else {
return CommandResult::error("Usage: /task show <id>");
return CommandResult::error_localized(
locale,
tr(locale, MessageId::CmdTaskUsageShow),
);
};
CommandResult::action(AppAction::TaskShow { id: id.to_string() })
}
"cancel" | "stop" => {
let Some(id) = remainder else {
return CommandResult::error("Usage: /task cancel <id>");
return CommandResult::error_localized(
locale,
tr(locale, MessageId::CmdTaskUsageCancel),
);
};
CommandResult::action(AppAction::TaskCancel { id: id.to_string() })
}
_ => CommandResult::error("Usage: /task [add <prompt>|list|show <id>|cancel <id>]"),
_ => CommandResult::error_localized(locale, tr(locale, MessageId::CmdTaskUsageGeneral)),
}
}

Expand Down
Loading
Loading