tview icon indicating copy to clipboard operation
tview copied to clipboard

The `TextArea` (a multi-line text editor) is now part of `tview`

Open rivo opened this issue 3 years ago • 32 comments

Update Sep 3, 2022: TextArea is now live! Please jump to the announcement for details!


Based on your feedback given in the survey (#578, you can still participate if you haven't yet, by the way), a widget which allows you to edit multi-line text is the feature that is missing the most from this package. I have ideas for this widget but my experience tells me that what I have in mind does not always match your requirements. So I'd like to use this issue to collect your feedback on what you need.

It's obvious that I won't implement a whole vim or Emacs editor inside of tview. So the question is rather, what is the minimum set of features that will allow you to proceed with your projects? Here's what I think the widget should do (and not do):

  • Allow the user to enter and edit text inside a dedicated rectangular area on screen.
  • Use common keybinds for editing and navigation (should be consistent with other keybinds used in the package).
  • Mouse handling (as much as what is possible in a terminal UI)
  • Optional word wrapping.
  • No file system access, i.e. text will be kept in RAM. (Again, I'm not going to reinvent file editors.) So there's a certain limit to the text size.
  • No "modes" as in "insert mode" or "navigation mode". Modes are bad UI. Everything is always in editing mode.

Feel free to add to this but be sure to include "why" you want that feature, i.e. provide an actual example from your application where your users needed it. Preference will always be given to existing real-world requirements.

Thank you!

rivo avatar Apr 27 '21 13:04 rivo

Will text area implement a cursor that can be controlled? For instance moving the cursor to particular part of the text area or else inserting text at the current cursor position?

Will text highlighting be supported? The use case here would be to highlight a word and than allow wrapping it in html/markdown tags or converting it to a html/markdown link.

barryodev avatar May 04 '21 11:05 barryodev

@barryodev Regarding highlighting, do you mean highlighting text with the mouse? This can be difficult when the text area is embedded in a Flex or Grid layout (maybe even with borders) and the text to be highlighted wraps over to the next line. I have to check if there are workarounds to this.

Wrapping text in tags is something you'd have to do yourself. (I'm not planning to write an HTML or Markdown editor.) I suppose, though, that if highlighting is generally available, it wouldn't be too hard.

rivo avatar May 04 '21 11:05 rivo

For my use case:

Must Haves:

  • Cursor with arbitrary navigation (move across lines, character, pages)
  • Editing in arbitrary positions (inserting/removing characters/lines in arbitrary points of the text view)
  • Word wrapping

Nice to Haves:

  • Highlight via keyboard w/ simple editing (remove/replace highlighted text)
  • API for modifying text at arbitrary positions
  • Copy/paste support

Unneeded but would be a bonus:

  • Mouse handling
  • Rich text support (whatever is possible in text mode)

matheusd avatar May 04 '21 12:05 matheusd

@rivo For my use case keyboard only, user can press a key combination to switch to highlight mode, cursor would freeze in current position and they could move a 2nd cursor around the text area to select text for highlighting.

I should have been clearer in my post, when I was talking about wrapping text in tags I was talking about the use case I'd have for the functionality of inserting text at the cursor and removing the currently highlighted text.

Highlighting text and editing it is something I could implement myself on top of text area, its more of a nice to have as @matheusd mentioned.

barryodev avatar May 04 '21 13:05 barryodev

I’m onboard with the roadmap here as-is. Basic navigation and paging with standard keys and editing are really my only hard features. Color would be nice, but not required at all, since I can always swap in a standard text view when not editing.

flowchartsman avatar May 06 '21 16:05 flowchartsman

Hello @rivo I discovered this package a couple of weeks ago and I have to say good job! it is an amazing work and very useful package.

I started using it to build an application, and I have also hit limitation(s) while using textview primitive. I would love to see the following features:

  • Text selection with mouse/cursor
  • Text copy with mouse/cursor

For me these are the important features to add.

AmrGanz avatar May 14 '21 13:05 AmrGanz

How important is undo/redo functionality to you?

From what I can see, I'll have to implement a Gap Buffer (OT or CRDT are beyond scope, I would think) but I want to keep it as simple as possible. That is, if I can avoid implementing undo/redo, it would make my life much easier. If you want to make a strong case in favour of undo/redo, however, please speak up.

rivo avatar May 29 '21 12:05 rivo

Undo/Redo not important to me.

matheusd avatar Jun 03 '21 15:06 matheusd

I won't be using Undo/Redo in my application so I don't think it is important for me.

AmrGanz avatar Jun 04 '21 08:06 AmrGanz

Unicodes

Konstantin8105 avatar Jul 05 '21 18:07 Konstantin8105

Any update on this?

ghost avatar Sep 23 '21 18:09 ghost

In the README there is an animated GIF, tview.gif, that shows syntax highlighted code in the right pane. I'd like to do something similar. It doesn't need to be editable, I just want to display it. I can't find any widget that does this type of thing. Is there one? If not I'd find one extremely useful. In any case, thanks for the library!

youngkin avatar Sep 24 '21 16:09 youngkin

In the README there is an animated GIF, tview.gif, that shows syntax highlighted code in the right pane. I'd like to do something similar. It doesn't need to be editable, I just want to display it. I can't find any widget that does this type of thing. Is there one? If not I'd find one extremely useful. In any case, thanks for the library!

The example uses the TextView widget. You can find the code here.

ghost avatar Sep 24 '21 18:09 ghost

In the README there is an animated GIF, tview.gif, that shows syntax highlighted code in the right pane. I'd like to do something similar. It doesn't need to be editable, I just want to display it. I can't find any widget that does this type of thing. Is there one? If not I'd find one extremely useful. In any case, thanks for the library!

The example uses the TextView widget. You can find the code here.

This demo code has the colors hardcoded in-line with the text/code. I was hoping for something that was context aware enough to be able to automatically set the colors. Thanks for the pointer though, it's a good example of how text can be colored.

youngkin avatar Sep 24 '21 22:09 youngkin

In the README there is an animated GIF, tview.gif, that shows syntax highlighted code in the right pane. I'd like to do something similar. It doesn't need to be editable, I just want to display it. I can't find any widget that does this type of thing. Is there one? If not I'd find one extremely useful. In any case, thanks for the library!

The example uses the TextView widget. You can find the code here.

This demo code has the colors hardcoded in-line with the text/code. I was hoping for something that was context aware enough to be able to automatically set the colors. Thanks for the pointer though, it's a good example of how text can be colored.

If you want dynamic syntax highlighting, you may use alecthomas/chroma with ANSIWriter().

ghost avatar Sep 25 '21 07:09 ghost

In the README there is an animated GIF, tview.gif, that shows syntax highlighted code in the right pane. I'd like to do something similar. It doesn't need to be editable, I just want to display it. I can't find any widget that does this type of thing. Is there one? If not I'd find one extremely useful. In any case, thanks for the library!

The example uses the TextView widget. You can find the code here.

This demo code has the colors hardcoded in-line with the text/code. I was hoping for something that was context aware enough to be able to automatically set the colors. Thanks for the pointer though, it's a good example of how text can be colored.

If you want dynamic syntax highlighting, you may use alecthomas/chroma with ANSIWriter().

Looks interesting, thanks for the tip!

youngkin avatar Sep 25 '21 18:09 youngkin

I think simple is good. If we had a multi-line editor just like the single line editor, but with up/down arrows in addition to the left/right arrows, it would go a long way. Enter should put in a \n character. Backspace/delete should remove \n if it encounters it. For a simple terminal based application, that would do it. I think if you want anything more, it's going to be custom anyway. Oh, and it should scroll, if there are more lines entered than shown.

cumminsd avatar Dec 30 '21 19:12 cumminsd

I think it would be nice if TextView's API could be modified to simply be editable, then it can be exposed using a SetEditable(bool) method. I think TextView already has what a multi-line editor should have except for being editable.

As a side-note, I can't remember if the current TextView allows selecting regions of texts using the mouse yet, but that would be required of a basic multi-line editor (in my opinion), so being able to implement this feature for both use cases would be awesome. There are lots of overlaps in features between the two that I'd rather see TextView being extended than a new widget.

diamondburned avatar Jan 01 '22 07:01 diamondburned

any updates on when can we expect a TextArea widget?

naqvijafar91 avatar Jan 10 '22 03:01 naqvijafar91

My application use case would be satisfied with fairly basic editting features. No real need for syntax highlighting, just plain text entry with the obvious navigation key sequences, and highlighting with cut/copy/paste. In the absence of an official solution, I'm currently using a fork of tview, where I've merged the code from the TextArea widget contributed in #447, and it more or less does what I need without too many rough edges. For any advanced editing features I'll just provide the user a way to spawn an external emacs/vim.

berrange avatar Mar 01 '22 10:03 berrange

For filling in forms in text mode many times you want the textbox having a fixed dimensions, like for example 20 characters wide and 4 rows, and the user being able to normally edit the field. As another comment has already mentioned, replacing carriage returns by "\n" in the returned string is very useful.

Two use cases for form come to mind:

You are generating an invoice form with a customer TextField. The customer TextField might be generated from the customer records ("Name", "VAT ID", "Address Line 1", "Address Line 2", etc.) but in the invoice you might just want to have a prepopulated TextField and store that as a text. The user could use the prepopulated text field as it is or add/modify something specific for that delivery or invoice.

I find replacing carriage returns by "\n"s very relevant in that case as it has been already requested in other comment. Although maybe it is even better to just return a slice of strings so the application can do whatever is needed.

Another common use case is a comments or notes field in a form, you would again want to store if possible as a single field without carriage returns (that makes harder to process data in files) and normally you want to put some boundaries into how far the user can go on each line as you might want to also print that.

marioemmanuel avatar Apr 24 '22 07:04 marioemmanuel

you want the textbox having a fixed dimensions, like for example 20 characters wide and 4 rows

I think the TextArea widget doesn't have to provide this. This is easily achievable by extending the widget's GetArea() method to implement the Primitive interface. Perhaps having a CenterBox widget for this purpose might make more sense and would avoid duplicating a lot of code.

diamondburned avatar Apr 24 '22 16:04 diamondburned

I have to agree with @berrange here. Simple is better. I think the prominent use case is for tools/utilities that are used on a server to enter information where there may not be a GUI installed. I think that if you are building a complex applications (financial, business, etc.) and are writing it as a console application, you are probably not using the right tools for the job. :-)

A simple, multi-line text field is all that is really needed. It should accept "enter" to move to a new line. Cursor keys should move in two dimensions. Scrolling in both dimensions is also preferred.

Colors and highlighting would be nice, but certainly not necessary. I'm not even concerned about copy/paste. Most terminal applications will handle that in a simple way, copying the screen and pasting it as keystrokes.

cumminsd avatar Apr 24 '22 16:04 cumminsd

Everyone, thanks for providing feedback! I will try to use my time off work during the summer to implement this widget which, by the way, is the most requested feature.

Many requests like this one have been submitted by you and they've been on my todo list for a long time. Please consider sponsoring me on GitHub! It will allow me to respond to your requests faster and implement new features sooner rather than later.

rivo avatar Jul 09 '22 12:07 rivo

There is a new branch textarea where I'm developing this new widget. It's not completely done yet and some things may still change but if you'd like to try it out, go ahead. If you find any bugs, please report them here (along with instructions on how to reproduce them).

rivo avatar Aug 26 '22 06:08 rivo

After eight weeks of developing the new TextArea widget, I'm finally releasing it into the wild (#759). Please have a look at the documentation for details.

I should note that it's not yet possible to add a TextArea to a Form as forms are currently only built for primitives with only one row. Adapting Form to be able to handle larger primitives is one of my next tasks.

