diff --git a/bordered_widget.go b/bordered_widget.go index 6c9eb6f..129c62c 100644 --- a/bordered_widget.go +++ b/bordered_widget.go @@ -22,7 +22,7 @@ THE SOFTWARE. package widgets import ( - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/button.go b/button.go index 822f690..c365dba 100644 --- a/button.go +++ b/button.go @@ -25,7 +25,7 @@ import ( "fmt" "strings" - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/checkbox.go b/checkbox.go index 751b50b..502b299 100644 --- a/checkbox.go +++ b/checkbox.go @@ -24,7 +24,7 @@ package widgets import ( "fmt" - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/field.go b/field.go index 7f0d2d8..9b49c35 100644 --- a/field.go +++ b/field.go @@ -24,7 +24,7 @@ package widgets import ( "fmt" - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3c2edc4 --- /dev/null +++ b/go.mod @@ -0,0 +1,13 @@ +module git.bullercodeworks.com/brian/tcell-widgets + +go 1.24.2 + +require github.com/gdamore/tcell v1.4.0 + +require ( + github.com/gdamore/encoding v1.0.0 // indirect + github.com/lucasb-eyer/go-colorful v1.0.3 // indirect + github.com/mattn/go-runewidth v0.0.7 // indirect + golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 // indirect + golang.org/x/text v0.3.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..72a6b71 --- /dev/null +++ b/go.sum @@ -0,0 +1,12 @@ +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.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU= +github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0= +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.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10= +golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/helpers/event_helpers.go b/helpers/event_helpers.go new file mode 100644 index 0000000..64c2c9f --- /dev/null +++ b/helpers/event_helpers.go @@ -0,0 +1,97 @@ +/* +Copyright © Brian Buller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package helpers + +import ( + "github.com/gdamore/tcell" +) + +func IsKeyEvent(e tcell.Event) bool { + _, ok := e.(*tcell.EventKey) + return ok +} + +func IsKey(e tcell.EventKey, opts ...tcell.Key) bool { + for i := range opts { + if e.Key() == opts[i] { + return true + } + } + return false +} + +func IsBS(e tcell.EventKey) bool { + return IsKey(e, tcell.KeyBackspace, tcell.KeyBackspace2) +} + +func KeyIsDisplayable(ev tcell.EventKey) bool { + return KeyIsSpace(ev) || KeyIsAlphaNumeric(ev) || KeyIsSymbol(ev) +} + +func KeyIsSpace(ev tcell.EventKey) bool { + r := ev.Rune() + return r == ' ' +} + +func KeyIsAlphaNumeric(ev tcell.EventKey) bool { + return KeyIsAlpha(ev) || KeyIsNumeric(ev) +} + +func KeyIsAlpha(ev tcell.EventKey) bool { + r := ev.Rune() + return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') +} + +// KeyIsNumeric Returns whether the event is a +// numeric Key press +func KeyIsNumeric(ev tcell.EventKey) bool { + r := ev.Rune() + return (r >= '0' && r <= '9') +} + +// KeyIsSymbol Returns whether the event is a +// symbol Key press +func KeyIsSymbol(ev tcell.EventKey) bool { + symbols := []rune{ + '!', '@', '#', '$', '%', '^', '&', '*', + '(', ')', '-', '_', '=', '+', '[', ']', '{', '}', '|', + ';', ':', '"', '\'', ',', '<', '.', '>', '/', '?', '`', '~', '\\', + } + k := ev.Rune() + for i := range symbols { + if k == symbols[i] { + return true + } + } + return false +} + +func HandleKeys(ev tcell.EventKey, keys map[tcell.Key]func() bool) bool { + for k, v := range keys { + if ev.Key() == k { + return v() + } + } + return false +} + +func HasCtrl(ev *tcell.EventKey) bool { return ev.Modifiers()&tcell.ModCtrl == tcell.ModCtrl } diff --git a/helpers/number_helpers.go b/helpers/number_helpers.go new file mode 100644 index 0000000..ce80839 --- /dev/null +++ b/helpers/number_helpers.go @@ -0,0 +1,50 @@ +/* +Copyright © Brian Buller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package helpers + +import "cmp" + +func Max[E cmp.Ordered](of ...E) E { + var m E + if len(of) > 0 { + m = of[0] + } + for i := range of { + if of[i] > m { + m = of[i] + } + } + return m +} + +func Min[E cmp.Ordered](of ...E) E { + var m E + if len(of) > 0 { + m = of[0] + } + for i := range of { + if of[i] < m { + m = of[i] + } + } + return m +} diff --git a/helpers/tcell_borders.go b/helpers/tcell_borders.go new file mode 100644 index 0000000..c601cd5 --- /dev/null +++ b/helpers/tcell_borders.go @@ -0,0 +1,180 @@ +/* +Copyright © Brian Buller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package helpers + +import ( + "github.com/gdamore/tcell" +) + +/* +The Border template starts at North and goes clockwise: +─, ┐, │, ┘, ─, └, │, ┌ +Then it has the crossing lines: +├, ─, ┤, ┬, │, ┴ +So a full border might look like this: + + []rune{ + '─', '┐', '│', '┘', '─', '└', '│', '┌', + '├', '─', '┤', '┬', '│', '┴', + } + +U+250x ─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏ +U+251x ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟ +U+252x ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯ +U+253x ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿ +U+254x ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏ +U+255x ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ +U+256x ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯ +U+257x ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿ +*/ +const ( + BRD_N = iota + BRD_NE + BRD_E + BRD_SE + BRD_S + BRD_SW + BRD_W + BRD_NW + BRD_CROSS_E + BRD_CROSS_H + BRD_CROSS_W + BRD_CROSS_S + BRD_CROSS_V + BRD_CROSS_N + BRD_CROSS_ALL +) + +var ( + BRD_SIMPLE = []rune{'─', '┐', '│', '┘', '─', '└', '│', '┌', '├', '─', '┤', '┬', '│', '┴', '┼'} + BRD_CSIMPLE = []rune{'─', '╮', '│', '╯', '─', '╰', '│', '╭', '├', '─', '┤', '┬', '│', '┴', '┼'} + BRD_DOUBLE = []rune{'═', '╗', '║', '╝', '═', '╚', '║', '╔', '╠', '═', '╣', '╦', '║', '╩', '╬'} + BRD_CSIMPLE_DOTSPLIT = []rune{'─', '╮', '│', '╯', '─', '╰', '│', '╭', '├', '┄', '┤', '┬', '┊', '┴', '┼'} + BRD_BLOCK_SHADOW = []rune{'░', '░', '▓', '▓', '▓', '░', '░', '░', '░', '░', '░', '░', '░', '░', '░'} +) + +// Horizontal/Vertical Rules +const ( + RULE_START = iota + RULE_FILL + RULE_END +) + +var ( + HRULE_SIMPLE = []rune{'├', '─', '┤'} + HRULE_DOUBLE = []rune{'╠', '═', '╣'} + + VRULE_SIMPLE = []rune{'┬', '│', '┴'} + VRULE_DOUBLE = []rune{'╦', '║', '╩'} +) + +func ValidateBorder(border []rune) []rune { + for len(border) < BRD_CROSS_ALL+1 { + border = append(border, ' ') + } + return border +} + +func ValidateRule(rule []rune) []rune { + for len(rule) < RULE_END+1 { + rule = append(rule, ' ') + } + return rule +} + +func HRule(x1, x2, y int, rule []rune, s tcell.Style, screen tcell.Screen) { + Fill(x1, y, x2, y, rule[RULE_FILL], s, screen) + screen.SetContent(x1, y, rule[RULE_START], nil, s) + screen.SetContent(x2, y, rule[RULE_END], nil, s) +} + +func VRule(x, y1, y2 int, rule []rune, s tcell.Style, screen tcell.Screen) { + Fill(x, y1, x, y2, rule[RULE_FILL], s, screen) + screen.SetContent(x, y1, rule[RULE_START], nil, s) + screen.SetContent(x, y2, rule[RULE_END], nil, s) +} + +func BorderFilled(x1, y1, x2, y2 int, border []rune, s tcell.Style, screen tcell.Screen) { + Border(x1, y1, x2, y2, border, s, screen) + Fill(x1+1, y1+1, x2-1, y2-1, ' ', s, screen) +} + +func Border(x1, y1, x2, y2 int, border []rune, s tcell.Style, screen tcell.Screen) { + border = ValidateBorder(border) + Fill(x1+1, y1, x2-1, y1, border[BRD_N], s, screen) + Fill(x2, y1+1, x2, y2-1, border[BRD_E], s, screen) + Fill(x1+1, y2, x2-1, y2, border[BRD_S], s, screen) + Fill(x1, y1+1, x1, y2-1, border[BRD_W], s, screen) + screen.SetContent(x1, y1, border[BRD_NW], nil, s) + screen.SetContent(x2, y1, border[BRD_NE], nil, s) + screen.SetContent(x1, y2, border[BRD_SW], nil, s) + screen.SetContent(x2, y2, border[BRD_SE], nil, s) +} + +func TitledBorderFilled(x1, y1, x2, y2 int, ttl string, border []rune, s tcell.Style, screen tcell.Screen) { + TitledBorder(x1, y1, x2, y2, ttl, border, s, screen) + Fill(x1+1, y1+1, x2-1, y2-1, ' ', s, screen) +} + +func TitledBorder(x1, y1, x2, y2 int, ttl string, border []rune, s tcell.Style, screen tcell.Screen) { + if ttl == "" { + Border(x1, y1, x2, y2, border, s, screen) + return + } + border = ValidateBorder(border) + ttlLength, maxTtlLength := len(ttl), (x2 - x1 - 2) + if ttlLength > maxTtlLength { + if maxTtlLength-3 > 0 { + ttlLength = maxTtlLength + ttl = ttl[0:maxTtlLength-3] + "..." + } + } + DrawText(x1+1, y1, ttl, s, screen) + Fill(x1+1+ttlLength, y1, x2-1, y1, border[BRD_N], s, screen) + Fill(x2, y1+1, x2, y2-1, border[BRD_E], s, screen) + Fill(x1+1, y2, x2-1, y2, border[BRD_S], s, screen) + Fill(x1, y1+1, x1, y2-1, border[BRD_W], s, screen) + screen.SetContent(x1, y1, border[BRD_NW], nil, s) + screen.SetContent(x2, y1, border[BRD_NE], nil, s) + screen.SetContent(x1, y2, border[BRD_SW], nil, s) + screen.SetContent(x2, y2, border[BRD_SE], nil, s) +} + +func BorderHasEast(border []rune) bool { + border = ValidateBorder(border) + return border[BRD_E] != ' ' || border[BRD_NE] != ' ' || border[BRD_SE] != ' ' +} + +func BorderHasWest(border []rune) bool { + border = ValidateBorder(border) + return border[BRD_W] != ' ' || border[BRD_NW] != ' ' || border[BRD_SW] != ' ' +} + +func BorderHasNorth(border []rune) bool { + border = ValidateBorder(border) + return border[BRD_N] != ' ' || border[BRD_NE] != ' ' || border[BRD_NW] != ' ' +} + +func BorderHasSouth(border []rune) bool { + border = ValidateBorder(border) + return border[BRD_S] != ' ' || border[BRD_NW] != ' ' || border[BRD_SW] != ' ' +} diff --git a/helpers/tcell_helpers.go b/helpers/tcell_helpers.go new file mode 100644 index 0000000..4a6e374 --- /dev/null +++ b/helpers/tcell_helpers.go @@ -0,0 +1,45 @@ +/* +Copyright © Brian Buller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package helpers + +import "github.com/gdamore/tcell" + +func DrawText(x, y int, text string, style tcell.Style, screen tcell.Screen) { + for _, r := range text { + screen.SetContent(x, y, r, nil, style) + x++ + } +} + +func Fill(x1, y1, x2, y2 int, r rune, style tcell.Style, screen tcell.Screen) { + if x1 > x2 { + x1, x2 = x2, x1 + } + if y1 > y2 { + y1, y2 = y2, y1 + } + for x := x1; x <= x2; x++ { + for y := y1; y <= y2; y++ { + screen.SetContent(x, y, r, nil, style) + } + } +} diff --git a/helpers/text_helpers.go b/helpers/text_helpers.go new file mode 100644 index 0000000..ba53105 --- /dev/null +++ b/helpers/text_helpers.go @@ -0,0 +1,159 @@ +/* +Copyright © Brian Buller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package helpers + +import ( + "bytes" + "fmt" + "strings" + "unicode" +) + +type Align int + +const ( + AlignLeft = iota + AlignCenter + AlignRight +) + +func Center(txt string, width int) string { + if len(txt) >= width { + // Trim from beg & end until width + for len(txt) > width { + txt = txt[:len(txt)-1] + if len(txt) > width { + txt = txt[1:] + } + } + return txt + } + for len(txt) < width { + txt = fmt.Sprintf(" %s", txt) + if len(txt) < width { + txt = fmt.Sprintf("%s ", txt) + } + } + return txt +} + +func CenterBetween(txt, left, right string, width int) string { + if len(txt) >= width { + return Center(txt, width) + } + for len(txt) < width { + txt = fmt.Sprintf("%s%s", left, txt) + if len(txt) < width { + txt = fmt.Sprintf("%s%s", txt, right) + } + } + return txt +} + +func PadR(txt string, width int) string { + if len(txt) < width { + txt = fmt.Sprintf("%s%s", txt, strings.Repeat(" ", width-len(txt))) + } + return txt +} + +func PadL(txt string, width int) string { + if len(txt) < width { + txt = fmt.Sprintf("%s%s", strings.Repeat(" ", width-len(txt)), txt) + } + return txt +} + +// WrapText inserts new lines to make the text +// wrap at width 'w' +func WrapText(txt string, w int) string { + init := make([]byte, 0, len(txt)) + buf := bytes.NewBuffer(init) + var current uint + var wordBuf, spaceBuf bytes.Buffer + var wordBufLen, spaceBufLen uint + writeBufs := func() { + current += spaceBufLen + wordBufLen + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + spaceBufLen = 0 + wordBuf.WriteTo(buf) + wordBuf.Reset() + wordBufLen = 0 + } + for _, char := range txt { + if char == '\n' { + // _Must_ wrap at newline + if wordBuf.Len() == 0 { + if int(current+spaceBufLen) > w { + current = 0 + } else { + current += spaceBufLen + spaceBuf.WriteTo(buf) + } + spaceBuf.Reset() + spaceBufLen = 0 + } else { + writeBufs() + } + buf.WriteRune(char) + current = 0 + } else if unicode.IsSpace(char) && char != 0xA0 { + // Can wrap at whitespace + if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { + writeBufs() + } + spaceBuf.WriteRune(char) + spaceBufLen++ + } else { + wordBuf.WriteRune(char) + wordBufLen++ + if int(current+wordBufLen+spaceBufLen) > w && int(wordBufLen) < w { + buf.WriteRune('\n') + current = 0 + spaceBuf.Reset() + spaceBufLen = 0 + } + } + } + + if wordBuf.Len() == 0 { + if int(current+spaceBufLen) <= w { + spaceBuf.WriteTo(buf) + } + } else { + spaceBuf.WriteTo(buf) + wordBuf.WriteTo(buf) + } + return buf.String() +} + +func Longest(of []string) int { + var ret int + for i := range of { + tst := len(of[i]) + if tst > ret { + ret = tst + } + } + return ret +} diff --git a/menu.go b/menu.go index 6f6c304..f5869ac 100644 --- a/menu.go +++ b/menu.go @@ -22,7 +22,7 @@ THE SOFTWARE. package widgets import ( - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/menu_item.go b/menu_item.go index 6e709d2..80822a3 100644 --- a/menu_item.go +++ b/menu_item.go @@ -22,7 +22,7 @@ THE SOFTWARE. package widgets import ( - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/searcher.go b/searcher.go index 6d23605..095ad45 100644 --- a/searcher.go +++ b/searcher.go @@ -25,7 +25,7 @@ import ( "fmt" "strings" - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/table.go b/table.go index 6a8584d..5b5295c 100644 --- a/table.go +++ b/table.go @@ -25,7 +25,7 @@ import ( "fmt" "strings" - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" ) diff --git a/text.go b/text.go index ea92857..4b74e8e 100644 --- a/text.go +++ b/text.go @@ -22,7 +22,7 @@ THE SOFTWARE. package widgets import ( - h "git.bullercodeworks.com/brian/dhcli/helpers" + h "git.bullercodeworks.com/brian/tcell-widgets/helpers" "github.com/gdamore/tcell" )