diff --git a/pokesay.go b/pokesay.go index c4485438..44d69abb 100644 --- a/pokesay.go +++ b/pokesay.go @@ -43,16 +43,18 @@ func parseFlags() pokesay.Args { listCategories := flag.Bool("list-categories", false, "list all available categories") listNames := flag.Bool("list-names", false, "list all available names") japaneseName := flag.Bool("japanese-name", false, "print the japanese name") + unicodeBox := flag.Bool("unicode-box", false, "use unicode characters to draw the speech box") flag.Parse() var args pokesay.Args if *fastest { args = pokesay.Args{ - Width: *width, - NoWrap: true, - TabSpaces: " ", - NoTabSpaces: true, + Width: *width, + NoWrap: true, + TabSpaces: " ", + NoTabSpaces: true, + BoxCharacters: pokesay.DetermineBoxCharacters(false), } } else { args = pokesay.Args{ @@ -66,6 +68,7 @@ func parseFlags() pokesay.Args { Category: *category, NameToken: *name, JapaneseName: *japaneseName, + BoxCharacters: pokesay.DetermineBoxCharacters(*unicodeBox), } } return args diff --git a/src/pokesay/print.go b/src/pokesay/print.go index 2df04aa3..9116e35f 100644 --- a/src/pokesay/print.go +++ b/src/pokesay/print.go @@ -12,10 +12,18 @@ import ( "github.com/tmck-code/pokesay/src/pokedex" ) -var ( - textStyleItalic *color.Color = color.New(color.Italic) - textStyleBold *color.Color = color.New(color.Bold) -) +type BoxCharacters struct { + HorizontalEdge string + VerticalEdge string + TopRightCorner string + TopLeftCorner string + BottomRightCorner string + BottomLeftCorner string + BalloonString string + Separator string + RightArrow string + CategorySeparator string +} type Args struct { Width int @@ -28,6 +36,44 @@ type Args struct { Category string NameToken string JapaneseName bool + BoxCharacters *BoxCharacters +} + +var ( + textStyleItalic *color.Color = color.New(color.Italic) + textStyleBold *color.Color = color.New(color.Bold) + AsciiBoxCharacters *BoxCharacters = &BoxCharacters{ + HorizontalEdge: "-", + VerticalEdge: "|", + TopRightCorner: "\\", + TopLeftCorner: "/", + BottomRightCorner: "/", + BottomLeftCorner: "\\", + BalloonString: "\\", + Separator: "|", + RightArrow: ">", + CategorySeparator: "/", + } + UnicodeBoxCharacters *BoxCharacters = &BoxCharacters{ + HorizontalEdge: "─", + VerticalEdge: "│", + TopRightCorner: "╮", + TopLeftCorner: "╭", + BottomRightCorner: "╯", + BottomLeftCorner: "╰", + BalloonString: "╲", + Separator: "│", + RightArrow: "→ ", + CategorySeparator: "/", + } +) + +func DetermineBoxCharacters(unicodeBox bool) *BoxCharacters { + if unicodeBox { + return UnicodeBoxCharacters + } else { + return AsciiBoxCharacters + } } // The main print function! This uses a chosen pokemon's index, names and categories, and an @@ -36,14 +82,14 @@ type Args struct { // 2. The cowfile data is retrieved using the matching index, decompressed (un-gzipped), // 3. The pokemon is printed along with the name & category information func Print(args Args, choice int, names []string, categories []string, cows embed.FS) { - printSpeechBubble(bufio.NewScanner(os.Stdin), args.Width, args.NoTabSpaces, args.TabSpaces, args.NoWrap) + printSpeechBubble(args.BoxCharacters, bufio.NewScanner(os.Stdin), args.Width, args.NoTabSpaces, args.TabSpaces, args.NoWrap) printPokemon(args, choice, names, categories, cows) } // Prints text from STDIN, surrounded by a speech bubble. -func printSpeechBubble(scanner *bufio.Scanner, width int, noTabSpaces bool, tabSpaces string, noWrap bool) { - border := strings.Repeat("-", width+2) - fmt.Println("/" + border + "\\") +func printSpeechBubble(boxCharacters *BoxCharacters, scanner *bufio.Scanner, width int, noTabSpaces bool, tabSpaces string, noWrap bool) { + border := strings.Repeat(boxCharacters.HorizontalEdge, width+2) + fmt.Println(boxCharacters.TopLeftCorner + border + boxCharacters.TopRightCorner) for scanner.Scan() { line := scanner.Text() @@ -52,39 +98,41 @@ func printSpeechBubble(scanner *bufio.Scanner, width int, noTabSpaces bool, tabS line = strings.Replace(line, "\t", tabSpaces, -1) } if noWrap { - printSpeechBubbleLine(line, width) + printSpeechBubbleLine(boxCharacters, line, width) } else { - printWrappedText(line, width, tabSpaces) + printWrappedText(boxCharacters, line, width, tabSpaces) } } - fmt.Println("\\" + border + "/") + fmt.Println(boxCharacters.BottomLeftCorner + border + boxCharacters.BottomRightCorner) for i := 0; i < 4; i++ { - fmt.Println(strings.Repeat(" ", i+8), "\\") + fmt.Println(strings.Repeat(" ", i+8), boxCharacters.BalloonString) } } // Prints a single speech bubble line -func printSpeechBubbleLine(line string, width int) { +func printSpeechBubbleLine(boxCharacters *BoxCharacters, line string, width int) { if len(line) > width { - fmt.Printf("| %s\n", line) + fmt.Printf("%s %s\n", boxCharacters.VerticalEdge, line) } else if len(line) == width { - fmt.Printf("| %s |\n", line) + fmt.Printf("%s %s %s\n", boxCharacters.VerticalEdge, line, boxCharacters.VerticalEdge) } else { - fmt.Printf("| %s%s |\n", line, strings.Repeat(" ", width-len(line))) + fmt.Printf( + "%s %s%s %s\n", + boxCharacters.VerticalEdge, line, strings.Repeat(" ", width-len(line)), boxCharacters.VerticalEdge, + ) } } // Prints line of text across multiple lines, wrapping it so that it doesn't exceed the desired width. -func printWrappedText(line string, width int, tabSpaces string) { +func printWrappedText(boxCharacters *BoxCharacters, line string, width int, tabSpaces string) { for _, wline := range strings.Split(wordwrap.WrapString(strings.Replace(line, "\t", tabSpaces, -1), uint(width)), "\n") { - printSpeechBubbleLine(wline, width) + printSpeechBubbleLine(boxCharacters, wline, width) } } // Prints a pokemon with its name & category information. func printPokemon(args Args, index int, names []string, categoryKeys []string, GOBCowData embed.FS) { d, _ := GOBCowData.ReadFile(pokedex.EntryFpath("build/assets/cows", index)) - delimiter := "|" namesFmt := make([]string, 0) for _, name := range names { @@ -93,17 +141,19 @@ func printPokemon(args Args, index int, names []string, categoryKeys []string, G if args.NoCategoryInfo { fmt.Printf( - "%s> %s\n", + "%s%s %s\n", pokedex.Decompress(d), - strings.Join(namesFmt, fmt.Sprintf(" %s ", delimiter)), + args.BoxCharacters.RightArrow, + strings.Join(namesFmt, fmt.Sprintf(" %s ", args.BoxCharacters.Separator)), ) } else { fmt.Printf( - "%s> %s %s %s\n", + "%s%s %s %s %s\n", pokedex.Decompress(d), - strings.Join(namesFmt, fmt.Sprintf(" %s ", delimiter)), - delimiter, - textStyleItalic.Sprint(strings.Join(categoryKeys, "/")), + args.BoxCharacters.RightArrow, + strings.Join(namesFmt, fmt.Sprintf(" %s ", args.BoxCharacters.Separator)), + args.BoxCharacters.Separator, + textStyleItalic.Sprint(strings.Join(categoryKeys, args.BoxCharacters.CategorySeparator)), ) } }