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
114
src/xz/list.c
114
src/xz/list.c
|
@ -57,6 +57,49 @@ typedef struct {
|
|||
} 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
|
||||
static const char check_names[LZMA_CHECK_ID_MAX + 1][12] = {
|
||||
// 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 };
|
||||
|
||||
|
||||
/// 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.
|
||||
static const char *
|
||||
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];
|
||||
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));
|
||||
printf(_(" Blocks: %s\n"),
|
||||
printf(" %-*s %s\n", COLON_STR(COLON_STR_BLOCKS),
|
||||
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,
|
||||
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,
|
||||
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));
|
||||
printf(_(" Check: %s\n"), checks_str);
|
||||
printf(_(" Stream padding: %s\n"),
|
||||
printf(" %-*s %s\n", COLON_STR(COLON_STR_CHECK), checks_str);
|
||||
printf(" %-*s %s\n", COLON_STR(COLON_STR_STREAM_PADDING),
|
||||
uint64_to_nicestr(stream_padding,
|
||||
NICESTR_B, NICESTR_TIB, true, 0));
|
||||
return;
|
||||
|
@ -734,10 +818,12 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
|
|||
}
|
||||
|
||||
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));
|
||||
printf(_(" Sizes in headers: %s\n"),
|
||||
printf(" %-*s %s\n", COLON_STR(COLON_STR_SIZES_IN_HEADERS),
|
||||
xfi->all_have_sizes ? _("Yes") : _("No"));
|
||||
//printf(" %-*s %s\n", COLON_STR(COLON_STR_MINIMUM_XZ_VERSION),
|
||||
printf(_(" Minimum XZ Utils version: %s\n"),
|
||||
xz_ver_to_str(xfi->min_version));
|
||||
}
|
||||
|
@ -902,17 +988,19 @@ print_totals_adv(void)
|
|||
{
|
||||
putchar('\n');
|
||||
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));
|
||||
print_adv_helper(totals.streams, totals.blocks,
|
||||
totals.compressed_size, totals.uncompressed_size,
|
||||
totals.checks, totals.stream_padding);
|
||||
|
||||
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));
|
||||
printf(_(" Sizes in headers: %s\n"),
|
||||
printf(" %-*s %s\n", COLON_STR(COLON_STR_SIZES_IN_HEADERS),
|
||||
totals.all_have_sizes ? _("Yes") : _("No"));
|
||||
//printf(" %-*s %s\n", COLON_STR(COLON_STR_MINIMUM_XZ_VERSION),
|
||||
printf(_(" Minimum XZ Utils version: %s\n"),
|
||||
xz_ver_to_str(totals.min_version));
|
||||
}
|
||||
|
@ -988,6 +1076,8 @@ list_file(const char *filename)
|
|||
return;
|
||||
}
|
||||
|
||||
init_field_widths();
|
||||
|
||||
// Unset opt_stdout so that io_open_src() won't accept special files.
|
||||
// Set opt_force so that io_open_src() will follow symlinks.
|
||||
opt_stdout = false;
|
||||
|
|
Loading…
Reference in New Issue