summaryrefslogtreecommitdiffstats
path: root/database.go
diff options
context:
space:
mode:
authorThibaut Horel <thibaut.horel@gmail.com>2016-03-15 22:12:44 -0400
committerThibaut Horel <thibaut.horel@gmail.com>2016-03-15 22:12:44 -0400
commit58011496071a49e8f5f916a0416c36806ee94614 (patch)
treec32bb04676b54ae0718fb68f97b984b970456628 /database.go
parent9a5261e37badd5422b8c16d93a5b1663c4be602f (diff)
downloadbibtex-58011496071a49e8f5f916a0416c36806ee94614.tar.gz
Add crossref resolution, minor api changes, first template inspired by plain.bst
Diffstat (limited to 'database.go')
-rw-r--r--database.go186
1 files changed, 145 insertions, 41 deletions
diff --git a/database.go b/database.go
index 57d2008..945f9eb 100644
--- a/database.go
+++ b/database.go
@@ -6,68 +6,172 @@ import (
"strings"
)
-type Literal interface{}
+type Value interface {
+ Marshal() string
+ String() string
+}
type BraceLiteral string
type StringLiteral string
type NumberLiteral int
-type VariableLiteral struct {
+type VarLiteral struct {
Name string
Value *Value
}
-func Marshal(l Literal) (res string) {
- switch v := l.(type) {
- case BraceLiteral:
- res = "{" + string(v) + "}"
- case StringLiteral:
- res = "\"" + string(v) + "\""
- case NumberLiteral:
- res = strconv.Itoa(int(v))
- case VariableLiteral:
- res = v.Name
- }
- return
+type LiteralList []Value
+
+func (l BraceLiteral) String() string {
+ return string(l)
+}
+
+func (l BraceLiteral) Marshal() string {
+ return "{" + string(l) + "}"
+}
+
+func (l StringLiteral) String() string {
+ return string(l)
+}
+
+func (l StringLiteral) Marshal() string {
+ return "\"" + string(l) + "\""
+}
+
+func (l NumberLiteral) Marshal() string {
+ return strconv.Itoa(int(l))
+}
+
+func (l NumberLiteral) String() string {
+ return strconv.Itoa(int(l))
+}
+
+func (l VarLiteral) String() string {
+ return (*l.Value).String()
}
-type Value []Literal
+func (l VarLiteral) Marshal() string {
+ return l.Name
+}
+
+func (l LiteralList) String() string {
+ var buf bytes.Buffer
+ for _, lit := range l {
+ buf.WriteString(lit.String())
+ }
+ return buf.String()
+}
-func (v Value) Marshal() string {
- res := make([]string, len(v))
- for i, l := range v {
- res[i] = Marshal(l)
+func (l LiteralList) Marshal() string {
+ res := make([]string, len(l))
+ for i, lit := range l {
+ res[i] = lit.Marshal()
}
return strings.Join(res, " # ")
}
-func (v Value) String() string {
- var buf bytes.Buffer
- for _, l := range v {
- switch lit := l.(type) {
- case BraceLiteral:
- buf.WriteString(string(lit))
- case StringLiteral:
- buf.WriteString(string(lit))
- case NumberLiteral:
- buf.WriteString(strconv.Itoa(int(lit)))
- case VariableLiteral:
- buf.WriteString(lit.Value.String())
+func flatten(v Value) Value {
+ switch t := v.(type) {
+ case LiteralList:
+ if len(t) == 1 {
+ return flatten(t[0])
+ } else {
+ return BraceLiteral(t.String())
}
+ case VarLiteral:
+ return flatten(*t.Value)
+ default:
+ return v
}
- return buf.String()
}
type Entry struct {
- Type string
- Key string
- Fields map[string]Value
- FNames []string
+ Type string `json:"type"`
+ Key string `json:"key"`
+ Fields map[string]Value `json:"fields"`
+ FNames []string `json:"-"`
+}
+
+func (e Entry) Marshal() string {
+ var buf bytes.Buffer
+ temp := make([]string, len(e.FNames))
+ open, close := "{", "}"
+ if strings.Contains(e.Key, "}") {
+ open, close = "(", ")"
+ }
+ buf.WriteString("@" + e.Type + open + e.Key + ",")
+ if len(e.FNames) == 0 {
+ buf.WriteString(close)
+ return buf.String()
+ } else {
+ buf.WriteString("\n\t")
+ }
+
+ for i, field := range e.FNames {
+ temp[i] = field + " = " + e.Fields[field].Marshal()
+ }
+ buf.WriteString(strings.Join(temp, ",\n\t"))
+ buf.WriteString("\n" + close)
+ return buf.String()
}
type Database struct {
- SNames []string
- Strings map[string]Value
- Entries map[string]Entry
- Preamble Value
- EKeys []string
+ SNames []string `json:"-"`
+ Strings map[string]Value `json:"strings,omitempty"`
+ Entries map[string]Entry `json:"entries"`
+ Preamble Value `json:"preamble,omitempty"`
+ EKeys []string `json:"-"`
+ CrossRefs map[string]int `json:"crossrefs,omitempty"`
+}
+
+func (d *Database) UnTex() {
+ for _, entry := range d.Entries {
+ for field, value := range entry.Fields {
+ switch v := value.(type) {
+ case BraceLiteral:
+ entry.Fields[field] = BraceLiteral(UnTex(v.String()))
+ case StringLiteral:
+ entry.Fields[field] = StringLiteral(UnTex(v.String()))
+ case Names:
+ v.untex()
+ }
+ }
+ }
+}
+
+func (d *Database) Flatten() {
+ for _, entry := range d.Entries {
+ for field, value := range entry.Fields {
+ entry.Fields[field] = flatten(value)
+ }
+ }
+}
+
+func (d *Database) SplitNames() {
+ for _, entry := range d.Entries {
+ for field, value := range entry.Fields {
+ if field == "author" || field == "editor" {
+ entry.Fields[field] = SplitNames(value.String())
+ }
+ }
+ }
+}
+
+func (d *Database) Resolve() {
+ var key string
+ var ref Entry
+ for _, entry := range d.Entries {
+ for field, value := range entry.Fields {
+ if field != "crossref" {
+ continue
+ }
+ key = strings.ToLower(value.String())
+ ref = d.Entries[key]
+ for f, v := range ref.Fields {
+ if _, in := entry.Fields[f]; !in {
+ entry.Fields[f] = v
+ entry.FNames = append(entry.FNames, f)
+ }
+ }
+ }
+ }
}