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
27 changes: 21 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,19 @@ to go.
## Quick start

```bash
# Register a prefix alias — `v <anything>` runs `vite <anything>`.
# Prefix alias — `v <anything>` runs `vite <anything>`.
relay add v vite

# Register an exact alias — `vd` always runs `vite dev`, no arguments.
# Prefix alias with default args — `gt <anything>` runs `git clone <anything>`.
relay add gt git -p clone

# Exact alias — `vd` always runs `vite dev`, no arguments accepted.
relay add vd vite dev

# Use them.
v dev # → vite dev
v build # → vite build
gt https://example.com/repo.git # → git clone https://example.com/repo.git
vd # → vite dev

# Inspect.
Expand Down Expand Up @@ -139,16 +143,26 @@ v build # → vite build
v --help # → vite --help
```

You can also register a prefix alias **with default arguments** using `--prefix` / `-p`.
The default args are always included, and any extra runtime args are appended after them:

```bash
relay add gt git -p clone
gt https://example.com/repo.git # → git clone https://example.com/repo.git
gt --depth 1 https://example.com/repo.git # → git clone --depth 1 https://example.com/repo.git
```

### Exact alias

`relay add <name> <program> <args...>` — the arguments are baked in; runtime args are ignored.
`relay add <name> <program> <args...>` (without `--prefix`) — the arguments are baked in; runtime args are rejected.

```bash
relay add vd vite dev
vd # → vite dev (always)
vd preview # → error: exact command does not accept extra arguments
```

Use **prefix** for tools you call with many subcommands (`v`, `g`, `n`). Use **exact** for one-liners you run all the time (`vd`, `gp`, `nci`).
Use **prefix** for tools you call with many subcommands (`v`, `g`, `n`). Use **prefix with args** when the command itself has a fixed subcommand but you want to pass extra flags (`gt` for `git clone`). Use **exact** for one-liners you run all the time with no variation (`vd`, `gp`, `nci`).

### Snippet

Expand Down Expand Up @@ -177,9 +191,10 @@ relay snippet run goback --dry-run
| Command | Description |
|---|---|
| `relay init` | Create `~/.relay`, write empty config, add `~/.relay/bin` to PATH |
| `relay add <name> <program> [args...]` | Register an alias (prefix if no args, exact otherwise) |
| `relay add <name> <program> [args...]` | Register an alias (prefix if no args or `--prefix`, exact otherwise) |
| `relay add <name> <program> -p [args...]` | Register a prefix alias with default args (runtime args appended) |
| `relay remove <name>` (alias: `rm`) | Delete an alias |
| `relay update <name> <program> [args...]` | Replace an existing alias |
| `relay update <name> <program> [args...]` | Replace an existing alias (accepts `--prefix` / `-p`) |
| `relay list` (alias: `ls`) | List all aliases by name |
| `relay info <name>` | Show details for one alias |
| `relay clear` (alias: `cls`) | Remove every alias (asks for confirmation) |
Expand Down
25 changes: 20 additions & 5 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,16 @@ npm 会通过 optionalDependencies 自动下载当前平台的二进制(`linux
# Prefix 简写 —— `v <任何参数>` 等价于 `vite <任何参数>`
relay add v vite

# Exact 简写 —— `vd` 永远执行 `vite dev`,不接受任何额外参数
# Prefix 简写带默认参数 —— `gt <参数>` 等价于 `git clone <参数>`,运行时参数会追加
relay add gt git -p clone

# Exact 简写 —— `vd` 永远执行 `vite dev`,不接受额外参数
relay add vd vite dev

# 使用
v dev # → vite dev
v build # → vite build
gt https://xxx/repo.git # → git clone https://xxx/repo.git
vd # → vite dev

# 查询
Expand Down Expand Up @@ -133,16 +137,26 @@ v build # → vite build
v --help # → vite --help
```

你也可以通过 `--prefix` / `-p` 注册**带默认参数**的 Prefix 简写。
默认参数始终包含在内,运行时输入的额外参数会追加到后面:

```bash
relay add gt git -p clone
gt https://example.com/repo.git # → git clone https://example.com/repo.git
gt --depth 1 https://example.com/repo.git # → git clone --depth 1 https://example.com/repo.git
```

### Exact 简写

`relay add <name> <program> <args...>` —— 参数被固化,运行时输入的参数会被忽略
`relay add <name> <program> <args...>`(不加 `--prefix`)—— 参数被固化,返回值输入的任何额外参数都会被拒绝

```bash
relay add vd vite dev
vd # → vite dev(永远)
vd preview # → 报错:exact command does not accept extra arguments
```

**Prefix** 适合你经常用多个子命令的工具(`v`、`g`、`n`);**Exact** 适合你天天敲的高频组合(`vd`、`gp`、`nci`)。
**Prefix** 适合你经常用多个子命令的工具(`v`、`g`、`n`);**Prefix 带参数** 适合命令本身包含固定子命令但你仍需要传递额外参数(如 `gt` 对应 `git clone`);**Exact** 适合你天天敲的高频组合(`vd`、`gp`、`nci`)。

### Snippet(Shell 片段)

Expand Down Expand Up @@ -171,9 +185,10 @@ relay snippet run goback --dry-run
| 命令 | 说明 |
|---|---|
| `relay init` | 创建 `~/.relay`,写入空 config,并把 `~/.relay/bin` 加入 PATH |
| `relay add <name> <program> [args...]` | 注册简写(无参数为 prefix,有参数为 exact) |
| `relay add <name> <program> [args...]` | 注册简写(无参数或带 `-p` 为 prefix,否则为 exact) |
| `relay add <name> <program> -p [args...]` | 注册带默认参数的 prefix 简写(运行时参数会追加) |
| `relay remove <name>`(别名 `rm`) | 删除简写 |
| `relay update <name> <program> [args...]` | 修改已有的简写 |
| `relay update <name> <program> [args...]` | 修改已有的简写(支持 `--prefix` / `-p`) |
| `relay list`(别名 `ls`) | 列出所有简写(按名字排序) |
| `relay info <name>` | 查看单个简写的详情 |
| `relay clear`(别名 `cls`) | 删除所有简写(会先确认) |
Expand Down
17 changes: 14 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ pub enum Command {
name: String,
/// The target program (e.g. `vite`).
program: String,
/// Optional fixed arguments — supplying any makes this an `exact` command.
/// Force prefix mode — extra args are always appended at runtime,
/// even when fixed arguments are supplied.
#[arg(long, short)]
prefix: bool,
/// Optional fixed arguments — supplying any without `--prefix` makes
/// this an `exact` command.
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
Expand All @@ -52,6 +57,10 @@ pub enum Command {
Update {
name: String,
program: String,
/// Force prefix mode — extra args are always appended at runtime,
/// even when fixed arguments are supplied.
#[arg(long, short)]
prefix: bool,
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
Expand Down Expand Up @@ -262,14 +271,16 @@ fn dispatch_with_root(command: Command, root: Option<std::path::PathBuf>) -> Res
Command::Add {
name,
program,
prefix,
args,
} => registry::add(&paths, name, program, args)?,
} => registry::add(&paths, name, program, args, *prefix)?,
Command::Remove { name } => registry::remove(&paths, name)?,
Command::Update {
name,
program,
prefix,
args,
} => registry::update(&paths, name, program, args)?,
} => registry::update(&paths, name, program, args, *prefix)?,
Command::List => registry::list(&paths)?,
Command::Info { name } => registry::info(&paths, name)?,
Command::Discover { program } => discover::run(&paths, program.as_deref())?,
Expand Down
8 changes: 4 additions & 4 deletions src/registry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fn is_default_root(paths: &Paths) -> bool {
}

/// `relay add` — register a new command.
pub fn add(paths: &Paths, name: &str, program: &str, args: &[String]) -> Result<()> {
pub fn add(paths: &Paths, name: &str, program: &str, args: &[String], prefix: bool) -> Result<()> {
validate_name(name)?;
// validate_program returns the normalized form (e.g. `.exe` stripped).
let program = validate_program(program)?;
Expand All @@ -88,7 +88,7 @@ pub fn add(paths: &Paths, name: &str, program: &str, args: &[String]) -> Result<
return Err(RelayError::SnippetNameConflict(name.to_string()));
}

let kind = if args.is_empty() {
let kind = if prefix || args.is_empty() {
CommandKind::Prefix
} else {
CommandKind::Exact
Expand Down Expand Up @@ -156,7 +156,7 @@ pub fn clear(paths: &Paths, auto_yes: bool) -> Result<()> {
}

/// `relay update` — replace an existing command's program/args.
pub fn update(paths: &Paths, name: &str, program: &str, args: &[String]) -> Result<()> {
pub fn update(paths: &Paths, name: &str, program: &str, args: &[String], prefix: bool) -> Result<()> {
let program = validate_program(program)?;
let mut config = config::load(paths)?;
let entry = config
Expand All @@ -165,7 +165,7 @@ pub fn update(paths: &Paths, name: &str, program: &str, args: &[String]) -> Resu
.ok_or_else(|| RelayError::UnknownCommand(name.to_string()))?;
entry.program = program.clone();
entry.args = args.to_vec();
entry.kind = if args.is_empty() {
entry.kind = if prefix || args.is_empty() {
CommandKind::Prefix
} else {
CommandKind::Exact
Expand Down
Loading