Skip to content

Commit

Permalink
add -postpone flag
Browse files Browse the repository at this point in the history
closes #16
  • Loading branch information
bokwoon95 committed Feb 9, 2025
1 parent 278412b commit 2636aac
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ $ wgo run -tags=fts5 -race -trimpath main.go
- [-exit](#exit-when-the-last-command-exits) - Exit when the last command exits.
- [-stdin](#enable-stdin) - Enable stdin for the last command.
- [-verbose](#log-file-events) - Log file events.
- [-debounce](#debounce-duration) - How quickly to react to file events. Lower debounce values will react quicker.
- [-postpone](#postpone-the-first-execution-of-the-command-until-a-file-is-modified) - Postpone the first execution of the command until a file is modified.

## Advanced Usage

Expand Down Expand Up @@ -334,6 +336,30 @@ Listening on localhost:8080
Listening on localhost:8080
```

## Debounce duration

File events are debounced to prevent a command from repeatedly restarting when a string of file events occur in rapid succession. The default debounce duration is 300ms. Change the duration with the -postpone flag. Lower values will react quicker.

```shell
# Wait 10 milliseconds before restarting.
$ wgo run -debounce 10ms main.go

# Wait 1 second before restarting.
$ wgo -debounce 1s go build -o out main.go :: ./out
```

## Postpone the first execution of the command until a file is modified

By default, wgo runs the command immediately. If you wish to postpone running the command until a file is modified, use the -postpone flag.

```shell
# Prints hello immediately, and whenever file is modified.
$ wgo echo hello

# Prints hello only when a file is modified.
$ wgo -postpone echo hello
```

## Debug Go code using GoLand or VSCode with wgo

You need to ensure the [delve debugger](https://github.com/go-delve/delve) is installed.
Expand Down
34 changes: 33 additions & 1 deletion wgo_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ type WgoCmd struct {
// Debounce duration for file events.
Debounce time.Duration

// If Postpone is true, WgoCmd will postpone the first execution of the
// command(s) until a file is modified.
Postpone bool

ctx context.Context
isRun bool // Whether the command is `wgo run`.
binPath string // Where the built go binary lives.
Expand Down Expand Up @@ -176,6 +180,7 @@ func WgoCommand(ctx context.Context, args []string) (*WgoCmd, error) {
flagset.BoolVar(&wgoCmd.Exit, "exit", false, "Exit when the last command exits.")
flagset.BoolVar(&wgoCmd.EnableStdin, "stdin", false, "Enable stdin for the last command.")
flagset.StringVar(&debounce, "debounce", "300ms", "How quickly to react to file events. Lower debounce values will react quicker.")
flagset.BoolVar(&wgoCmd.Postpone, "postpone", false, "Postpone the first execution of the command until a file is modified.")
flagset.Func("root", "Specify an additional root directory to watch. Can be repeated.", func(value string) error {
root, err := filepath.Abs(value)
if err != nil {
Expand Down Expand Up @@ -368,9 +373,36 @@ func (wgoCmd *WgoCmd) Run() error {
timer := time.NewTimer(0)
timer.Stop()

for {
for restartCount := 0; ; restartCount++ {
CMD_CHAIN:
for i, args := range wgoCmd.ArgsList {
if restartCount == 0 && wgoCmd.Postpone {
for {
select {
case <-wgoCmd.ctx.Done():
return nil
case event := <-watcher.Events:
if !event.Has(fsnotify.Create) && !event.Has(fsnotify.Write) && !event.Has(fsnotify.Remove) {
continue
}
fileinfo, err := os.Stat(event.Name)
if err != nil {
continue
}
if fileinfo.IsDir() {
if event.Has(fsnotify.Create) {
wgoCmd.addDirsRecursively(watcher, event.Name)
}
continue
}
if wgoCmd.match(event.Op.String(), event.Name) {
timer.Reset(wgoCmd.Debounce)
}
case <-timer.C:
break CMD_CHAIN
}
}
}
// Step 1: Prepare the command.
//
// We are not using exec.CommandContext() because it uses
Expand Down
49 changes: 48 additions & 1 deletion wgo_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ func TestWgoCommands(t *testing.T) {
}, {
description: "wgo flags",
args: []string{
"wgo", "-root", "/secrets", "-file", ".", "-verbose", "echo", "hello",
"wgo", "-root", "/secrets", "-file", ".", "-verbose", "-postpone", "echo", "hello",
},
wantCmds: []*WgoCmd{{
Roots: []string{".", "/secrets"},
Expand All @@ -389,6 +389,7 @@ func TestWgoCommands(t *testing.T) {
{"echo", "hello"},
},
Debounce: 300 * time.Millisecond,
Postpone: true,
}},
}, {
description: "escaped ::",
Expand Down Expand Up @@ -644,6 +645,52 @@ func TestWgoCmd_Run(t *testing.T) {
t.Errorf("\ngot: %q\nwant: %q", got, want)
}
})

t.Run("postpone off", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
wgoCmd, err := WgoCommand(ctx, []string{
"-file", ".none", "echo", "hello",
})
if err != nil {
t.Fatal(err)
}
buf := &Buffer{}
wgoCmd.Stdout = buf
err = wgoCmd.Run()
if err != nil {
t.Fatal(err)
}
got := strings.TrimSpace(buf.String())
want := "hello"
if got != want {
t.Errorf("\ngot: %q\nwant: %q", got, want)
}
})

t.Run("postpone on", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
wgoCmd, err := WgoCommand(ctx, []string{
"-file", ".none", "-postpone", "echo", "hello",
})
if err != nil {
t.Fatal(err)
}
buf := &Buffer{}
wgoCmd.Stdout = buf
err = wgoCmd.Run()
if err != nil {
t.Fatal(err)
}
got := strings.TrimSpace(buf.String())
want := ""
if got != want {
t.Errorf("\ngot: %q\nwant: %q", got, want)
}
})
}

func TestWgoCmd_FileEvent(t *testing.T) {
Expand Down

0 comments on commit 2636aac

Please sign in to comment.