Skip to content
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

feature request: option to heed formfeed (control-L) as forcing a new page #496

Open
lindes opened this issue Apr 6, 2024 · 8 comments
Open

Comments

@lindes
Copy link

lindes commented Apr 6, 2024

Hi there. Thank you for your continued work over the decades on less! Neat to see that it seems to be the same original author still actively maintaining it. I've been using less for several of those decades, now, and appreciate having it around. :)

Anyway, I was wondering:

Would it be possible to get less to treat ^L (aka formfeed, \f, ASCII FF, etc.) as a signal of wanting a new page of output?

Your old friend more does "pause" on seeing this character, though that fails to get the nice less behavior of clearing the screen when about to display a page. IMHO, it'd be nice to have this pause option in less as well, where it would behave more or less similarly to how it behaves when displaying the next of multiple specified input files.

I don't imagine it would be desirable to make this the default behavior, because it might surprise a lot of folks, so, the request here is to add a command-line option (-f is taken, but -l seems to be available? And I might propose --form-feed as the long option name, though I'm open to whatever makes sense to you), and when that option is specified, either on the command line or in one's $LESS, then it behaves as I'm suggesting.

Also, I'm thinking that unlike more, it would make sense for less to not print anything related to the ^L when this option is on. Just pause and then, upon spacebar, start a new screen page of display. I'm not entirely sure what would make sense as far as backwards scrolling from there. Maybe control-B would just skip you back to the last screen page of the prior section, and k would actually cause the ^L to display after all, and treat it as though it was an unbroken section of text, at least as long as that ^L is on the screen (after which, hitting space again might get you back to the requested behavior).

Hopefully this request makes sense and might be reasonable to accommodate. I know I'd appreciate having this functionality, and while it's certainly possible it's a rare desire, it seems I'm not the only one to have it: I came across a stackoverflow (well, superuser stackexchange) question asking for the same sort of thing.

Thanks again!

@lindes
Copy link
Author

lindes commented Apr 10, 2024

P.S. If you (or anyone) has any pointers on how I might go about this, with a little guidance, I'd probably be up for trying to build a patch. I tried looking through the codebase a little, and I think I could wrap my head around it with time, but I wasn't quite sure where to start, and got a little overwhelmed.

@auerswal
Copy link

Would it be possible to get less to treat ^L (aka formfeed, \f, ASCII FF, etc.) as a signal of wanting a new page of output?

I would like that, too. :-)

Your old friend more does "pause" on seeing this character, though that fails to get the nice less behavior of clearing the screen when about to display a page. IMHO, it'd be nice to have this pause option in less as well, where it would behave more or less similarly to how it behaves when displaying the next of multiple specified input files.

At least on my system, more allows clearing the screen for a new page using either the -c or -p option. But more exits at the end of the file, so one cannot go back from the last page. (This is more from util-linux 2.34.)

I don't imagine it would be desirable to make this the default behavior, because it might surprise a lot of folks, so, the request here is to add a command-line option (-f is taken, but -l seems to be available? And I might propose --form-feed as the long option name, though I'm open to whatever makes sense to you), and when that option is specified, either on the command line or in one's $LESS, then it behaves as I'm suggesting.

I would also think that a new option should be required to activate ending a page on ASCII FF.

Perhaps also enable stopping at ASCII FF when the environment variable LESS_IS_MORE is set to 1? In this mode, the option -l could be added to disable stopping on ASCII FF, as done by the util-linux more implementation? (Sorry for the scope creep….)

Also, I'm thinking that unlike more, it would make sense for less to not print anything related to the ^L when this option is on. Just pause and then, upon spacebar, start a new screen page of display. I'm not entirely sure what would make sense as far as backwards scrolling from there. Maybe control-B would just skip you back to the last screen page of the prior section, and k would actually cause the ^L to display after all, and treat it as though it was an unbroken section of text, at least as long as that ^L is on the screen (after which, hitting space again might get you back to the requested behavior).

With more, going back one page shows goes back to either just after the previous ASCII FF or one screen full of lines, depending of what is less.

Hopefully this request makes sense and might be reasonable to accommodate. I know I'd appreciate having this functionality, and while it's certainly possible it's a rare desire, it seems I'm not the only one to have it: I came across a stackoverflow (well, superuser stackexchange) question asking for the same sort of thing.

IETF RFCs numbered less then 8650 use ASCII FF for pagination. It would be great if less in a sufficiently large terminal could show such an RFC page by page. (In general, the pages have different sizes, such that there is not a single terminal size that just works without stopping on ASCII FF.)

Also, some old source code, e.g., some files in GNU Inetutils, contain ASCII FF characters.

Additionally, support for ending a page on ASCII FF would improve the usefulness of less for checking the result of using pr.

