Documentation
¶
Index ¶
Constants ¶
const (
// ArgumentsKey is the key used to store positional arguments in Params
ArgumentsKey = "ARGUMENTS"
)
Variables ¶
var ( // ErrEmptyKey is returned when a parameter key is empty ErrEmptyKey = errors.New("empty key in parameter") // ErrInvalidEscapeSequence is returned when an escape sequence is invalid ErrInvalidEscapeSequence = errors.New("invalid escape sequence") // ErrInvalidFormat is returned when the input format is invalid ErrInvalidFormat = errors.New("invalid parameter format: missing '='") // ErrMismatchedQuotes is returned when quotes don't match ErrMismatchedQuotes = errors.New("mismatched quote types") // ErrUnclosedQuote is returned when a quoted string is not properly closed ErrUnclosedQuote = errors.New("unclosed quote") )
Functions ¶
func ValidatePath ¶
ValidatePath validates a file path for basic safety checks. Note: This tool is designed to work with user-created markdown files in their workspace and grants read access to files the user can read. The primary defense is that users should only use trusted markdown files.
Types ¶
type Argument ¶
type Argument struct {
Key string `parser:"(@Term Assign)?"`
Value string `parser:"(@String | @Term)"`
}
Argument represents either a named (key=value) or positional argument
type Block ¶
type Block struct {
SlashCommand *SlashCommand `parser:"@@"`
Text *Text `parser:"| @@"`
}
Block represents either a slash command or text content
type Input ¶
type Input struct {
Blocks []Block `parser:"@@*"`
}
Input is the top-level wrapper for parsing
type NamedParam ¶
type NamedParam struct {
Pos lexer.Position
Key string `parser:"@Token"`
PreEqualsSpace *string `parser:"Whitespace?"`
Equals string `parser:"@Assign"`
PostEqualsSpace *string `parser:"Whitespace?"`
Value *Value `parser:"@@?"` // Optional to handle empty values like key=
}
NamedParam represents a key=value pair
type Params ¶
Params is a map of string keys to string slice values with convenience methods for accessing single and multiple values.
func ParseParams ¶
ParseParams parses a parameter string into a Params map that supports both named parameters (key-value pairs) and positional arguments.
The function provides a flexible, permissive parser that handles various quoting styles, escape sequences, and separators.
Named Parameters:
Basic syntax: key=value Multiple pairs can be separated by commas, spaces, or both Whitespace around the = sign is optional Keys are case-insensitive (converted to lowercase) The same key can appear multiple times; all values are collected Examples: "key=value" "key=value,foo=bar" "key = value, foo = bar" "key=value1 key=value2 key=value3" // Multiple values for same key
Positional Arguments:
Values without a key are treated as positional arguments and stored
under the ArgumentsKey constant ("ARGUMENTS").
Positional and named parameters can be interleaved.
Examples:
"value"
"value1 value2 value3"
"value1, value2, value3"
"key=value positional1 positional2"
"positional1 key=value positional2"
Quoted Values:
Both single and double quotes are supported for values containing special characters. Quotes can be escaped within matching quote types. Empty quoted values create a value with an empty string. Examples: `key="string value"` `key='string value'` `key="value=with=equals"` `key="value,with,commas"` `key="bar\"baz\""` // Escaped quotes
Unquoted Values:
Unquoted values cannot contain spaces (spaces separate arguments). Values containing =, ,, or spaces should be quoted. Trailing whitespace is trimmed from unquoted values.
Escape Sequences:
Escape sequences work in both quoted and unquoted contexts:
Standard: \n (newline), \t (tab), \r (carriage return), \\
(backslash), \" (double quote), \' (single quote)
Numeric: \xHH (hex), \uHHHH (Unicode), \OOO (octal, 1-3 digits)
Other: Any other escape returns the character after backslash
Examples:
`key="line1\nline2\ttabbed"`
`key="\x41\x42"` // "AB"
`key="\u00a0"` // Non-breaking space
Separators:
Multiple separators are supported: commas, spaces, or both. Trailing separators are ignored. Examples: "key=value,foo=bar" "key=value foo=bar" "key=value, foo=bar, baz=qux"
Empty Values:
Unquoted empty: key= creates an empty slice []string{}
Quoted empty: key="" or key='' creates []string{""}
Unicode Support:
Full Unicode and UTF-8 support for keys and values. Unicode whitespace is recognized as separators. All unicode whitespace is automatically trimmed from start/end of values. Examples: "ключ=значение" "key=こんにちは" "emoji=🚀"
Error Conditions:
Returns errors for: - Unclosed quotes: key="unclosed - Empty keys: =value - Invalid escape sequences: incomplete or invalid hex/unicode escapes - Mismatched quotes: key='value" or key="value'
Return Value:
The returned Params map has:
- Named parameters: lowercase keys with string slice values
- Positional arguments: stored under ArgumentsKey ("ARGUMENTS")
Example:
params, _ := ParseParams("key=value1 key=value2 arg1 arg2")
// params["key"] = []string{"value1", "value2"}
// params[ArgumentsKey] = []string{"arg1", "arg2"}
See the Params type methods (Value, Values, Arguments, Lookup) for convenient access to parsed parameters.
func (Params) Arguments ¶
Arguments returns all positional arguments (values without keys), or an empty slice if there are no positional arguments. This is distinct from named parameters accessed via Value() or Values().
func (Params) Expand ¶
expand performs all types of expansion on the content in a single pass: 1. Parameter expansion: ${param_name} 2. Command expansion: !`command` 3. Path expansion: @path SECURITY: Processes rune-by-rune to prevent injection attacks where expanded content contains further expansion sequences (e.g., command output with ${param}).
type ParamsInput ¶
type ParamsInput struct {
Items []ParamsItem `parser:"@@*"`
}
ParamsInput is the top-level structure for parsing parameters It now directly parses into named parameters and positional arguments
type ParamsItem ¶
type ParamsItem struct {
Pos lexer.Position
Separator *Separator `parser:"@@"` // Whitespace or comma
Named *NamedParam `parser:"| @@"` // key=value
Positional *Value `parser:"| @@"` // standalone value
}
ParamsItem represents either a named parameter or a positional argument
type SlashCommand ¶
type SlashCommand struct {
LeadingWhitespace string `parser:"Whitespace?"`
Name string `parser:"Slash @Term"`
Arguments []Argument `parser:"(Whitespace @@)* Whitespace? Newline?"`
}
SlashCommand represents a command starting with "/" that ends with a newline or EOF The newline is optional to handle EOF, but when present, prevents matching inline slashes Leading whitespace is optional to allow indented commands
func (*SlashCommand) Params ¶
func (s *SlashCommand) Params() Params
Params converts the slash command's arguments into a parameter map using ParseParams. This provides a more permissive parser that supports commas, single quotes, and other features. Returns a map with: - "ARGUMENTS": positional arguments (values without keys) - named parameters: key-value pairs from key="value" or key='value' arguments
func (SlashCommand) String ¶
func (s SlashCommand) String() string
String returns the original text representation of a slash command
type Task ¶
type Task []Block
Task represents a parsed task, which is a sequence of blocks
func ParseTask ¶
ParseTask parses a task string into a structured Task representation. A task consists of alternating blocks of text content and slash commands (commands starting with /). The parser distinguishes between inline slashes (part of text) and command slashes (at the start of a line).
Task Structure:
A Task is a sequence of Block elements, where each block is either:
- A Text block: regular text content
- A SlashCommand block: a command starting with / at line start
(optional whitespace before / is allowed)
Command Detection:
Command: A / at the start of a line (after newline or at start of input) starts a command. Optional whitespace (spaces or tabs) before the / is allowed and preserved.
Text: A / not at the start of a line, or preceded by non-whitespace characters, is treated as regular text
Line boundaries: Newlines separate commands from text
Examples: "/fix-bug" // Command " /deploy" // Command (whitespace before slash allowed) "Some text /fix" // Text (slash not at line start) "text/deploy" // Text (non-whitespace before slash prevents command)
Command Arguments:
Commands can have: - Positional arguments: values without keys - Named arguments: key=value pairs - Quoted arguments: both single and double quotes supported - Mixed arguments: positional and named can be interleaved Examples: "/fix-bug 123 urgent" // Positional only "/deploy env=\"production\"" // Named only "/task arg1 key=\"value\" arg2" // Mixed "/deploy arg1 env=\"production\" arg2" // Positional before/after named Note: The argument parsing in ParseTask uses a simpler grammar than ParseParams. For more advanced parsing (commas, escape sequences, etc.), use the Params() method on SlashCommand.
Text Content:
Text blocks: - Preserve whitespace: all whitespace, including indentation - Can span multiple lines - No special processing: stored as-is Examples: "Line 1\n Indented line 2\nLine 3"
Task Composition:
Tasks can contain: - Only text: "This is a task with only text." - Only commands: "/command1\n/command2\n" - Mixed: "Introduction text\n/command1 arg1\nMiddle text\n/command2\n"
SlashCommand.Params() Method:
The SlashCommand type provides a Params() method that converts command
arguments to a Params map using ParseParams. This provides:
- Full ParseParams feature support (commas, escape sequences, etc.)
- Consistent API with ParseParams
- More permissive parsing than the initial grammar
Example:
task, _ := ParseTask("/deploy env=\"production\" region=\"us-east-1\"\n")
cmd := task[0].SlashCommand
params := cmd.Params()
// params["env"] = []string{"production"}
// params["region"] = []string{"us-east-1"}
Error Conditions:
The function rarely returns errors due to the permissive grammar. Potential errors include malformed input that cannot be tokenized.
Examples:
// Simple text task
task, _ := ParseTask("This is a simple text block.")
// task[0].Text.Content() == "This is a simple text block."
// Simple command
task, _ := ParseTask("/fix-bug\n")
// task[0].SlashCommand.Name == "fix-bug"
// Command with whitespace before slash (allowed)
task, _ := ParseTask(" /deploy env=\"production\"\n")
// task[0].SlashCommand.Name == "deploy"
// Command with positional arguments
task, _ := ParseTask("/fix-bug 123 urgent\n")
// task[0].SlashCommand.Arguments[0].Value == "123"
// Mixed content
task, _ := ParseTask("Introduction text\n/fix-bug 123\nSome text after")
// len(task) == 3 (text, command, text)
type Text ¶
type Text struct {
Lines []TextLine `parser:"@@+"`
}
Text represents a block of text It can span multiple lines, consuming line content and newlines But it will stop before a newline that's followed by a slash (potential command)
type TextLine ¶
type TextLine struct {
NonSlashStart []string `parser:"(@Term | @String | @Assign | @Whitespace)"` // First token can't be Slash
RestOfLine []string `parser:"(@Term | @String | @Slash | @Assign | @Whitespace)*"` // Rest can include Slash
NewlineOpt string `parser:"@Newline?"`
}
TextLine is a single line of text content (not starting with a slash) It matches tokens until the end of the line