diff options
-rw-r--r-- | fountain/parse.go | 95 | ||||
-rw-r--r-- | lex/type.go | 23 | ||||
-rw-r--r-- | pdf/create.go | 52 | ||||
-rw-r--r-- | readme.md | 6 | ||||
-rw-r--r-- | rules/rules.go | 63 |
5 files changed, 239 insertions, 0 deletions
diff --git a/fountain/parse.go b/fountain/parse.go new file mode 100644 index 0000000..dc4602f --- /dev/null +++ b/fountain/parse.go @@ -0,0 +1,95 @@ +package parse + +import ( + "strings" +) + +var example = ` +INT. HOUSE - DAY + +MARY +I can't believe how easy it is to write in Fountain. + +TOM +(typing) +Look! I just made a parenthetical! + +SOMETHING HAPPENS! + +(what? I don't know...) + +EXT. GARDEN + +TOM +What am I doing here now? +To be honest, I have absolutely no idea! + +And that means really no idea! +` + +var action = map[string]struct { + Left, Width float64 +}{ + "action": {1.5, 6}, + "speaker": {4.2, 3.3}, + "dialog": {2.9, 3.3}, + "scene": {1.5, 6}, + "paren": {3.6, 2}, + "trans": {6, 1.5}, + "note": {1.5, 6}, + "allcaps": {1.5, 6}, + "empty": {1.5, 6}, +} + +var tr func(string) string + +type Tree struct { + PDF *gofpdf.Fpdf + F []struct { + Format string + Text string + } +} + +func (t Tree) pr(a string, text string) { + line(t.PDF, action[a].Left, action[a].Width, text) +} + +func (t Tree) Render() { + for _, row := range t.F { + t.pr(row.Format, row.Text) + } +} + +func line(pdf *gofpdf.Fpdf, jump, width float64, text string) { + pdf.SetX(jump) + pdf.MultiCell(width, 0.19, tr(text), "", "aligned", false) +} + +func (t *Tree) ParseString(play string) { + toParse := strings.Split(play, "\n") + for i, row := range toParse { + action := "action" + if row == strings.ToUpper(row) { + action = "allcaps" + } + if row == "" { + action = "empty" + } else { + if i > 0 { + switch t.F[i-1].Format { + case "allcaps": + t.F[i-1].Format = "speaker" + if row[0] == '(' && row[len(row)-1] == ')' { + action = "paren" + } else { + action = "dialog" + } + case "paren", "dialog": + action = "dialog" + } + } + } + t.F = append(t.F, struct{ Format, Text string }{action, row}) + } +} diff --git a/lex/type.go b/lex/type.go new file mode 100644 index 0000000..47439f4 --- /dev/null +++ b/lex/type.go @@ -0,0 +1,23 @@ +package lex + +import ( + "io" + "fmt" +) + +type Screenplay []Line + +type Line struct{ + Type string + Contents string +} + +func Parse(file io.Reader) (out Screenplay) { + var err error + line := Line{} + for err == nil { + _, err = fmt.Fscanf(file, "%s: %s", &line.Type, &line.Contents) + out = append(out, line) + } + return out +} diff --git a/pdf/create.go b/pdf/create.go new file mode 100644 index 0000000..abf0284 --- /dev/null +++ b/pdf/create.go @@ -0,0 +1,52 @@ +package pdf + +import ( + "github.com/lapingvino/lexington/lex" + "github.com/lapingvino/lexington/rules" + + "github.com/jung-kurt/gofpdf" +) + +var tr func(string) string + +type Tree struct { + PDF *gofpdf.Fpdf + Rules rules.Set + F lex.Screenplay +} + +func (t Tree) pr(a string, text string) { + line(t.PDF, t.Rules.Get(a), text) +} + +func (t Tree) Render() { + for _, row := range t.F { + if t.Rules.Get(row.Type).Hide { + continue + } + t.pr(row.Type, row.Contents) + } +} + +func line(pdf *gofpdf.Fpdf, format rules.Format, text string) { + pdf.SetFont(format.Font, format.Style, format.Size) + pdf.SetX(format.Left) + pdf.MultiCell(format.Width, 0.19, tr(text), "", "aligned", false) +} + +func Create(file string, format rules.Set, contents lex.Screenplay) { + pdf := gofpdf.New("P", "in", "Letter", "") + tr = pdf.UnicodeTranslatorFromDescriptor("") + pdf.AddPage() + pdf.SetMargins(1, 1, 1) + pdf.SetXY(1, 1) + f := Tree{ + Rules: format, + F: contents, + } + f.Render() + err := pdf.OutputFileAndClose(file) + if err != nil { + panic(err) + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..dc87e0d --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +Lexington commandline tool for screenwriters +============================================ + +Lexington helps you convert between Final Draft, Fountain and its own lex file formats, and output to PDF, HTML and ebook formats. + +At the moment the tool is not yet usable, please come back later or fork and contribute! diff --git a/rules/rules.go b/rules/rules.go new file mode 100644 index 0000000..07fe588 --- /dev/null +++ b/rules/rules.go @@ -0,0 +1,63 @@ +package rules + +type Format struct{ + Width float64 + Left float64 + Font string + Style string + Size float64 + Hide bool +} + +type Set map[string]Format + +func (s Set) Get(action string) (f Format) { + f, ok := s[action] + if !ok { + f = s["action"] + f.Hide = true + } + if f.Font == "" { + f.Font = "courier" + } + if f.Size == 0 { + f.Size = 12 + } + return f +} + +var Default = Set{ + "action": { + Left: 1.5, + Width: 6, + }, + "speaker": { + Left: 4.2, + Width: 3.3, + }, + "dialog": { + Left: 2.9, + Width: 3.3, + }, + "scene": { + Left: 1.5, + Width: 6, + Style: "b", + }, + "paren": { + Left: 3.6, + Width: 2, + }, + "trans": { + Left: 6, + Width: 1.5, + }, + "note": { + Left: 1.5, + Width: 6, + }, + "allcaps": { + Left: 1.5, + Width: 6, + }, +} |