replvar

package module
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Jan 3, 2026 License: MIT Imports: 8 Imported by: 0

README

GoDoc

replvar

A Go library for variable replacement and expression evaluation in strings. It parses template strings containing {{variable}} expressions and resolves them against a context, supporting arithmetic operations, logical operators, comparisons, and nested field access.

Installation

go get github.com/KarpelesLab/replvar

Features

  • Variable substitution with {{name}} syntax
  • Field/member access with dot notation: {{obj.field}}
  • Arithmetic operators: +, -, *, /, % (modulo)
  • Bitwise operators: |, &, ^, ~ (NOT), <<, >> (shifts)
  • Logical operators: ||, &&, !
  • Comparison operators: ==, !=, <, <=, >, >=
  • Proper operator precedence (e.g., 2 + 3 * 4 = 14)
  • String literals with single quotes, double quotes, or backticks
  • Escape sequences in double-quoted strings (\n, \t, \r, \v, \\)
  • JSON mode for automatic JSON encoding of embedded values
  • Static value optimization (compile once, resolve many times)

Usage

Basic Variable Replacement
package main

import (
    "context"
    "fmt"

    "github.com/KarpelesLab/replvar"
)

func main() {
    // Create a context with values
    ctx := context.Background()
    ctx = context.WithValue(ctx, "name", "World")

    // Replace variables in a string
    result, err := replvar.Replace(ctx, "Hello {{name}}!", "text")
    if err != nil {
        panic(err)
    }
    fmt.Println(result) // Output: Hello World!
}
Field Access
ctx := context.Background()
ctx = context.WithValue(ctx, "user", map[string]any{
    "name": "Alice",
    "age":  30,
})

result, _ := replvar.Replace(ctx, "Name: {{user.name}}, Age: {{user.age}}", "text")
fmt.Println(result) // Output: Name: Alice, Age: 30
Arithmetic Operations
ctx := context.Background()
ctx = context.WithValue(ctx, "price", 100)
ctx = context.WithValue(ctx, "quantity", 5)

result, _ := replvar.Replace(ctx, "Total: {{price * quantity}}", "text")
fmt.Println(result) // Output: Total: 500
Comparisons and Logic
ctx := context.Background()
ctx = context.WithValue(ctx, "score", 85)

result, _ := replvar.Replace(ctx, "Pass: {{score == 85}}", "text")
fmt.Println(result) // Output: Pass: 1

result, _ = replvar.Replace(ctx, "High: {{score != 0}}", "text")
fmt.Println(result) // Output: High: 0
Parse Once, Resolve Many

For better performance when resolving the same template multiple times:

// Parse the template once
template, err := replvar.ParseString("Hello {{name}}!", "text")
if err != nil {
    panic(err)
}

// Check if the template contains only static values
if template.IsStatic() {
    // No variables, result is constant
}

// Resolve with different contexts
ctx1 := context.WithValue(context.Background(), "name", "Alice")
ctx2 := context.WithValue(context.Background(), "name", "Bob")

result1, _ := template.Resolve(ctx1) // "Hello Alice!"
result2, _ := template.Resolve(ctx2) // "Hello Bob!"
JSON Mode

When using "json" mode, embedded variables are automatically JSON-encoded:

ctx := context.Background()
ctx = context.WithValue(ctx, "data", map[string]any{"key": "value"})

result, _ := replvar.Replace(ctx, `{"nested": {{data}}}`, "json")
// Output: {"nested": {"key":"value"}}
String Literals

Variables can contain string literals with different quote types:

// Single quotes - no escape processing
result, _ := replvar.Replace(ctx, "Value: {{'hello world'}}", "text")

// Double quotes - supports escape sequences
result, _ := replvar.Replace(ctx, "Value: {{\"hello\\tworld\"}}", "text")

// Backticks - raw strings, no escape processing
result, _ := replvar.Replace(ctx, "Value: {{`hello\\nworld`}}", "text")

API Reference

Functions
Replace(ctx context.Context, s string, mode string) (string, error)

Parses and resolves a template string in one step. This is the simplest way to perform variable replacement.

  • ctx: Context containing variable values (accessed via ctx.Value(key))
  • s: Template string with {{variable}} expressions
  • mode: Either "text" or "json" (for automatic JSON encoding)
ParseString(s string, mode string) (Var, error)

Parses a template string into a Var that can be resolved multiple times.

ParseVariable(s string) (Var, error)

Parses a variable expression (the content inside {{}}).

Var Interface
type Var interface {
    Resolve(context.Context) (any, error)
    IsStatic() bool
}
  • Resolve: Evaluates the expression against the given context
  • IsStatic: Returns true if the value is constant (no variables)

Expression Syntax

