rivo / tview

Terminal UI library with rich, interactive widgets — written in Golang
MIT License
11.17k stars 574 forks source link

Controlling position of cursor in InputField #892

Open paololazzari opened 1 year ago

paololazzari commented 1 year ago

Consider:

package main

import (
    "github.com/rivo/tview"
)

func main() {
    app := tview.NewApplication()
    inputField := tview.NewInputField().
        SetText(">>>>>> X <<<<<<")

    if err := app.SetRoot(inputField, true).SetFocus(inputField).Run(); err != nil {
        panic(err)
    }
}

how can I change the position of the cursor so that when I start typing it types right in the middle of the string (where X is) ?

digitallyserviced commented 1 year ago

@paololazzari

I am not sure what you are exactly looking for here.

Currently there are zero exported functions to directly change the cursors position within a text field. While it is not a major problem. There are ways around it.

However, your example seems to show that the X (or whatever is between the > <) is all they would be modifying correct? If the surrounding characters are forced and will always be included, dont let the user even have them as part of the editable field, and just append them when you use the field's value.

If you really need to make it seem like those characters are there, then I would just make the text field's placeholder text X, and then surround the InputField with two TextViews on either side that have your >>>>> <<<<<.

Method One (simplest, most consistent, requires editing tview)

If it is REALLY necessary that those characters be part of the InputField the simplest option (which is simplest for me, maybe not for you) is to just add another method to the inputfield.go in tview and start using a hacked/customized version instead of the master repo.

I would add this somewhere in inputfield.go


// SetCursorPos sets position of cursor in field.
func (i *InputField) SetCursorPos(pos int) *InputField {
    i.cursorPos = pos
    return i
}

Method Two (not simple, hacky, not consistent, no editing tview)


inputField := tview.NewInputField().
        SetText(">>>>>> X <<<<<<")

// somewhere else...

// focus the field if not already
app.SetFocus(inputField)
// get input field x,y position
x,y,_,_ := inputField.GetInnerRect()
// add the length of chars to skip over
offset := x + len(">>>>>> ")
// make a fake mouse event targeting the new offset position, and specify buttons
mouseEvent := tcell.NewEventMouse(x+offset,y,tcell.ButtonPrimary, tcell.ModNone)
// get field mouse handler
handler := inputField.MouseHandler()
// call mouse handler with fake event, specified mouse action, and nil setFocus handler since we already focused earlier
handler(MouseLeftClick, mouseEvent, nil)

This method is hacky because of the reliance on an input event to get it done.

You can also do it via InputHandler but you would have to specify multiple keyboard events if you cant skip words or whatever...

Ultimately you will need to re-think your interface. This is not a GUI, but a TUI. This means that you cannot always rely on the usual GUI interactions that you may be trying to implement.

You will need to be creative about how your application lays things out and even change the way you are doing things to be more terminal friendly.

Here is an example of one of my apps where I make extensive use of TextView, style tags, and unicode/powerline characters to make the TUI elements, widgets, and overall experience more aesthetically pleasing. I have a theming addon that I use to format strings and a hook into the style tags so you can define styles by name instead of having to specify a [fg:bg:attr] each time.

Specifying your label text or textview's text as something like this to give more pop to your TUI is what I am suggesting...

quickColorTitle = "[badgeText][::r]   [blue:gray:-] QuickColor [gray:#303030:-][-:-:-][badgeIcon] %[1]s [-:-:-]%[2]s"

https://github.com/digitallyserviced/tview-theming/blob/main/theme.toml

Just be creatie! Hit me up on discord or twitter if you wanna ask more

demo-nvim-script

https://github.com/digitallyserviced/tview-theming/blob/main/symbols.txt

 ▘▝▀▖▌▞▛▗▚▐▜▄▙▟█⎧ 🬀🬁🬂🬃🬄🬅🬆🬇🬈🬊🬋🬌🬍🬎🬏🬐🬑🬒🬓▌🬔🬕🬖🬗🬘🬙🬚🬛🬜🬝⎫♠♥🯰🯱🯲🯳🯴🯵🯶🯷🯸🯹⅗⅘⅙⅚⅛⎧▕▏⎫┌╥─╥─╥┐🭩
