taskparser

package
v0.0.34 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 26, 2025 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// ArgumentsKey is the key used to store positional arguments in Params
	ArgumentsKey = "ARGUMENTS"
)

Variables

View Source
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

func ValidatePath(path string) error

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

func (Argument) String

func (a Argument) String() string

String returns the original text representation of an argument

type Block

type Block struct {
	SlashCommand *SlashCommand `parser:"@@"`
	Text         *Text         `parser:"| @@"`
}

Block represents either a slash command or text content

func (Block) String

func (b Block) String() string

String returns the original text representation of a block

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

type Params map[string][]string

Params is a map of string keys to string slice values with convenience methods for accessing single and multiple values.

func ParseParams

func ParseParams(value string) (Params, error)

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

func (p Params) Arguments() []string

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

func (p Params) Expand(content string) (string, error)

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}).

func (Params) Lookup

func (p Params) Lookup(key string) (string, bool)

func (Params) Set

func (p Params) Set(value string) error

func (Params) String

func (p Params) String() string

func (Params) Value

func (p Params) Value(key string) string

Value returns the first value for the given key, or an empty string if the key is not found or has no values.

func (Params) Values

func (p Params) Values(key string) []string

Values returns all values for the given key, or an empty slice if the key is not found.

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 Separator

type Separator struct {
	Pos lexer.Position
	Val string `parser:"(@Whitespace | @Comma)"`
}

Separator represents whitespace or comma separators

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

func ParseTask(text string) (Task, error)

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)

func (Task) String

func (t Task) String() string

String returns the original text representation of a task

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)

func (*Text) Content

func (t *Text) Content() string

Content returns the text content with all lines concatenated

func (Text) String

func (t Text) String() string

String returns the original text representation of text

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

type Value

type Value struct {
	Pos lexer.Position
	Raw string `parser:"(@QuotedDouble | @QuotedSingle | @Token)"`
}

Value represents a parsed value (quoted or unquoted) The Raw field captures the entire token including quotes and escapes

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL