aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile21
-rw-r--r--README.md0
-rw-r--r--cmd/clock.go203
-rw-r--r--cmd/root.go18
-rw-r--r--go.mod20
-rw-r--r--go.sum27
-rw-r--r--main.go16
8 files changed, 306 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fb4efc6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/term-clock
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b390a3c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+BIN := term-clock
+
+all: build
+
+.PHONY: run
+run: build
+ ./$(BIN)
+
+.PHONY: build
+build: $(BIN)
+
+$(BIN): main.go
+ go build -o $(BIN)
+
+.PHONY: fmt
+fmt:
+ go fmt
+
+.PHONY: clean
+clean:
+ go clean
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/cmd/clock.go b/cmd/clock.go
new file mode 100644
index 0000000..69c125d
--- /dev/null
+++ b/cmd/clock.go
@@ -0,0 +1,203 @@
+package cmd
+
+import (
+ "log"
+ "time"
+
+ "github.com/gdamore/tcell/v2"
+ "github.com/spf13/cobra"
+)
+
+func drawSquare(scr tcell.Screen, xOffset, yOffset, w, h int, style tcell.Style) {
+ for dx := 0; dx < w; dx++ {
+ x := xOffset + dx
+ for dy := 0; dy < h; dy++ {
+ y := yOffset + dy
+ scr.SetContent(x, y, ' ', nil, style)
+ }
+ }
+}
+
+func drawNumber(scr tcell.Screen, n, xOffset, yOffset, squareW, squareH int, style tcell.Style) {
+ defs := [...][15]bool{
+ {
+ true, true, true,
+ true, false, true,
+ true, false, true,
+ true, false, true,
+ true, true, true,
+ },
+ {
+ false, false, true,
+ false, false, true,
+ false, false, true,
+ false, false, true,
+ false, false, true,
+ },
+ {
+ true, true, true,
+ false, false, true,
+ true, true, true,
+ true, false, false,
+ true, true, true,
+ },
+ {
+ true, true, true,
+ false, false, true,
+ true, true, true,
+ false, false, true,
+ true, true, true,
+ },
+ {
+ true, false, true,
+ true, false, true,
+ true, true, true,
+ false, false, true,
+ false, false, true,
+ },
+ {
+ true, true, true,
+ true, false, false,
+ true, true, true,
+ false, false, true,
+ true, true, true,
+ },
+ {
+ true, true, true,
+ true, false, false,
+ true, true, true,
+ true, false, true,
+ true, true, true,
+ },
+ {
+ true, true, true,
+ false, false, true,
+ false, false, true,
+ false, false, true,
+ false, false, true,
+ },
+ {
+ true, true, true,
+ true, false, true,
+ true, true, true,
+ true, false, true,
+ true, true, true,
+ },
+ {
+ true, true, true,
+ true, false, true,
+ true, true, true,
+ false, false, true,
+ true, true, true,
+ },
+ }
+
+ squares := defs[n]
+ for i, draw := range squares {
+ if !draw {
+ continue
+ }
+ x := i % 3
+ y := i / 3
+ drawSquare(scr, xOffset+squareW*x, yOffset+squareH*y, squareW, squareH, style)
+ }
+}
+
+func drawClock(scr tcell.Screen, now time.Time, bgStyle, clockStyle tcell.Style) {
+ // Clear the entire screen.
+ scr.SetStyle(bgStyle)
+ scr.Clear()
+
+ // Calculate square width/height and offset.
+ scrW, scrH := scr.Size()
+ // 17
+ // <--------------->
+ // ### ### ### ### ^
+ // # # # # # # # # # |
+ // # # # # # # # # | 5
+ // # # # # # # # # # |
+ // ### ### ### ### v
+ squareW := scrW / (17 + 2)
+ squareH := scrH / (5 + 2)
+ if squareH > squareW {
+ squareH = squareW
+ }
+ if squareW > squareH*3/2 {
+ squareW = squareH * 3 / 2
+ }
+ xOffset := (scrW - squareW*17) / 2
+ yOffset := (scrH - squareH*5) / 2
+
+ // Hour
+ hour := now.Hour()
+ drawNumber(scr, hour/10, xOffset+squareW*0, yOffset, squareW, squareH, clockStyle)
+ drawNumber(scr, hour%10, xOffset+squareW*4, yOffset, squareW, squareH, clockStyle)
+
+ // Colon
+ drawSquare(scr, xOffset+squareW*8, yOffset+squareH*1, squareW, squareH, clockStyle)
+ drawSquare(scr, xOffset+squareW*8, yOffset+squareH*3, squareW, squareH, clockStyle)
+
+ // Minute
+ minute := now.Minute()
+ drawNumber(scr, minute/10, xOffset+squareW*10, yOffset, squareW, squareH, clockStyle)
+ drawNumber(scr, minute%10, xOffset+squareW*14, yOffset, squareW, squareH, clockStyle)
+}
+
+func cmdClock(cmd *cobra.Command, args []string) {
+ bgStyle := tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
+ clockStyle := tcell.StyleDefault.Foreground(tcell.ColorWhite).Background(tcell.ColorOlive)
+
+ scr, err := tcell.NewScreen()
+ if err != nil {
+ log.Fatalf("%+v", err)
+ }
+ if err := scr.Init(); err != nil {
+ log.Fatalf("%+v", err)
+ }
+ defer scr.Fini()
+
+ drawClock(scr, time.Now(), bgStyle, clockStyle)
+
+ quitC := make(chan struct{})
+
+ go func() {
+ for {
+ scr.Show()
+
+ ev := scr.PollEvent()
+ switch ev := ev.(type) {
+ case *tcell.EventResize:
+ drawClock(scr, time.Now(), bgStyle, clockStyle)
+ scr.Sync()
+ case *tcell.EventKey:
+ if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC || ev.Rune() == 'q' {
+ close(quitC)
+ return
+ }
+ }
+ }
+ }()
+
+ t := time.NewTicker(1 * time.Second)
+ defer t.Stop()
+
+ prev := time.Now()
+ for {
+ select {
+ case <-quitC:
+ return
+ case now := <-t.C:
+ if now.Minute() != prev.Minute() {
+ drawClock(scr, now, bgStyle, clockStyle)
+ scr.Show()
+ prev = now
+ }
+ }
+ }
+}
+
+var clockCmd =&cobra.Command{
+ Use: "clock",
+ Short: "Clock mode",
+ Run: cmdClock,
+}
diff --git a/cmd/root.go b/cmd/root.go
new file mode 100644
index 0000000..d0f9713
--- /dev/null
+++ b/cmd/root.go
@@ -0,0 +1,18 @@
+package cmd
+
+import (
+ "github.com/spf13/cobra"
+)
+
+var rootCmd = &cobra.Command{
+ Use: "term-clock",
+ Short: "A clock on your terminal",
+}
+
+func init() {
+ rootCmd.AddCommand(clockCmd)
+}
+
+func Execute() error {
+ return rootCmd.Execute()
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..ff88bd3
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,20 @@
+module github.com/nsfisis/term-clock
+
+go 1.18
+
+require (
+ github.com/gdamore/tcell/v2 v2.4.0
+ github.com/spf13/cobra v1.6.1
+)
+
+require (
+ github.com/gdamore/encoding v1.0.0 // indirect
+ github.com/inconshreveable/mousetrap v1.0.1 // indirect
+ github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
+ github.com/mattn/go-runewidth v0.0.10 // indirect
+ github.com/rivo/uniseg v0.1.0 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
+ golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
+ golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
+ golang.org/x/text v0.3.0 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..728874d
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,27 @@
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+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/v2 v2.4.0 h1:W6dxJEmaxYvhICFoTY3WrLLEXsQ11SaFnKGVEXW57KM=
+github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
+github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
+github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
+github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
+github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
+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=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
+github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
+golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
+golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..8bcded2
--- /dev/null
+++ b/main.go
@@ -0,0 +1,16 @@
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/nsfisis/term-clock/cmd"
+)
+
+func main() {
+ err := cmd.Execute()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}