-
-
Notifications
You must be signed in to change notification settings - Fork 834
feat: add pager to allow scrolling of long outputs in the REPL #2162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@Snehil-Shah Thanks for providing a concrete implementation. However, I am not sure that it is a good idea to auto-page. There are likely to be times when paging is not what you want. For example, if a function returns a large blog of JSON, I may want to copy the entire blob and paste in my editor for further processing. If we adopted this PR, it is not clear to me that is possible anymore when auto-paging is enabled, as the entire content is never displayed in the terminal at any one time. And I am not of the opinion we should add "special" behavior to paging to support this use case. Instead, I might suggest exposing the pager as a function. E.g., something along the lines of
where In short, the user should explicitly opt-in to paging when applied more generally. Data analysis tasks in which you want to clean-up and munge some data before copying the results for further processing elsewhere is just too common a task (I, for one, do this quite regularly) to make the behavior currently introduced in this PR the default. |
FWIW: exposing the pager as a separate function was my initial approach for implementing And note that I did not try to implement |
@kgryte with the current behaviour, hitting CTRL+X exits paging and we can see the entire output at once to copy. Can I get some feedback on the in REPL scrolling UI? How is it compared to a full window |
By UI, you mean the still visible command which triggered paging? |
In general, the advantage of |
@kgryte I think we should leave clearing the terminal to the user using the clear command. The current implementation, allows the user to see the previous stuff that has happened in the REPL both in scroll mode and after leaving the scroll mode. Regarding a pager mode, the current implementation employs this using the |
@kgryte I am attaching some clips of the current behavior of the pager UI
pager.2.mp4
allow_mouse.1.mp4
ctrlx.1.mp4 |
@kgryte OK so I researched and tried some stuff, and it might need some discussion
We can control the printing of the return value as we explicitly do it ourselves and so can intercept it easily to check for paging. The problem comes with the
The problem: REPL-specific commands like
If there are issues with this approach too, then we can stick to the original RFC of just paging What do you think? |
@Snehil-Shah Thanks for investigating and summarizing. I don't have a good sense at the moment what the "right" (if there is such a thing) approach should be without doing a bit of digging myself. With a bit of luck, I'll get a bit of time this weekend to poke around at the REPL implementation and circle back. |
This commit avoids the need for mutating a provided output stream. Further, enabling and disabling paging can be performed programmatically.
…/Snehil-Shah/2162
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
One other addendum: there's also the scenario where a user resizes a terminal to less than 80 columns. This will cause text to wrap to the next line and muck with rendering. For clarity, I don't think we should do anything about this. All of the documentation assumes at least 80 columns (i.e., the default terminal width), and accommodating narrower views would require reflowing text (and examples!), which is definitely beyond the scope of this PR. |
Another something I noticed is that when doing
the rendering seems to get messed up. This may be due to text wrapping beyond the number of terminal columns and can be considered related to my previous comment. I suppose this is a more general problem. Suppose a function returns a very long string with no line breaks and which takes up more rows that currently visible within the viewport. Currently, we base paging on line breaks but that is not the only way to get long output. We should probably make this more robust, but this should be left to a follow-up PR. |
@kgryte Made some changes (avoiding welcome text to trigger paging and a SIGINT check to exit paging) and fixed some bugs related to viewport height and resizing the terminal. It's working as expected now at all terminal heights. The readline's completer doesn't seem happy with the pager and I can't seem to figure out why. Each completion is on a new line. Moreover, if the list of tab completions are taller than the terminal, nothing is printed and we presumably enter paging mode (as the page is blank and cursor is hidden). Only after pressing I don't think we need to stress about it now as we have written our own completer in #1855 and we can change it to use the
Can't we add a check in the Regarding tests: I know we shouldn't be accessing internal properties in tests, but this was the only way I could get it to enter paging. After it enters paging this is how the I can't see the 'Use up/down arrows...' help text in there, but we know it's paging as we don't see the entire output of the help command. Doing the same thing with Should I move ahead with the tests using this? |
@Snehil-Shah Yeah, testing the pager seems tricky. One thing you could try is to put the output stream in "object mode". Regarding internal properties, I'd approach this differently. Rather than access via var inspectSinkStream = require( '@stdlib/streams/node/inspect-sink' );
var repl = require( './fixtures/repl.js' );
// ...
var ostream = inspectSinkStream( onWrite ); // <= could also put into object mode
ostream.columns = 80;
ostream.rows = 42;
var opts = {
'input': new DebugStream({...}),
'output': ostream,
// ...
};
var r = repl( opts, onClose ); |
I think we can punt on this for now. I think it is enough to make the default behavior TTY-specific. If a user starts mucking about and fiddling, for now, it is fine to leave it "buyer beware". |
Yes, actually that test output seems reasonable. If you Also, to avoid test fixtures changing out from beneath you (e.g., we should not assume the contents of any API's help text), I suggest using
|
Re: TAB completion. Indeed, that is strange. Not sure why it formats differently. And agreed, we can punt on this in this PR and address in a follow up PR. |
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@kgryte Wrote tests for the pager, let me know if they are okay or needs changes... Btw, when I was trying to push my changes, I was getting some errors by the pre-push hook:
I think it's also trying to run fixture files as test files.. |
@Snehil-Shah Thanks for working on the tests. I'll try and take a look in the next day or so. |
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Thanks for catching. I've found the error in our hook script and will push a patch shortly. Although it is not clear why attempting to "run" the fixture file should be problematic, given that the file has no side effects. |
…/Snehil-Shah/2162
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks, @Snehil-Shah!
Resolves #2149
Description
This pull request:
The pager allows scrolling in place meaning the user stays in the REPL, when scrolling through. (demo attached below)
pager.2.mp4
Related Issues
This pull request:
help()
documentation pager in REPL #2149Questions
The above is the design I had in mind. Is the design good? I feel it's better than a
less
type of behaviour, as the user stays in the REPL and can scroll up to see previous commands and outputs while in scroll mode.The current implementation also allows scrolling of all outputs rather than just the
help()
documentation. I felt this is a useful feature in general and not just limited to documentation (pagingreadFile
outputs for example)Other
As mentioned in the RFC, it would be helpful to know the approach taken by @kgryte in prior attempts at implementing this...
Checklist
@stdlib-js/reviewers