-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.go
177 lines (152 loc) · 4.73 KB
/
main.go
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"github.com/sirupsen/logrus"
)
func setLogLevel() {
logLevel := os.Getenv("MDX_LOG_LEVEL")
switch logLevel {
case "DEBUG":
logrus.SetLevel(logrus.DebugLevel)
case "INFO":
logrus.SetLevel(logrus.InfoLevel)
case "ERROR":
logrus.SetLevel(logrus.ErrorLevel)
default:
logrus.SetLevel(logrus.WarnLevel)
}
}
func errorExit(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, format+"\n", args...)
os.Exit(1)
}
/*
getMarkdownFilePaths returns a list of markdown files to load commands from.
The order of precedence is:
1. The file flag
2. The MDX_FILE_DIR environment variable
3. The MDX_FILE_PATH environment variable
4. The current working directory
*/
func getMarkdownFilePaths(fileFlag string) []string {
var mdFiles []string
if fileFlag != "" {
logrus.Debug("using file flag to find markdown files")
mdFiles = []string{fileFlag}
} else if mdxFileDir := os.Getenv("MDX_FILE_DIR"); mdxFileDir != "" {
logrus.Debug("using MDX_FILE_DIR")
var err error
mdFiles, err = filepath.Glob(filepath.Join(mdxFileDir, "*.md"))
logrus.Debug(fmt.Sprintf("Searching for markdown files in %s", mdxFileDir))
if err != nil {
errorExit("Error searching for markdown files in %s: %v", mdxFileDir, err)
}
} else if mdxFilePath := os.Getenv("MDX_FILE_PATH"); mdxFilePath != "" {
logrus.Debug("using MDX_FILE_PATH")
var err error
mdFiles = []string{mdxFilePath}
logrus.Debug(fmt.Sprintf("Searching in markdown file %s", mdxFilePath))
if err != nil {
errorExit("Error searching for markdown files in %s: %v", mdxFilePath, err)
}
} else {
logrus.Debug("using CWD to find markdown files")
var err error
mdFiles, err = filepath.Glob("*.md")
if err != nil {
errorExit("Error searching for markdown files: %v", err)
}
}
if len(mdFiles) == 0 {
errorExit("No markdown files found")
}
return mdFiles
}
// Defaults for ConfigBlock are set in findHeadingWalker
type ConfigBlock struct {
OnError string // Valid OnError values are 'ignore' and 'fail'. Default is 'ignore'
SheBang bool
}
type CodeBlock struct {
Lang string // the infostring from the code fence
Code string // the content of the code fence
Config ConfigBlock // contains metadata for the code block
}
// CommandBlock represents a heading, which contains one to multiple code fences.
type CommandBlock struct {
Name string // the name of the command, same as the key in the commands map
Dependencies []string // commands to execute before this command
CodeBlocks []CodeBlock // the code fences below the heading
Filename string // the filename of the markdown file
Meta map[string]any // placeholder for the future
}
func listCommands(commands map[string]CommandBlock) {
fmt.Println("Available commands:")
for name, command := range commands {
if len(command.Dependencies) > 0 {
fmt.Printf("%s: %s (%s)\n", name, command.Dependencies, command.Filename)
} else {
fmt.Printf("%s (%s)\n", name, command.Filename)
}
}
}
func main() {
setLogLevel()
fileFlag := flag.String("file", "", "Specify a markdown file")
fileFlagShort := flag.String("f", "", "Specify a markdown file (shorthand)")
listFlag := flag.Bool("list", false, "list commands")
listFlagShort := flag.Bool("l", false, "list commands (shorthand)")
listLaunchersFlag := flag.Bool("list-launchers", false, "list commands")
listLaunchersFlagShort := flag.Bool("ll", false, "list commands (shorthand)")
flag.Parse()
if *fileFlagShort != "" {
fileFlag = fileFlagShort
}
if *listFlagShort {
listFlag = listFlagShort
}
if *listLaunchersFlagShort {
listLaunchersFlag = listLaunchersFlagShort
}
logrus.Debug("MDX started with parameters:", os.Args)
// Check for subcommands
if flag.NArg() < 1 && !*listFlag && !*listLaunchersFlag {
errorExit("Usage: mdx [-file <markdown-file>] [-list] <command> [args]")
}
commandName := flag.Arg(0)
commandArgs := []string{}
if flag.NArg() > 1 {
commandArgs = flag.Args()[1:]
}
if error := loadLaunchers(); error != nil {
errorExit("Error loading launchers: %v", error)
}
if *listLaunchersFlag {
listLaunchers()
os.Exit(0)
}
var commands = map[string]CommandBlock{}
mdFiles := getMarkdownFilePaths(*fileFlag)
for _, mdFile := range mdFiles {
logrus.Debug(fmt.Sprintf("Loading file %s", mdFile))
err := loadCommands(mdFile, commands)
if err != nil {
errorExit("Error loading commands from %s: %v", mdFile, err)
}
}
if *listFlag {
listCommands(commands)
os.Exit(0)
}
if command, ok := commands[commandName]; ok {
err := executeCommandBlock(commands, &command, commandArgs...)
if err != nil {
errorExit("Error executing command: %v", err)
}
} else {
errorExit("Command not found: %s", commandName)
}
}