diff --git a/go.mod b/go.mod index 2fabc46..2d49054 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,8 @@ module gitlab.com/dananglin/Pominal -go 1.12 +go 1.13 -require github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21 +require ( + github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21 + github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329 +) diff --git a/go.sum b/go.sum index b4a5680..f30e104 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,23 @@ github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21 h1:moSC7ACaTejHmVRRwfDTMgByRSwjg2vZooncdWLj7o8= github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21/go.mod h1:NtXa9WwQsukMHZpjNakTTz0LArxvGYdPA9CjIcUSZ6s= +github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08= +github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM= +github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= +github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4= +github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= +github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329 h1:MubHhHJ4mB0A5wMcc2am0/51RydztIDoumyOd0r0yBw= +github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329/go.mod h1:/rBeY22VG2QprWnEqG57IBC8biVu3i0DOIjRLc9I8H0= +github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191018095205-727590c5006e h1:ZtoklVMHQy6BFRHkbG6JzK+S6rX82//Yeok1vMlizfQ= +golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go index 2269dac..78bbb8b 100644 --- a/main.go +++ b/main.go @@ -22,8 +22,9 @@ import ( "flag" "fmt" "os" - "os/exec" "time" + + "github.com/rivo/tview" ) const ( @@ -83,22 +84,14 @@ func main() { maxWorkSessions, ) - pominal.Run() -} + app := tview.NewApplication() + infoUI := newInfoUI() + timerUI := newTimerUI(app) + flex := newFlex(infoUI, timerUI) -// printScreen prints the details of the Pominal session on screen including -// the current work session number, the timer's current label and the current countdoen. -// TODO: To be removed when TUI is implemented. -func printScreen(countdown float64, pominalCount, workSessionCount, maxWorkSession int, label string) { - clearScreen() - fmt.Printf("Pominal cycle: %d\nWork session: %d of %d\n\n", pominalCount, workSessionCount, maxWorkSession) - fmt.Printf("Session: %s\nTime remaining: %02d:%02d", label, int(countdown)/60, int(countdown)%60) -} + go pominal.Run(infoUI, timerUI) + if err := app.SetRoot(flex, true).SetFocus(flex).Run(); err != nil { + panic(err) + } -// clearScreen clears the terminal screen -// TODO: To be removed when TUI is implemented -func clearScreen() { - cmd := exec.Command("clear") - cmd.Stdout = os.Stdout - cmd.Run() } diff --git a/pominal.go b/pominal.go index df0982a..ceab8f6 100644 --- a/pominal.go +++ b/pominal.go @@ -19,11 +19,12 @@ package main import ( - "fmt" "os" "os/signal" "syscall" "time" + + "github.com/rivo/tview" ) type Pominal struct { @@ -70,35 +71,29 @@ func NewPominal(w, s, l float64, m int) Pominal { } // Run Pominal -func (p *Pominal) Run() { +func (p *Pominal) Run(infoUI, timerUI *tview.TextView) { s := make(chan os.Signal, 1) signal.Notify(s, syscall.SIGINT, syscall.SIGTERM) - p.UpdateSession() + p.UpdateSession(infoUI) t := time.NewTicker(1 * time.Second) infinite: for { select { - case sig := <-s: - fmt.Printf("\n\nReceived signal '%s'. Closing Pominal.\n", sig) + case <-s: + // fmt.Printf("\n\nReceived signal '%s'. Closing Pominal.\n", sig) t.Stop() break infinite case <-t.C: p.countdown-- if p.countdown < 0 { - fmt.Printf("\n%s session has finished.\n", p.label) t.Stop() - p.UpdateSession() + p.UpdateSession(infoUI) time.Sleep(1 * time.Second) t = time.NewTicker(1 * time.Second) } else { - printScreen(p.countdown, - p.cycle, - p.workSession, - p.maxWorkSessions, - p.label, - ) + drawTimer(timerUI, p.countdown) } } } @@ -110,7 +105,7 @@ infinite: // If a 'long break' session is over then the Pominal cycle // is incremented and the work session counter is reset // to 1. -func (p *Pominal) UpdateSession() { +func (p *Pominal) UpdateSession(i *tview.TextView) { switch p.label { case workTimerLabel: if p.workSession >= p.maxWorkSessions { @@ -133,6 +128,7 @@ func (p *Pominal) UpdateSession() { p.countdown = p.work p.label = workTimerLabel } + drawInfo(i, p.cycle, p.workSession, p.maxWorkSessions, p.label) alert(p.label) } diff --git a/ui.go b/ui.go new file mode 100644 index 0000000..bbac8a4 --- /dev/null +++ b/ui.go @@ -0,0 +1,59 @@ +/* + Pominal + Copyright (C) 2019 Daniel Anglin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +package main + +import ( + "fmt" + + "github.com/rivo/tview" +) + +func newInfoUI() *tview.TextView { + i := tview.NewTextView() + i.SetBorder(true) + i.SetTitle(" Pominal ") + i.SetTitleAlign(tview.AlignLeft) + + return i +} + +func newTimerUI(app *tview.Application) *tview.TextView { + t := tview.NewTextView().SetTextAlign(tview.AlignCenter).SetChangedFunc(func() { + app.Draw() + }) + t.SetBorder(true) + + return t +} + +func newFlex(info, timer *tview.TextView) *tview.Flex { + f := tview.NewFlex().AddItem(info, 30, 1, false).AddItem(timer, 50, 1, false) + + return f +} + +func drawInfo(t *tview.TextView, pominalCycle, workSessions, maxWorkSessions int, label string) { + t.Clear() + fmt.Fprintf(t, "\nPominal cycle: %d\nWork session: %d of %d\nSession: %s", pominalCycle, workSessions, maxWorkSessions, label) +} + +func drawTimer(t *tview.TextView, countdown float64) { + t.Clear() + fmt.Fprintf(t, "\nTime remaining:\n%02d:%02d", int(countdown)/60, int(countdown)%60) +}