render

package
v0.5.1 Latest Latest
Warning

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

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

README

Render

Рендер произвольных Go-структур в красивое дерево или plain-текст для терминала.

Построение дерева здесь собственное, на strings.Builder — без промежуточных узлов-объектов. Изначально дерево строилось через lipgloss/tree, но на больших ответах (тысячи пакетов) это было значительно медленнее и жрало аллокации, поэтому осталась только стилизация из lipgloss (цвета, bold), а разметку веток пакет рисует сам. Ориентир по скорости: дерево из 3000 элементов рендерится за ~4-5 мс (go test -bench=. ./pkg/render/).

Пример

type Pkg struct {
    Name    string `json:"name"`
    Version string `json:"version"`
}

type Response struct {
    Message string `json:"message"`
    Package Pkg    `json:"package"`
}

r := render.New(render.DefaultColors(),
    render.WithAccentKeys("name"), // значения этих ключей — акцентным цветом
)

resp := Response{
    Message: "Package found",
    Package: Pkg{Name: "vim", Version: "9.1"},
}

// ToDataMap превращает структуру в map, ключи — из json-тегов
fmt.Println(r.RenderText(render.ToDataMap(resp), render.FormatTypeTree, false))
├── Package found
│
╰── package
    ├── name: vim
    ╰── version: 9.1

FormatTypePlain даёт плоский вывод, вложенность — через точку (appStream.id: ...) — удобно для grep. isError=true рисует message цветом ошибки.

Числа приходят в WithValueFormatter единым типом json.Number и печатаются точно (render.AsInt в помощь); типы со своим String() не трогаются. Ключ message — контракт пакета (как msg в slog): рендерится первым как заголовок, FilterFields его сохраняет; если у вас это обычное поле — переименуйте его до рендера.

Зависимости задаются снаружи

Переводы и человеческие имена полей по умолчанию:

render.SetTranslator(myGettext)
render.SetKeyTranslator(myFieldNames)    // "packageName" -> "Имя пакета"

Семантика конкретных ключей задаётся опциями конструктора:

r := render.New(myColors,
    render.WithAccentKeys("name", "url"),       // какие значения подсвечивать
    render.WithValueFormatter(mySizeFormatter), // своё форматирование значения по ключу
)

Фильтрация полей

FilterFields оставляет только запрошенные поля (в apm это флаг -o fields=...), точка выбирает вложенные:

data := map[string]interface{}{
    "message": "Found",
    "package": map[string]interface{}{
        "name":      "vim",
        "version":   "9.1",
        "appStream": map[string]interface{}{"id": "vim.desktop", "icon": "..."},
    },
}
filtered := render.FilterFields(data, []string{"name", "appStream.id"})
fmt.Println(r.RenderText(filtered, render.FormatTypeTree, false))

Documentation

Index

Constants

This section is empty.

Variables

View Source
var T_ = func(msgId string) string { return msgId }

T_ is the string translation hook, defaults to identity

Functions

func AsInt

func AsInt(value interface{}) (int, bool)

AsInt extracts an int from a canonical json.Number value

func FilterFields

func FilterFields(data map[string]interface{}, fields []string) map[string]interface{}

FilterFields keeps only the requested fields, dot notation selects nested ones

func NormalizeDataMap

func NormalizeDataMap(data map[string]interface{}) map[string]interface{}

NormalizeDataMap normalizes all map values to basic JSON types

func SetKeyTranslator

func SetKeyTranslator(fn func(key string) string)

SetKeyTranslator sets the field label translator

func SetTranslator

func SetTranslator(fn func(msgId string) string)

SetTranslator sets the translation function

func ToDataMap

func ToDataMap(data interface{}) map[string]interface{}

ToDataMap converts any value to a data map via JSON round-trip

Types

type Colors

type Colors struct {
	Accent      string `yaml:"accent"`
	TreeBranch  string `yaml:"treeBranch"`
	ResultError string `yaml:"resultError"`
}

Colors is the renderer color scheme

func DefaultColors

func DefaultColors() Colors

DefaultColors returns the default color scheme

type FormatType

type FormatType string

FormatType selects the text layout

const (
	FormatTypeTree  FormatType = "tree"
	FormatTypePlain FormatType = "plain"
)

Text format types

type Option

type Option func(*Renderer)

Option configures a Renderer

func WithAccentKeys

func WithAccentKeys(keys ...string) Option

WithAccentKeys sets keys whose values are highlighted with the accent style

func WithValueFormatter

func WithValueFormatter(fn func(key string, value interface{}) (string, bool)) Option

WithValueFormatter sets a custom scalar value formatter, handled=true overrides the default

type Renderer

type Renderer struct {
	// contains filtered or unexported fields
}

Renderer renders data maps as styled tree or plain text

func New

func New(colors Colors, opts ...Option) *Renderer

New creates a Renderer with the given color scheme

func (*Renderer) RenderText

func (r *Renderer) RenderText(dataMap map[string]interface{}, formatType FormatType, isError bool) string

RenderText renders the data map in the given format type

Jump to

Keyboard shortcuts

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