Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions crates/modalkit/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ impl<C: Command> CommandMachine<C> {
self.names.insert(cmd.name(), cmd);
}

/// Map a new alias to an existing command.
pub fn add_alias(&mut self, alias: &str, cmd: &str) -> Result<(), CommandError> {
let c = self.get(cmd)?;
self.aliases.insert(alias.to_owned(), c.clone());
Ok(())
}

/// Generate a list of completion candidates for command names.
pub fn complete_name(&self, prefix: &str) -> Vec<String> {
completion_keys(&self.names, prefix)
Expand All @@ -123,11 +130,16 @@ impl<C: Command> CommandMachine<C> {
completion_keys(&self.aliases, prefix)
}

/// Get the previously executed command.
/// Get the specified command by alias or name.
///
/// Aliases are checked first, so that [Command::add_alias] overrides can take precedence,
/// and then the actual command names.
///
/// This returns [CommandError::InvalidCommand] if there is nothing mapped.
pub fn get(&self, name: &str) -> Result<&C, CommandError> {
if let Some(m) = self.names.get(name) {
if let Some(m) = self.aliases.get(name) {
Ok(m)
} else if let Some(m) = self.aliases.get(name) {
} else if let Some(m) = self.names.get(name) {
Ok(m)
} else {
Err(CommandError::InvalidCommand(name.into()))
Expand Down
25 changes: 25 additions & 0 deletions crates/modalkit/src/env/vim/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,31 @@ mod tests {
assert_eq!(res.unwrap(), vec![(act.clone(), ctx.clone())]);
}

#[test]
fn test_alias_overrides() {
let (mut cmds, ctx) = mkcmd();

let exp = vec![(
WindowAction::Split(OpenTarget::Current, Horizontal, Previous, 1.into()).into(),
ctx.clone(),
)];

// Can overwrite an existing command name ("read") to instead map to an already
// existing alias name ("sp"):
cmds.add_alias("read", "sp").unwrap();
let res = cmds.input_cmd("read", ctx.clone());
assert_eq!(res.unwrap(), exp);

// Can overwrite an existing alias with another command name:
cmds.add_alias("r", "split").unwrap();
let res = cmds.input_cmd("r", ctx.clone());
assert_eq!(res.unwrap(), exp);

// Fails if the target command doesn't exist:
let res = cmds.add_alias("q", "foobar");
assert!(res.is_err());
}

#[test]
fn test_split_direction() {
let (mut cmds, ctx) = mkcmd();
Expand Down
Loading