rivo / tview

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

Text selection in TextView #774

Open F1bonacc1 opened 1 year ago

F1bonacc1 commented 1 year ago

First of all, absolutely love the library, its flexibility, the extensive documentation, and all the examples you provide.

I noticed that you've asked before about text selection in #694 My issue is a little different - when using the regular (terminal) selection (mouse mode on + shift || mouse off) it also selects the borders which surround the TextView. You mentioned that maybe it can be done using regions. I also have been thinking along those lines, but I am not sure it will be responsive enough with the regex (for region eval) that runs during the selection.

Do you have any ideas what would be the best way to approach this? Thanks!

rivo commented 1 year ago

Well, I guess I was a bit quick to say that because while I still think it may be possible, it might be difficult to be made to work. Regions allow you to show selections in a TextView object. But then you still have to map mouse positions to locations in the text. Or you have to insert regions inbetween each character, which could work but is not great.

Would the new TextArea primitive help you? That primitive supports text selections like the ones you're asking for. You'd still have to integrate the clipboard with your OS's clipboard, though. And it's not a read-only element. (I don't know your use case so maybe that's ok?)

F1bonacc1 commented 1 year ago

@rivo Thank you for getting back to me. Using TextArea is an interesting idea... Maybe if I can convert it to a read-only, it would actually work. My use case is a log viewer for running processes and some users asked for the ability to select snippets from that log. It's an open-source project so feel free to check it out here: https://github.com/F1bonacc1/process-compose

Also, TextArea doesn't implement the Writer pattern, which is very useful for a log viewer. I suppose that can be added. I am still not sure what is the best direction here:

  1. The text selection functionality to TextView
  2. Add read-only, Write interface to TextArea
rivo commented 1 year ago

With the TextArea, you could set max-length to 1 or something. But thinking about it some more, I don't think it's a great solution. TextArea is made for text input primarily. Scrolling, for example, happens by positioning the cursor. Its keyboard controls are very different from those of TextView. It doesn't support colours etc.

I guess the only correct way to do it is for me to implement mouse selection support in TextView.

I will keep this issue open until this has been added. I should note, though, that I don't want to give you false hope of this being available very soon. I.e. it might take a while. There are a bunch of other issues that need to be taken care of first.

F1bonacc1 commented 1 year ago

Thank you for taking this under consideration. And once again thank you for such a great library!

digitallyserviced commented 1 year ago

@F1bonacc1 Check out https://github.com/pgavlin/femto

I dunno if it will work for your use case as a simple input view but I use it in my project as a js editor with syntax highlighting.... Makes it a bit easier to handle styling/formatting if you can define a syntax/format for your text.... The dude basically stripped micro 1.4 down to the textarea and wrapped tview primitive around it.

image

F1bonacc1 commented 1 year ago

@digitallyserviced Thanks for pointing this out, I will definitely check it. The solution that I eventually implemented in my project is:

  1. When a user enters Selection Mode I switch to TextArea (from TextView)
  2. I keep all the styling and copy the text so it is almost seamless.
  3. When Selection Mode is exited, I reverse the whole process.

Surprisingly this wasn't the most difficult part. The most difficult part was finding a cross-platform clipboard library. There are solutions that require additional installations (xclip or xsel), and I didn't want to ask my users to mess with all that. So I created a new Frankenstein package from all the pieces that I found: https://github.com/F1bonacc1/glippy

quantonganh commented 1 year ago

I'm building a simple terminal UI for ChatGPT: https://github.com/quantonganh/chatgpt

My issue is the same as @F1bonacc1:

when using the regular (terminal) selection (mouse mode on + shift || mouse off) it also selects the borders which surround the TextView.

Regions allow you to show selections in a TextView object. But then you still have to map mouse positions to locations in the text. Or you have to insert regions inbetween each character, which could work but is not great.

Could you please elaborate more? How can I use regions to make the selections does not select the border?

I guess the only correct way to do it is for me to implement mouse selection support in TextView.

I can use mouse to select text in TextView, but the issue is, as I said above, it also selects the border:

Screen Shot 2023-03-30 at 5 23 24 PM

Btw, do you know why the highlight is not clear?

I will keep this issue open until this has been added. I should note, though, that I don't want to give you false hope of this being available very soon. I.e. it might take a while. There are a bunch of other issues that need to be taken care of first.

Do you have a plan to add it?

Thank you for great work!

The solution that I eventually implemented in my project is:

When a user enters Selection Mode I switch to TextArea (from TextView) I keep all the styling and copy the text so it is almost seamless. When Selection Mode is exited, I reverse the whole process.

Not sure if I miss something, but when I select text in TextArea, it also selects the border:

Screen Shot 2023-03-30 at 5 41 53 PM
quantonganh commented 1 year ago

As a workaround, I have to hold the option-command key down while dragging the left mouse button to select block of text.

rivo commented 1 year ago

@quantonganh The answers to all of your questions are given in this thread further above.

digitallyserviced commented 1 year ago

@quantonganh Please read the posts above yours like my mention of micro

Could you please elaborate more? How can I use regions to make the selections does not select the border?

Regions wont eliminate the mouse selecting borders. The only way you can resolve this possibly is to replace the Borders defined runes (borders.go) to just ' ' spaces. And then use a different background color as border styles. This way a mouse doesnt select a border rune character as it is a space. But this does not look very good.

I can use mouse to select text in TextView, but the issue is, as I said above, it also selects the border:

Again, the tty/terminal emulator/console you are using does not have any awareness of what is, and isnt a part of the UI, and what should be useful for selection. Other applications usually stop the selection process, and then manually (within their app), show that text is being selected. Just like micro does. I would highly suggest looking at pgavlin/femto. because the femto widget was ported to be embedded into a tview app, and has more functionality that would be expected from a text input control in a GUI application.

@zydeddia/micro app is a text editor that is geared towards specifically editing text. rivo/tview is simply a framework for building TUIs and while has support for TextArea and things it is not focusing/geared/catering to building text editors. You can see in th gif that holding shift and arrows selects text. Also the mouse selects ONLY the text in the buffer. Again this is handled by the APP, because like stated above, the terminal emulator is stupid.

Peek 2023-04-02 18-19