-
Notifications
You must be signed in to change notification settings - Fork 0
/
spectator.go
154 lines (143 loc) · 3.77 KB
/
spectator.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
// Copyright 2020 The Go Authors and UGO Authors
/*
Package ugoSpectator implements a simple library to watch files on the
directory specified.
Methods:
Init() (*UgoSpectator, error)
Close() error
*/
package spectator
import (
"context"
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/ugo-framework/ugo-logger/logger"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
"time"
)
// UgoSpectator struct with Watcher and all methods
type UgoSpectator struct {
Watcher *fsnotify.Watcher // *fsnotify watcher instance
osV string // osV take the current os
dirname string // dirname to watch
Ch chan bool // ch to trigger on file change
CancelCtx context.CancelFunc // context to cancel
}
// Init initializes the fsnotify NewWatcher and
// a *fsnotify watcher instance and an error
func Init(dirname string) (*UgoSpectator, error) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return &UgoSpectator{}, err
}
ugoWatcher := &UgoSpectator{Watcher: watcher, osV: runtime.GOOS, Ch: make(chan bool)}
clear(ugoWatcher.osV)
logger.Info("Ugo Spectator is watching your files")
ctx, cancel := context.WithCancel(context.Background())
ugoWatcher.CancelCtx = cancel
cPath, err := os.Getwd()
if err != nil {
return &UgoSpectator{}, err
}
pathToWatch := path.Join(cPath, dirname)
ugoWatcher.dirname = pathToWatch
logger.Warn("at ", pathToWatch)
dirsToWatch := []string{pathToWatch}
files, err := ioutil.ReadDir(pathToWatch)
if err != nil {
fmt.Println(err)
}
for _, f := range files {
if f.IsDir() {
err := filepath.Walk(f.Name(),
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() && info.Name()[:1] != "." {
dirsToWatch = append(dirsToWatch, path)
}
return nil
})
if err != nil {
fmt.Println(err)
}
}
}
for _, p := range dirsToWatch {
err = watcher.Add(p)
if err != nil {
fmt.Println(err)
}
}
// calling fsNotifiyFunc in a goroutine
go fsNotifiyFunc(ctx, ugoWatcher.osV, ugoWatcher)
return ugoWatcher, nil
}
// Close return error if an error occurs during the closing of the
// fsnotify watcher instance
func (u *UgoSpectator) Close() error {
u.CancelCtx()
logger.Error("\nUgo Spectator Closing\n")
return u.Watcher.Close()
}
// Clear screen function
func clear(osV string) {
if osV == "linux" {
cmd := exec.Command("clear")
cmd.Stdout = os.Stdout
cmd.Run()
}
if osV == "darwin" {
cmd := exec.Command("clear")
cmd.Stdout = os.Stdout
cmd.Run()
}
if osV == "windows" {
cmd := exec.Command("cmd", "/c", "cls")
cmd.Stdout = os.Stdout
cmd.Run()
}
}
func fsNotifiyFunc(ctx context.Context, osV string, u *UgoSpectator) {
for {
select {
case event, ok := <-u.Watcher.Events:
if !ok {
return
}
fileSplit := strings.SplitN(event.Name, "/", -1)
if event.Op == fsnotify.Create {
fmt.Printf("modified file: %s/%s\n", fileSplit[len(fileSplit)-2], fileSplit[len(fileSplit)-1])
}
if event.Op == fsnotify.Write {
fmt.Printf("modified file: %s/%s\n", fileSplit[len(fileSplit)-2], fileSplit[len(fileSplit)-1])
}
if event.Op&fsnotify.Remove == fsnotify.Remove {
fmt.Printf("Removed file: %s/%s\n", fileSplit[len(fileSplit)-2], fileSplit[len(fileSplit)-1])
logger.Warn("\nat ", "Reloading...")
}
u.Ch <- true
logger.Info("Reloading...")
time.Sleep(time.Second * 1)
clear(osV)
logger.Info("Ugo Spectator is watching your files")
logger.Info("\nat ", u.dirname)
ctx.Done()
if event.Op&fsnotify.Rename == fsnotify.Rename {
fmt.Printf("Removed file: %s/%s\n", fileSplit[len(fileSplit)-2], fileSplit[len(fileSplit)-1])
}
case err, ok := <-u.Watcher.Errors:
if !ok {
return
}
fmt.Println("error:", err)
}
}
}