~nromdotcom/gemif

ref: 0661a68757e5de04e963cc5d7b23a618e5303966 gemif/cmd/gemifc/main.go -rw-r--r-- 2.9 KiB
0661a687Norm MacLennan Initial story compiler with two examples 1 year, 1 month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main

// yaml.v3 doesn't serialize multi-line strings
// correctly for some reason, so we use v2.
import (
	"fmt"
	"gemif/pkg/gamemanager"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v2"
)

func readFile(path string) (string, error) {
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("couldn't read file: %w", err)
	}

	return string(contents), nil
}

func findFilesWithExtension(root, pattern string) ([]string, error) {
	var matches []string

	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		if matched, err := filepath.Match(pattern, filepath.Base(path)); err != nil {
			return err
		} else if matched {
			matches = append(matches, path)
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	return matches, nil
}

func main() {
	correctNumArguments := 3
	if len(os.Args) != correctNumArguments {
		log.Fatal("Usage: gemifc [input_path] [output_path]")
	}

	inputPath := os.Args[1]
	outputPath := os.Args[2]

	fmt.Printf("Compiling story %s to %s\n", inputPath, outputPath)

	fileContents, err := readFile(fmt.Sprintf("%s/metadata.yml", inputPath))
	if err != nil {
		log.Fatalf("Couldn't read metadata file: %s", err)
	}

	var metadata *gamemanager.StoryMetadata
	if err := yaml.Unmarshal([]byte(fileContents), &metadata); err != nil {
		log.Fatalf("Malformed metadata.yml: %s", err)
	}

	files, err := findFilesWithExtension(inputPath, "*.gemif")
	if err != nil {
		log.Fatalf("Couldn't load *.gemif files %s", err)
	}

	storyRooms := []gamemanager.Room{}

	for _, file := range files {
		thisFile, err := readFile(file)
		if err != nil {
			log.Fatalf("Couldn't read .gemif file: %s", err)
		}

		isMetadata := false
		currentRoom := gamemanager.Room{}

		for _, filePiece := range strings.Split(thisFile, "---") {
			if filePiece == "" {
				isMetadata = !isMetadata

				continue
			}

			if isMetadata {
				if err := yaml.Unmarshal([]byte(filePiece), &currentRoom); err != nil {
					log.Fatalf("Couldn't parse story metadata from yaml: %s", err)
				}
			} else {
				currentRoom.Description = filePiece
				storyRooms = append(storyRooms, currentRoom)
				currentRoom = gamemanager.Room{}
			}

			isMetadata = !isMetadata
		}
	}

	story := gamemanager.Story{
		Metadata: *metadata,
		Rooms:    storyRooms,
	}

	fmt.Printf(`
Finished loading story:
  Name: %s
  Author: %s
  Descriptions: %s
  Number of Rooms: %d

`, story.Metadata.Name, story.Metadata.Author, story.Metadata.Description, len(story.Rooms))

	fmt.Println("Serializing and writing to disk...")

	storyOut, err := yaml.Marshal(story)
	if err != nil {
		log.Fatal("Couldn't load story metadata")
	}

	err = ioutil.WriteFile(fmt.Sprintf("%s/%s.yml", outputPath, story.Metadata.ID), storyOut, 0644) // #nosec G306
	if err != nil {
		log.Fatalf("Couldn't write compiled output: %s", err)
	}

	fmt.Println("Done!")
}