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

flexible handling of GetConsoleWidth method's default value would be useful in scripting #1300

Open
Nejat opened this issue Jul 19, 2021 · 4 comments
Labels
Area-Output Issue related to CLI output Issue-Feature This is a feature request for the Windows Package Manager client.

Comments

@Nejat
Copy link

Nejat commented Jul 19, 2021

Description of the new feature/enhancement

When listing output winget truncates column width(s) to accommodate for the total width of the console, which is determined by a call to GetConsoleWidth in src\AppInstallerCLICore\TableOutput.h

    namespace details
    {
        // Gets the column width of the console.
        inline size_t GetConsoleWidth()
        {
            CONSOLE_SCREEN_BUFFER_INFO consoleInfo{};
            if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))
            {
                return static_cast<size_t>(consoleInfo.dwSize.X);
            }
            else
            {
                return 120;
            }
        }
    }

If the console is not wide enough, output of a column is truncated and a UTF8 Horizontal Ellipsis (…) is append to the end of the column, also in src\AppInstallerCLICore\TableOutput.h; see the first listing in the image below.

        void OutputLineToStream(const line_t& line)
        {
            auto out = m_reporter.Info();

            for (size_t i = 0; i < FieldCount; ++i)
            {
                const auto& col = m_columns[i];

                if (col.MaxLength)
                {
                    size_t valueLength = Utility::UTF8ColumnWidth(line[i]);

                    if (valueLength > col.MaxLength)
                    {
                        size_t actualWidth;
                        out << Utility::UTF8TrimRightToColumnWidth(line[i], col.MaxLength - 1, actualWidth) << "\xE2\x80\xA6"; // UTF8 encoding of ellipsis (…) character

                        // Some characters take 2 unit space, the trimmed string length might be 1 less than the expected length.
                        if (actualWidth != col.MaxLength - 1)
                        {
                            out << ' ';
                        }

                        if (col.SpaceAfter)
                        {
                            out << ' ';
                        }
                    }
                    else
                    {
                        out << line[i];

                        if (col.SpaceAfter)
                        {
                            out << std::string(col.MaxLength - valueLength + 1, ' ');
                        }
                    }
                }
            }

            out << std::endl;
        }

When the console is wide enough, all of the columns are output in their entirety; see the second listing in the image below.

However, if you either pipe the output to a subsequent command, such as winget upgrade | Select-Object -skip 3, or you assign it to a variable, GetConsoleWidth uses a hard coded 120 for the console width, because it can't get console buffer info for std out. Besides being truncated, the output is also garbled because it is not captured as UTF8; ; see the third listing in the image below.

image

Proposed technical implementation details (optional)

Adding native PowerShell support as proposed in #221 would be the ideal solution, however a quick simple patch to bump up the default value to 180+ would be great in the mean time.

    namespace details
    {
        // Gets the column width of the console.
        inline size_t GetConsoleWidth()
        {
            CONSOLE_SCREEN_BUFFER_INFO consoleInfo{};
            if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))
            {
                return static_cast<size_t>(consoleInfo.dwSize.X);
            }
            else
            {
                return 180; // or more if your heart desires 😋
            }
        }
    }
@Nejat Nejat added the Issue-Feature This is a feature request for the Windows Package Manager client. label Jul 19, 2021
@ghost ghost added the Needs-Triage Issue need to be triaged label Jul 19, 2021
@denelon denelon removed the Needs-Triage Issue need to be triaged label Jul 19, 2021
@sredna
Copy link
Contributor

sredna commented Jul 26, 2021

Why truncate at all? If stdout is a file or a pipe, long lines should never be truncated!

@Nejat
Copy link
Author

Nejat commented Jul 26, 2021

Why truncate at all? If stdout is a file or a pipe, long lines should never be truncated!

I agree, but that would require more work, which would become unnecessary once powershell is natively supported, hence the simple solution suggestion to change one default.

@panther7
Copy link

panther7 commented Jan 9, 2023

Duplicate #2603

@Trenly
Copy link
Contributor

Trenly commented Jun 16, 2023

[Policy] Area-Output

@microsoft-github-policy-service microsoft-github-policy-service bot added the Area-Output Issue related to CLI output label Jun 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Output Issue related to CLI output Issue-Feature This is a feature request for the Windows Package Manager client.
Projects
None yet
Development

No branches or pull requests

5 participants