modlike

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jul 8, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

README

go-modlike

Language: [ EN | RU ]

go-modlike is a Go library for parsing, building, and serializing configuration files in the Modlike format.

Modlike is inspired by the go.mod syntax: data is written as key value lines, while nested structures are represented with parenthesized blocks.

Features

  • parsing from []byte, string, and io.Reader;
  • document serialization to []byte, string, or io.Writer;
  • ordered data model: key order and list item order are preserved;
  • support for lists, maps, and string values;
  • string literals with escape sequences;
  • line and block comments at the lexical analysis stage;
  • strict per-key typing: once a key is first created as a list, it cannot later become a map.

Installation

go get github.com/80lk/modlike

The minimum Go version is specified in go.mod.

Format Example

project (
	name project_name
	version 1.0.0
)

project author 80LK

meta my_data "string value"

tags (
	tag1
	tag2
	tag3
	tag4
)

The root document is a map. Root key values can be:

  • a list, when the value is written as a single string or as a block without keys;
  • a map, when a nested key follows the root key or when a block contains key value pairs.

When a key appears more than once, values of the same type are merged: lists are appended, and maps are merged recursively.

Quick Start

package main

import (
	"fmt"
	"log"

	"github.com/80lk/modlike"
)

func main() {
	doc, err := modlike.ParseString(`
project (
	name project_name
	version 1.0.0
)

tags (
	tag1
	tag2
)
`)
	if err != nil {
		log.Fatal(err)
	}

	project, err := doc.GetMap("project")
	if err != nil {
		log.Fatal(err)
	}

	nameList, err := project.GetList("name")
	if err != nil {
		log.Fatal(err)
	}

	name, err := nameList.GetStringFirst()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(name)

	out, err := modlike.SerializeString(doc)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(out)
}

Building a Document

func buildDocument() (modlike.Document, error) {
	doc := modlike.New()

	require, err := doc.CreateMap("require")
	if err != nil {
		return nil, err
	}

	module, err := require.CreateList("github.com/example/module")
	if err != nil {
		return nil, err
	}
	module.AppendString("v1.0.0")

	replace, err := doc.CreateMap("replace")
	if err != nil {
		return nil, err
	}

	oldModule, err := replace.CreateList("github.com/old/module")
	if err != nil {
		return nil, err
	}
	oldModule.AppendString("github.com/new/module")

	return doc, nil
}

Public API

Main package functions:

  • modlike.New() Document - creates an empty document;
  • modlike.Parse(data []byte) (Document, error) - parses a document from bytes;
  • modlike.ParseString(src string) (Document, error) - parses a document from a string;
  • modlike.ParseReader(r io.Reader) (Document, error) - parses a document from a stream;
  • modlike.Serialize(doc Document) ([]byte, error) - serializes a document;
  • modlike.SerializeString(doc Document) (string, error) - serializes a document to a string;
  • modlike.WriteTo(w io.Writer, doc Document) error - writes a serialized document to a stream.

Marshal and Unmarshal are declared, but currently return modlike: not implemented.

Data Model

Document is the root map with the following methods:

  • Has(key string) bool;
  • GetKind(key string) Kind;
  • Keys() []string;
  • Get(key string) Value;
  • GetList(key string) (*List, error);
  • CreateList(key string) (*List, error);
  • GetMap(key string) (*Map, error);
  • CreateMap(key string) (*Map, error);
  • Delete(key string);
  • All(func(string, Value) bool).

Map stores values by string keys and supports the same operations for nested lists and maps.

List stores an ordered sequence of values. Strings, maps, and nested lists can be added to a list:

  • AppendString, PrependString, InsertString;
  • AppendNewMap, PrependNewMap, InsertNewMap;
  • AppendNewList, PrependNewList, InsertNewList;
  • GetString, GetStringFirst, GetStringLast;
  • GetMap, GetMapFirst, GetMapLast;
  • GetList, GetListFirst, GetListLast;
  • Delete, DeleteFirst, DeleteLast;
  • All(func(int, Value) bool).

Value kind can be checked with Kind:

  • modlike.K_NONE;
  • modlike.K_LIST;
  • modlike.K_MAP;
  • modlike.K_STRING.

Syntax Brief

  • identifiers are used as unquoted keys and values;
  • strings with spaces are written in double quotes;
  • supported escape sequences are \n, \r, \t, \", \\;
  • a block starts with ( and ends with );
  • // starts a line comment;
  • /* ... */ defines a block comment;
  • empty lines are allowed.

Detailed grammar and format description are available in docs/spec.en.md, docs/modlike.ebnf, and docs/modlike.g4.

Tests

go test ./...

Status

The project is under active development. The parser, model transformer, and serializer are covered by tests, but the Marshal/Unmarshal API is not implemented yet.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Serialize

func Serialize(file Document) ([]byte, error)

func SerializeString

func SerializeString(file Document) (string, error)

func WriteTo

func WriteTo(w io.Writer, file Document) error

Types

type Decoder

type Decoder = model.Decoder

type Document

type Document = *model.Document

func New

func New() Document

func Parse

func Parse(src []byte) (Document, error)

func ParseReader

func ParseReader(r io.Reader) (Document, error)

func ParseString

func ParseString(src string) (Document, error)

type Kind

type Kind = model.KindValue
const (
	K_NONE   Kind = model.KV_NONE
	K_LIST   Kind = model.KV_LIST
	K_MAP    Kind = model.KV_MAP
	K_STRING Kind = model.KV_STRING
)

type Value

type Value = model.Value

Directories

Path Synopsis
errors
internal

Jump to

Keyboard shortcuts

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