openSUSE / zypper

World's most powerful command line package manager
http://en.opensuse.org/Portal:Zypper
Other
405 stars 110 forks source link

Automatically adapt CLI to terminal size on resize. #524

Closed RokeJulianLockhart closed 8 months ago

RokeJulianLockhart commented 8 months ago

When performing something like sudo zypper dup, each package installation output is displayed to the terminal at the maximum width that the terminal was when it was outputted. This isn't a problem until the terminal is resized. Resizing to a smaller size causes it to wrap or be hidden outside the terminal's boundaries. Resizing it to a larger size causes it to display at a size which might have been previously problematic (hence the user's choice to resize the terminal). Most tools nowadays are immune to this; they dynamically resize themselves to the maximum terminal size on resize. An example of this is https://github.com/ClementTsang/bottom.git, although it takes control of the entire display, which I don't suggest.

mlandres commented 8 months ago

Zypper is a commandline tool. We intentionally don't use any kind of window or widget based Ui (like ncurses). We at most use ANSI escape sequences, in case the terminal supports this, but we also work on dumb terminals. That's why the current line is adjusted to the terminals current with, but written lines are no longer within our scope.

The YAST ncurses backend would provide you such a kind of window based UI.

RokeJulianLockhart commented 8 months ago

https://github.com/openSUSE/zypper/issues/524#issuecomment-1888781209

@mlandres, I just used the wrong word in the title - TUI, not CLI. That doesn't impact the proposal, which itself doesn't have any reliance upon a TUI. Additionally, I certainly don't understand your rationale for https://github.com/openSUSE/zypper/issues/524#event-11467000880, because having this be possible wouldn't affect any "dumb" terminals like ttys. You can prove this by invoking the aforecited project via such terminals.

mlandres commented 8 months ago

@RokeJulianLockhart Currently zypper (and the subcommands it executes) simply write their output lines to stdout (or stderr).

In case a terminal is connected to stdout and the terminal offers retrieving it's current width, we try to format our lines accordingly. If no terminal is connected (i.e. the output is piped or redirected) we use some default. But once a line is written, it's gone.

In case a terminal is connected to stdout, the terminal displays the line it received and the terminal handles it's content (i.e. the lines zypper already wrote) when being resized. It's the terminal 'decision' whether the content is wrapped or clipped. If no terminal is connected, the lines may be consumed in a pipe or stored in a file.

A graphical approach (bottom or ncurses or..) is completely different. Zypper (and the subcommands) would not simply produce a steam of output lines. It would need to 'paint' the data on the screen. And it would need to be able to re-paint the data, if the screen size changes. Zypper would need to collect and store the output it produced. Together with the data we'd need to store the information how to render it (as ProgressBar, Table, Text...), so we are able to re-render and re-paint it on the screen whenever the size changes.

This kind of output cannot be consumed by pipes or being redirected to files. And it's not zyppers intent to provide such a graphical UI.

We do this re-painting on the last line only to draw progress - if we're connected to a terminal and the terminal has all the capabilites we need. But once the progress is closed, the information about it is gone.

RokeJulianLockhart commented 8 months ago

https://github.com/openSUSE/zypper/issues/524#issuecomment-1889604466

@mlandres, this seems to me like you expect that the human-readable content outputted also needs to be consumed programmatically, meaning that you can't do either properly. I'm aware that bash is the de-facto default shell for most Linux distributions (due to its POSIX support) rather an object-oriented one like PowerShell, so you can't provide programmatic output using objects, but wouldn't it be better to expect those consuming the data to use DBus rather than pipes, and in doing so be able to improve the UX? I don't see any downside.

By the way, in case you're getting the wrong idea from the example I provided, man is also an example of a command-line utility which adjusts itself, although it does also take the entire display like btm does.

mlandres commented 8 months ago

IMO not (at least not my man). man renders the data to text according to the current terminal with and then uses less as a pager to display it. Less stores all the lines and handles the display. But less does not re-format the original lines. It does wrapping or clipping (depending on it's -S switch), but the original format does not change.

If I make the terminal smaller

SCREEN(1)           General Commands Manual           SCREEN(1)

NAME
       screen  - screen manager with VT100/ANSI terminal emula-
       tion

becomes

SCREEN(1)           General Commands Manual
           SCREEN(1)

NAME
       screen  - screen manager with VT100/
ANSI terminal emula-
       tion

Similar you can pipe zypper's output through less (zypper lr | less or zypper lr | less -S )

Zypper is for terminal and scripts. YAST'S packagemanager provides a graphical UI (Qt or ncurses). PackageKit (with the zypp-backend) provides a dbus interface. All three are based on libzypp, which does the repo and package management.

The idea is tempting, but ATM we will not compete with YAST ncurses UI.

RokeJulianLockhart commented 8 months ago

https://github.com/openSUSE/zypper/issues/524#issuecomment-1889673780

Sorry, @mlandres. I'm a little unwell. I don't know why I thought man did that. You're right. Regardless, thanks for the explanation of the differences between the tools, and thus which to use. However, what's the purpose ultimately of zypper when libzypp provides a proper dbus interface via PackageKit? I've noticed that PackageKit (via pkcon) can't perform some of the things zypper can, so it just seems like both are trying to reinvent the same wheel.

mlandres commented 8 months ago

Not every system runs a graphical desktop, or has dbus enabled. But a shell is present almost everywhere.