Commit
+105 -10 +/-5 browse
1 | diff --git a/README.md b/README.md |
2 | index dac20d9..28fe9e5 100644 |
3 | --- a/README.md |
4 | +++ b/README.md |
5 | @@ -59,6 +59,21 @@ Example: |
6 | |
7 | ## Integrations |
8 | |
9 | + By default pomo will setup a Unix socket and serve it's status there. |
10 | + |
11 | + ```bash |
12 | + echo | socat stdio UNIX-CONNECT:/home/kevin/.pomo/pomo.sock | jq . |
13 | + { |
14 | + "state": 1, |
15 | + "remaining": 1492000000000, |
16 | + "count": 0, |
17 | + "n_pomodoros": 4 |
18 | + } |
19 | + ``` |
20 | + |
21 | + Alternately by setting the `publish` flag to `true` it will publish it's status |
22 | + to an existing socket. |
23 | + |
24 | ### Status Bars |
25 | |
26 | The Pomo CLI can output the current state of a running task session via the `pomo status` |
27 | @@ -76,6 +91,43 @@ interval = 1 |
28 | exec = pomo status |
29 | ``` |
30 | |
31 | + #### [luastatus](https://github.com/shdown/luastatus) |
32 | + |
33 | + Configured this bar by setting `publish` to `true`. |
34 | + |
35 | + ```lua |
36 | + widget = { |
37 | + plugin = "unixsock", |
38 | + opts = { |
39 | + path = "pomo.sock", |
40 | + timeout = 2, |
41 | + }, |
42 | + cb = function(t) |
43 | + local full_text |
44 | + local foreground = "" |
45 | + local background = "" |
46 | + if t.what == "line" then |
47 | + if string.match(t.line, "R") then |
48 | + -- green |
49 | + foreground = "#ffffff" |
50 | + background = "#307335" |
51 | + end |
52 | + if string.match(t.line, "B") or string.match(t.line, "P") or string.match(t.line, "C") then |
53 | + -- red |
54 | + foreground = "#ffffff" |
55 | + background = "ff8080" |
56 | + end |
57 | + return { full_text = t.line, background = background, foreground = foreground } |
58 | + elseif t.what == "timeout" then |
59 | + return { full_text = "-" } |
60 | + elseif t.what == "hello" then |
61 | + return { full_text = "-" } |
62 | + end |
63 | + end, |
64 | + } |
65 | + |
66 | + ``` |
67 | + |
68 | |
69 | ## Roadmap |
70 | |
71 | diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go |
72 | index 0f6825c..2c8fdc9 100644 |
73 | --- a/pkg/cmd/cmd.go |
74 | +++ b/pkg/cmd/cmd.go |
75 | @@ -212,13 +212,13 @@ func _status(config *pomo.Config) func(*cli.Cmd) { |
76 | cmd.Action = func() { |
77 | client, err := pomo.NewClient(config.SocketPath) |
78 | if err != nil { |
79 | - pomo.OutputStatus(pomo.Status{}) |
80 | + fmt.Println(pomo.FormatStatus(pomo.Status{})) |
81 | return |
82 | } |
83 | defer client.Close() |
84 | status, err := client.Status() |
85 | maybe(err) |
86 | - pomo.OutputStatus(*status) |
87 | + fmt.Println(pomo.FormatStatus(*status)) |
88 | } |
89 | } |
90 | } |
91 | diff --git a/pkg/internal/config.go b/pkg/internal/config.go |
92 | index e5090f1..04d3a44 100644 |
93 | --- a/pkg/internal/config.go |
94 | +++ b/pkg/internal/config.go |
95 | @@ -21,6 +21,12 @@ type Config struct { |
96 | DBPath string `json:"dbPath"` |
97 | SocketPath string `json:"socketPath"` |
98 | IconPath string `json:"iconPath"` |
99 | + // Publish pushes updates to the configured |
100 | + // SocketPath rather than listening for requests |
101 | + Publish bool `json:"publish"` |
102 | + // PublishJson pushes socket updates as a JSON |
103 | + // encoded status message instead of string formatted |
104 | + PublishJson bool `json:"publishJson"` |
105 | } |
106 | |
107 | type ColorMap struct { |
108 | diff --git a/pkg/internal/server.go b/pkg/internal/server.go |
109 | index 38357c7..03e7443 100644 |
110 | --- a/pkg/internal/server.go |
111 | +++ b/pkg/internal/server.go |
112 | @@ -6,14 +6,18 @@ import ( |
113 | "fmt" |
114 | "net" |
115 | "os" |
116 | + "time" |
117 | ) |
118 | |
119 | // Server listens on a Unix domain socket |
120 | // for Pomo status requests |
121 | type Server struct { |
122 | - listener net.Listener |
123 | - runner *TaskRunner |
124 | - running bool |
125 | + listener net.Listener |
126 | + runner *TaskRunner |
127 | + running bool |
128 | + publish bool |
129 | + publishJson bool |
130 | + socketPath string |
131 | } |
132 | |
133 | func (s *Server) listen() { |
134 | @@ -31,17 +35,50 @@ func (s *Server) listen() { |
135 | } |
136 | } |
137 | |
138 | + func (s *Server) push() { |
139 | + ticker := time.NewTicker(1 * time.Second) |
140 | + for s.running { |
141 | + conn, err := net.Dial("unix", s.socketPath) |
142 | + if err != nil { |
143 | + <-ticker.C |
144 | + continue |
145 | + } |
146 | + status := s.runner.Status() |
147 | + if s.publishJson { |
148 | + raw, _ := json.Marshal(status) |
149 | + json.NewEncoder(conn).Encode(raw) |
150 | + } else { |
151 | + conn.Write([]byte(FormatStatus(*status) + "\n")) |
152 | + } |
153 | + conn.Close() |
154 | + <-ticker.C |
155 | + } |
156 | + } |
157 | + |
158 | func (s *Server) Start() { |
159 | s.running = true |
160 | - go s.listen() |
161 | + if s.publish { |
162 | + go s.push() |
163 | + } else { |
164 | + go s.listen() |
165 | + } |
166 | } |
167 | |
168 | func (s *Server) Stop() { |
169 | s.running = false |
170 | - s.listener.Close() |
171 | + if s.listener != nil { |
172 | + s.listener.Close() |
173 | + } |
174 | } |
175 | |
176 | func NewServer(runner *TaskRunner, config *Config) (*Server, error) { |
177 | + if config.Publish { |
178 | + return &Server{ |
179 | + runner: runner, |
180 | + publish: true, |
181 | + publishJson: config.PublishJson, |
182 | + socketPath: config.SocketPath}, nil |
183 | + } |
184 | //check if socket file exists |
185 | if _, err := os.Stat(config.SocketPath); err == nil { |
186 | _, err := net.Dial("unix", config.SocketPath) |
187 | diff --git a/pkg/internal/util.go b/pkg/internal/util.go |
188 | index 70b4433..f8b0c5c 100644 |
189 | --- a/pkg/internal/util.go |
190 | +++ b/pkg/internal/util.go |
191 | @@ -68,14 +68,14 @@ func SummerizeTasks(config *Config, tasks []*Task) { |
192 | } |
193 | } |
194 | |
195 | - func OutputStatus(status Status) { |
196 | + func FormatStatus(status Status) string { |
197 | state := "?" |
198 | if status.State >= RUNNING { |
199 | state = string(status.State.String()[0]) |
200 | } |
201 | if status.State == RUNNING { |
202 | - fmt.Printf("%s [%d/%d] %s", state, status.Count, status.NPomodoros, status.Remaining) |
203 | + return fmt.Sprintf("%s [%d/%d] %s", state, status.Count, status.NPomodoros, status.Remaining) |
204 | } else { |
205 | - fmt.Printf("%s [%d/%d] -", state, status.Count, status.NPomodoros) |
206 | + return fmt.Sprintf("%s [%d/%d] -", state, status.Count, status.NPomodoros) |
207 | } |
208 | } |