Skip to content

Commit

Permalink
curl: make --help adapt to the terminal width
Browse files Browse the repository at this point in the history
Instead of assuming and working with 80 colums, try figuring out what
width is actually used.

Ref: #13141

Closes #13171
  • Loading branch information
bagder committed Mar 27, 2024
1 parent 97c417a commit 2efc111
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 37 deletions.
49 changes: 31 additions & 18 deletions src/tool_cb_prg.c
Expand Up @@ -229,28 +229,25 @@ int tool_progress_cb(void *clientp,
return 0;
}

void progressbarinit(struct ProgressData *bar,
struct OperationConfig *config)
{
char *colp;
memset(bar, 0, sizeof(struct ProgressData));

/* pass the resume from value through to the progress function so it can
* display progress towards total file not just the part that's left. */
if(config->use_resume)
bar->initial_size = config->resume_from;
/*
* 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.
*/

colp = curlx_getenv("COLUMNS");
unsigned int get_terminal_columns(void)
{
unsigned int width = 0;
char *colp = curlx_getenv("COLUMNS");
if(colp) {
char *endptr;
long num = strtol(colp, &endptr, 10);
if((endptr != colp) && (endptr == colp + strlen(colp)) && (num > 20) &&
(num < 10000))
bar->width = (int)num;
width = (unsigned int)num;
curl_free(colp);
}

if(!bar->width) {
if(!width) {
int cols = 0;

#ifdef TIOCGSIZE
Expand All @@ -277,14 +274,30 @@ void progressbarinit(struct ProgressData *bar,
}
}
#endif /* TIOCGSIZE */
if(cols > 20)
bar->width = cols;
if(cols < 10000)
width = 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)
{
int cols;
memset(bar, 0, sizeof(struct ProgressData));

/* pass the resume from value through to the progress function so it can
* display progress towards total file not just the part that's left. */
if(config->use_resume)
bar->initial_size = config->resume_from;

if(!bar->width)
bar->width = 79;
else if(bar->width > MAX_BARLENGTH)
cols = get_terminal_columns();
if(cols > MAX_BARLENGTH)
bar->width = MAX_BARLENGTH;
else if(cols > 20)
bar->width = cols;

bar->out = tool_stderr;
bar->tick = 150;
Expand Down
4 changes: 4 additions & 0 deletions src/tool_cb_prg.h
Expand Up @@ -40,9 +40,13 @@ struct ProgressData {
int barmove;
};

struct OperationConfig;

void progressbarinit(struct ProgressData *bar,
struct OperationConfig *config);

unsigned int get_terminal_columns(void);

/*
** callback for CURLOPT_PROGRESSFUNCTION
*/
Expand Down
33 changes: 14 additions & 19 deletions src/tool_help.c
Expand Up @@ -30,6 +30,7 @@
#include "tool_libinfo.h"
#include "tool_util.h"
#include "tool_version.h"
#include "tool_cb_prg.h"

#include "memdebug.h" /* keep this as LAST include */

Expand Down Expand Up @@ -73,13 +74,7 @@ static const struct category_descriptors categories[] = {
{NULL, NULL, CURLHELP_HIDDEN}
};

#ifdef _WIN32
#define BORDER 78
#else
#define BORDER 79
#endif

static void print_category(curlhelp_t category)
static void print_category(curlhelp_t category, unsigned int cols)
{
unsigned int i;
size_t longopt = 5;
Expand All @@ -96,17 +91,16 @@ static void print_category(curlhelp_t category)
if(len > longdesc)
longdesc = len;
}
if(longopt + longdesc >= BORDER) {
longdesc -= 3;
longopt = BORDER -1 - longdesc;
}
if(longopt + longdesc > cols)
longopt = cols - longdesc;

for(i = 0; helptext[i].opt; ++i)
if(helptext[i].categories & category) {
int opt = (int)longopt;
size_t desclen = strlen(helptext[i].desc);
if(opt + desclen >= (BORDER -1)) {
if(desclen < (BORDER -1))
opt = (BORDER -2) - (int)desclen;
if(opt + desclen >= (cols - 2)) {
if(desclen < (cols - 2))
opt = (cols - 3) - (int)desclen;
else
opt = 0;
}
Expand All @@ -115,13 +109,13 @@ static void print_category(curlhelp_t category)
}

/* Prints category if found. If not, it returns 1 */
static int get_category_content(const char *category)
static int get_category_content(const char *category, unsigned int cols)
{
unsigned int i;
for(i = 0; categories[i].opt; ++i)
if(curl_strequal(categories[i].opt, category)) {
printf("%s: %s\n", categories[i].opt, categories[i].desc);
print_category(categories[i].category);
print_category(categories[i].category, cols);
return 0;
}
return 1;
Expand All @@ -138,25 +132,26 @@ static void get_categories(void)

void tool_help(char *category)
{
unsigned int cols = get_terminal_columns();
puts("Usage: curl [options...] <url>");
/* If no category was provided */
if(!category) {
const char *category_note = "\nThis is not the full help, this "
"menu is stripped into categories.\nUse \"--help category\" to get "
"an overview of all categories.\nFor all options use the manual"
" or \"--help all\".";
print_category(CURLHELP_IMPORTANT);
print_category(CURLHELP_IMPORTANT, cols);
puts(category_note);
}
/* Lets print everything if "all" was provided */
else if(curl_strequal(category, "all"))
/* Print everything except hidden */
print_category(~(CURLHELP_HIDDEN));
print_category(~(CURLHELP_HIDDEN), cols);
/* Lets handle the string "category" differently to not print an errormsg */
else if(curl_strequal(category, "category"))
get_categories();
/* Otherwise print category and handle the case if the cat was not found */
else if(get_category_content(category)) {
else if(get_category_content(category, cols)) {
puts("Invalid category provided, here is a list of all categories:\n");
get_categories();
}
Expand Down

0 comments on commit 2efc111

Please sign in to comment.