curl: make warnings and other messages aware of terminal width

This removes unnecessary line wraps when the terminal is wider than 79
columns and it also makes messages look better in narrower terminals.

The get_terminal_columns() function is not split out into its own source
file.

Suggested-by: Elliott Balsley
Fixes #13804
Closes #13808
This commit is contained in:
Daniel Stenberg 2024-05-28 09:44:27 +02:00
parent 67b0692f09
commit 6946b3a799
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
7 changed files with 128 additions and 66 deletions

View File

@ -59,6 +59,7 @@ CURLX_HFILES = \
CURL_CFILES = \
slist_wc.c \
terminal.c \
tool_binmode.c \
tool_bname.c \
tool_cb_dbg.c \
@ -103,6 +104,7 @@ CURL_CFILES = \
CURL_HFILES = \
slist_wc.h \
terminal.h \
tool_binmode.h \
tool_bname.h \
tool_cb_dbg.h \

91
src/terminal.c Normal file
View File

@ -0,0 +1,91 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "tool_setup.h"
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include "terminal.h"
#include "memdebug.h" /* keep this as LAST include */
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#elif defined(HAVE_TERMIO_H)
# include <termio.h>
#endif
/*
* get_terminal_columns() returns the number of columns in the current
* terminal. It will return 79 on failure. Also, the number can be very big.
*/
unsigned int get_terminal_columns(void)
{
unsigned int width = 0;
char *colp = curl_getenv("COLUMNS");
if(colp) {
char *endptr;
long num = strtol(colp, &endptr, 10);
if((endptr != colp) && (endptr == colp + strlen(colp)) && (num > 20) &&
(num < 10000))
width = (unsigned int)num;
curl_free(colp);
}
if(!width) {
int cols = 0;
#ifdef TIOCGSIZE
struct ttysize ts;
if(!ioctl(STDIN_FILENO, TIOCGSIZE, &ts))
cols = ts.ts_cols;
#elif defined(TIOCGWINSZ)
struct winsize ts;
if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts))
cols = (int)ts.ws_col;
#elif defined(_WIN32)
{
HANDLE stderr_hnd = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO console_info;
if((stderr_hnd != INVALID_HANDLE_VALUE) &&
GetConsoleScreenBufferInfo(stderr_hnd, &console_info)) {
/*
* Do not use +1 to get the true screen-width since writing a
* character at the right edge will cause a line wrap.
*/
cols = (int)
(console_info.srWindow.Right - console_info.srWindow.Left);
}
}
#endif /* TIOCGSIZE */
if(cols >= 0 && cols < 10000)
width = (unsigned int)cols;
}
if(!width)
width = 79;
return width; /* 79 for unknown, might also be very small or very big */
}

30
src/terminal.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef HEADER_CURL_TERMINAL_H
#define HEADER_CURL_TERMINAL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "tool_setup.h"
unsigned int get_terminal_columns(void);
#endif /* HEADER_CURL_TERMINAL_H */

View File

@ -23,10 +23,6 @@
***************************************************************************/
#include "tool_setup.h"
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
@ -35,17 +31,12 @@
#include "tool_cb_prg.h"
#include "tool_util.h"
#include "tool_operate.h"
#include "terminal.h"
#include "memdebug.h" /* keep this as LAST include */
#define MAX_BARLENGTH 256
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#elif defined(HAVE_TERMIO_H)
# include <termio.h>
#endif
/* 200 values generated by this perl code:
my $pi = 3.1415;
@ -229,59 +220,6 @@ int tool_progress_cb(void *clientp,
return 0;
}
/*
* get_terminal_columns() returns the number of columns in the current
* terminal. It will return 79 on failure. Also, the number can be very big.
*/
unsigned int get_terminal_columns(void)
{
unsigned int width = 0;
char *colp = curl_getenv("COLUMNS");
if(colp) {
char *endptr;
long num = strtol(colp, &endptr, 10);
if((endptr != colp) && (endptr == colp + strlen(colp)) && (num > 20) &&
(num < 10000))
width = (unsigned int)num;
curl_free(colp);
}
if(!width) {
int cols = 0;
#ifdef TIOCGSIZE
struct ttysize ts;
if(!ioctl(STDIN_FILENO, TIOCGSIZE, &ts))
cols = ts.ts_cols;
#elif defined(TIOCGWINSZ)
struct winsize ts;
if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts))
cols = (int)ts.ws_col;
#elif defined(_WIN32)
{
HANDLE stderr_hnd = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO console_info;
if((stderr_hnd != INVALID_HANDLE_VALUE) &&
GetConsoleScreenBufferInfo(stderr_hnd, &console_info)) {
/*
* Do not use +1 to get the true screen-width since writing a
* character at the right edge will cause a line wrap.
*/
cols = (int)
(console_info.srWindow.Right - console_info.srWindow.Left);
}
}
#endif /* TIOCGSIZE */
if(cols >= 0 && cols < 10000)
width = (unsigned int)cols;
}
if(!width)
width = 79;
return width; /* 79 for unknown, might also be very small or very big */
}
void progressbarinit(struct ProgressData *bar,
struct OperationConfig *config)
{

View File

@ -45,8 +45,6 @@ struct OperationConfig;
void progressbarinit(struct ProgressData *bar,
struct OperationConfig *config);
unsigned int get_terminal_columns(void);
/*
** callback for CURLOPT_PROGRESSFUNCTION
*/

View File

@ -31,6 +31,7 @@
#include "tool_util.h"
#include "tool_version.h"
#include "tool_cb_prg.h"
#include "terminal.h"
#include "memdebug.h" /* keep this as LAST include */

View File

@ -29,6 +29,8 @@
#include "tool_cfgable.h"
#include "tool_msgs.h"
#include "tool_cb_prg.h"
#include "terminal.h"
#include "memdebug.h" /* keep this as LAST include */
@ -46,7 +48,7 @@ static void voutf(struct GlobalConfig *config,
const char *fmt,
va_list ap)
{
size_t width = (79 - strlen(prefix));
size_t width = (get_terminal_columns() - strlen(prefix));
DEBUGASSERT(!strchr(fmt, '\n'));
if(!config->silent) {
size_t len;