-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
185 lines (153 loc) · 6.3 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
178
179
180
181
182
183
184
185
// Copyright 2023 The FIT SDK for Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/muktihari/fit/internal/cmd/fitgen/builder"
"github.com/muktihari/fit/internal/cmd/fitgen/factory"
"github.com/muktihari/fit/internal/cmd/fitgen/generator"
"github.com/muktihari/fit/internal/cmd/fitgen/lookup"
"github.com/muktihari/fit/internal/cmd/fitgen/parser"
"github.com/muktihari/fit/internal/cmd/fitgen/pkg/flagutil"
"github.com/muktihari/fit/internal/cmd/fitgen/pkg/strutil"
"github.com/muktihari/fit/internal/cmd/fitgen/pkg/xlsxlite"
"github.com/muktihari/fit/internal/cmd/fitgen/profile"
"github.com/muktihari/fit/internal/cmd/fitgen/profile/mesgdef"
"github.com/muktihari/fit/internal/cmd/fitgen/profile/typedef"
"github.com/muktihari/fit/internal/cmd/fitgen/profile/untyped/fieldnum"
"github.com/muktihari/fit/internal/cmd/fitgen/profile/untyped/mesgnum"
"github.com/thedatashed/xlsxreader"
)
var aboutFitgen = `
The FIT SDK for Go Generator, also known as "fitgen", is a program designed to create
several *.go files using Garmin SDK specifications (Profile.xlsx). These generated files
enable this FIT SDK to carry out the decoding and encoding process of FIT files.
The files are organized into distinct packages:
- profile: mesgdef, typedef, untyped
- factory
To define your manufacturer specifications, duplicate the Profile.xlsx file and
incorporate your specifications within it. Afterward, utilize the provided command-line
interface (CLI) to generate a customized SDK. When executing the CLI command, specify
the path to the edited-file such as "Profile-copy.xlsx" using the "--path" option.
Example:
- "./fitgen --profile-file Profile-copy.xlsx --path ../../../ --builders all --profile-version 21.115 -v -y"
- "./fitgen -f Profile-copy.xlsx -p ../../../ -b all --profile-version 21.115 -v -y"
Note: The existing Garmin SDK specifications must not be altered, as such modifications
could lead to data that does not align with the terms and conditions of the FIT Protocol.
`
func main() {
var verbose, verboseHelp = false, "Print list of generated files to stdout"
flag.BoolVar(&verbose, "v", false, verboseHelp)
flag.BoolVar(&verbose, "verbose", false, verboseHelp)
var profileFilePath, profileFilePathHelp = "", "Path/to/Profile.xlsx"
flag.StringVar(&profileFilePath, "f", "", profileFilePathHelp)
flag.StringVar(&profileFilePath, "profile-file", "", profileFilePathHelp)
var generatePath, generatePathHelp = "", "Root path to generate files (e.g. \"../../../\")"
flag.StringVar(&generatePath, "p", "", generatePathHelp)
flag.StringVar(&generatePath, "path", "", generatePathHelp)
var whichBuilder string
whichBuilderHelp := "Which builder to generate (separated by comma): [types, mesgs, profile, factory] or all"
flag.StringVar(&whichBuilder, "b", "", whichBuilderHelp)
flag.StringVar(&whichBuilder, "builders", "", whichBuilderHelp)
var profileVersion, profileVersionHelp = "", "Garmin FIT SDK Profile Version (e.g. \"21.115\")"
flag.StringVar(&profileVersion, "profile-version", "", profileVersionHelp)
var confirm, confirmHelp = false, "Confirm action"
flag.BoolVar(&confirm, "y", false, confirmHelp)
var about bool
flag.BoolVar(&about, "about", false, "Show about fitgen CLI description then exit program.")
flag.Usage = flagutil.Usage
flag.Parse()
if about {
fmt.Println(aboutFitgen)
os.Exit(0)
}
if profileFilePath == "" {
fatalf("missing flag: --profile-file=Path/to/Profile.xlsx\n")
}
if generatePath == "" {
fatalf("missing flag: --path=root/path/to/generate/files\n")
}
if profileVersion == "" {
fatalf("missing flag: --profile-version=<version> e.g 21.115\n")
}
generatePath = abspath(generatePath)
if !confirm {
fmt.Printf("fitgen will generate files relative to given path: %q.\nDo you want to continue? [y/n]: ", generatePath)
var confimation string
fmt.Scanf("%s\n", &confimation)
if strings.ToLower(confimation)[0] != 'y' {
fatalf("aborted.\n")
}
}
xlsxreader, err := xlsxreader.OpenFile(profileFilePath)
if err != nil {
fatalf("could not open Profile.xlsx: %v\n", err)
}
defer xlsxreader.Close()
ps := parser.New(xlsxlite.New(xlsxreader), map[parser.Sheet]string{
parser.SheetTypes: "Types", // maps the actual sheet name in the file
parser.SheetMessages: "Messages", // to the one that the parser is using.
})
parsedtypes, err := ps.ParseTypes()
if err != nil {
fatalf(fmt.Sprintf("could no parse types: %v\n", err))
}
parsedmesgs, err := ps.ParseMessages()
if err != nil {
fatalf(fmt.Sprintf("could no parse message: %v\n", err))
}
lookup := lookup.NewLookup(parsedtypes, parsedmesgs)
var (
typedefb = typedef.NewBuilder(generatePath, parsedtypes)
profileb = profile.NewBuilder(generatePath, profileVersion, parsedtypes)
factoryb = factory.NewBuilder(generatePath, lookup, parsedtypes, parsedmesgs)
mesgnumb = mesgnum.NewBuilder(generatePath, parsedtypes)
fielnumb = fieldnum.NewBuilder(generatePath, lookup, parsedmesgs, parsedtypes)
mesgdefb = mesgdef.NewBuilder(generatePath, lookup, parsedmesgs, parsedtypes)
)
var builders []builder.Builder
whichBuilders := strings.Split(strutil.TrimRepeatedChar(whichBuilder, ','), ",")
loop:
for _, selected := range whichBuilders {
switch s := strings.TrimSpace(selected); s {
case "", "all":
builders = []builder.Builder{typedefb, profileb, factoryb, mesgnumb, fielnumb, mesgdefb}
break loop
case "typedef":
builders = append(builders, typedefb)
case "profile":
builders = append(builders, profileb)
case "factory":
builders = append(builders, factoryb)
case "untyped":
builders = append(builders, fielnumb, mesgnumb)
case "mesgnum":
builders = append(builders, mesgnumb)
case "fieldnum":
builders = append(builders, fielnumb)
case "mesgdef":
builders = append(builders, mesgdefb)
default:
fatalf("invalid builder named %q\n", strings.TrimSpace(selected))
}
}
if err := generator.New(verbose).Generate(builders, 0o755); err != nil {
fatalf("could not generate files: %v\n", err)
}
}
func fatalf(format string, args ...interface{}) {
fmt.Printf(format, args...)
os.Exit(1)
}
func abspath(path string) string {
abspath, err := filepath.Abs(path)
if err != nil {
return path
}
return abspath
}