mirror of
https://git.tukaani.org/xz.git
synced 2024-04-04 12:36:23 +02:00
xz: Automatically align strings ending in a colon in --list output.
This should avoid alignment errors in translations with these strings.
This commit is contained in:
parent
1e3f29b62f
commit
6cb42e8aa1
1 changed files with 102 additions and 12 deletions
114
src/xz/list.c
114
src/xz/list.c
|
@ -57,6 +57,49 @@ typedef struct {
|
||||||
} block_header_info;
|
} block_header_info;
|
||||||
|
|
||||||
|
|
||||||
|
/// Strings ending in a colon. These are used for lines like
|
||||||
|
/// " Foo: 123 MiB". These are groupped because translated strings
|
||||||
|
/// may have different maximum string length, and we want to pad all
|
||||||
|
/// strings so that the values are aligned nicely.
|
||||||
|
static const char *colon_strs[] = {
|
||||||
|
N_("Streams:"),
|
||||||
|
N_("Blocks:"),
|
||||||
|
N_("Compressed size:"),
|
||||||
|
N_("Uncompressed size:"),
|
||||||
|
N_("Ratio:"),
|
||||||
|
N_("Check:"),
|
||||||
|
N_("Stream Padding:"),
|
||||||
|
N_("Memory needed:"),
|
||||||
|
N_("Sizes in headers:"),
|
||||||
|
// This won't be aligned because it's so long:
|
||||||
|
//N_("Minimum XZ Utils version:"),
|
||||||
|
N_("Number of files:"),
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Enum matching the above strings.
|
||||||
|
enum {
|
||||||
|
COLON_STR_STREAMS,
|
||||||
|
COLON_STR_BLOCKS,
|
||||||
|
COLON_STR_COMPRESSED_SIZE,
|
||||||
|
COLON_STR_UNCOMPRESSED_SIZE,
|
||||||
|
COLON_STR_RATIO,
|
||||||
|
COLON_STR_CHECK,
|
||||||
|
COLON_STR_STREAM_PADDING,
|
||||||
|
COLON_STR_MEMORY_NEEDED,
|
||||||
|
COLON_STR_SIZES_IN_HEADERS,
|
||||||
|
//COLON_STR_MINIMUM_XZ_VERSION,
|
||||||
|
COLON_STR_NUMBER_OF_FILES,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Field widths to use with printf to pad the strings to use the same number
|
||||||
|
/// of columns on a terminal.
|
||||||
|
static int colon_strs_fw[ARRAY_SIZE(colon_strs)];
|
||||||
|
|
||||||
|
/// Convenience macro to get the translated string and its field width
|
||||||
|
/// using a COLON_STR_foo enum.
|
||||||
|
#define COLON_STR(num) colon_strs_fw[num], _(colon_strs[num])
|
||||||
|
|
||||||
|
|
||||||
/// Check ID to string mapping
|
/// Check ID to string mapping
|
||||||
static const char check_names[LZMA_CHECK_ID_MAX + 1][12] = {
|
static const char check_names[LZMA_CHECK_ID_MAX + 1][12] = {
|
||||||
// TRANSLATORS: Indicates that there is no integrity check.
|
// TRANSLATORS: Indicates that there is no integrity check.
|
||||||
|
@ -112,6 +155,47 @@ static struct {
|
||||||
} totals = { 0, 0, 0, 0, 0, 0, 0, 0, 50000002, true };
|
} totals = { 0, 0, 0, 0, 0, 0, 0, 0, 50000002, true };
|
||||||
|
|
||||||
|
|
||||||
|
/// Initialize the printf field widths that are needed to get nicely aligned
|
||||||
|
/// output with translated strings.
|
||||||
|
static void
|
||||||
|
init_field_widths(void)
|
||||||
|
{
|
||||||
|
// Lengths of translated strings as bytes.
|
||||||
|
size_t lens[ARRAY_SIZE(colon_strs)];
|
||||||
|
|
||||||
|
// Lengths of translated strings as columns.
|
||||||
|
size_t widths[ARRAY_SIZE(colon_strs)];
|
||||||
|
|
||||||
|
// Maximum number of columns needed by a translated string.
|
||||||
|
size_t width_max = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(colon_strs); ++i) {
|
||||||
|
widths[i] = tuklib_mbstr_width(colon_strs[i], &lens[i]);
|
||||||
|
|
||||||
|
// If debugging is enabled, catch invalid strings with
|
||||||
|
// an assertion. However, when not debugging, use the
|
||||||
|
// byte count as the fallback width. This shouldn't
|
||||||
|
// ever happen unless there is a bad string in the
|
||||||
|
// translations, but in such case I guess it's better
|
||||||
|
// to try to print something useful instead of failing
|
||||||
|
// completely.
|
||||||
|
assert(widths[i] != (size_t)-1);
|
||||||
|
if (widths[i] == (size_t)-1)
|
||||||
|
widths[i] = lens[i];
|
||||||
|
|
||||||
|
if (widths[i] > width_max)
|
||||||
|
width_max = widths[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the field width for printf("%*s") so that the strings
|
||||||
|
// will use width_max columns on a terminal.
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(colon_strs); ++i)
|
||||||
|
colon_strs_fw[i] = (int)(lens[i] + width_max - widths[i]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Convert XZ Utils version number to a string.
|
/// Convert XZ Utils version number to a string.
|
||||||
static const char *
|
static const char *
|
||||||
xz_ver_to_str(uint32_t ver)
|
xz_ver_to_str(uint32_t ver)
|
||||||
|
@ -548,20 +632,20 @@ print_adv_helper(uint64_t stream_count, uint64_t block_count,
|
||||||
char checks_str[CHECKS_STR_SIZE];
|
char checks_str[CHECKS_STR_SIZE];
|
||||||
get_check_names(checks_str, checks, true);
|
get_check_names(checks_str, checks, true);
|
||||||
|
|
||||||
printf(_(" Streams: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_STREAMS),
|
||||||
uint64_to_str(stream_count, 0));
|
uint64_to_str(stream_count, 0));
|
||||||
printf(_(" Blocks: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_BLOCKS),
|
||||||
uint64_to_str(block_count, 0));
|
uint64_to_str(block_count, 0));
|
||||||
printf(_(" Compressed size: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_COMPRESSED_SIZE),
|
||||||
uint64_to_nicestr(compressed_size,
|
uint64_to_nicestr(compressed_size,
|
||||||
NICESTR_B, NICESTR_TIB, true, 0));
|
NICESTR_B, NICESTR_TIB, true, 0));
|
||||||
printf(_(" Uncompressed size: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_UNCOMPRESSED_SIZE),
|
||||||
uint64_to_nicestr(uncompressed_size,
|
uint64_to_nicestr(uncompressed_size,
|
||||||
NICESTR_B, NICESTR_TIB, true, 0));
|
NICESTR_B, NICESTR_TIB, true, 0));
|
||||||
printf(_(" Ratio: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_RATIO),
|
||||||
get_ratio(compressed_size, uncompressed_size));
|
get_ratio(compressed_size, uncompressed_size));
|
||||||
printf(_(" Check: %s\n"), checks_str);
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_CHECK), checks_str);
|
||||||
printf(_(" Stream padding: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_STREAM_PADDING),
|
||||||
uint64_to_nicestr(stream_padding,
|
uint64_to_nicestr(stream_padding,
|
||||||
NICESTR_B, NICESTR_TIB, true, 0));
|
NICESTR_B, NICESTR_TIB, true, 0));
|
||||||
return;
|
return;
|
||||||
|
@ -734,10 +818,12 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detailed) {
|
if (detailed) {
|
||||||
printf(_(" Memory needed: %s MiB\n"), uint64_to_str(
|
printf(" %-*s %s MiB\n", COLON_STR(COLON_STR_MEMORY_NEEDED),
|
||||||
|
uint64_to_str(
|
||||||
round_up_to_mib(xfi->memusage_max), 0));
|
round_up_to_mib(xfi->memusage_max), 0));
|
||||||
printf(_(" Sizes in headers: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_SIZES_IN_HEADERS),
|
||||||
xfi->all_have_sizes ? _("Yes") : _("No"));
|
xfi->all_have_sizes ? _("Yes") : _("No"));
|
||||||
|
//printf(" %-*s %s\n", COLON_STR(COLON_STR_MINIMUM_XZ_VERSION),
|
||||||
printf(_(" Minimum XZ Utils version: %s\n"),
|
printf(_(" Minimum XZ Utils version: %s\n"),
|
||||||
xz_ver_to_str(xfi->min_version));
|
xz_ver_to_str(xfi->min_version));
|
||||||
}
|
}
|
||||||
|
@ -902,17 +988,19 @@ print_totals_adv(void)
|
||||||
{
|
{
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
puts(_("Totals:"));
|
puts(_("Totals:"));
|
||||||
printf(_(" Number of files: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_NUMBER_OF_FILES),
|
||||||
uint64_to_str(totals.files, 0));
|
uint64_to_str(totals.files, 0));
|
||||||
print_adv_helper(totals.streams, totals.blocks,
|
print_adv_helper(totals.streams, totals.blocks,
|
||||||
totals.compressed_size, totals.uncompressed_size,
|
totals.compressed_size, totals.uncompressed_size,
|
||||||
totals.checks, totals.stream_padding);
|
totals.checks, totals.stream_padding);
|
||||||
|
|
||||||
if (message_verbosity_get() >= V_DEBUG) {
|
if (message_verbosity_get() >= V_DEBUG) {
|
||||||
printf(_(" Memory needed: %s MiB\n"), uint64_to_str(
|
printf(" %-*s %s MiB\n", COLON_STR(COLON_STR_MEMORY_NEEDED),
|
||||||
|
uint64_to_str(
|
||||||
round_up_to_mib(totals.memusage_max), 0));
|
round_up_to_mib(totals.memusage_max), 0));
|
||||||
printf(_(" Sizes in headers: %s\n"),
|
printf(" %-*s %s\n", COLON_STR(COLON_STR_SIZES_IN_HEADERS),
|
||||||
totals.all_have_sizes ? _("Yes") : _("No"));
|
totals.all_have_sizes ? _("Yes") : _("No"));
|
||||||
|
//printf(" %-*s %s\n", COLON_STR(COLON_STR_MINIMUM_XZ_VERSION),
|
||||||
printf(_(" Minimum XZ Utils version: %s\n"),
|
printf(_(" Minimum XZ Utils version: %s\n"),
|
||||||
xz_ver_to_str(totals.min_version));
|
xz_ver_to_str(totals.min_version));
|
||||||
}
|
}
|
||||||
|
@ -988,6 +1076,8 @@ list_file(const char *filename)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_field_widths();
|
||||||
|
|
||||||
// Unset opt_stdout so that io_open_src() won't accept special files.
|
// Unset opt_stdout so that io_open_src() won't accept special files.
|
||||||
// Set opt_force so that io_open_src() will follow symlinks.
|
// Set opt_force so that io_open_src() will follow symlinks.
|
||||||
opt_stdout = false;
|
opt_stdout = false;
|
||||||
|
|
Loading…
Reference in a new issue