Syntax Description Example
{{name}} Variable lookup {{username}}
{{a.b}} Field access {{user.email}}
{{a + b}} Addition {{price + tax}}
{{a - b}} Subtraction {{total - discount}}
{{a * b}} Multiplication {{qty * price}}
{{a / b}} Division {{total / count}}
{{a % b}} Modulo {{index % 2}}
{{a << b}} Left shift {{1 << 4}}
{{a >> b}} Right shift {{16 >> 2}}
{{a | b}} Bitwise OR {{flags | mask}}
{{a & b}} Bitwise AND {{flags & mask}}
{{a ^ b}} Bitwise XOR {{a ^ b}}
{{~a}} Bitwise NOT {{~mask}}
{{a || b}} Logical OR {{a || b}}
{{a && b}} Logical AND {{a && b}}
{{!a}} Logical NOT {{!enabled}}
{{a == b}} Equality {{status == 'ok'}}
{{a != b}} Inequality {{status != 'error'}}
{{a < b}} Less than {{age < 18}}
{{a <= b}} Less than or equal {{score <= 100}}
{{a > b}} Greater than {{count > 0}}
{{a >= b}} Greater than or equal {{level >= 5}}
{{'str'}} Single-quoted string {{'hello'}}
{{"str"}} Double-quoted string (with escapes) {{"hello\n"}}
{{`str`}} Backtick string (raw) {{`hello`}}
{{123}} Number literal {{42}}
{{1.5}} Float literal {{3.14}}

Operator Precedence

Operators are evaluated according to standard precedence rules (higher precedence binds tighter):

Precedence Operators Description
1 (highest) . Member access
2 ! ~ Unary NOT (logical, bitwise)
3 * / % Multiplication, division, modulo
4 + - Addition, subtraction
5 << >> Bit shifts
6 < <= > >= Relational comparisons
7 == != Equality comparisons
8 & Bitwise AND
9 ^ Bitwise XOR
10 | Bitwise OR
11 && Logical AND
12 (lowest) || Logical OR

For example, 2 + 3 * 4 evaluates to 14 (not 20), and 1 || 0 && 0 evaluates to 1 (not 0).

License

See LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Replace

func Replace(ctx context.Context, s string, mode string) (string, error)

Replace will replace any variable found in s with their value from the context

func Resolve deprecated added in v0.1.0

func Resolve(ctx context.Context, v string) any

Resolve returns the value for a variable name based on the context

Deprecated: use ParseVariable and resolve instead

func ResolveString deprecated added in v0.1.0

func ResolveString(ctx context.Context, v string) string

ResolveString returns the string value for a variable name based on the context

Deprecated: use ParseVariable and resolve instead

Types

type Token added in v0.1.0

type Token int

Token represents a lexical token type identified during parsing. Tokens are the basic building blocks used to construct the AST.

const (
	TokenInvalid        Token = iota // Invalid or unrecognized token
	TokenVariable                    // Identifier/variable name (e.g., "foo", "myVar")
	TokenNumber                      // Numeric literal (integer or float)
	TokenStringConstant              // String literal delimiter (", ', or `)
	TokenVariableEnd                 // End of variable expression: }}

	// Operators
	TokenDot          // Member access: .
	TokenAdd          // Addition: +
	TokenSubtract     // Subtraction: -
	TokenMultiply     // Multiplication: *
	TokenDivide       // Division: /
	TokenModulo       // Modulo: %
	TokenEqual        // Equality comparison: ==
	TokenDifferent    // Inequality comparison: !=
	TokenLess         // Less than: <
	TokenLessEqual    // Less than or equal: <=
	TokenGreater      // Greater than: >
	TokenGreaterEqual // Greater than or equal: >=
	TokenNot          // Logical NOT: !
	TokenBitwiseNot   // Bitwise NOT: ~
	TokenOr           // Bitwise OR: |
	TokenLogicOr      // Logical OR: ||
	TokenAnd          // Bitwise AND: &
	TokenLogicAnd     // Logical AND: &&
	TokenXor          // Bitwise XOR: ^
	TokenShiftLeft    // Left shift: <<
	TokenShiftRight   // Right shift: >>
)

Token type constants representing all recognized lexical elements.

func (Token) IsUnary added in v0.1.3

func (t Token) IsUnary() bool

IsUnary returns true if this token is a unary operator.

func (Token) MathOp added in v0.1.0

func (t Token) MathOp() string

MathOp returns the string representation of a math/logic operator token. Returns an empty string if the token is not a recognized operator.

func (Token) Precedence added in v0.1.3

func (t Token) Precedence() int

Precedence returns the operator precedence for this token. Lower values bind tighter (higher precedence). Returns 0 for non-operator tokens.

type Var added in v0.1.0

type Var interface {
	// Resolve evaluates this variable in the given context and returns its value.
	Resolve(context.Context) (any, error)
	// IsStatic returns true if the value is constant (does not depend on context).
	IsStatic() bool
}

Var is the interface for all resolvable variable expressions. Implementations represent different node types in the expression AST, from simple static values to complex operations.

func ParseString added in v0.1.0

func ParseString(s string, mode string) (Var, error)

ParseString parses a string that may contain embedded variable expressions. Variable expressions are delimited by {{ and }}. The mode parameter controls how nested variables are handled:

  • "text": variables are resolved to their string representation
  • "json": variables are automatically JSON-encoded when embedded

func ParseVariable added in v0.1.0

func ParseVariable(s string) (Var, error)

ParseVariable parses a variable expression (the content typically found inside {{}}). This handles variable names, operators, and nested expressions directly.

Jump to

Keyboard shortcuts

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