gwsw added a commit that referenced this issue Jun 25, 2024
@gwsw
Copy link
Owner

gwsw commented Jun 25, 2024

I've added a --form-feed option in the post659 branch, change a0d1f5b. The behavior isn't exactly as was proposed here: the ^L is displayed (which I think is useful so the user can tell why the scroll stopped early), and the screen isn't cleared on any forward movement (which I think is more consistent behavior; for example after stopping, j will move one line as it always does, rather than acting like f).

If anyone has comments on the behavior, please let me know.

@auerswal
Copy link

This does not seem to work as I would have imagined. In fact, I do not see any difference between the following two commands (output in the form of a screenshot, to illustrate what is shown inside an XTerm):

$ printf -- '1\n\f\n2\n' | ./less --form-feed

less_--form-feed

and

$ printf -- '1\n\f\n2\n' | ./less

just_less

This is with the post659 branch:

$ git branch
* post659
$ git log -n1
commit 4c86653bb7fe5fd18781ce1c06c6938a33306bb7 (HEAD -> post659, origin/post659)
Author: Mark Nudelman <[email protected]>
Date:   2024-06-25 00:01:51 -0700

    Add support for mouse drag.
    With --mouse, dragging will scroll text forward and backward.
    Single clicking still sets the # mark, but a click and drag
    would previously set a mark where the drag ends.
    Now the drag scrolls the text, and no mark is set when the drag ends.
$ ./less --version
less 659.1x (POSIX regular expressions)
Copyright (C) 1984-2024  Mark Nudelman

** This is an EXPERIMENTAL build of the 'less' software,
** and may not function correctly.
** Obtain release builds from the web page below.

less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Home page: https://greenwoodsoftware.com/less

With more I get the following:

$ printf -- '1\n\f\n2\n' | more

more_pt1

After pressing the spacebar:

more_pt2

@gwsw
Copy link
Owner

gwsw commented Jun 27, 2024

In the current implementation, less never stops scrolling if doing so would leave less than a screenful of data on the screen. Doing so can lead to various weirdnesses, like repainting the screen with r only printing a few lines, stopping at a form feed, and leaving the screen in an inconsistent state. If you try your test with more text between the form feeds you'll see the new behavior:

( seq 100; printf '\f\n'; seq 50; printf '\f\n'; seq 20; printf '\f\n'; seq 100) | less --form-feed

@auerswal
Copy link

Thanks for the explanation, @gwsw!

As far as I understand it, less --form-feed requires one full page of output first, and after that it stops on formfeeds. A small test case for this using an 80x24 terminal window would be:

$ { seq 25; printf 'a\n\f\nb\n'; } | ./less --form-feed

This continues with additional single lines, e.g.:

$ { seq 25; printf 'a\n\f\nb\n\f\nc\n'; } | ./less --form-feed

This works for me as long as the first formfeed comes at the end of a full screen of text. The following looks good to me:

$ { seq 21; printf 'a\n\f\nb\n\f\nc\n'; } | ./less --form-feed

But the following does not, because it continues across the first formfeed:

$ { seq 20; printf 'a\n\f\nb\n\f\nc\n'; } | ./less --form-feed 

The combination with -c, --clear-screen always exhibits the behavior of not stopping on the formfeeds in the above examples.

This is not what I had in mind, and it does not work as well for reading IETF RFCs as using more -c. You are, of course, free to create an implementation you like! Additionally, I have no experience with implementing a pager, and as such have to defer to your judgement regarding an inconsistent screen state.

I do hope that @lindes also finds the time to look at this and to add a comment.

Thanks for looking into this! I really appreciate that you invested time into this issue and worked on a solution that fits into less. I would have preferred a different result, but I didn't even provide a pull request, and I am happy that you considered my opinion. Thanks again!

@gwsw
Copy link
Owner

gwsw commented Jun 27, 2024

Well, more work could possibly be done to make it work more like what you were expecting. When I ran across the issues caused by displaying a partial screen I fixed them by just not allowing a partial screen to be displayed. Possibly something better could be done. If you want to see the issues, you can apply this patch. You'll see that in your examples it does pause after each form feed as you want, but other things don't work well. For example, press r while a partial screen is displayed.

--- a/forwback.c
+++ b/forwback.c
@@ -346,7 +346,7 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, i>
            continue;
        }
        put_line();
-       if (stop_on_form_feed && !do_repaint && line_is_ff() && position(TOP) != NULL_POSITION)
+       if (stop_on_form_feed && !do_repaint && line_is_ff())
            break;
 #189 
        /* {{ 

@auerswal
Copy link

Thanks for the explanation and the diff! I can see the problems with pressing r now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants