gcla / gowid

Compositional widgets for terminal user interfaces, written in Go, inspired by urwid.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature Request] Scroll support in terminal widget

Peter2121 opened this issue · comments

It would be nice to see the support of scroll in terminal widget.

Hi @Peter2121 - I finally had some time to work on this! Please give it a try, if it's still useful to you, and let me know if it does the job.

This is really a great improvement! Thanks a lot!
I've just tried it - for me it works as expected. I need some time to test it in different environments, but I think that this issue can be closed - if I find any issue I'll open another one.

I see a problem though.
I pass Ctrl-Z as a meta key to the terminal. The key still works (the next input is ignored by the terminal), but UnhandledInput is not called.

Thanks @Peter2121 , I'll check that out too.

Hi @Peter2121 - could you help me to reproduce the issue? I tried a test with the terminal demo in examples/gowid-terminal/ - I added a log line to UnhandledInput like this

func (h handler) UnhandledInput(app gowid.IApp, ev interface{}) bool {
	logrus.Infof("Unhandled input is called - event is %v", ev)

If I then run the terminal demo and hit C-b n (n being a key that will not be processed), I see the log line appear.

I am guessing you have HotKeyFunctions set via the Options struct to your terminal. The way I have it set up, if one of those functions returns true then subsequent hot-key functions are not run, and the terminal is considered to have accepted the input. In that case, UnhandledInput will not be run. Maybe it needs to be more flexible for your needs? Let me know :-)

Thanks for digging, @gcla !
I don't set any HotKeyFunctions for my terminal at all.
I want just block terminal input with HotKey, to be able to process the next key pressed by UnhandledInput. Maybe it is not the correct approach, but it was working in gowid just before you added scroll support. I have the same logger in UnhandledInput, I see that this function is not fired. The key following the HotKey is correctly ignored by the terminal though, so it seems to be completely lost.
I set the HotKey in terminal.NewExt as HotKey: terminal.HotKey{K: tcell.KeyCtrlZ}.
You can see the full code in cbsd-tui.go in dev branch of cbsd-tui project. Your critique is welcome ;)

Hi @Peter2121 - I think I see the error I made. Could you try with the latest from HEAD? I also added an OnHotKey(..) callback to the widget, in case that's useful. The demo examples/gowid-terminal uses the callback to turn the title blue while the hotkey is active. I will follow your project with interest now! If now, or as you make further progress, you would be willing to send me a screenshot, I'll put a link on the gowid github page :-) I see now the utility of the terminal widget for your purposes. I had considered building a sort of TUI front-end to virsh, maybe along similar lines to what you're doing, using the terminal widget to display the VM console. But I haven't written a single line of code in that direction!

It seems to be fixed (tested the HEAD of doubleclick branch).

After some tests I see a problem.
If I produce some output in terminal, then I use scrollbar to go up and see the beginning of my output - I cannot use the terminal anymore, the input seems to be lost. Even if I return to the bottom with scrollbar - the cursor is correctly placed, but there is no input. The interesting thing is that up/down keys produce scrolling up/down. So, it seems that the input is definitely moved to scrollbar and does not come back to the terminal itself.

Thanks @Peter2121 , I'll check this out!

Any news here? I saw some commits in master, are they related to the input focus problem?

Sorry @Peter2121 , I switched my attention and then have been distracted for one reason or another. I'll investigate this ASAP.

hi @Peter2121 - I've been trying to reproduce this on my simple terminal demo program, and haven't been able to yet. You can run that demo by typing this in a shell that's in the root of the gowid git repo:

go run examples/gowid-terminal/terminal.go

Would you mind trying to see if you see the same symptoms with that program? What I see is that after generating a few screens of text, then clicking up a few times, then clicking down a few times, the first keypress in the main terminal cancels "scroll" mode, and then user input works as normal.

Hi @gcla
Sorry for delay, I was really busy the last week.
Yes, I have exactly the same symptoms running examples/gowid-terminal/terminal.go on my workstation.
Doing some efforts (some random mouse clicks and buttons presses), I can get the focus back. Unfortunately, it is really random, I cannot understand what really brings the focus back.
I'm ready to debug deeper, please, give me some ideas ;)

BTW, in the same example the exit on Ctrl-C or Esc does not work for me. 's' to disable scrollbar works correctly.
I tested in two different terminals (Terminology and LXTerminal) and in two different shells (zsh and bash) - the same behavior.
PS I'm on FreeBSD 12.3 (but I don't think it is important).

I think I understand what's happening.
There is a function ResetScroll() in terminal.go to disable scroll, show the current line and pass the input to the terminal. I see in the code that this function is called ONLY if one press 'Q' or 'q' in scroll mode. This is not the behavior I expected to see :)
Indeed, if I press 'Q' or 'q' in scroll mode - everything works as expected. But IMHO the scroll mode should be disabled when one scrolls to the bottom (like in tmux).

I patched terminal.go as follows, I've got the behavior I supposed to have ;)

@@ -379,6 +379,10 @@
 	} else {
 	        lines = w.canvas.ScrollBuffer(dir, false, gwutil.SomeInt(lines))
 	}
+	// Disable scroll if we are at the bottom and we tried to scroll down
+	if w.isScrolling && (lines == 0) && (dir == ScrollDown) {
+	        w.ResetScroll()
+	}
 	// Scrolling is now true if it (a) was previously, or (b) wasn't, but we
 	// scrolled more than one line
 	w.isScrolling = w.isScrolling || lines != 0

Maybe there is a better way to obtain the same result ;)

I patched terminal.go as follows, I've got the behavior I supposed to have ;)

@@ -379,6 +379,10 @@
 	} else {
 	        lines = w.canvas.ScrollBuffer(dir, false, gwutil.SomeInt(lines))
 	}
+	// Disable scroll if we are at the bottom and we tried to scroll down
+	if w.isScrolling && (lines == 0) && (dir == ScrollDown) {
+	        w.ResetScroll()
+	}
 	// Scrolling is now true if it (a) was previously, or (b) wasn't, but we
 	// scrolled more than one line
 	w.isScrolling = w.isScrolling || lines != 0

Maybe there is a better way to obtain the same result ;)

Terrific! Thank you! This is concise and I don't see any problem with applying this directly. I'll get things merged and tagged this weekend.

Hi @Peter2121 - I applied your patch with a small tweak, pushed to master and updated your doubleclick branch too. Thanks!