stract

package
v2.0.0-...-6ba723b Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2025 License: MIT Imports: 5 Imported by: 0

README

stract Library

The stract library provides a parser for structured text files with variable substitution and hierarchical contexts. It's designed for parsing configuration files, templates, or any text with a specific structure and variable references.

Installation

import "github.com/getevo/evo/v2/lib/stract"

Features

  • Structured Text Parsing: Parse text files with a specific syntax
  • Variable Substitution: Replace variables using ${variable} syntax
  • Hierarchical Contexts: Support for nested contexts with scoped variables
  • File Imports: Import other files with @import directive
  • Rich Query API: Methods for querying and manipulating the parsed context
  • Pattern Matching: Check variables against patterns, prefixes, suffixes, etc.

Usage Examples

Basic Parsing
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/stract"
)

func main() {
    // Parse a file
    context, err := stract.OpenAndParse("config.txt")
    if err != nil {
        fmt.Printf("Error parsing file: %v\n", err)
        return
    }
    
    // Access variables
    exists, values := context.Get("database_host")
    if exists {
        fmt.Printf("Database host: %s\n", values[0])
    }
    
    // Get a single value
    port := context.GetSingleValue("database_port")
    fmt.Printf("Database port: %s\n", port)
    
    // Check if a variable has a specific value
    if context.VaryDictHas("environment", "production") {
        fmt.Println("Running in production mode")
    }
    
    // Print the entire context structure
    fmt.Println(stract.PrettyStruct(context))
}
Working with Hierarchical Contexts
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/stract"
)

func main() {
    // Parse a file with nested contexts
    context, err := stract.OpenAndParse("config.txt")
    if err != nil {
        fmt.Printf("Error parsing file: %v\n", err)
        return
    }
    
    // Access a child context
    exists, dbContext := context.GetChild("database")
    if exists {
        // Access variables in the child context
        host := dbContext.GetSingleValue("host")
        port := dbContext.GetSingleValue("port")
        user := dbContext.GetSingleValue("username")
        pass := dbContext.GetSingleValue("password")
        
        fmt.Printf("Database connection: %s:%s@%s:%s\n", user, pass, host, port)
    }
    
    // Iterate through all children
    for _, child := range context.GetChildren() {
        fmt.Printf("Child context: %s\n", child.Name)
        
        // Print all variables in this context
        for _, vary := range child.GetVaryDicts() {
            fmt.Printf("  %s = %v\n", vary.Key, vary.Values)
        }
    }
}
Pattern Matching with Variables
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/stract"
    "regexp"
)

func main() {
    // Parse a file
    context, err := stract.OpenAndParse("config.txt")
    if err != nil {
        fmt.Printf("Error parsing file: %v\n", err)
        return
    }
    
    // Check if a variable contains a substring
    hasLog, logPath := context.VaryDictContains("paths", "logs")
    if hasLog {
        fmt.Printf("Log path found: %s\n", logPath)
    }
    
    // Check if a variable starts with a prefix
    hasTemp, tempPath := context.VaryDictStartsWith("paths", "/tmp")
    if hasTemp {
        fmt.Printf("Temporary path found: %s\n", tempPath)
    }
    
    // Check if a variable ends with a suffix
    hasConfig, configPath := context.VaryDictEndsWith("paths", ".conf")
    if hasConfig {
        fmt.Printf("Config path found: %s\n", configPath)
    }
    
    // Match a variable against a regular expression
    ipRegex := regexp.MustCompile(`^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$`)
    hasIP, matches := context.VaryDictMatch("allowed_ips", ipRegex)
    if hasIP {
        for _, match := range matches {
            fmt.Printf("IP address found: %s\n", match[0])
        }
    }
}
Parsing Variables from Strings
package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/stract"
)

func main() {
    // Parse a variable from a string
    value := stract.ParseVar("timeout:30", "timeout")
    fmt.Printf("Timeout value: %s\n", value) // Output: 30
    
    value = stract.ParseVar("retry(3)", "retry")
    fmt.Printf("Retry value: %s\n", value) // Output: 3
    
    // No match
    value = stract.ParseVar("unknown:value", "timeout")
    fmt.Printf("Value: %s\n", value) // Output: empty string
}

Example Input File Format

The stract library can parse files with the following format:

# This is a comment

# Simple key-value pairs
database_host localhost
database_port 5432
database_user admin
database_pass secret

# Multiple values for a key
allowed_ips 192.168.1.1 192.168.1.2 10.0.0.1

# Variable substitution
server_url http://${database_host}:8080

# Nested context
database {
    host localhost
    port 5432
    username admin
    password secret
}

# Importing another file
@import common.txt

How It Works

The stract library parses text files into a hierarchical context structure. The parsing process involves:

  1. Tokenizing the input text, handling special characters and quoted strings
  2. Building a context tree with variables and nested contexts
  3. Resolving variable references using the ${variable} syntax
  4. Processing import directives to include other files

The resulting context structure can be queried using various methods:

  • Get(): Get all values for a variable
  • GetSingleValue(): Get the first value of a variable
  • GetChild(): Get a child context by name
  • VaryDictHas(): Check if a variable has a specific value
  • VaryDictContains(): Check if a variable contains a substring
  • VaryDictStartsWith(): Check if a variable starts with a prefix
  • VaryDictEndsWith(): Check if a variable ends with a suffix
  • VaryDictMatch(): Match a variable against a regular expression

The library is particularly useful for parsing configuration files, templates, or any text with a specific structure and variable references.

For more detailed information, please refer to the source code and comments within the library.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseVar

func ParseVar(input string, key string) string

func PrettyStruct

func PrettyStruct(data any) string

Types

type Context

type Context struct {
	Parent   *Context   `json:"-"`
	Children []*Context `json:"children"`
	Name     string     `json:"name"`
	VaryDict []VaryDict `json:"vary_dict"`
}

func OpenAndParse

func OpenAndParse(path string) (*Context, error)

func (*Context) Get

func (c *Context) Get(s string) (bool, []string)

func (*Context) GetChild

func (ctx *Context) GetChild(name string) (bool, *Context)

func (*Context) GetChildren

func (ctx *Context) GetChildren() []*Context

func (*Context) GetSingleValue

func (c *Context) GetSingleValue(s string) string

func (*Context) GetVaryDict

func (ctx *Context) GetVaryDict(name string) (bool, []string)

func (*Context) GetVaryDicts

func (ctx *Context) GetVaryDicts() []VaryDict

func (*Context) VaryDictContains

func (ctx *Context) VaryDictContains(name string, value string) (bool, string)

func (*Context) VaryDictEndsWith

func (ctx *Context) VaryDictEndsWith(name string, value string) (bool, string)

func (*Context) VaryDictHas

func (ctx *Context) VaryDictHas(name string, value string) bool

func (*Context) VaryDictMatch

func (ctx *Context) VaryDictMatch(name string, regex *regexp.Regexp) (bool, [][]string)

func (*Context) VaryDictStartsWith

func (ctx *Context) VaryDictStartsWith(name string, value string) (bool, string)

type Token

type Token struct {
	Value string
	Pos   int
}

type VaryDict

type VaryDict struct {
	Key    string
	Values []string
}

func (*VaryDict) VaryDictContains

func (vary *VaryDict) VaryDictContains(value string) (bool, string)

func (VaryDict) VaryDictEndsWith

func (vary VaryDict) VaryDictEndsWith(value string) (bool, string)

func (*VaryDict) VaryDictGetVar

func (vary *VaryDict) VaryDictGetVar(value string) string

func (*VaryDict) VaryDictHas

func (vary *VaryDict) VaryDictHas(value string) bool

func (*VaryDict) VaryDictMatch

func (vary *VaryDict) VaryDictMatch(regex *regexp.Regexp) (bool, [][]string)

func (*VaryDict) VaryDictStartsWith

func (vary *VaryDict) VaryDictStartsWith(value string) (bool, string)

Jump to

Keyboard shortcuts

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