feat: add positional argument support to slash commands (#3456)

Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
This commit is contained in:
rienkim
2025-10-30 04:54:24 +09:00
committed by GitHub
parent 972c0893dd
commit a9cae7b335
2 changed files with 52 additions and 1 deletions

View File

@@ -1504,6 +1504,9 @@ export namespace SessionPrompt {
}) })
export type CommandInput = z.infer<typeof CommandInput> export type CommandInput = z.infer<typeof CommandInput>
const bashRegex = /!`([^`]+)`/g const bashRegex = /!`([^`]+)`/g
const argsRegex = /(?:[^\s"']+|"[^"]*"|'[^']*')+/g
const placeholderRegex = /\$(\d+)/g
const quoteTrimRegex = /^["']|["']$/g
/** /**
* Regular expression to match @ file references in text * Regular expression to match @ file references in text
* Matches @ followed by file paths, excluding commas, periods at end of sentences, and backticks * Matches @ followed by file paths, excluding commas, periods at end of sentences, and backticks
@@ -1515,7 +1518,25 @@ export namespace SessionPrompt {
const command = await Command.get(input.command) const command = await Command.get(input.command)
const agentName = command.agent ?? input.agent ?? "build" const agentName = command.agent ?? input.agent ?? "build"
let template = command.template.replaceAll("$ARGUMENTS", input.arguments) const raw = input.arguments.match(argsRegex) ?? []
const args = raw.map((arg) => arg.replace(quoteTrimRegex, ""))
const placeholders = command.template.match(placeholderRegex) ?? []
let last = 0
for (const item of placeholders) {
const value = Number(item.slice(1))
if (value > last) last = value
}
// Let the final placeholder swallow any extra arguments so prompts read naturally
const withArgs = command.template.replaceAll(placeholderRegex, (_, index) => {
const position = Number(index)
const argIndex = position - 1
if (argIndex >= args.length) return ""
if (position === last) return args.slice(argIndex).join(" ")
return args[argIndex]
})
let template = withArgs.replaceAll("$ARGUMENTS", input.arguments)
const shell = ConfigMarkdown.shell(template) const shell = ConfigMarkdown.shell(template)
if (shell.length > 0) { if (shell.length > 0) {

View File

@@ -129,6 +129,36 @@ Run the command with arguments:
And `$ARGUMENTS` will be replaced with `Button`. And `$ARGUMENTS` will be replaced with `Button`.
You can also access individual arguments using positional parameters:
- `$1` - First argument
- `$2` - Second argument
- `$3` - Third argument
- And so on...
For example:
```md title=".opencode/command/create-file.md"
---
description: Create a new file with content
---
Create a file named $1 in the directory $2
with the following content: $3
```
Run the command:
```bash frame="none"
/create-file config.json src "{ \"key\": \"value\" }"
```
This replaces:
- `$1` with `config.json`
- `$2` with `src`
- `$3` with `{ "key": "value" }`
--- ---
### Shell output ### Shell output