123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- package hhc_common
- import (
- "fmt"
- "github.com/cheynewallace/tabby"
- "github.com/mattn/go-runewidth"
- "github.com/ttacon/chalk"
- "io"
- "strings"
- "text/tabwriter"
- "unicode"
- )
- func FPrintHelp(w io.Writer, h []SDTHelpInfo) {
- sw := &strings.Builder{}
- t := tabby.NewCustom(tabwriter.NewWriter(sw, 0, 0, 2, ' ', 0))
- for i, v := range h {
- t.AddLine(i, v.Name, v.Description)
- }
- t.Print()
- ostr := sw.String()
- pcrlf := strings.ReplaceAll(ostr, "\n", "\r\n")
- _, _ = fmt.Fprint(w, pcrlf)
- }
- func GetUnicodeDeleteWidth(r rune) int {
- // Tested with ASCII non-control, Chinese, Japanese characters and Emoji.
- // I am not sure this is ok for all Unicode characters, so I made it as a dedicated function.
- return runewidth.RuneWidth(r)
- }
- type PrintableMessage struct {
- Text string
- Style chalk.Style
- }
- func splitStringInWidth(tw int, cll int, s string) []string {
- rstrl := []string{}
- nstr := strings.Builder{}
- lcc := cll
- for _, v := range []rune(s) {
- rw := runewidth.RuneWidth(v)
- if rw+lcc > tw {
- lcc = rw
- rstrl = append(rstrl, nstr.String())
- nstr = strings.Builder{}
- nstr.WriteRune(v)
- } else {
- lcc += rw
- nstr.WriteRune(v)
- }
- }
- if nstr.Len() > 0 {
- rstrl = append(rstrl, nstr.String())
- }
- return rstrl
- }
- func transToChalkedText(colorful bool, s string, styl chalk.Style) string {
- if colorful {
- if styl != nil {
- return styl.Style(s)
- }
- }
- return s
- }
- func PrintPrintablMessagesIntoLines(pm []PrintableMessage, termWidth int, colorful bool) []string {
- rlns := []string{}
- cln := strings.Builder{}
- clcnt := 0
- for _, v := range pm {
- sw := runewidth.StringWidth(v.Text)
- if sw+clcnt > termWidth {
- spll := splitStringInWidth(termWidth, clcnt, v.Text)
- for xis, vs := range spll {
- if xis == 0 {
- cln.WriteString(transToChalkedText(colorful, vs, v.Style))
- rlns = append(rlns, cln.String())
- cln = strings.Builder{}
- clcnt = 0
- } else {
- if xis == len(spll)-1 {
- cln.WriteString(transToChalkedText(colorful, vs, v.Style))
- clcnt += runewidth.StringWidth(vs)
- } else {
- rlns = append(rlns, transToChalkedText(colorful, vs, v.Style))
- }
- }
- }
- } else {
- clcnt += sw
- cln.WriteString(transToChalkedText(colorful, v.Text, v.Style))
- }
- if clcnt == termWidth {
- rlns = append(rlns, cln.String())
- cln = strings.Builder{}
- }
- }
- if cln.Len() > 0 {
- rlns = append(rlns, cln.String())
- }
- return rlns
- }
- func PrintStringIntoLines(s string, termWidth int) []string {
- if runewidth.StringWidth(s) <= termWidth {
- return []string{s}
- }
- rlns := []string{}
- cln := strings.Builder{}
- clcnt := 0
- ra := []rune(s)
- for _, v := range ra {
- rw := runewidth.RuneWidth(v)
- if rw+clcnt > termWidth {
- rlns = append(rlns, cln.String())
- cln = strings.Builder{}
- cln.WriteRune(v)
- clcnt = rw
- } else {
- cln.WriteRune(v)
- clcnt += rw
- }
- }
- if cln.Len() > 0 {
- rlns = append(rlns, cln.String())
- }
- return rlns
- }
- func TestRuneSlice(r1, r2 []rune) bool {
- if r1 == nil && r2 == nil {
- return true
- }
- if r1 == nil || r2 == nil {
- return false
- }
- if len(r1) != len(r2) {
- return false
- }
- for i := range r1 {
- if r1[i] != r2[i] {
- return false
- }
- }
- return true
- }
- func PrintRunesIntoLinesWithCursor(ra []rune, termWidth int, cursorPos int) (l []string, curY, curX int) {
- if runewidth.StringWidth(string(ra)) <= termWidth {
- return []string{string(ra)}, 0, cursorPos + 1
- }
- rlns := []string{}
- cln := strings.Builder{}
- clcnt := 0
- linecount := 0
- cpy, cpx := 0, 0
- hit := false
- for i, v := range ra {
- rw := runewidth.RuneWidth(v)
- if rw+clcnt > termWidth {
- rlns = append(rlns, cln.String())
- linecount++
- cln = strings.Builder{}
- cln.WriteRune(v)
- clcnt = rw
- } else {
- cln.WriteRune(v)
- clcnt += rw
- }
- if i == cursorPos {
- cpy = linecount
- cpx = clcnt
- hit = true
- }
- }
- if cln.Len() > 0 {
- rlns = append(rlns, cln.String())
- linecount++
- }
- if !hit {
- cpy = linecount - 1
- cpx = clcnt + 1
- }
- //fmt.Println("CPY=", cpy, "CPX=", cpx)
- return rlns, cpy, cpx
- }
- func FirstToUpper(s string) string {
- rs := []rune(s)
- if len(rs) > 0 {
- rs[0] = unicode.ToUpper(rs[0])
- }
- return string(rs)
- }
- func GetCompleteSuffix(cmd, prefix string) string {
- return strings.TrimPrefix(cmd, prefix) + " "
- }
|