diff --git a/ChangeLog b/ChangeLog index e2b180771..46012cd0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -109,6 +109,8 @@ Bugs Heusler). + Fixed bug #1210 so that widths are taken from localized strings instead of hardcoded. + + Fixed bug #1218 so that description columns minimum width is calculated + correctly. + Improved hyphenation by splitting on commas (even if no whitespace after). Leads to better output of, for example, 'task show', where comma-separated lists are common. diff --git a/src/ViewTask.cpp b/src/ViewTask.cpp index 61340141f..53cffb00d 100644 --- a/src/ViewTask.cpp +++ b/src/ViewTask.cpp @@ -27,11 +27,13 @@ #define L10N // Localization complete. +#include #include #include #include #include #include +#include #include extern Context context; @@ -153,41 +155,56 @@ std::string ViewTask::render (std::vector & data, std::vector & seque ideal.push_back (global_ideal); } - if (!print_empty_columns && global_min != 0) + if (! print_empty_columns && global_min != 0) { - nonempty_columns.push_back(*i); + nonempty_columns.push_back (*i); } } - if (!print_empty_columns) + if (! print_empty_columns) _columns = nonempty_columns; - // Sum the minimal widths. - int sum_minimal = 0; - std::vector ::iterator c; - for (c = minimal.begin (); c != minimal.end (); ++c) - sum_minimal += *c; + int all_extra = _left_margin + + (2 * _extra_padding) + + ((_columns.size () - 1) * _intra_padding); + + // Sum the widths. + int sum_minimal = std::accumulate (minimal.begin (), minimal.end (), 0); + int sum_ideal = std::accumulate (ideal.begin (), ideal.end (), 0); - // Sum the ideal widths. - int sum_ideal = 0; - for (c = ideal.begin (); c != ideal.end (); ++c) - sum_ideal += *c; // Calculate final column widths. - int overage = _width - - _left_margin - - (2 * _extra_padding) - - ((_columns.size () - 1) * _intra_padding); + int overage = _width - sum_minimal - all_extra; + context.debug (format ("ViewTask::render min={1} ideal={2} overage={3}", + sum_minimal + all_extra, + sum_ideal + all_extra, + overage)); std::vector widths; - if (_width == 0 || sum_ideal <= overage) + + // Ideal case. Everything fits. + if (_width == 0 || sum_ideal + all_extra <= _width) + { widths = ideal; - else if (sum_minimal > overage || overage < 0) + } + + // Not enough for minimum. + else if (overage < 0) + { + context.error (format (STRING_VIEW_TOO_SMALL, sum_minimal + all_extra, _width)); widths = minimal; + } + + // Perfect minimal width. + else if (overage == 0) + { + widths = minimal; + } + + // Extra space to share. else if (overage > 0) { widths = minimal; - overage -= sum_minimal; // Spread 'overage' among columns where width[i] < ideal[i] bool needed = true; diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index 33771d6c4..0c33bf180 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -52,7 +52,11 @@ ColumnDescription::ColumnDescription () _styles.push_back ("truncated"); _styles.push_back ("count"); - std::string t = Date ().toString (context.config.get ("dateformat")); + _dateformat = context.config.get ("dateformat.annotation"); + if (_dateformat == "") + _dateformat = context.config.get ("dateformat"); + + std::string t = Date ().toString (_dateformat); std::string d = STRING_COLUMN_EXAMPLES_DESC; std::string a1 = STRING_COLUMN_EXAMPLES_ANNO1; std::string a2 = STRING_COLUMN_EXAMPLES_ANNO2; @@ -74,6 +78,8 @@ ColumnDescription::ColumnDescription () _examples.push_back (d + " [4]"); _hyphenate = context.config.getBoolean ("hyphenate"); + + _indent = context.config.getInteger ("indent.annotation"); } //////////////////////////////////////////////////////////////////////////////// @@ -99,24 +105,24 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int if (_style == "default" || _style == "combined") { - int indent = context.config.getInteger ("indent.annotation"); - std::string format = context.config.get ("dateformat.annotation"); - if (format == "") - format = context.config.get ("dateformat"); - - int min_desc = longestWord (description); - int min_anno = indent + Date::length (format); - minimum = std::max (min_desc, min_anno); + minimum = longestWord (description); maximum = utf8_width (description); - std::map annos; - task.getAnnotations (annos); - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); i++) + if (task.annotation_count) { - unsigned int len = min_anno + 1 + utf8_width (i->second); - if (len > maximum) - maximum = len; + int min_anno = _indent + Date::length (_dateformat); + if (min_anno > minimum) + minimum = min_anno; + + std::map annos; + task.getAnnotations (annos); + std::map ::iterator i; + for (i = annos.begin (); i != annos.end (); i++) + { + unsigned int len = min_anno + 1 + utf8_width (i->second); + if (len > maximum) + maximum = len; + } } } @@ -130,20 +136,18 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int // The text ... else if (_style == "oneline") { - std::string format = context.config.get ("dateformat.annotation"); - if (format == "") - format = context.config.get ("dateformat"); - - int min_desc = longestWord (description); - int min_anno = Date::length (format); - minimum = std::max (min_desc, min_anno); + minimum = longestWord (description); maximum = utf8_width (description); - std::map annos; - task.getAnnotations (annos); - std::map ::iterator i; - for (i = annos.begin (); i != annos.end (); i++) - maximum += utf8_width (i->second) + minimum + 1; + if (task.annotation_count) + { + int min_anno = Date::length (_dateformat); + std::map annos; + task.getAnnotations (annos); + std::map ::iterator i; + for (i = annos.begin (); i != annos.end (); i++) + maximum += min_anno + 1 + utf8_width (i->second); + } } // The te... @@ -156,11 +160,8 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int // The text [2] else if (_style == "count") { - std::map annos; - task.getAnnotations (annos); - // + ' ' + '[' + + ']' - maximum = utf8_width (description) + 3 + utf8_width (format ((int)annos.size ())); + maximum = utf8_width (description) + 1 + 1 + format (task.annotation_count).length () + 1; minimum = longestWord (description); } @@ -183,21 +184,15 @@ void ColumnDescription::render ( if (_style == "default" || _style == "combined") { - int indent = context.config.getInteger ("indent.annotation"); - std::map annos; task.getAnnotations (annos); if (annos.size ()) { - std::string format = context.config.get ("dateformat.annotation"); - if (format == "") - format = context.config.get ("dateformat"); - std::map ::iterator i; for (i = annos.begin (); i != annos.end (); i++) { Date dt (strtol (i->first.substr (11).c_str (), NULL, 10)); - description += "\n" + std::string (indent, ' ') + dt.toString (format) + " " + i->second; + description += "\n" + std::string (_indent, ' ') + dt.toString (_dateformat) + " " + i->second; } } @@ -227,15 +222,11 @@ void ColumnDescription::render ( task.getAnnotations (annos); if (annos.size ()) { - std::string format = context.config.get ("dateformat.annotation"); - if (format == "") - format = context.config.get ("dateformat"); - std::map ::iterator i; for (i = annos.begin (); i != annos.end (); i++) { Date dt (atoi (i->first.substr (11).c_str ())); - description += " " + dt.toString (format) + " " + i->second; + description += " " + dt.toString (_dateformat) + " " + i->second; } } diff --git a/src/columns/ColDescription.h b/src/columns/ColDescription.h index 922402aa5..e6f4ea239 100644 --- a/src/columns/ColDescription.h +++ b/src/columns/ColDescription.h @@ -47,6 +47,8 @@ public: private: bool _hyphenate; + std::string _dateformat; + int _indent; }; #endif diff --git a/src/en-US.h b/src/en-US.h index b0fdde8a5..73bbae47c 100644 --- a/src/en-US.h +++ b/src/en-US.h @@ -858,6 +858,9 @@ #define STRING_UTF8_INVALID_CP_REP "Invalid codepoint representation." #define STRING_UTF8_INVALID_CP "Invalid Unicode codepoint." +// View +#define STRING_VIEW_TOO_SMALL "The report has a minimum width of {1} and does not fit in the available width of {2}." + // Usage text. This is an exception, and contains \n characters and formatting. #define STRING_CMD_HELP_TEXT \ "Documentation for Taskwarrior can be found using 'man task', 'man taskrc', 'man " \ diff --git a/src/es-ES.h b/src/es-ES.h index 3ace0b590..56f64f433 100644 --- a/src/es-ES.h +++ b/src/es-ES.h @@ -875,6 +875,9 @@ #define STRING_UTF8_INVALID_CP_REP "Representación de codepoint no válida." #define STRING_UTF8_INVALID_CP "Codepoint Unicode no válido." +// View +#define STRING_VIEW_TOO_SMALL "The report has a minimum width of {1} and does not fit in the available width of {2}." + // **************************************************************************************************** // Usage text. This is an exception, and contains \n characters and formatting. /* FIXME más abajo