╲╿╱ ◨◧ ◪◩ ◖◗ ⫷⫸ ⎩🬟🬠🬡🬢🬣🬤🬥🬦🬧▐🬨🬩🬪🬫🬬🬭🬮🬯🬰🬱🬲🬳🬴🬵🬶🬷🬸🬹🬺🬻█⎭♦♣¼½¾⅐⅑⅒⅓⅔⅕⅖⅜⅝⅞⅟↉⎪🮇▎⎪├╜╓╫╖╙┤🭫
╾╳╼ ◲◱ ◶◵ 🮣🮠 🮤🮥◜◝ ◿◺ 🮞🮟 ◢◣ ┌┐─  ┏┓━ ╭╮─  ╔╗═ 🭽🭾▁ ⩘▵△▹▷▿▽◃◁⭡⭣⭠⭢⭧⭩⭦⭨⎪🮈▍⎪├─╨╫╨─┤┇
╱╽╲ ◳◰ ◷◴ 🮡🮢 🮦🮧◟◞ ◹◸ 🮝🮜 ◥◤ └┘│  ┗┛┃ ╰╯│  ╚╝║ 🭼🭿🭵 ⩗▴⏶⯅▲▸⏵⯈▶▾⏷⯆▼◂⏴⯇◀⎪▐▌⎪╞═╤╬╤═╡┋
⎡⠀⠁⠈⠉⠂⠃⠊⠋⠐⠑⠘⠙⠒⠓⠚⠛⠄⠅⠌⠍⠆⠇⠎⠏⠔⠕⠜⠝⠖⠗⠞⠟⠠⠡⠨⠩⠢⠣⠪⠫⠰⠱⠸⠹⠲⠳⠺⠻⠤⠥⠬⠭⠦⠧⠮⠯⠴⠵⠼⠽⠶⠷⠾⠿⎤⎨🮉▋⎬╞╕╘╬╛╒╡┊
⎢⡀⡁⡈⡉⡂⡃⡊⡋⡐⡑⡘⡙⡒⡓⡚⡛⡄⡅⡌⡍⡆⡇⡎⡏⡔⡕⡜⡝⡖⡗⡞⡟⡠⡡⡨⡩⡢⡣⡪⡫⡰⡱⡸⡹⡲⡳⡺⡻⡤⡥⡬⡭⡦⡧⡮⡯⡴⡵⡼⡽⡶⡷⡾⡿⎥⎪🮊▊⎪└┴─╨─┴┘╏
⎢⢀⢁⢈⢉⢂⢃⢊⢋⢐⢑⢘⢙⢒⢓⢚⢛⢄⢅⢌⢍⢆⢇⢎⢏⢔⢕⢜⢝⢖⢗⢞⢟⢠⢡⢨⢩⢢⢣⢪⢫⢰⢱⢸⢹⢲⢳⢺⢻⢤⢥⢬⢭⢦⢧⢮⢯⢴⢵⢼⢽⢶⢷⢾⢿⎥⎪🮋▉⎪╭──╮⟬⟭╔╗
⎣⣀⣁⣈⣉⣂⣃⣊⣋⣐⣑⣘⣙⣒⣓⣚⣛⣄⣅⣌⣍⣆⣇⣎⣏⣔⣕⣜⣝⣖⣗⣞⣟⣠⣡⣨⣩⣢⣣⣪⣫⣰⣱⣸⣹⣲⣳⣺⣻⣤⣥⣬⣭⣦⣧⣮⣯⣴⣵⣼⣽⣶⣷⣾⣿⎦⎪██⎪│╭╮│╔═╝║
 ▔🭶🭷🭸🭹🭺🭻▁ 🭁🭌 🭂🭍 🭃🭎 🭄🭏 🭅🭐 🭆🭑 🭇🬼 🭈🬽 🭉🬾 🭊🬿 🭋🭀 ₀₁₂₃₄₅₆₇₈₉ ⎛ ▁▂▃▄▅▆▇█ ⎞⎪🭨🭪⎪╰╯││║╔═╝
 ▏🭰🭱🭲🭳🭴🭵▕ 🭒🭝 🭓🭞 🭔🭟 🭕🭠 🭖🭡 🭧🭜 🭢🭗 🭣🭘 🭤🭙 🭥🭚 🭦🭛 ⁰¹²³⁴⁵⁶⁷⁸⁹ ⎝ ▔🮂🮃▀🮄🮅🮆█ ⎠⎩🭪🭨⎭⧒⧑╰╯╚╝❨❩
paololazzari commented 1 year ago

Thanks @digitallyserviced ,

would it be unreasonable to request that SetCursorPos is added to tview ? Are there any reasons not to add this functionality?

digitallyserviced commented 1 year ago

@paololazzari

It is not up to me unfortunately. Many PRs sit unattended for new/convenience features.

It would be up to @rivo

This is why we end up with things like this...

https://github.com/rivo/tview/compare/master...digitallyserviced:tview:digitally?expand=1

https://github.com/tslocum/cview

rivo commented 1 year ago

would it be unreasonable to request that SetCursorPos is added to tview ? Are there any reasons not to add this functionality?

I'm planning on replacing the InputField "engine" with that of TextArea so we get all the TextArea functionality (e.g. copy+paste, selections, etc.) in InputField also. When that is done, it is conceivable that I add a SetCursorPos method.

This can take some time though. It's quite possible that one of the forks will have this before this repo does.

digitallyserviced commented 1 year ago

@paololazzari

in case @rivo feels frisky...

893

if he doesn't feel frisky...

# for just this addition... (overkill to redirect to repo for just one patch)
go mod edit -replace github.com/rivo/tview=github.com/digitallyserviced/tview@input-field-cursor-pos

# for future edits and your own local version...  (you will inevitably end up doing to tview because reasons)
cd YOURPROJECTDIR
mkdir pkgs
git clone https://github.com/rivo/tview pkgs/tview
cd pkgs/tview
git remote add digipatch https://github.com/digitallyserviced/tview
git pull digipatch input-field-cursor-pos
cd ../..
go mod edit -replace github.com/rivo/tview=YOURPROJECTDIR/pkgs/tview
go get
go mod vendor