Skip to content

Commit

Permalink
feat: add banner package
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Sep 23, 2019
1 parent 6955b78 commit e6ac308
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
Empty file removed go/internal/.gitkeep
Empty file.
98 changes: 98 additions & 0 deletions go/internal/banner/banner.go
@@ -0,0 +1,98 @@
package banner

import (
"fmt"
"strings"
)

const (
startLine = 2
stopLine = 5
startColumn = 26
stopColumn = 72
totalLines = stopLine - startLine + 1
totalColumns = stopColumn - startColumn + 1
)

const banner = `
/\
/\ / /\ ______
/ /\/ / \/ | \
| | \/ | ()| |
\ \ | |____|
\ \ \____/ __ __
\/ / / / ___ ____/ /___ __
/ __/ / _ \/ -_) __/ __/ // /
/_____/ /____/\__/_/ \__/\__ /
/__/ /___/
`

func Banner() string {
return banner
}

func Say(message string) string {
ml := strings.Split(wordwrap(message, stopColumn-startColumn), "\n")
// append empty line at the top for short quotes
if len(ml) > totalLines {
line := ml[totalLines-1]
if len(line) >= totalColumns-6 {
line = line[:totalColumns-6]
}
ml[totalLines-1] = line + " [...]"
}
for i := 0; i < (totalLines-len(ml))/2; i++ {
ml = append([]string{""}, ml...)
}

bl := strings.Split(banner, "\n")
output := []string{}
j := 0
for i := 0; i < len(bl); i++ {
if i >= startLine && i <= stopLine {
left := bl[i]
if missing := startColumn - len(bl[i]); missing > 0 {
left += strings.Repeat(" ", missing)
}
right := ""
if j < len(ml) {
right = ml[j]
j++
if missing := totalColumns - len(right); missing/2 > 1 {
right = strings.Repeat(" ", missing/2) + right
}
}
line := fmt.Sprintf("%s%s", left, right)
output = append(output, strings.TrimRight(line, " "))
} else {
output = append(output, bl[i])
}
}
return strings.Join(output, "\n") + "\n"
}

func OfTheDay() string {
q := QOTD()
return Say(q.String())
}

func wordwrap(text string, lineWidth int) string {
words := strings.Fields(strings.TrimSpace(text))
if len(words) == 0 {
return text
}
wrapped := words[0]
spaceLeft := lineWidth - len(wrapped)
for _, word := range words[1:] {
if len(word)+1 > spaceLeft {
wrapped += "\n" + word
spaceLeft = lineWidth - len(word)
} else {
wrapped += " " + word
spaceLeft -= 1 + len(word)
}
}

return wrapped

}
39 changes: 39 additions & 0 deletions go/internal/banner/banner_test.go
@@ -0,0 +1,39 @@
package banner

import (
"fmt"
)

func Example_Say() {
fmt.Println(Say("hello world!"))
// Output:
// /\
// /\ / /\ ______
// / /\/ / \/ | \ hello world!
// | | \/ | ()| |
// \ \ | |____|
// \ \ \____/ __ __
// \/ / / / ___ ____/ /___ __
// / __/ / _ \/ -_) __/ __/ // /
// /_____/ /____/\__/_/ \__/\__ /
// /__/ /___/
}

func Example_Say_Long() {
fmt.Println(Say(`Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`))
// Output:
// /\
// /\ / /\ ______ Lorem ipsum dolor sit amet, consectetur
// / /\/ / \/ | \ adipiscing elit, sed do eiusmod tempor
// | | \/ | ()| | incididunt ut labore et dolore magna aliqua.
// \ \ | |____| Ut enim ad minim veniam, quis nostrud [...]
// \ \ \____/ __ __
// \/ / / / ___ ____/ /___ __
// / __/ / _ \/ -_) __/ __/ // /
// /_____/ /____/\__/_/ \__/\__ /
// /__/ /___/
}

func Example_OfTheDay() {
fmt.Println(OfTheDay())
}
42 changes: 42 additions & 0 deletions go/internal/banner/quote.go
@@ -0,0 +1,42 @@
package banner

import (
"fmt"
"math/rand"
"time"
)

type Quote struct {
Author string
Text string
}

var quotes = []Quote{
{"Albert Camus", "A free press can be good or bad, but, most certainly, without freedom a press will never be anything but bad."},
{"Bruce Schneier", "Cryptography products may be declared illegal, but the information will never be."},
{"Bruce Schneier", "If you think technology can solve your security problems, then you don't understand the problems and you don't understand the technology."},
{"David Brin", "When it comes to privacy and accountability, people always demand the former for themselves and the latter for everyone else."},
{"Edmund Burke", "Better be despised for too anxious apprehensions, than ruined by too confident security."},
{"Gary Kovacs", "Privacy is not an option, and it shouldn’t be the price we accept for just getting on the Internet."},
{"Harry Belafonte", "You can cage the singer but not the song."},
{"John Perry Barlow", "When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl."},
{"Noam Chomsky", "If we don't believe in freedom of expression for people we despise, we don't believe in it at all."},
{"Robbie Sinclair", "Security is always excessive until it’s not enough."},
{"Tom Smothers", "The only valid censorship of ideas is the right of people not to listen."},
{"Voltaire", "We have a natural right to make use of our pens as of our tongue, at our peril, risk and hazard."},
}

func RandomQuote() Quote {
return quotes[rand.Intn(len(quotes))]
}

func QOTD() Quote {
base := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) // FIXME: use local timezone if available
seed := time.Now().Sub(base).Hours() / 24
r := rand.New(rand.NewSource(int64(seed)))
return quotes[r.Intn(len(quotes))]
}

func (q Quote) String() string {
return fmt.Sprintf(`"%s" --%s`, q.Text, q.Author)
}

0 comments on commit e6ac308

Please sign in to comment.