mirror of
https://github.com/tmedwards/tweego.git
synced 2025-07-04 21:50:33 -04:00
Initial Bitbucket→GitHub migration commit, based on release v2.0.0.
This commit is contained in:
commit
57e1aa52ff
36 changed files with 5026 additions and 0 deletions
261
config.go
Normal file
261
config.go
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
Copyright © 2014–2019 Thomas Michael Edwards. All rights reserved.
|
||||
Use of this source code is governed by a Simplified BSD License which
|
||||
can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
// standard packages
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
// internal packages
|
||||
"bitbucket.org/tmedwards/tweego/internal/option"
|
||||
// external packages
|
||||
"github.com/paulrosania/go-charset/charset"
|
||||
)
|
||||
|
||||
type outputMode int
|
||||
|
||||
const (
|
||||
outModeHTML outputMode = iota
|
||||
outModeTwee3
|
||||
outModeTwee1
|
||||
outModeTwine2Archive
|
||||
outModeTwine1Archive
|
||||
)
|
||||
|
||||
type common struct {
|
||||
formatID string // ID of the story format to use
|
||||
startName string // name of the starting passage
|
||||
}
|
||||
|
||||
type config struct {
|
||||
cmdline common
|
||||
common
|
||||
|
||||
encoding string // input encoding
|
||||
sourcePaths []string // slice of paths to seach for source files
|
||||
modulePaths []string // slice of paths to seach for module files
|
||||
headFile string // name of the head file
|
||||
outFile string // name of the output file
|
||||
outMode outputMode // output mode
|
||||
|
||||
formats storyFormatsMap // map of all enumerated story formats
|
||||
testMode bool // enable test mode
|
||||
twee2Compat bool // enable Twee2 header extension compatibility mode
|
||||
watchFiles bool // enable filesystem watching
|
||||
logStats bool // log story statistics
|
||||
logFiles bool // log input files
|
||||
}
|
||||
|
||||
const (
|
||||
defaultFormatID = "sugarcube-2"
|
||||
defaultOutFile = "-" // <stdout>
|
||||
defaultOutMode = outModeHTML
|
||||
defaultStartName = "Start"
|
||||
)
|
||||
|
||||
// newConfig creates a new config instance
|
||||
func newConfig() *config {
|
||||
// Get the base paths to search for story formats.
|
||||
formatDirs := (func() []string {
|
||||
var (
|
||||
baseDirnames = []string{
|
||||
"storyformats",
|
||||
".storyformats",
|
||||
"story-formats", // DEPRECATED
|
||||
"storyFormats", // DEPRECATED
|
||||
"targets", // DEPRECATED
|
||||
}
|
||||
basePaths = []string{programDir}
|
||||
searchDirnames []string
|
||||
)
|
||||
if homeDir, err := userHomeDir(); err == nil {
|
||||
if !stringSliceContains(basePaths, homeDir) {
|
||||
basePaths = append(basePaths, homeDir)
|
||||
}
|
||||
}
|
||||
if !stringSliceContains(basePaths, workingDir) {
|
||||
basePaths = append(basePaths, workingDir)
|
||||
}
|
||||
for _, basePath := range basePaths {
|
||||
for _, baseDirname := range baseDirnames {
|
||||
searchDirname := filepath.Join(basePath, baseDirname)
|
||||
if info, err := os.Stat(searchDirname); err == nil && info.IsDir() {
|
||||
searchDirnames = append(searchDirnames, searchDirname)
|
||||
}
|
||||
}
|
||||
}
|
||||
return searchDirnames
|
||||
})()
|
||||
|
||||
// Create a new instance of `config` and assign defaults.
|
||||
c := &config{
|
||||
common: common{formatID: defaultFormatID, startName: defaultStartName},
|
||||
outFile: defaultOutFile,
|
||||
outMode: defaultOutMode,
|
||||
}
|
||||
|
||||
// Merge values from the environment variables.
|
||||
// /*
|
||||
// LEGACY
|
||||
// */
|
||||
// for _, env := range []string{"TWEEGO_CHARSET", "TWEEGO_FORMAT"} {
|
||||
// if _, exists := os.LookupEnv(env); exists {
|
||||
// log.Printf("warning: Detected obsolete environment variable %q. Please remove it from your environment.", env)
|
||||
// }
|
||||
// }
|
||||
// /*
|
||||
// END LEGACY
|
||||
// */
|
||||
if env := os.Getenv("TWEEGO_PATH"); env != "" {
|
||||
formatDirs = append(formatDirs, filepath.SplitList(env)...)
|
||||
}
|
||||
|
||||
// TODO: Move story formats out of the config?
|
||||
// Enumerate story formats.
|
||||
if len(formatDirs) == 0 {
|
||||
log.Fatal("error: Story format search directories not found.")
|
||||
}
|
||||
c.formats = newStoryFormatsMap(formatDirs)
|
||||
if c.formats.isEmpty() {
|
||||
log.Print("error: Story formats not found within the search directories: (in order)")
|
||||
for i, path := range formatDirs {
|
||||
log.Printf(" %2d. %s", i+1, path)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Merge values from the command line.
|
||||
options := option.NewParser()
|
||||
options.Add("archive_twine2", "-a|--archive-twine2")
|
||||
options.Add("archive_twine1", "--archive-twine1")
|
||||
options.Add("decompile_twee3", "-d|--decompile-twee3|--decompile") // NOTE: "--decompile" is deprecated.
|
||||
options.Add("decompile_twee1", "--decompile-twee1")
|
||||
options.Add("encoding", "-c=s|--charset=s")
|
||||
options.Add("format", "-f=s|--format=s")
|
||||
options.Add("head", "--head=s")
|
||||
options.Add("help", "-h|--help")
|
||||
options.Add("listcharsets", "--list-charsets")
|
||||
options.Add("listformats", "--list-formats")
|
||||
options.Add("logfiles", "--log-files")
|
||||
options.Add("logstats", "-l|--log-stats")
|
||||
options.Add("module", "-m=s+|--module=s+")
|
||||
options.Add("output", "-o=s|--output=s")
|
||||
options.Add("start", "-s=s|--start=s")
|
||||
options.Add("test", "-t|--test")
|
||||
options.Add("twee2_compat", "--twee2-compat")
|
||||
options.Add("version", "-v|--version")
|
||||
options.Add("watch", "-w|--watch")
|
||||
if opts, sources, err := options.ParseCommandLine(); err == nil {
|
||||
for opt, val := range opts {
|
||||
switch opt {
|
||||
case "archive_twine2":
|
||||
c.outMode = outModeTwine2Archive
|
||||
case "archive_twine1":
|
||||
c.outMode = outModeTwine1Archive
|
||||
case "decompile_twee3":
|
||||
c.outMode = outModeTwee3
|
||||
case "decompile_twee1":
|
||||
c.outMode = outModeTwee1
|
||||
case "encoding":
|
||||
c.encoding = val.(string)
|
||||
case "format":
|
||||
c.cmdline.formatID = val.(string)
|
||||
c.formatID = c.cmdline.formatID
|
||||
case "head":
|
||||
c.headFile = val.(string)
|
||||
case "help":
|
||||
usage()
|
||||
case "listcharsets":
|
||||
usageCharsets()
|
||||
case "listformats":
|
||||
usageFormats(c.formats)
|
||||
case "logfiles":
|
||||
c.logFiles = true
|
||||
case "logstats":
|
||||
c.logStats = true
|
||||
case "module":
|
||||
c.modulePaths = append(c.modulePaths, val.([]string)...)
|
||||
case "output":
|
||||
c.outFile = val.(string)
|
||||
case "start":
|
||||
c.cmdline.startName = val.(string)
|
||||
c.startName = c.cmdline.startName
|
||||
case "test":
|
||||
c.testMode = true
|
||||
case "twee2_compat":
|
||||
c.twee2Compat = true
|
||||
case "version":
|
||||
usageVersion()
|
||||
case "watch":
|
||||
c.watchFiles = true
|
||||
}
|
||||
}
|
||||
if len(sources) > 0 {
|
||||
c.sourcePaths = append(c.sourcePaths, sources...)
|
||||
}
|
||||
} else {
|
||||
log.Printf("error: %s", err.Error())
|
||||
usage()
|
||||
}
|
||||
|
||||
// Basic sanity checks.
|
||||
if c.encoding != "" {
|
||||
if cs := charset.Info(c.encoding); cs == nil {
|
||||
log.Printf("error: Charset %q is unsupported.", c.encoding)
|
||||
usageCharsets()
|
||||
}
|
||||
}
|
||||
if len(c.sourcePaths) == 0 {
|
||||
log.Print("error: Input sources not specified.")
|
||||
usage()
|
||||
}
|
||||
if c.watchFiles {
|
||||
if c.outFile == "-" {
|
||||
log.Fatal("error: Writing to standard output is unsupported in watch mode.")
|
||||
}
|
||||
// if c.logFiles {
|
||||
// log.Print("warning: File logging is unsupported in watch mode.")
|
||||
// }
|
||||
// if c.logStats {
|
||||
// log.Print("warning: Statistic logging is unsupported in watch mode.")
|
||||
// }
|
||||
}
|
||||
|
||||
// Return the base configuration.
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *config) mergeStoryConfig(s *story) {
|
||||
if c.cmdline.formatID != "" {
|
||||
c.formatID = c.cmdline.formatID
|
||||
} else if s.twine2.format != "" {
|
||||
c.formatID = c.formats.getIDFromTwine2NameAndVersion(s.twine2.format, s.twine2.formatVersion)
|
||||
if c.formatID == "" {
|
||||
log.Printf("error: Story format named %q at version %q is not available.", s.twine2.format, s.twine2.formatVersion)
|
||||
usageFormats(c.formats)
|
||||
}
|
||||
} else {
|
||||
c.formatID = defaultFormatID
|
||||
}
|
||||
if !c.formats.hasByID(c.formatID) {
|
||||
log.Printf("error: Story format %q is not available.", c.formatID)
|
||||
usageFormats(c.formats)
|
||||
}
|
||||
|
||||
if c.cmdline.startName != "" {
|
||||
c.startName = c.cmdline.startName
|
||||
} else if s.twine2.start != "" {
|
||||
c.startName = s.twine2.start
|
||||
} else {
|
||||
c.startName = defaultStartName
|
||||
}
|
||||
|
||||
// Finalize the story setup.
|
||||
s.format = c.formats.getByID(c.formatID)
|
||||
s.twine2.options["debug"] = s.twine2.options["debug"] || c.testMode
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue