awesome-gocui / gocui

Minimalist Go package aimed at creating Console User Interfaces.
BSD 3-Clause "New" or "Revised" License
350 stars 39 forks source link

Allow access to tcell.Screen for redrawing/complex scenarios #82

Closed lawrencegripper closed 3 years ago

lawrencegripper commented 3 years ago

Firstly, thanks for all the work on the fork it's awesome!

Describe the feature you'd like

I'd like to have methods which allow me to use the underlying screen.

I build out a terminal based browser for Azure Cloud which lets you browse to an item and then open your favourite editor to edit it (nano, vi) then once you save and close the editor the update is pushed and the gocui UI redrawn.

With the old gocui we had our own fork which exposed out Flush for us to do this, with the tcell based version I can do the same once I have access to the screen object from tcell_driver.go

Would you be open to a PR to allow get/set public funcs on the screen to enable this and other complex scenarios?

Describe alternatives you've considered

Alternative would be not to expose screen but allow public funcs for

func TcellInit() error {
    return tcellInit()
}

func TCellClose() {
    screen.Fini()
}

Additional context Here is my PR and a gif showing the flow the change allows.

https://github.com/lawrencegripper/azbrowse/pull/310#issuecomment-802112303

editv3

glvr182 commented 3 years ago

Interesting idea, I would be open to exposing a few functions like you proposed. I would like to keep the access screen limited, so this seems like a good alternative.

@dankox what do you think?

lawrencegripper commented 3 years ago

Awesome, works well for me. I've put in a PR to show what the changes would look like, bonus is they're super small.

dankox commented 3 years ago

@glvr182 Actually this is something I would appreciate too :)

What I did in my application is kinda cumbersome with the current API. I stored the full view setup and close gocui and open vim editor. After the vim is finished, I reinitialise gocui with the previously setup layers and content.

This would be definitely beneficial for more people (I remember seeing the approach which I used also in some other project using gocui). I guess it doesn't have to be function directly mentioning tcell though. Could be more like gocui.Suspend() and gocui.Resume() or something like that, to make it more obvious what are they for.

glvr182 commented 3 years ago

Yes that sounds like a good idea, this would enable developers to take more control over tcell while still being within the limits of what should be exposed.

Would either of you be able to create a PR for this?

lawrencegripper commented 3 years ago

Great, sounds good to me. I've updated my PR to use the suggested method names so hopefully good to go.

Chillance commented 3 years ago

So, I was looking at termui and there you have a "Block" which essentially draws the border (or Frame as it's called in gocui). Widgets extend this "Block" and do their thing using the lower level SetCell() function. First I thought this issue was about that, but not directly I guess. However, since it's related I figured I bring this up here and see if we can expose that here too or something? Or should I create a separate issue?

Reason I ask is it seems to me that if available, using termui widgets could be easier to port over and also it could open up for more nice things like that. Looking at gocui View's functions it seems more made for some kind of text editor, not as a generic Canvas to draw something in... I use gocui myself so it would be nice to be able to reuse already made widgets.

dankox commented 3 years ago

@Chillance I don't think this is really related as this issue is about exposing tcell package functions, while what you would like to have is to be able to translate the Block of termui cells into gocui cells.

Exposing tcell.SetCell wouldn't help with that (if I understood your request correctly). What you could do though, is to translate the underlying buffer into ANSI escaped strings and pass it to view thru fmt.Fprint function.
You could iterate over that buffer (which is something like [][]cell) and for each cell in it you would create ANSI escaped sequence with correct coloring. Look at _examples/colorstrue.go example, which iterates over HSV range to create the "image".
You would do basically the same, but you would iterate over the termui cell buffer.

There isn't much to do about this unfortunatelly and that's because how gocui works. It doesn't expose cell layer because that would be in conflict with the "text layer". If you write text and set cell, what has higher priority? Text is translated to cells at the end. So you wouldn't know what came first.

dankox commented 3 years ago

btw... closing as the PR is merged...

Chillance commented 3 years ago

@Chillance I don't think this is really related as this issue is about exposing tcell package functions, while what you would like to have is to be able to translate the Block of termui cells into gocui cells.

Exposing tcell.SetCell wouldn't help with that (if I understood your request correctly).

Sounds contradictory, but ok. :) And yes, I was talking about exposing tcell function(s). tcell.SetCell in this case. But sure, I could translate those termui widgets into instead of using tcell directly, use fmt.Fprintf as you say. Basically termui is on a lower level, setting the values of a matrix grid, while gocui would print the grid row by row... :)

dankox commented 3 years ago

@Chillance After some more looking around... I have to say, that there is SetCell function exposed already :) I was wrong.

It's called gocui.SetRune. But the problem here is, that it is SetCell as you would want, which means, no binding on views. That's the problem with cells and gocui view representation.
So the idea how to use it, is to be sure you do not overwrite it with your view. Because view content is resolved at the end, so the cells set by this function will be overwritten with view. ~if the buffer lines goes over them. Even if you call SetRune after fmt.Fprint(view, "qwerty")~ Just keep that in mind.

Chillance commented 3 years ago

Oh, cool. SetRune might work. Might need some logic to handle global (whole terminal) vs local (view) coordinates...