aboutsummaryrefslogtreecommitdiff
path: root/model
diff options
context:
space:
mode:
author2026-02-17 21:33:24 +0300
committer2026-02-21 16:23:10 +0300
commitba06314d59e55945b103ead2c7a9e01f58c6a93c (patch)
tree34ab8ac19307da60bd5caf76d844a6dc2e730361 /model
parentinit (diff)
downloadconf-ba06314d59e55945b103ead2c7a9e01f58c6a93c.tar.gz
conf-ba06314d59e55945b103ead2c7a9e01f58c6a93c.tar.bz2
conf-ba06314d59e55945b103ead2c7a9e01f58c6a93c.tar.xz
conf-ba06314d59e55945b103ead2c7a9e01f58c6a93c.zip
v0.0.1v0.0.1
Diffstat (limited to 'model')
-rw-r--r--model/assignment.go6
-rw-r--r--model/command.go9
-rw-r--r--model/doc.go43
-rw-r--r--model/lookup.go49
-rw-r--r--model/value.go42
5 files changed, 139 insertions, 10 deletions
diff --git a/model/assignment.go b/model/assignment.go
new file mode 100644
index 0000000..746e2b3
--- /dev/null
+++ b/model/assignment.go
@@ -0,0 +1,6 @@
+package model
+
+type Assignment struct {
+ Key string
+ Value Values
+}
diff --git a/model/command.go b/model/command.go
new file mode 100644
index 0000000..237e94f
--- /dev/null
+++ b/model/command.go
@@ -0,0 +1,9 @@
+package model
+
+type Command struct {
+ Name string
+ Arguments Values
+ Body *Doc
+}
+
+type Commands []*Command
diff --git a/model/doc.go b/model/doc.go
index 76f03e4..9c13a4c 100644
--- a/model/doc.go
+++ b/model/doc.go
@@ -1,18 +1,41 @@
package model
-type Doc []any
+type Doc struct {
+ items []any
+ vars map[string]Values
+ commands map[string]Commands
+}
-type Assignment struct {
- Key string
- Value []Value
+func New(cap int) *Doc {
+ return &Doc{
+ items: make([]any, 0, cap),
+ vars: make(map[string]Values, cap),
+ commands: make(map[string]Commands, cap),
+ }
}
-type Command struct {
- Name string
- Arguments []Value
- Body Doc
+func (d *Doc) AppendAssignment(e *Assignment) {
+ d.items = append(d.items, e)
+ d.vars[e.Key] = append(d.vars[e.Key], e.Value...)
}
-type Value any
+func (d *Doc) AppendCommand(c *Command) {
+ d.items = append(d.items, c)
+ d.commands[c.Name] = append(d.commands[c.Name], c)
+}
-type Word string
+func (d *Doc) Vars() map[string]Values {
+ return d.vars
+}
+
+func (d *Doc) Get(key string) Values {
+ return d.vars[key]
+}
+
+func (d *Doc) Commands(name string) Commands {
+ return d.commands[name]
+}
+
+func (d *Doc) Items() []any {
+ return d.items
+}
diff --git a/model/lookup.go b/model/lookup.go
new file mode 100644
index 0000000..e8cc8bf
--- /dev/null
+++ b/model/lookup.go
@@ -0,0 +1,49 @@
+package model
+
+import (
+ "os"
+ "strings"
+)
+
+// WordLookup тип определяющий функцию поиска замены слов при
+// стрингификации Values.
+type WordLookup func(word Word) string
+
+// chainLookup утилитарная функция для последовательных применений функций
+// поиска до первого нахождения подстановки. Если returnOrigin == true,
+// то в случае неудачи вернёт имя слова.
+func chainLookup(lookups ...WordLookup) WordLookup {
+ return func(word Word) string {
+ for _, lookup := range lookups {
+ if v := lookup(word); v != "" {
+ return v
+ }
+ }
+ return string(word)
+ }
+}
+
+// LookupEnv функция типа WordLookup которая пытается подставить вместо word
+// соответствующую ему переменную окружения ОС. При этом он срабатывает только
+// если слово начинается со знака `$`.
+func LookupEnv(word Word) string {
+ if !strings.HasPrefix(string(word), "$") {
+ return ""
+ }
+ varName := strings.TrimPrefix(string(word), "$")
+ if result, ok := os.LookupEnv(varName); ok {
+ return result
+ }
+ return ""
+}
+
+// LookupSubst функция типа WordLookup которая пытается подставить вместо word
+// значение из словаря подстановок по соответствующему ключу.
+func LookupSubst(subst map[Word]string) WordLookup {
+ return func(word Word) string {
+ if result, ok := subst[word]; ok {
+ return result
+ }
+ return ""
+ }
+}
diff --git a/model/value.go b/model/value.go
new file mode 100644
index 0000000..4ec7344
--- /dev/null
+++ b/model/value.go
@@ -0,0 +1,42 @@
+package model
+
+import (
+ "strconv"
+ "strings"
+)
+
+type Value any
+
+type Values []Value
+
+// BuildString собирает из значений Value цельную строку, при этом приводя все
+// значения к типу string. Так же принимает функции типа WordLookup, которые
+// последовательно будут пытаться привести значения типа Word к
+// контекстозависимым значениям. Например, пытаться находить по имени переменную
+// окружения ОС.
+func (v Values) BuildString(lookups ...WordLookup) string {
+ sw := strings.Builder{}
+
+ for _, v := range v {
+ switch v := v.(type) {
+ case string:
+ sw.WriteString(v)
+ case float64:
+ sw.WriteString(strconv.FormatFloat(v, 'f', 5, 64))
+ case int:
+ sw.WriteString(strconv.Itoa(v))
+ case bool:
+ if v {
+ sw.WriteString("true")
+ continue
+ }
+ sw.WriteString("false")
+ case Word:
+ sw.WriteString(chainLookup(lookups...)(v))
+ }
+ }
+
+ return sw.String()
+}
+
+type Word string