diff --git a/main.go b/main.go index 5d993f9..ee03fae 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "fes/modules/doc" "fes/modules/new" "fes/modules/server" + "fes/modules/ui" "fes/modules/version" ) @@ -34,13 +35,13 @@ func init() { func main() { flag.Usage = func() { fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] \n", os.Args[0]) - fmt.Fprintf(os.Stderr, "Commands:") - fmt.Fprintf(os.Stderr, " new Create a new project") - fmt.Fprintf(os.Stderr, " doc Open documentation") - fmt.Fprintf(os.Stderr, " run Start the server") - fmt.Fprintf(os.Stderr, "Options:") + fmt.Fprintln(flag.CommandLine.Output(), "Commands:") + fmt.Fprintln(flag.CommandLine.Output(), " new Create a new project") + fmt.Fprintln(flag.CommandLine.Output(), " doc Open documentation") + fmt.Fprintln(flag.CommandLine.Output(), " run Start the server") + fmt.Fprintln(flag.CommandLine.Output(), "Options:") flag.PrintDefaults() - fmt.Fprintf(os.Stderr, "For bug reports, contact a developer and describe the issue. Provide the output of the `-V1` flag.") + fmt.Fprintln(flag.CommandLine.Output(), "For bug reports, contact a developer and describe the issue. Provide the output of the `-V1` flag.") } showVersion := flag.Bool("version", false, "Show version and exit") @@ -89,6 +90,7 @@ func main() { os.Exit(1) } case "run": + ui.Log("Fes version=%s, commit=%s, just started", version.VERSION, version.GetCommit()) if err := server.Start(dir); err != nil { if errors.Is(err, os.ErrNotExist) { fmt.Fprintf(os.Stderr, "%s does not exist\n", dir) diff --git a/modules/server/server.go b/modules/server/server.go index 10c329b..848e8e1 100644 --- a/modules/server/server.go +++ b/modules/server/server.go @@ -1,11 +1,10 @@ package server import ( + "errors" "fes/modules/config" "fes/modules/ui" "fmt" - "github.com/pelletier/go-toml/v2" - lua "github.com/yuin/gopher-lua" "html/template" "io/fs" "net/http" @@ -15,6 +14,9 @@ import ( "sort" "strings" "time" + + "github.com/pelletier/go-toml/v2" + lua "github.com/yuin/gopher-lua" ) /* this is the request data we pass over the bus to the application, via the fes.bus interface */ @@ -378,18 +380,26 @@ func loadDirs() map[string]string { /* helper to parse the Fes.toml and generate config */ func parseConfig() config.AppConfig { + defaultCfg := config.AppConfig{} + defaultCfg.App.Authors = []string{"unknown"} + defaultCfg.App.Name = "unknown" + defaultCfg.App.Version = "unknown" + tomlDocument, err := os.ReadFile("Fes.toml") if err != nil { - ui.Error("failed to read Fes.toml", err) - os.Exit(1) + if errors.Is(err, os.ErrNotExist) { + ui.WARN("no config file found, using the default config. In order to specify a config file write to Fes.toml") + return defaultCfg + } else { + ui.Error("failed to read Fes.toml", err) + os.Exit(1) + } } docStr := fixMalformedToml(string(tomlDocument)) var cfg config.AppConfig if err := toml.Unmarshal([]byte(docStr), &cfg); err != nil { ui.Warning("failed to parse Fes.toml", err) - cfg.App.Authors = []string{"unknown"} - cfg.App.Name = "unknown" - cfg.App.Version = "unknown" + cfg = defaultCfg } return cfg } @@ -466,6 +476,6 @@ func Start(dir string) error { w.Write(data) }) - fmt.Printf("Server is running on http://localhost:%d\n", *config.Port) + ui.Log("Ready to accept connections on http://localhost:%d", *config.Port) return http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", *config.Port), nil) } diff --git a/modules/ui/ui.go b/modules/ui/ui.go index 3ec152a..8aee517 100644 --- a/modules/ui/ui.go +++ b/modules/ui/ui.go @@ -4,75 +4,101 @@ import ( "errors" "fmt" "strings" + "time" "fes/modules/config" - "fes/modules/version" "github.com/fatih/color" ) const ( - hint_color = 0xbda02a + hintColor = 0xbda02a ) -/* print out the current path (route) and relevant error */ -func Path(path string, err error) { - path = strings.TrimPrefix(path, "/") +func formatTimestamp() string { + return time.Now().Format("02 Jan 2006 15:04") +} - if path == "" { - path = "(null)" - } - - fmt.Printf(" > %s ", path) - if err == nil { - OK("ok") - return - } else if errors.Is(err, config.ErrRouteMiss) { - WARN(config.ErrRouteMiss.Error()) +func logMessage(prefix string, msg string, args ...any) { + formatted := fmt.Sprintf(msg, args...) + if prefix == "" { + fmt.Printf("%s * %s\n", formatTimestamp(), formatted) } else { - ERROR("bad") + fmt.Printf("%s * %s: %s\n", formatTimestamp(), prefix, formatted) } } -/* print general system warning */ -func Warning(msg string, err error) error { - fmt.Printf("%s: %s: %v\n", version.PROGRAM_NAME, color.MagentaString("warning"), err) - return err +// Generic log +func Log(msg string, args ...any) { + logMessage("", msg, args...) } -/* print general system error */ -func Error(msg string, err error) error { - fmt.Printf("%s: %s: %v\n", version.PROGRAM_NAME, color.RedString("error"), err) - return err +// OK message (green) +func OK(msg string, args ...any) { + formatted := fmt.Sprintf(msg, args...) + color.Green("%s * %s\n", formatTimestamp(), formatted) } -/* print fatality and panic */ -func Fatal(msg string, err error) error { - fmt.Printf("%s: %s: %v\n", version.PROGRAM_NAME, color.RedString("fatal"), err) - panic(err) +// Warning message (magenta) +func WARN(msg string, args ...any) { + formatted := fmt.Sprintf(msg, args...) + color.Magenta("%s # %s\n", formatTimestamp(), formatted) } -/* print a useful hint to the user */ -func Hint(format string, args ...any) { +// Error message (red) +func ERROR(msg string, args ...any) { + formatted := fmt.Sprintf(msg, args...) + color.Red("%s ! %s\n", formatTimestamp(), formatted) +} + +// Fatal message and panic +func FATAL(msg string, args ...any) { + formatted := fmt.Sprintf(msg, args...) + color.Red("%s % %s\n", formatTimestamp(), formatted) + panic(formatted) +} + +// Hint message (custom color) +func Hint(msg string, args ...any) { + formatted := fmt.Sprintf(msg, args...) color.RGB(func(hex int) (r, g, b int) { r = (hex >> 16) & 0xFF g = (hex >> 8) & 0xFF b = hex & 0xFF return - }(hint_color)).Printf("hint: %s\n", fmt.Sprintf(format, args...)) + }(hintColor)).Printf("%s * hint: %s\n", formatTimestamp(), formatted) } -/* print message using the ok status color */ -func OK(msg string) { - color.Green(msg) +// Path logging: prints route and status +func Path(path string, err error) { + path = strings.TrimPrefix(path, "/") + if path == "" { + path = "(null)" + } + + if err == nil { + OK("Route: %s - ok", path) + } else if errors.Is(err, config.ErrRouteMiss) { + WARN("Route: %s - %s", path, config.ErrRouteMiss.Error()) + } else { + ERROR("Route: %s - bad", path) + } } -/* print message using the warning status color */ -func WARN(msg string) { - color.Magenta(msg) +// System warning with prefix +func Warning(msg string, err error) error { + WARN("%s: %v", msg, err) + return err } -/* print message using the error status color */ -func ERROR(msg string) { - color.Red(msg) +// System error with prefix +func Error(msg string, err error) error { + ERROR("%s: %v", msg, err) + return err +} + +// Fatal system error +func Fatal(msg string, err error) error { + FATAL("%s: %v", msg, err) + return err } diff --git a/modules/version/version.go b/modules/version/version.go index 8be492c..ec4e087 100644 --- a/modules/version/version.go +++ b/modules/version/version.go @@ -20,3 +20,7 @@ func FullVersion() { fmt.Printf("%s+%s\n", VERSION, gitCommit) os.Exit(0) } + +func GetCommit() string { + return gitCommit +}