16 Commits

Author SHA1 Message Date
Christian Rocha
bdd909a5d7 Textinput: bind home/end and fix behavior of delete key 2020-10-22 15:36:54 -04:00
Will Bradley
b08b3efa02 add a couple alternate key bindings to make the scrolling slightly more intuitive 2020-10-21 22:54:58 -04:00
Christian Muehlhaeuser
83b6a2205f Add an EchoMode and EchoCharacter property to textinputs (#11)
EchoModes are:

- EchoNormal, displays text as is
- EchoPassword, displays EchoCharacter mask instead of actual characters
- EchoNone, displays nothing

Note that EchoOnEdit, which should displays character as they are entered and is otherwise identical to EchoPassword, is not yet implemented.
2020-10-21 18:17:41 -04:00
Christian Rocha
c06af8962d Update footer in README 2020-10-20 10:17:26 -04:00
Christian Muehlhaeuser
3a65be950a Remove release badge from README 2020-10-19 06:20:37 +02:00
Christian Muehlhaeuser
2dd6e0c80b Update README badges 2020-10-19 06:19:24 +02:00
Christian Muehlhaeuser
1e50e6d291 Add GitHub workflows 2020-10-19 06:16:01 +02:00
John Diego
573f90a876 Fix typo 2020-10-19 06:02:37 +02:00
Christian Rocha
a498b857d6 Update paginator for bubbletea 0.12.0 2020-10-16 14:36:08 -04:00
Christian Rocha
82097a1c79 Remove unused function 2020-10-16 11:54:44 -04:00
Christian Rocha
a8ec421800 Update bubbletea and termenv dependencies 2020-10-16 11:54:00 -04:00
Christian Rocha
9c10cd0586 Remove unused ErrMsg type from textinput module 2020-10-15 18:52:36 -04:00
Christian Rocha
154f3763f7 textinput.View can just accept a textinput.Model argument 2020-10-15 18:43:08 -04:00
Christian Rocha
eff931bdea Remove replace directive for bubbletea in go.mod 2020-10-12 22:15:02 -04:00
Christian Rocha
0d7b3ed8e8 Fix URLs to Charm and Glow in README 2020-10-06 13:25:46 -04:00
Christian Rocha
cbafae84f9 Update mouse wheel stuff in paginator per last-minute Bubble Tea API change 2020-10-06 12:29:18 -04:00
9 changed files with 183 additions and 88 deletions

37
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: build
on: [push, pull_request]
jobs:
test:
strategy:
matrix:
go-version: [1.13.x, 1.14.x, 1.15.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
env:
GO111MODULE: "on"
steps:
- name: Install Go
uses: actions/setup-go@v1
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Download Go modules
run: go mod download
- name: Build
run: go build -v ./...
- name: Test
run: go test ./...
- name: Coverage
env:
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
go test -race -covermode atomic -coverprofile=profile.cov ./...
GO111MODULE=off go get github.com/mattn/goveralls
$(go env GOPATH)/bin/goveralls -coverprofile=profile.cov -service=github
if: matrix.go-version == '1.15.x' && matrix.os == 'ubuntu-latest'

20
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: lint
on: [push, pull_request]
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.30
# Optional: golangci-lint command line arguments.
args: --issues-exit-code=0
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: show only new issues if it's a pull request. The default value is `false`.
only-new-issues: true

26
.golangci.yml Normal file
View File

@@ -0,0 +1,26 @@
run:
tests: false
issues:
max-issues-per-linter: 0
max-same-issues: 0
linters:
enable:
- bodyclose
- dupl
- exportloopref
- goconst
- godot
- godox
- goimports
- gomnd
- goprintffuncname
- gosec
- misspell
- prealloc
- rowserrcheck
- sqlclosecheck
- unconvert
- unparam
- whitespace

View File

@@ -1,17 +1,16 @@
Bubbles Bubbles
======= =======
<p> [![Build Status](https://github.com/charmbracelet/bubbles/workflows/build/badge.svg)](https://github.com/charmbracelet/bubbles/actions)
<a href="https://pkg.go.dev/github.com/charmbracelet/bubbles?tab=doc"><img src="https://godoc.org/github.com/golang/gddo?status.svg" alt="GoDoc"></a> [![Go ReportCard](http://goreportcard.com/badge/charmbracelet/bubbles)](http://goreportcard.com/report/charmbracelet/bubbles)
<a href="https://github.com/charmbracelet/bubbles/actions"><img src="https://github.com/charmbracelet/glow/workflows/build/badge.svg" alt="Build Status"></a> [![GoDoc](https://godoc.org/github.com/golang/gddo?status.svg)](https://pkg.go.dev/github.com/charmbracelet/bubbles)
</p>
Some components for [Bubble Tea](https://github.com/charmbracelet/bubbletea) applications. Some components for [Bubble Tea](https://github.com/charmbracelet/bubbletea) applications.
These components are used in production in [Glow][glow] and [Charm][charm]. These components are used in production in [Glow][glow] and [Charm][charm].
[glow]: https://github.com/charmbraclet/glow [glow]: https://github.com/charmbracelet/glow
[charm]: https://github.com/charmbraclet/charm [charm]: https://github.com/charmbracelet/charm
## Spinner ## Spinner
@@ -59,7 +58,7 @@ for applications which make use of the alterate screen buffer.
* [Example code](https://github.com/charmbracelet/tea/tree/master/examples/pager/main.go) * [Example code](https://github.com/charmbracelet/tea/tree/master/examples/pager/main.go)
This compoent is well complimented with [Reflow][reflow] for ANSI-aware This component is well complimented with [Reflow][reflow] for ANSI-aware
indenting and text wrapping. indenting and text wrapping.
[reflow]: https://github.com/muesli/reflow [reflow]: https://github.com/muesli/reflow
@@ -72,8 +71,9 @@ indenting and text wrapping.
*** ***
A [Charm](https://charm.sh) project. Part of [Charm](https://charm.sh).
<img alt="the Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"> <a href="https://charm.sh/"><img alt="the Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"></a>
Charm热爱开源! / Charm loves open source!
Charm热爱开源!

9
go.mod
View File

@@ -4,10 +4,9 @@ go 1.13
require ( require (
github.com/atotto/clipboard v0.1.2 github.com/atotto/clipboard v0.1.2
github.com/charmbracelet/bubbletea v0.10.3 github.com/charmbracelet/bubbletea v0.12.1
github.com/mattn/go-runewidth v0.0.9 github.com/mattn/go-runewidth v0.0.9
github.com/muesli/termenv v0.7.2 github.com/muesli/termenv v0.7.4
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect
golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a // indirect
) )
replace github.com/charmbracelet/bubbletea => ../bubbletea

33
go.sum
View File

@@ -1,5 +1,9 @@
github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY= github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY=
github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/charmbracelet/bubbletea v0.12.1 h1:t21pkG2IDBRduPbt2J64Dx5yt8yIidAkXwhhrc11SzY=
github.com/charmbracelet/bubbletea v0.12.1/go.mod h1:3gZkYELUOiEUOp0bTInkxguucy/xRbGSOcbMs1geLxg=
github.com/containerd/console v1.0.1 h1:u7SFAJyRqWcG6ogaMAx3KjSTy1e3hT9QxqX7Jco7dRc=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4= github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4=
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4= github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
@@ -8,27 +12,24 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/muesli/termenv v0.5.3-0.20200625163851-04b5c30e4c04 h1:Wr876oXlAk6avTWi0daXAriOr+r5fqIuyDmtNc/KwY0=
github.com/muesli/termenv v0.5.3-0.20200625163851-04b5c30e4c04/go.mod h1:O1/I6sw+6KcrgAmcs6uiUVr7Lui+DNVbHTzt9Lm/PlI=
github.com/muesli/termenv v0.7.0 h1:KcLfgg/KICGxOxNr+P9gmkrJ5azxOm3WzkfXMePGTq4=
github.com/muesli/termenv v0.7.0/go.mod h1:SohX91w6swWA4AYU+QmPx+aSgXhWO0juiyID9UZmbpA=
github.com/muesli/termenv v0.7.2 h1:r1raklL3uKE7rOvWgSenmEm2px+dnc33OTisZ8YR1fw= github.com/muesli/termenv v0.7.2 h1:r1raklL3uKE7rOvWgSenmEm2px+dnc33OTisZ8YR1fw=
github.com/muesli/termenv v0.7.2/go.mod h1:ct2L5N2lmix82RaY3bMWwVu/jUFc9Ule0KGDCiKYPh8= github.com/muesli/termenv v0.7.2/go.mod h1:ct2L5N2lmix82RaY3bMWwVu/jUFc9Ule0KGDCiKYPh8=
github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03 h1:pd4YKIqCB0U7O2I4gWHgEUA2mCEOENmco0l/bM957bU= github.com/muesli/termenv v0.7.4 h1:/pBqvU5CpkY53tU0vVn+xgs2ZTX63aH5nY+SSps5Xa8=
github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03/go.mod h1:Z9+Ul5bCbBKnbCvdOWbLqTHhJiYV414CURZJba6L8qA= github.com/muesli/termenv v0.7.4/go.mod h1:pZ7qY9l3F7e5xsAOS0zCew2tME+p7bWeBkotCEcIIcc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM=
golang.org/x/sys v0.0.0-20200819171115-d785dc25833f h1:KJuwZVtZBVzDmEDtB2zro9CXkD9O0dpCv4o2LHbQIAw= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200819171115-d785dc25833f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a h1:e3IU37lwO4aq3uoRKINC7JikojFmE5gO7xhfxs8VC34=
golang.org/x/sys v0.0.0-20200821140526-fda516888d29 h1:mNuhGagCf3lDDm5C0376C/sxh6V7fy9WbdEu/YDNA04= golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200821140526-fda516888d29/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -164,11 +164,7 @@ func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
} }
// View renders the pagination to a string. // View renders the pagination to a string.
func View(model tea.Model) string { func View(m Model) string {
m, ok := model.(Model)
if !ok {
return "could not perform assertion on model"
}
switch m.Type { switch m.Type {
case Dots: case Dots:
return dotsView(m) return dotsView(m)

View File

@@ -11,32 +11,49 @@ import (
"github.com/muesli/termenv" "github.com/muesli/termenv"
) )
const defaultBlinkSpeed = time.Millisecond * 600
const ( const (
defaultBlinkSpeed = time.Millisecond * 600 // EchoNormal displays text as is. This is the default behavior.
EchoNormal EchoMode = iota
// EchoPassword displays the EchoCharacter mask instead of actual
// characters. This is commonly used for password fields.
EchoPassword
// EchoNone displays nothing as characters are entered. This is commonly
// seen for password fields on the command line.
EchoNone
// EchoOnEdit
) )
// EchoMode sets the input behavior of the text input field.
type EchoMode int
var ( var (
// color is a helper for returning colors. // color is a helper for returning colors.
color func(s string) termenv.Color = termenv.ColorProfile().Color color func(s string) termenv.Color = termenv.ColorProfile().Color
) )
// ErrMsg indicates there's been an error. We don't handle errors in the this // Model is the Bubble Tea model for this text input element.
// package; we're expecting errors to be handle in the program that implements
// this text input.
type ErrMsg error
// Model is the Tea model for this text input element.
type Model struct { type Model struct {
Err error Err error
Prompt string
Cursor string Prompt string
BlinkSpeed time.Duration Placeholder string
Placeholder string
Cursor string
BlinkSpeed time.Duration
TextColor string TextColor string
BackgroundColor string BackgroundColor string
PlaceholderColor string PlaceholderColor string
CursorColor string CursorColor string
EchoMode EchoMode
EchoCharacter rune
// CharLimit is the maximum amount of characters this input element will // CharLimit is the maximum amount of characters this input element will
// accept. If 0 or less, there's no limit. // accept. If 0 or less, there's no limit.
CharLimit int CharLimit int
@@ -46,21 +63,21 @@ type Model struct {
// viewport. If 0 or less this setting is ignored. // viewport. If 0 or less this setting is ignored.
Width int Width int
// Underlying text value // Underlying text value.
value []rune value []rune
// Focus indicates whether user input focus should be on this input // Focus indicates whether user input focus should be on this input
// component. When false, don't blink and ignore keyboard input. // component. When false, don't blink and ignore keyboard input.
focus bool focus bool
// Cursor blink state // Cursor blink state.
blink bool blink bool
// Cursor position // Cursor position.
pos int pos int
// Used to emulate a viewport when width is set and the content is // Used to emulate a viewport when width is set and the content is
// overflowing // overflowing.
offset int offset int
offsetRight int offsetRight int
} }
@@ -84,8 +101,8 @@ func (m Model) Value() string {
return string(m.value) return string(m.value)
} }
// Cursor start moves the cursor to the given position. If the position is out // SetCursor start moves the cursor to the given position. If the position is
// of bounds the cursor will be moved to the start or end accordingly. // out of bounds the cursor will be moved to the start or end accordingly.
func (m *Model) SetCursor(pos int) { func (m *Model) SetCursor(pos int) {
m.pos = clamp(pos, 0, len(m.value)) m.pos = clamp(pos, 0, len(m.value))
m.handleOverflow() m.handleOverflow()
@@ -285,19 +302,36 @@ func (m *Model) wordRight() {
} }
} }
func (m Model) echoTransform(v string) string {
switch m.EchoMode {
case EchoPassword:
return strings.Repeat(string(m.EchoCharacter), rw.StringWidth(v))
case EchoNone:
return ""
default:
return v
}
}
// BlinkMsg is sent when the cursor should alternate it's blinking state. // BlinkMsg is sent when the cursor should alternate it's blinking state.
type BlinkMsg struct{} type BlinkMsg struct{}
// NewModel creates a new model with default settings. // NewModel creates a new model with default settings.
func NewModel() Model { func NewModel() Model {
return Model{ return Model{
Prompt: "> ", Prompt: "> ",
BlinkSpeed: defaultBlinkSpeed, Placeholder: "",
Placeholder: "",
BlinkSpeed: defaultBlinkSpeed,
TextColor: "", TextColor: "",
PlaceholderColor: "240", PlaceholderColor: "240",
CursorColor: "", CursorColor: "",
CharLimit: 0,
EchoCharacter: '*',
CharLimit: 0,
value: nil, value: nil,
focus: false, focus: false,
@@ -316,9 +350,7 @@ func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch msg.Type { switch msg.Type {
case tea.KeyBackspace: case tea.KeyBackspace: // delete character before cursor
fallthrough
case tea.KeyDelete:
if len(m.value) > 0 { if len(m.value) > 0 {
m.value = append(m.value[:max(0, m.pos-1)], m.value[m.pos:]...) m.value = append(m.value[:max(0, m.pos-1)], m.value[m.pos:]...)
if m.pos > 0 { if m.pos > 0 {
@@ -345,13 +377,13 @@ func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
fallthrough fallthrough
case tea.KeyCtrlB: // ^B, back one charcter case tea.KeyCtrlB: // ^B, back one charcter
fallthrough fallthrough
case tea.KeyCtrlA: // ^A, go to beginning case tea.KeyHome, tea.KeyCtrlA: // ^A, go to beginning
m.CursorStart() m.CursorStart()
case tea.KeyCtrlD: // ^D, delete char under cursor case tea.KeyDelete, tea.KeyCtrlD: // ^D, delete char under cursor
if len(m.value) > 0 && m.pos < len(m.value) { if len(m.value) > 0 && m.pos < len(m.value) {
m.value = append(m.value[:m.pos], m.value[m.pos+1:]...) m.value = append(m.value[:m.pos], m.value[m.pos+1:]...)
} }
case tea.KeyCtrlE: // ^E, go to end case tea.KeyCtrlE, tea.KeyEnd: // ^E, go to end
m.CursorEnd() m.CursorEnd()
case tea.KeyCtrlK: // ^K, kill text after cursor case tea.KeyCtrlK: // ^K, kill text after cursor
m.value = m.value[:m.pos] m.value = m.value[:m.pos]
@@ -382,9 +414,6 @@ func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
} }
} }
case ErrMsg:
m.Err = msg
case BlinkMsg: case BlinkMsg:
m.blink = !m.blink m.blink = !m.blink
return m, Blink(m) return m, Blink(m)
@@ -396,12 +425,7 @@ func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
} }
// View renders the textinput in its current state. // View renders the textinput in its current state.
func View(model tea.Model) string { func View(m Model) string {
m, ok := model.(Model)
if !ok {
return "could not perform assertion on model"
}
// Placeholder text // Placeholder text
if len(m.value) == 0 && m.Placeholder != "" { if len(m.value) == 0 && m.Placeholder != "" {
return placeholderView(m) return placeholderView(m)
@@ -409,12 +433,11 @@ func View(model tea.Model) string {
value := m.value[m.offset:m.offsetRight] value := m.value[m.offset:m.offsetRight]
pos := max(0, m.pos-m.offset) pos := max(0, m.pos-m.offset)
v := m.colorText(m.echoTransform(string(value[:pos])))
v := m.colorText(string(value[:pos]))
if pos < len(value) { if pos < len(value) {
v += cursorView(string(value[pos]), m) // cursor and text under it v += cursorView(m.echoTransform(string(value[pos])), m) // cursor and text under it
v += m.colorText(string(value[pos+1:])) // text after cursor v += m.colorText(m.echoTransform(string(value[pos+1:]))) // text after cursor
} else { } else {
v += cursorView(" ", m) v += cursorView(" ", m)
} }
@@ -445,10 +468,7 @@ func placeholderView(m Model) string {
// Cursor // Cursor
if m.blink && m.PlaceholderColor != "" { if m.blink && m.PlaceholderColor != "" {
v += cursorView( v += cursorView(m.colorPlaceholder(p[:1]), m)
m.colorPlaceholder(p[:1]),
m,
)
} else { } else {
v += cursorView(p[:1], m) v += cursorView(p[:1], m)
} }

View File

@@ -304,14 +304,14 @@ func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
} }
// Down half page // Down half page
case "d": case "d", "ctrl+d":
lines := m.HalfViewDown() lines := m.HalfViewDown()
if m.HighPerformanceRendering { if m.HighPerformanceRendering {
cmd = ViewDown(m, lines) cmd = ViewDown(m, lines)
} }
// Up half page // Up half page
case "u": case "u", "ctrl+u":
lines := m.HalfViewUp() lines := m.HalfViewUp()
if m.HighPerformanceRendering { if m.HighPerformanceRendering {
cmd = ViewUp(m, lines) cmd = ViewUp(m, lines)
@@ -333,7 +333,7 @@ func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
} }
case tea.MouseMsg: case tea.MouseMsg:
switch msg.Button { switch msg.Type {
case tea.MouseWheelUp: case tea.MouseWheelUp:
lines := m.LineUp(3) lines := m.LineUp(3)
if m.HighPerformanceRendering { if m.HighPerformanceRendering {
@@ -389,7 +389,3 @@ func max(a, b int) int {
} }
return b return b
} }
func clamp(val, low, high int) int {
return max(low, min(high, val))
}