mirror of
https://github.com/alda-lang/alda.git
synced 2026-03-03 18:23:36 +01:00
160 lines
3.6 KiB
Go
160 lines
3.6 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"alda.io/client/color"
|
|
"alda.io/client/help"
|
|
"alda.io/client/json"
|
|
log "alda.io/client/logging"
|
|
"alda.io/client/model"
|
|
"alda.io/client/parser"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var outputType string
|
|
|
|
func init() {
|
|
parseCmd.Flags().StringVarP(
|
|
&file, "file", "f", "", "Read Alda source code from a file",
|
|
)
|
|
|
|
parseCmd.Flags().StringVarP(
|
|
&code, "code", "c", "", "Supply Alda source code as a string",
|
|
)
|
|
|
|
parseCmd.Flags().StringVarP(
|
|
&outputType, "output", "o", "data", "The desired parse output",
|
|
)
|
|
}
|
|
|
|
var parseCmd = &cobra.Command{
|
|
Use: "parse",
|
|
Short: "Display the result of parsing Alda source code",
|
|
Long: fmt.Sprintf(`Display the result of parsing Alda source code
|
|
|
|
---
|
|
|
|
%s
|
|
|
|
---
|
|
|
|
The -o / --output parameter determines what output is displayed.
|
|
Options include:
|
|
|
|
events:
|
|
|
|
A JSON array of objects, each of which represents an "event" parsed from the
|
|
source code.
|
|
|
|
data (default):
|
|
|
|
A JSON object representing the score that is constructed after parsing the
|
|
source code into events and evaluating them in order within the context of a
|
|
new score.
|
|
|
|
---`,
|
|
sourceCodeInputOptions("parse", false),
|
|
),
|
|
RunE: func(_ *cobra.Command, args []string) error {
|
|
switch outputType {
|
|
case "events", "data": // OK to proceed
|
|
default:
|
|
return help.UserFacingErrorf(
|
|
`%s is not a supported output type.
|
|
|
|
Please choose one of:
|
|
|
|
%s
|
|
A JSON array of objects, each of which represents an "event" parsed from the
|
|
source code.
|
|
|
|
%s (default)
|
|
A JSON object representing the score that is constructed after parsing the
|
|
source code into events and evaluating them in order within the context of a
|
|
new score.`,
|
|
color.Aurora.BrightYellow(outputType),
|
|
color.Aurora.BrightYellow("events"),
|
|
color.Aurora.BrightYellow("data"),
|
|
)
|
|
}
|
|
|
|
var scoreUpdates []model.ScoreUpdate
|
|
var err error
|
|
|
|
switch {
|
|
case file != "":
|
|
scoreUpdates, err = parser.ParseFile(file)
|
|
|
|
case code != "":
|
|
scoreUpdates, err = parser.ParseString(code)
|
|
|
|
default:
|
|
scoreUpdates, err = parseStdin()
|
|
}
|
|
|
|
if err == errNoInputSupplied {
|
|
return userFacingNoInputSuppliedError("parse")
|
|
}
|
|
|
|
// Errors with source context are presented to the user as-is.
|
|
//
|
|
// TODO: Consider writing better user-facing error messages with suggestions
|
|
// for the users to try, etc. The Elm compiler is a good source of
|
|
// inspiration.
|
|
//
|
|
// TODO: If we do the above, we should also consider providing a flag that
|
|
// keeps the error messages terse/parseable, the way they are now. That way,
|
|
// tooling can be built around the parseable error messages with source
|
|
// context, e.g. an editor plugin can easily parse out the line and column
|
|
// number and display the error message at the relevant position in the
|
|
// file.
|
|
switch err.(type) {
|
|
case *model.AldaSourceError:
|
|
err = &help.UserFacingError{Err: err}
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if outputType == "events" {
|
|
updates := json.Array()
|
|
for _, update := range scoreUpdates {
|
|
updates.ArrayAppend(update.JSON())
|
|
}
|
|
|
|
fmt.Println(updates.String())
|
|
|
|
return nil
|
|
}
|
|
|
|
score := model.NewScore()
|
|
start := time.Now()
|
|
err = score.Update(scoreUpdates...)
|
|
|
|
// Errors with source context are presented to the user as-is.
|
|
//
|
|
// TODO: See TODO comment above about writing better user-facing error
|
|
// messages.
|
|
switch err.(type) {
|
|
case *model.AldaSourceError:
|
|
err = &help.UserFacingError{Err: err}
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info().
|
|
Int("updates", len(scoreUpdates)).
|
|
Str("took", fmt.Sprintf("%s", time.Since(start))).
|
|
Msg("Constructed score.")
|
|
|
|
fmt.Println(score.JSON().String())
|
|
|
|
return nil
|
|
},
|
|
}
|