The text area is a complex beast, as all text editors are. If you find any bugs, it's crucial that you give precise instructions on how to reproduce them. Just sending a panic stack is not going to be enough. I'm pasting a minimal program below that you should use for your bug reports (or something of similar size). Please let me know exactly what you did (all keystrokes!), what your expectation was, and how the result is different from your expectation. If you can post a video, that could also work well in some cases.

package main

import "github.com/rivo/tview"

func main() {
	textArea := tview.NewTextArea()
	tview.NewApplication().EnableMouse(true).SetRoot(textArea, true).Run()
}

As always, I'm not planning on making breaking changes in the long run but if in the new few days, it turns out I missed something major, there could be changes.

Enjoy!

rivo avatar Sep 03 '22 10:09 rivo

fooooooo
_
barrrrrrrr

the _ stands for the current cursor on an empty line, while pressing up/down arrow, the cursor will jump to the tail of lines:

fooooooo_

barrrrrrrr_

this behavior is confusing, the cursor should go to the head of lines in most of text editors

deluxghost avatar Sep 05 '22 09:09 deluxghost

Where was the cursor previously? In editors like vim, that affects where the cursor will end up:

  • If the cursor was previously at the start, going to an empty line then a non-empty line will put it at the start
  • If the cursor was previously at the end, going to an empty line then a non-empty line will put it roughly at the previous column

diamondburned avatar Sep 05 '22 13:09 diamondburned

@diamondburned is right. The horizontal cursor position is preserved, even when the line before/after it is shorter. If the cursor is somewhere on the right and you move it up or down, conceptually, you would still expect it to be on the right, even when it can't be due to an empty or short line.

I tried this in lots of editors, including Vim, VS Code, Pages (I would assume Word does it, too). And even the textarea HTML element behaves like this in all browsers.

I noticed that some editors (e.g. Vim) even have a notion of "the cursor is at the end of the line" which is then preserved during vertical movement. I didn't implement that, though.

rivo avatar Sep 05 '22 14:09 rivo

@rivo @diamondburned

I did more tests, looks like it was the behavior with the enter key that confused me In Vim/VSCode/HTML textarea, when I press enter, the cursor will return to the start, no matter how the cursor goes up and down, it is still at the start. But it indeed remembers the previous cursor column if I didn't press enter yet

HTML textarea: msedge_2022-09-06_13-50-33

tview textarea demo: Code_2022-09-06_13-51-35

I only used up/down/enter to change lines in these tests

deluxghost avatar Sep 06 '22 05:09 deluxghost