diff --git a/cmd/otter/dev.go b/cmd/otter/dev.go index e711b45..e935aba 100644 --- a/cmd/otter/dev.go +++ b/cmd/otter/dev.go @@ -10,12 +10,14 @@ import ( "os/exec" "os/signal" "path/filepath" + "runtime" "strings" "sync" "syscall" "time" "github.com/a-h/templ/cmd/templ/generatecmd" + "github.com/a-h/templ/cmd/templ/sloghandler" "github.com/fsnotify/fsnotify" "github.com/martinmunillas/otter/env" "github.com/spf13/cobra" @@ -29,6 +31,8 @@ var devCmd = &cobra.Command{ port := env.RequiredIntEnvVar("PORT") actualPort := port - 1 + verbose, _ := cmd.Flags().GetBool("verbose") + userInterrupt := make(chan os.Signal, 1) signal.Notify(userInterrupt, syscall.SIGTERM, syscall.SIGINT) ctx, cancel := context.WithCancel(context.Background()) @@ -41,28 +45,46 @@ var devCmd = &cobra.Command{ os.Exit(1) }() + loggingLevel := slog.LevelInfo.Level() + if verbose { + loggingLevel = slog.LevelDebug.Level() + } + + logger := slog.New(sloghandler.NewHandler(os.Stderr, &slog.HandlerOptions{ + AddSource: verbose, + Level: loggingLevel, + })) + var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() - runTemplProxy(ctx, port, actualPort) + runTemplProxy(ctx, logger, port, actualPort) }() go func() { defer wg.Done() - runReloadServer(ctx, actualPort) + runReloadServer(ctx, logger, actualPort) }() wg.Wait() }, } -func runTemplProxy(ctx context.Context, port int64, actualPort int64) { - err := generatecmd.Run(ctx, slog.Default(), generatecmd.Arguments{ - Watch: true, - ProxyPort: int(port), - Proxy: fmt.Sprintf("http://localhost:%d", actualPort), - OpenBrowser: true, +func init() { + devCmd.PersistentFlags().BoolP("verbose", "v", false, "Enable verbose output") +} + +func runTemplProxy(ctx context.Context, logger *slog.Logger, port int64, actualPort int64) { + err := generatecmd.Run(ctx, logger, generatecmd.Arguments{ + Watch: true, + ProxyPort: int(port), + Proxy: fmt.Sprintf("http://localhost:%d", actualPort), + OpenBrowser: true, + KeepOrphanedFiles: false, + WorkerCount: runtime.NumCPU(), + IncludeVersion: true, + Path: ".", }) if err != nil { log.Printf("Error running templ command: %v", err) @@ -76,17 +98,17 @@ func makeMainCmd(port int64) *exec.Cmd { return cmd } -func runReloadServer(ctx context.Context, port int64) { +func runReloadServer(ctx context.Context, logger *slog.Logger, port int64) { watcher, err := fsnotify.NewWatcher() if err != nil { - log.Fatal(err) + logger.Error(err.Error()) } defer watcher.Close() - err = addAllGoDirectories(watcher) + err = addAllGoDirectories(watcher, logger) if err != nil { - log.Fatal(err) + logger.Error(err.Error()) } cmd := makeMainCmd(port) @@ -100,14 +122,17 @@ func runReloadServer(ctx context.Context, port int64) { if !ok { return } - if !event.Has(fsnotify.Write) || !event.Has(fsnotify.Create) || !strings.HasSuffix(event.Name, ".go") { + if !(event.Has(fsnotify.Write) || event.Has(fsnotify.Create)) || !strings.HasSuffix(event.Name, ".go") { continue } + logger.Debug(fmt.Sprintf("Go file %s changed", event.Name)) if cmd.Process != nil { + logger.Debug("Stopping running server") stop(cmd) _ = cmd.Wait() + logger.Debug("Stopped running server") } - log.Printf("Restarting server, file %s changed\n", event.Name) + logger.Debug("Restarting server") cmd = makeMainCmd(port) cmd.Start() defer stop(cmd) @@ -115,13 +140,13 @@ func runReloadServer(ctx context.Context, port int64) { if !ok { return } - log.Println("error:", err) + logger.Error(err.Error()) } } } -func addAllGoDirectories(w *fsnotify.Watcher) error { +func addAllGoDirectories(w *fsnotify.Watcher, logger *slog.Logger) error { root, err := filepath.Abs("./") if err != nil { return err @@ -133,6 +158,7 @@ func addAllGoDirectories(w *fsnotify.Watcher) error { if !d.IsDir() && strings.HasSuffix(path, ".go") { dir := filepath.Dir(path) err = w.Add(dir) + logger.Debug(fmt.Sprintf("Watching %s directory", dir)) if err != nil { return err } diff --git a/go.mod b/go.mod index 9afc15c..fdb1a6a 100644 --- a/go.mod +++ b/go.mod @@ -17,14 +17,16 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cli/browser v1.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fatih/color v1.16.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.24.0 // indirect golang.org/x/sys v0.23.0 // indirect - golang.org/x/term v0.23.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index aed1cda..910b440 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -26,6 +28,11 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -59,16 +66,14 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=