v0.1.0 initial commit
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"github.com/lixenwraith/terminal"
|
||||
)
|
||||
|
||||
// InputOpts configures single-line input field
|
||||
type InputOpts struct {
|
||||
Label string
|
||||
LabelFg terminal.RGB
|
||||
Text string
|
||||
Cursor int // Cursor position in text (rune index)
|
||||
CursorBg terminal.RGB
|
||||
TextFg terminal.RGB
|
||||
Bg terminal.RGB
|
||||
}
|
||||
|
||||
// Input renders labeled text input field on row y, handling cursor display and horizontal scrolling
|
||||
func (r Region) Input(y int, opts InputOpts) {
|
||||
if y < 0 || y >= r.H || r.W < 5 {
|
||||
return
|
||||
}
|
||||
|
||||
x := 0
|
||||
|
||||
// Label
|
||||
if opts.Label != "" {
|
||||
for _, ch := range opts.Label {
|
||||
if x >= r.W {
|
||||
break
|
||||
}
|
||||
r.Cell(x, y, ch, opts.LabelFg, opts.Bg, terminal.AttrNone)
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
// Available width for input text
|
||||
inputW := r.W - x
|
||||
if inputW < 3 {
|
||||
return
|
||||
}
|
||||
|
||||
runes := []rune(opts.Text)
|
||||
cursor := opts.Cursor
|
||||
if cursor > len(runes) {
|
||||
cursor = len(runes)
|
||||
}
|
||||
if cursor < 0 {
|
||||
cursor = 0
|
||||
}
|
||||
|
||||
// Horizontal scroll to keep cursor visible
|
||||
scroll := 0
|
||||
if cursor >= inputW-1 {
|
||||
scroll = cursor - inputW + 2
|
||||
}
|
||||
|
||||
// Render visible portion
|
||||
for i := 0; i < inputW; i++ {
|
||||
runeIdx := scroll + i
|
||||
ch := ' '
|
||||
if runeIdx < len(runes) {
|
||||
ch = runes[runeIdx]
|
||||
}
|
||||
|
||||
bg := opts.Bg
|
||||
if runeIdx == cursor {
|
||||
bg = opts.CursorBg
|
||||
}
|
||||
|
||||
r.Cell(x+i, y, ch, opts.TextFg, bg, terminal.AttrNone)
|
||||
}
|
||||
|
||||
// Cursor at end if past text
|
||||
if cursor == len(runes) && cursor-scroll < inputW {
|
||||
r.Cell(x+cursor-scroll, y, ' ', opts.TextFg, opts.CursorBg, terminal.AttrNone)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user