Merge remote-tracking branch 'origin/pr/1306' into work/v0.8.34
# Conflicts: # crates/tui/src/commands/mod.rs # crates/tui/src/tui/ui/tests.rs # crates/tui/src/tui/widgets/mod.rs
This commit is contained in:
@@ -142,37 +142,37 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
// Core commands
|
||||
CommandInfo {
|
||||
name: "anchor",
|
||||
aliases: &[],
|
||||
aliases: &["maodian"],
|
||||
usage: "/anchor <text> | /anchor list | /anchor remove <n>",
|
||||
description_id: MessageId::CmdAnchorDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "help",
|
||||
aliases: &["?"],
|
||||
aliases: &["?", "bangzhu", "帮助"],
|
||||
usage: "/help [command]",
|
||||
description_id: MessageId::CmdHelpDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "clear",
|
||||
aliases: &[],
|
||||
aliases: &["qingping"],
|
||||
usage: "/clear",
|
||||
description_id: MessageId::CmdClearDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "exit",
|
||||
aliases: &["quit", "q"],
|
||||
aliases: &["quit", "q", "tuichu"],
|
||||
usage: "/exit",
|
||||
description_id: MessageId::CmdExitDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "model",
|
||||
aliases: &[],
|
||||
aliases: &["moxing"],
|
||||
usage: "/model [name]",
|
||||
description_id: MessageId::CmdModelDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "models",
|
||||
aliases: &[],
|
||||
aliases: &["moxingliebiao"],
|
||||
usage: "/models",
|
||||
description_id: MessageId::CmdModelsDescription,
|
||||
},
|
||||
@@ -196,25 +196,25 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "hooks",
|
||||
aliases: &["hook"],
|
||||
aliases: &["hook", "gouzi"],
|
||||
usage: "/hooks [list|events]",
|
||||
description_id: MessageId::CmdHooksDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "subagents",
|
||||
aliases: &["agents"],
|
||||
aliases: &["agents", "zhinengti"],
|
||||
usage: "/subagents",
|
||||
description_id: MessageId::CmdSubagentsDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "agent",
|
||||
aliases: &[],
|
||||
aliases: &["daili"],
|
||||
usage: "/agent [N] <task>",
|
||||
description_id: MessageId::CmdAgentDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "links",
|
||||
aliases: &["dashboard", "api"],
|
||||
aliases: &["dashboard", "api", "lianjie"],
|
||||
usage: "/links",
|
||||
description_id: MessageId::CmdLinksDescription,
|
||||
},
|
||||
@@ -226,7 +226,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "home",
|
||||
aliases: &["stats", "overview"],
|
||||
aliases: &["stats", "overview", "zhuye", "shouye"],
|
||||
usage: "/home",
|
||||
description_id: MessageId::CmdHomeDescription,
|
||||
},
|
||||
@@ -244,7 +244,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "attach",
|
||||
aliases: &["image", "media"],
|
||||
aliases: &["image", "media", "fujian"],
|
||||
usage: "/attach <path>",
|
||||
description_id: MessageId::CmdAttachDescription,
|
||||
},
|
||||
@@ -256,7 +256,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "jobs",
|
||||
aliases: &["job"],
|
||||
aliases: &["job", "zuoye"],
|
||||
usage: "/jobs [list|show <id>|poll <id>|wait <id>|stdin <id> <input>|cancel <id>]",
|
||||
description_id: MessageId::CmdJobsDescription,
|
||||
},
|
||||
@@ -275,7 +275,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
// Session commands
|
||||
CommandInfo {
|
||||
name: "rename",
|
||||
aliases: &[],
|
||||
aliases: &["gaiming", "chongmingming"],
|
||||
usage: "/rename <new title>",
|
||||
description_id: MessageId::CmdRenameDescription,
|
||||
},
|
||||
@@ -293,13 +293,13 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "load",
|
||||
aliases: &[],
|
||||
aliases: &["jiazai"],
|
||||
usage: "/load [path]",
|
||||
description_id: MessageId::CmdLoadDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "compact",
|
||||
aliases: &[],
|
||||
aliases: &["yasuo"],
|
||||
usage: "/compact",
|
||||
description_id: MessageId::CmdCompactDescription,
|
||||
},
|
||||
@@ -317,7 +317,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "cycles",
|
||||
aliases: &[],
|
||||
aliases: &["zhouqi"],
|
||||
usage: "/cycles",
|
||||
description_id: MessageId::CmdCyclesDescription,
|
||||
},
|
||||
@@ -335,7 +335,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "export",
|
||||
aliases: &[],
|
||||
aliases: &["daochu"],
|
||||
usage: "/export [path]",
|
||||
description_id: MessageId::CmdExportDescription,
|
||||
},
|
||||
@@ -348,7 +348,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "mode",
|
||||
aliases: &[],
|
||||
aliases: &["jihua", "zidong"],
|
||||
usage: "/mode [agent|plan|yolo|1|2|3]",
|
||||
description_id: MessageId::CmdModeDescription,
|
||||
},
|
||||
@@ -366,7 +366,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "trust",
|
||||
aliases: &[],
|
||||
aliases: &["xinren"],
|
||||
usage: "/trust [on|off|add <path>|remove <path>|list]",
|
||||
description_id: MessageId::CmdTrustDescription,
|
||||
},
|
||||
@@ -391,7 +391,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "system",
|
||||
aliases: &[],
|
||||
aliases: &["xitong"],
|
||||
usage: "/system",
|
||||
description_id: MessageId::CmdSystemDescription,
|
||||
},
|
||||
@@ -421,7 +421,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "retry",
|
||||
aliases: &[],
|
||||
aliases: &["chongshi"],
|
||||
usage: "/retry",
|
||||
description_id: MessageId::CmdRetryDescription,
|
||||
},
|
||||
@@ -445,7 +445,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
},
|
||||
CommandInfo {
|
||||
name: "goal",
|
||||
aliases: &[],
|
||||
aliases: &["mubiao"],
|
||||
usage: "/goal [objective] [budget: N]",
|
||||
description_id: MessageId::CmdGoalDescription,
|
||||
},
|
||||
@@ -470,19 +470,19 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
// Skills commands
|
||||
CommandInfo {
|
||||
name: "skills",
|
||||
aliases: &[],
|
||||
aliases: &["jinengliebiao"],
|
||||
usage: "/skills [--remote|sync|<prefix>]",
|
||||
description_id: MessageId::CmdSkillsDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "skill",
|
||||
aliases: &[],
|
||||
aliases: &["jineng"],
|
||||
usage: "/skill <name|install <spec>|update <name>|uninstall <name>|trust <name>>",
|
||||
description_id: MessageId::CmdSkillDescription,
|
||||
},
|
||||
CommandInfo {
|
||||
name: "review",
|
||||
aliases: &[],
|
||||
aliases: &["shencha"],
|
||||
usage: "/review <target>",
|
||||
description_id: MessageId::CmdReviewDescription,
|
||||
},
|
||||
@@ -495,7 +495,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
// RLM command
|
||||
CommandInfo {
|
||||
name: "rlm",
|
||||
aliases: &["recursive"],
|
||||
aliases: &["recursive", "digui"],
|
||||
usage: "/rlm [N] <file_or_text>",
|
||||
description_id: MessageId::CmdRlmDescription,
|
||||
},
|
||||
@@ -509,7 +509,7 @@ pub const COMMANDS: &[CommandInfo] = &[
|
||||
// Profile switching (#390)
|
||||
CommandInfo {
|
||||
name: "profile",
|
||||
aliases: &[],
|
||||
aliases: &["dangan"],
|
||||
usage: "/profile <name>",
|
||||
description_id: MessageId::CmdHelpDescription, // reuse for now
|
||||
},
|
||||
@@ -537,40 +537,40 @@ pub fn execute(cmd: &str, app: &mut App) -> CommandResult {
|
||||
// Match command or alias
|
||||
match command {
|
||||
// Core commands
|
||||
"anchor" => anchor::anchor(app, arg),
|
||||
"help" | "?" => core::help(app, arg),
|
||||
"clear" => core::clear(app),
|
||||
"exit" | "quit" | "q" => core::exit(),
|
||||
"model" => core::model(app, arg),
|
||||
"models" => core::models(app),
|
||||
"anchor" | "maodian" => anchor::anchor(app, arg),
|
||||
"help" | "?" | "bangzhu" | "帮助" => core::help(app, arg),
|
||||
"clear" | "qingping" => core::clear(app),
|
||||
"exit" | "quit" | "q" | "tuichu" => core::exit(),
|
||||
"model" | "moxing" => core::model(app, arg),
|
||||
"models" | "moxingliebiao" => core::models(app),
|
||||
"provider" => provider::provider(app, arg),
|
||||
"queue" | "queued" => queue::queue(app, arg),
|
||||
"stash" | "park" => stash::stash(app, arg),
|
||||
"hooks" | "hook" => hooks::hooks(app, arg),
|
||||
"subagents" | "agents" => core::subagents(app),
|
||||
"agent" => agent(app, arg),
|
||||
"links" | "dashboard" | "api" => core::deepseek_links(app),
|
||||
"hooks" | "hook" | "gouzi" => hooks::hooks(app, arg),
|
||||
"subagents" | "agents" | "zhinengti" => core::subagents(app),
|
||||
"agent" | "daili" => agent(app, arg),
|
||||
"links" | "dashboard" | "api" | "lianjie" => core::deepseek_links(app),
|
||||
"feedback" => feedback::feedback(app, arg),
|
||||
"home" | "stats" | "overview" => core::home_dashboard(app),
|
||||
"home" | "stats" | "overview" | "zhuye" | "shouye" => core::home_dashboard(app),
|
||||
"note" => note::note(app, arg),
|
||||
"memory" => memory::memory(app, arg),
|
||||
"attach" | "image" | "media" => attachment::attach(app, arg),
|
||||
"attach" | "image" | "media" | "fujian" => attachment::attach(app, arg),
|
||||
"task" | "tasks" => task::task(app, arg),
|
||||
"jobs" | "job" => jobs::jobs(app, arg),
|
||||
"jobs" | "job" | "zuoye" => jobs::jobs(app, arg),
|
||||
"mcp" => mcp::mcp(app, arg),
|
||||
"network" => network::network(app, arg),
|
||||
|
||||
// Session commands
|
||||
"rename" => rename::rename(app, arg),
|
||||
"rename" | "gaiming" | "chongmingming" => rename::rename(app, arg),
|
||||
"save" => session::save(app, arg),
|
||||
"sessions" | "resume" => session::sessions(app, arg),
|
||||
"load" => session::load(app, arg),
|
||||
"compact" => session::compact(app),
|
||||
"relay" | "batonpass" | "接力" => relay(app, arg),
|
||||
"cycles" => cycle::list_cycles(app),
|
||||
"load" | "jiazai" => session::load(app, arg),
|
||||
"compact" | "yasuo" => session::compact(app),
|
||||
"cycles" | "zhouqi" => cycle::list_cycles(app),
|
||||
"cycle" => cycle::show_cycle(app, arg),
|
||||
"recall" => cycle::recall_archive(app, arg),
|
||||
"export" => session::export(app, arg),
|
||||
"export" | "daochu" => session::export(app, arg),
|
||||
|
||||
// Config commands
|
||||
"config" => config::config_command(app, arg),
|
||||
@@ -578,9 +578,11 @@ pub fn execute(cmd: &str, app: &mut App) -> CommandResult {
|
||||
"status" => status::status(app),
|
||||
"statusline" => config::status_line(app),
|
||||
"mode" => config::mode(app, arg),
|
||||
"jihua" => config::mode(app, Some("plan")),
|
||||
"zidong" => config::mode(app, Some("yolo")),
|
||||
"theme" => config::theme(app, arg),
|
||||
"verbose" => config::verbose(app, arg),
|
||||
"trust" => config::trust(app, arg),
|
||||
"trust" | "xinren" => config::trust(app, arg),
|
||||
"logout" => config::logout(app),
|
||||
|
||||
// Debug commands
|
||||
@@ -591,7 +593,7 @@ pub fn execute(cmd: &str, app: &mut App) -> CommandResult {
|
||||
|
||||
// ChangeLog command
|
||||
"change" => change::change(app, arg),
|
||||
"system" => debug::system_prompt(app),
|
||||
"system" | "xitong" => debug::system_prompt(app),
|
||||
"context" | "ctx" => debug::context(app),
|
||||
"edit" => debug::edit(app),
|
||||
"diff" => debug::diff(app),
|
||||
@@ -610,25 +612,25 @@ pub fn execute(cmd: &str, app: &mut App) -> CommandResult {
|
||||
result
|
||||
}
|
||||
}
|
||||
"retry" => debug::retry(app),
|
||||
"retry" | "chongshi" => debug::retry(app),
|
||||
|
||||
// Project commands
|
||||
"init" => init::init(app),
|
||||
"lsp" => config::lsp_command(app, arg),
|
||||
"share" => share::share(app, arg),
|
||||
"goal" => goal::goal(app, arg),
|
||||
"goal" | "mubiao" => goal::goal(app, arg),
|
||||
|
||||
// Skills commands
|
||||
"skills" => skills::list_skills(app, arg),
|
||||
"skill" => skills::run_skill(app, arg),
|
||||
"review" => review::review(app, arg),
|
||||
"skill" | "jineng" => skills::run_skill(app, arg),
|
||||
"review" | "shencha" => review::review(app, arg),
|
||||
"restore" => restore::restore(app, arg),
|
||||
|
||||
// Profile switch (#390)
|
||||
"profile" => core::profile_switch(app, arg),
|
||||
"profile" | "dangan" => core::profile_switch(app, arg),
|
||||
|
||||
// RLM command
|
||||
"rlm" | "recursive" => rlm(app, arg),
|
||||
"rlm" | "recursive" | "digui" => rlm(app, arg),
|
||||
|
||||
// Legacy command migrations (kept out of registry/autocomplete intentionally).
|
||||
"set" => CommandResult::error(
|
||||
@@ -1096,7 +1098,7 @@ mod tests {
|
||||
.iter()
|
||||
.find(|cmd| cmd.name == "links")
|
||||
.expect("links command should exist");
|
||||
assert_eq!(links.aliases, &["dashboard", "api"]);
|
||||
assert_eq!(links.aliases, &["dashboard", "api", "lianjie"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1281,7 +1283,7 @@ mod tests {
|
||||
#[test]
|
||||
fn execute_links_and_aliases_return_links_message() {
|
||||
let mut app = create_test_app();
|
||||
for cmd in ["/links", "/dashboard", "/api"] {
|
||||
for cmd in ["/links", "/dashboard", "/api", "/lianjie"] {
|
||||
let result = execute(cmd, &mut app);
|
||||
let msg = result.message.expect("links commands should return text");
|
||||
assert!(msg.contains("https://platform.deepseek.com"));
|
||||
|
||||
@@ -448,7 +448,7 @@ fn handle_command_deepseek(
|
||||
}
|
||||
|
||||
match trimmed {
|
||||
"/help" => {
|
||||
"/help" | "/?" | "/bangzhu" | "/帮助" => {
|
||||
print_help();
|
||||
}
|
||||
"/history" => {
|
||||
@@ -488,7 +488,7 @@ fn handle_command_official(
|
||||
}
|
||||
|
||||
match trimmed {
|
||||
"/help" => {
|
||||
"/help" | "/?" | "/bangzhu" | "/帮助" => {
|
||||
print_help();
|
||||
}
|
||||
"/history" => {
|
||||
@@ -668,6 +668,9 @@ fn create_editor() -> Result<Editor<CommandCompleter, DefaultHistory>> {
|
||||
let helper = CommandCompleter {
|
||||
commands: vec![
|
||||
"/help".to_string(),
|
||||
"/?".to_string(),
|
||||
"/bangzhu".to_string(),
|
||||
"/帮助".to_string(),
|
||||
"/clear".to_string(),
|
||||
"/history".to_string(),
|
||||
"/stats".to_string(),
|
||||
|
||||
@@ -2521,11 +2521,13 @@ fn apply_slash_menu_selection_appends_space_for_arg_commands() {
|
||||
name: "/model".to_string(),
|
||||
description: String::new(),
|
||||
is_skill: false,
|
||||
alias_hint: None,
|
||||
},
|
||||
crate::tui::widgets::SlashMenuEntry {
|
||||
name: "/settings".to_string(),
|
||||
description: String::new(),
|
||||
is_skill: false,
|
||||
alias_hint: None,
|
||||
},
|
||||
];
|
||||
app.slash_menu_selected = 0;
|
||||
@@ -2553,6 +2555,7 @@ fn apply_slash_menu_selection_uses_skill_command_form() {
|
||||
name: "/skill search-files".to_string(),
|
||||
description: "Search files".to_string(),
|
||||
is_skill: true,
|
||||
alias_hint: None,
|
||||
}];
|
||||
|
||||
assert!(apply_slash_menu_selection(&mut app, &entries, true));
|
||||
|
||||
@@ -846,8 +846,24 @@ impl Renderable for ComposerWidget<'_> {
|
||||
};
|
||||
let menu_bottom = (menu_top + menu_visible_rows).min(menu_total);
|
||||
|
||||
// Label column width for two-column layout (name + description)
|
||||
let label_width = 22.min(content_width.saturating_sub(4));
|
||||
// Label column width — grows to fit the widest visible name
|
||||
// (including alias hint like " or /bangzhu") but stays bounded.
|
||||
let label_width = self
|
||||
.slash_menu_entries
|
||||
.iter()
|
||||
.take(menu_bottom)
|
||||
.skip(menu_top)
|
||||
.map(|e| {
|
||||
if let Some(ref hint) = e.alias_hint {
|
||||
format!("{} or /{}", e.name, hint).width()
|
||||
} else {
|
||||
e.name.width()
|
||||
}
|
||||
})
|
||||
.max()
|
||||
.unwrap_or(22)
|
||||
.min(content_width.saturating_sub(4))
|
||||
.max(8);
|
||||
for (idx, entry) in self
|
||||
.slash_menu_entries
|
||||
.iter()
|
||||
@@ -881,12 +897,20 @@ impl Renderable for ComposerWidget<'_> {
|
||||
Style::default().fg(palette::TEXT_DIM)
|
||||
};
|
||||
|
||||
// Build display name: canonical name, with "or /alias" hint
|
||||
// when the user typed via a pinyin alias.
|
||||
let display_name = if let Some(ref hint) = entry.alias_hint {
|
||||
format!("{} or /{}", entry.name, hint)
|
||||
} else {
|
||||
entry.name.clone()
|
||||
};
|
||||
|
||||
let name_display = {
|
||||
let display_width: usize = entry.name.width();
|
||||
let display_width: usize = display_name.width();
|
||||
if display_width > label_width {
|
||||
let mut s = String::new();
|
||||
let mut w = 0;
|
||||
for ch in entry.name.chars() {
|
||||
for ch in display_name.chars() {
|
||||
let cw = ch.width().unwrap_or(0);
|
||||
if w + cw + 1 > label_width {
|
||||
break;
|
||||
@@ -902,7 +926,7 @@ impl Renderable for ComposerWidget<'_> {
|
||||
s
|
||||
} else {
|
||||
// pad to label_width display cols
|
||||
let mut s = entry.name.clone();
|
||||
let mut s = display_name;
|
||||
while s.width() < label_width {
|
||||
s.push(' ');
|
||||
}
|
||||
@@ -2010,6 +2034,9 @@ pub(crate) struct SlashMenuEntry {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub is_skill: bool,
|
||||
/// Matching pinyin/alias prefix hint, e.g. when user types `/bang` and
|
||||
/// the command `/help` matches via alias `bangzhu`.
|
||||
pub alias_hint: Option<String>,
|
||||
}
|
||||
|
||||
pub(crate) fn slash_completion_hints(
|
||||
@@ -2035,17 +2062,42 @@ pub(crate) fn slash_completion_hints(
|
||||
// built-in ones from the static registry and use a generic label for
|
||||
// user-defined commands.
|
||||
if completing_skill_arg.is_none() {
|
||||
let prefix_lower = prefix.to_ascii_lowercase();
|
||||
for name in commands::all_command_names_matching(prefix, workspace) {
|
||||
let command_key = name.trim_start_matches('/');
|
||||
let description = if let Some(info) = commands::get_command_info(command_key) {
|
||||
info.description_for(locale).to_string()
|
||||
let (description, alias_hint) = if let Some(info) = commands::get_command_info(command_key) {
|
||||
// Detect matching alias: if the user typed via pinyin rather
|
||||
// than the canonical name, record which alias matched.
|
||||
let hint = if !command_key.to_ascii_lowercase().starts_with(&prefix_lower) {
|
||||
info.aliases
|
||||
.iter()
|
||||
.find(|a| a.to_ascii_lowercase().starts_with(&prefix_lower))
|
||||
.map(|a| a.to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let desc = if info.aliases.is_empty() {
|
||||
info.description_for(locale).to_string()
|
||||
} else {
|
||||
format!(
|
||||
"{} (aliases: {})",
|
||||
info.description_for(locale),
|
||||
info.aliases
|
||||
.iter()
|
||||
.map(|a| format!("/{a}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
};
|
||||
(desc, hint)
|
||||
} else {
|
||||
String::from("User-defined command")
|
||||
(String::from("User-defined command"), None)
|
||||
};
|
||||
entries.push(SlashMenuEntry {
|
||||
name,
|
||||
description,
|
||||
is_skill: false,
|
||||
alias_hint,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2062,6 +2114,7 @@ pub(crate) fn slash_completion_hints(
|
||||
name: format!("/skill {skill_name}"),
|
||||
description: skill_desc.clone(),
|
||||
is_skill: true,
|
||||
alias_hint: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2074,6 +2127,7 @@ pub(crate) fn slash_completion_hints(
|
||||
name: format!("/model {model_name}"),
|
||||
description: String::from("Switch to this model"),
|
||||
is_skill: false,
|
||||
alias_hint: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2639,12 +2693,14 @@ mod tests {
|
||||
name: format!("/skill{i}"),
|
||||
description: String::new(),
|
||||
is_skill: false,
|
||||
alias_hint: None,
|
||||
})
|
||||
.collect();
|
||||
let one_match = vec![SlashMenuEntry {
|
||||
name: "/skill".to_string(),
|
||||
description: String::new(),
|
||||
is_skill: false,
|
||||
alias_hint: None,
|
||||
}];
|
||||
let no_matches = Vec::<SlashMenuEntry>::new();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user