Lexer: Migrated commify, ucFirst and lowerCase from text to Lexer

This commit is contained in:
Paul Beckingham 2015-10-30 10:57:14 -04:00
parent 7119c42780
commit 51def4b12b
15 changed files with 169 additions and 163 deletions

View file

@ -25,13 +25,14 @@
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <Color.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <algorithm>
#include <main.h>
#include <Color.h>
#include <Lexer.h>
#include <text.h>
#include <i18n.h>
@ -112,7 +113,7 @@ Color::Color (const std::string& spec)
std::string word;
for (auto& it : words)
{
word = lowerCase (trim (it));
word = Lexer::lowerCase (trim (it));
if (word == "bold") fg_value |= _COLOR_BOLD;
else if (word == "bright") bg_value |= _COLOR_BRIGHT;

View file

@ -25,6 +25,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <Config.h>
#include <iostream>
#include <fstream>
#include <sstream>
@ -37,7 +38,7 @@
#include <FS.h>
#include <Timer.h>
#include <JSON.h>
#include <Config.h>
#include <Lexer.h>
#include <text.h>
#include <util.h>
#include <i18n.h>
@ -587,7 +588,7 @@ bool Config::getBoolean (const std::string& key)
{
if ((*this).find (key) != (*this).end ())
{
std::string value = lowerCase ((*this)[key]);
std::string value = Lexer::lowerCase ((*this)[key]);
if (value == "t" || // TODO Deprecate
value == "true" ||
value == "1" ||

View file

@ -387,12 +387,12 @@ bool namedDates (const std::string& name, Variant& value)
if (Lexer::isDigit (name[1]))
{
number = strtol (name.substr (0, 2).c_str (), NULL, 10);
ordinal = lowerCase (name.substr (2));
ordinal = Lexer::lowerCase (name.substr (2));
}
else
{
number = strtol (name.substr (0, 1).c_str (), NULL, 10);
ordinal = lowerCase (name.substr (1));
ordinal = Lexer::lowerCase (name.substr (1));
}
// Sanity check.

View file

@ -514,7 +514,7 @@ bool ISO8601d::parse_formatted (Nibbler& n, const std::string& format)
std::string dayName;
if (n.getUntil (format[f + 1], dayName))
{
wday = ISO8601d::dayOfWeek (lowerCase (dayName));
wday = ISO8601d::dayOfWeek (Lexer::lowerCase (dayName));
if (wday == -1)
{
n.restore ();
@ -543,7 +543,7 @@ bool ISO8601d::parse_formatted (Nibbler& n, const std::string& format)
std::string monthName;
if (n.getUntil (format[f + 1], monthName))
{
month = ISO8601d::monthOfYear (lowerCase (monthName));
month = ISO8601d::monthOfYear (Lexer::lowerCase (monthName));
if (month == -1)
{
n.restore ();
@ -1265,7 +1265,7 @@ std::string ISO8601d::monthName (int month)
assert (month > 0);
assert (month <= 12);
return ucFirst (months[month - 1]);
return Lexer::ucFirst (months[month - 1]);
}
////////////////////////////////////////////////////////////////////////////////
@ -1283,7 +1283,7 @@ std::string ISO8601d::dayName (int dow)
STRING_DATE_SATURDAY,
};
return ucFirst (days[dow]);
return Lexer::ucFirst (days[dow]);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -412,6 +412,100 @@ std::string::size_type Lexer::commonLength (
return l;
}
////////////////////////////////////////////////////////////////////////////////
std::string Lexer::commify (const std::string& data)
{
// First scan for decimal point and end of digits.
int decimalPoint = -1;
int end = -1;
int i;
for (int i = 0; i < (int) data.length (); ++i)
{
if (Lexer::isDigit (data[i]))
end = i;
if (data[i] == '.')
decimalPoint = i;
}
std::string result;
if (decimalPoint != -1)
{
// In reverse order, transfer all digits up to, and including the decimal
// point.
for (i = (int) data.length () - 1; i >= decimalPoint; --i)
result += data[i];
int consecutiveDigits = 0;
for (; i >= 0; --i)
{
if (Lexer::isDigit (data[i]))
{
result += data[i];
if (++consecutiveDigits == 3 && i && Lexer::isDigit (data[i - 1]))
{
result += ',';
consecutiveDigits = 0;
}
}
else
result += data[i];
}
}
else
{
// In reverse order, transfer all digits up to, but not including the last
// digit.
for (i = (int) data.length () - 1; i > end; --i)
result += data[i];
int consecutiveDigits = 0;
for (; i >= 0; --i)
{
if (Lexer::isDigit (data[i]))
{
result += data[i];
if (++consecutiveDigits == 3 && i && Lexer::isDigit (data[i - 1]))
{
result += ',';
consecutiveDigits = 0;
}
}
else
result += data[i];
}
}
// reverse result into data.
std::string done;
for (int i = (int) result.length () - 1; i >= 0; --i)
done += result[i];
return done;
}
////////////////////////////////////////////////////////////////////////////////
std::string Lexer::lowerCase (const std::string& input)
{
std::string output = input;
std::transform (output.begin (), output.end (), output.begin (), tolower);
return output;
}
////////////////////////////////////////////////////////////////////////////////
std::string Lexer::ucFirst (const std::string& input)
{
std::string output = input;
if (output.length () > 0)
output[0] = toupper (output[0]);
return output;
}
////////////////////////////////////////////////////////////////////////////////
// Lexer::Type::string
// '|"

View file

@ -87,6 +87,9 @@ public:
static int hexToInt (int, int, int, int);
static std::string::size_type commonLength (const std::string&, const std::string&);
static std::string::size_type commonLength (const std::string&, std::string::size_type, const std::string&, std::string::size_type);
static std::string commify (const std::string&);
static std::string lowerCase (const std::string&);
static std::string ucFirst (const std::string&);
// Stream Classifiers.
bool isEOS () const;

View file

@ -30,6 +30,7 @@
#include <stdlib.h>
#include <Context.h>
#include <ViewText.h>
#include <Lexer.h>
#include <i18n.h>
#include <text.h>
#include <util.h>
@ -98,7 +99,7 @@ int CmdCalendar::execute (std::string& output)
// Set up a vector of months, for autoComplete.
std::vector <std::string> monthNames;
for (int i = 1; i <= 12; ++i)
monthNames.push_back (lowerCase (ISO8601d::monthName (i)));
monthNames.push_back (Lexer::lowerCase (ISO8601d::monthName (i)));
// For autoComplete results.
std::vector <std::string> matches;
@ -113,15 +114,15 @@ int CmdCalendar::execute (std::string& output)
for (auto& arg : words)
{
// Some version of "calendar".
if (autoComplete (lowerCase (arg), commandNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
if (autoComplete (Lexer::lowerCase (arg), commandNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
continue;
// "due".
else if (autoComplete (lowerCase (arg), keywordNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
else if (autoComplete (Lexer::lowerCase (arg), keywordNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
getpendingdate = true;
// "y".
else if (lowerCase (arg) == "y")
else if (Lexer::lowerCase (arg) == "y")
argWholeYear = true;
// YYYY.
@ -137,7 +138,7 @@ int CmdCalendar::execute (std::string& output)
}
// "January" etc.
else if (autoComplete (lowerCase (arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
else if (autoComplete (Lexer::lowerCase (arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1)
{
argMonth = ISO8601d::monthOfYear (matches[0]);
if (argMonth == -1)

View file

@ -25,6 +25,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <CmdEdit.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
@ -33,6 +34,7 @@
#include <unistd.h>
#include <ISO8601.h>
#include <Context.h>
#include <Lexer.h>
#include <Filter.h>
#include <Nibbler.h>
#include <i18n.h>
@ -40,7 +42,6 @@
#include <util.h>
#include <i18n.h>
#include <main.h>
#include <CmdEdit.h>
#include <JSON.h>
extern Context context;
@ -213,12 +214,12 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat)
before << "# " << STRING_EDIT_TABLE_HEADER_1 << "\n"
<< "# " << STRING_EDIT_TABLE_HEADER_2 << "\n"
<< "# ID: " << task.id << "\n"
<< "# UUID: " << task.get ("uuid") << "\n"
<< "# Status: " << ucFirst (Task::statusToText (task.getStatus ())) << "\n" // L10N safe ucFirst.
<< "# Mask: " << task.get ("mask") << "\n"
<< "# iMask: " << task.get ("imask") << "\n"
<< " Project: " << task.get ("project") << "\n";
<< "# ID: " << task.id << "\n"
<< "# UUID: " << task.get ("uuid") << "\n"
<< "# Status: " << Lexer::ucFirst (Task::statusToText (task.getStatus ())) << "\n"
<< "# Mask: " << task.get ("mask") << "\n"
<< "# iMask: " << task.get ("imask") << "\n"
<< " Project: " << task.get ("project") << "\n";
std::vector <std::string> tags;
task.getTags (tags);

View file

@ -119,7 +119,7 @@ int CmdInfo::execute (std::string& output)
view.set (row, 0, STRING_COLUMN_LABEL_ID);
view.set (row, 1, (task.id ? format (task.id) : "-"));
std::string status = ucFirst (Task::statusToText (task.getStatus ())); // L10N safe ucFirst.
std::string status = Lexer::ucFirst (Task::statusToText (task.getStatus ()));
// description
Color c;

View file

@ -34,6 +34,7 @@
#include <inttypes.h>
#include <Context.h>
#include <ISO8601.h>
#include <Lexer.h>
#include <main.h>
#include <text.h>
#include <util.h>
@ -64,7 +65,7 @@ std::string taskDifferences (const Task& before, const Task& after)
std::stringstream out;
for (auto& name : beforeOnly)
out << " - "
<< format (STRING_FEEDBACK_DELETED, ucFirst (name))
<< format (STRING_FEEDBACK_DELETED, Lexer::ucFirst (name))
<< "\n";
for (auto& name : afterOnly)
@ -83,7 +84,7 @@ std::string taskDifferences (const Task& before, const Task& after)
else
out << " - "
<< format (STRING_FEEDBACK_ATT_SET,
ucFirst (name),
Lexer::ucFirst (name),
renderAttribute (name, after.get (name)))
<< "\n";
}
@ -116,7 +117,7 @@ std::string taskDifferences (const Task& before, const Task& after)
else
out << " - "
<< format (STRING_FEEDBACK_ATT_MOD,
ucFirst (name),
Lexer::ucFirst (name),
renderAttribute (name, before.get (name)),
renderAttribute (name, after.get (name)))
<< "\n";
@ -175,13 +176,13 @@ std::string taskInfoDifferences (
}
else if (name == "start")
{
out << format (STRING_FEEDBACK_ATT_DEL_DUR, ucFirst (name),
out << format (STRING_FEEDBACK_ATT_DEL_DUR, Lexer::ucFirst (name),
ISO8601p (current_timestamp - last_timestamp).format ())
<< "\n";
}
else
{
out << format (STRING_FEEDBACK_ATT_DEL, ucFirst (name))
out << format (STRING_FEEDBACK_ATT_DEL, Lexer::ucFirst (name))
<< "\n";
}
}
@ -209,7 +210,7 @@ std::string taskInfoDifferences (
last_timestamp = current_timestamp;
out << format (STRING_FEEDBACK_ATT_WAS_SET,
ucFirst (name),
Lexer::ucFirst (name),
renderAttribute (name, after.get (name), dateformat))
<< "\n";
}
@ -244,7 +245,7 @@ std::string taskInfoDifferences (
}
else
out << format (STRING_FEEDBACK_ATT_WAS_MOD,
ucFirst (name),
Lexer::ucFirst (name),
renderAttribute (name, before.get (name), dateformat),
renderAttribute (name, after.get (name), dateformat))
<< "\n";

View file

@ -357,100 +357,6 @@ bool extractLine (
return true;
}
////////////////////////////////////////////////////////////////////////////////
std::string commify (const std::string& data)
{
// First scan for decimal point and end of digits.
int decimalPoint = -1;
int end = -1;
int i;
for (int i = 0; i < (int) data.length (); ++i)
{
if (Lexer::isDigit (data[i]))
end = i;
if (data[i] == '.')
decimalPoint = i;
}
std::string result;
if (decimalPoint != -1)
{
// In reverse order, transfer all digits up to, and including the decimal
// point.
for (i = (int) data.length () - 1; i >= decimalPoint; --i)
result += data[i];
int consecutiveDigits = 0;
for (; i >= 0; --i)
{
if (Lexer::isDigit (data[i]))
{
result += data[i];
if (++consecutiveDigits == 3 && i && Lexer::isDigit (data[i - 1]))
{
result += ',';
consecutiveDigits = 0;
}
}
else
result += data[i];
}
}
else
{
// In reverse order, transfer all digits up to, but not including the last
// digit.
for (i = (int) data.length () - 1; i > end; --i)
result += data[i];
int consecutiveDigits = 0;
for (; i >= 0; --i)
{
if (Lexer::isDigit (data[i]))
{
result += data[i];
if (++consecutiveDigits == 3 && i && Lexer::isDigit (data[i - 1]))
{
result += ',';
consecutiveDigits = 0;
}
}
else
result += data[i];
}
}
// reverse result into data.
std::string done;
for (int i = (int) result.length () - 1; i >= 0; --i)
done += result[i];
return done;
}
////////////////////////////////////////////////////////////////////////////////
std::string lowerCase (const std::string& input)
{
std::string output = input;
std::transform (output.begin (), output.end (), output.begin (), tolower);
return output;
}
////////////////////////////////////////////////////////////////////////////////
std::string ucFirst (const std::string& input)
{
std::string output = input;
if (output.length () > 0)
output[0] = toupper (output[0]);
return output;
}
////////////////////////////////////////////////////////////////////////////////
const std::string str_replace (
std::string &str,

View file

@ -46,9 +46,6 @@ void split (std::vector<std::string>&, const std::string&, const char);
void split (std::vector<std::string>&, const std::string&, const std::string&);
void join (std::string&, const std::string&, const std::vector<std::string>&);
void join (std::string&, const std::string&, const std::vector<int>&);
std::string commify (const std::string&);
std::string lowerCase (const std::string&);
std::string ucFirst (const std::string&);
const std::string str_replace (std::string&, const std::string&, const std::string&);
const std::string str_replace (const std::string&, const std::string&, const std::string&);
const char* optionalBlankLine ();

View file

@ -51,6 +51,7 @@
#include <signal.h>
#include <sys/select.h>
#include <Lexer.h>
#include <text.h>
#include <main.h>
#include <i18n.h>
@ -89,7 +90,7 @@ bool confirm (const std::string& question)
std::string answer {""};
std::getline (std::cin, answer);
context.debug ("STDIN '" + answer + "'");
answer = std::cin.eof () ? STRING_UTIL_CONFIRM_NO : lowerCase (trim (answer));
answer = std::cin.eof () ? STRING_UTIL_CONFIRM_NO : Lexer::lowerCase (trim (answer));
autoComplete (answer, options, matches, 1); // Hard-coded 1.
}
@ -129,7 +130,7 @@ int confirm4 (const std::string& question)
std::string answer {""};
std::getline (std::cin, answer);
context.debug ("STDIN '" + answer + "'");
answer = std::cin.eof () ? STRING_UTIL_CONFIRM_QUIT : lowerCase (trim (answer));
answer = std::cin.eof () ? STRING_UTIL_CONFIRM_QUIT : Lexer::lowerCase (trim (answer));
autoComplete (answer, options, matches, 1); // Hard-coded 1.
}
while (! std::cin.eof () && matches.size () != 1);
@ -159,7 +160,7 @@ std::string formatBytes (size_t bytes)
else if (bytes >= 995) sprintf (formatted, "%.1f %s", (bytes / 1000.0), STRING_UTIL_KIBIBYTES);
else sprintf (formatted, "%d %s", (int)bytes, STRING_UTIL_BYTES);
return commify (formatted);
return Lexer::commify (formatted);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -37,7 +37,7 @@ Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int, char**)
{
UnitTest t (1226);
UnitTest t (1253);
std::vector <std::pair <std::string, Lexer::Type>> tokens;
std::string token;
@ -551,6 +551,37 @@ int main (int, char**)
t.is (Lexer::typeName (Lexer::Type::date), "date", "Lexer::typeName (Lexer::Type::date)");
t.is (Lexer::typeName (Lexer::Type::duration), "duration", "Lexer::typeName (Lexer::Type::duration)");
// std::string Lexer::lowerCase (const std::string& input)
t.is (Lexer::lowerCase (""), "", "Lexer::lowerCase '' -> ''");
t.is (Lexer::lowerCase ("pre01_:POST"), "pre01_:post", "Lexer::lowerCase 'pre01_:POST' -> 'pre01_:post'");
// std::string Lexer::commify (const std::string& data)
t.is (Lexer::commify (""), "", "Lexer::commify '' -> ''");
t.is (Lexer::commify ("1"), "1", "Lexer::commify '1' -> '1'");
t.is (Lexer::commify ("12"), "12", "Lexer::commify '12' -> '12'");
t.is (Lexer::commify ("123"), "123", "Lexer::commify '123' -> '123'");
t.is (Lexer::commify ("1234"), "1,234", "Lexer::commify '1234' -> '1,234'");
t.is (Lexer::commify ("12345"), "12,345", "Lexer::commify '12345' -> '12,345'");
t.is (Lexer::commify ("123456"), "123,456", "Lexer::commify '123456' -> '123,456'");
t.is (Lexer::commify ("1234567"), "1,234,567", "Lexer::commify '1234567' -> '1,234,567'");
t.is (Lexer::commify ("12345678"), "12,345,678", "Lexer::commify '12345678' -> '12,345,678'");
t.is (Lexer::commify ("123456789"), "123,456,789", "Lexer::commify '123456789' -> '123,456,789'");
t.is (Lexer::commify ("1234567890"), "1,234,567,890", "Lexer::commify '1234567890' -> '1,234,567,890'");
t.is (Lexer::commify ("1.0"), "1.0", "Lexer::commify '1.0' -> '1.0'");
t.is (Lexer::commify ("12.0"), "12.0", "Lexer::commify '12.0' -> '12.0'");
t.is (Lexer::commify ("123.0"), "123.0", "Lexer::commify '123.0' -> '123.0'");
t.is (Lexer::commify ("1234.0"), "1,234.0", "Lexer::commify '1234.0' -> '1,234.0'");
t.is (Lexer::commify ("12345.0"), "12,345.0", "Lexer::commify '12345.0' -> '12,345.0'");
t.is (Lexer::commify ("123456.0"), "123,456.0", "Lexer::commify '123456.0' -> '123,456.0'");
t.is (Lexer::commify ("1234567.0"), "1,234,567.0", "Lexer::commify '1234567.0' -> '1,234,567.0'");
t.is (Lexer::commify ("12345678.0"), "12,345,678.0", "Lexer::commify '12345678.0' -> '12,345,678.0'");
t.is (Lexer::commify ("123456789.0"), "123,456,789.0", "Lexer::commify '123456789.0' -> '123,456,789.0'");
t.is (Lexer::commify ("1234567890.0"), "1,234,567,890.0", "Lexer::commify '1234567890.0' -> '1,234,567,890.0'");
t.is (Lexer::commify ("pre"), "pre", "Lexer::commify 'pre' -> 'pre'");
t.is (Lexer::commify ("pre1234"), "pre1,234", "Lexer::commify 'pre1234' -> 'pre1,234'");
t.is (Lexer::commify ("1234post"), "1,234post", "Lexer::commify '1234post' -> '1,234post'");
t.is (Lexer::commify ("pre1234post"), "pre1,234post", "Lexer::commify 'pre1234post' -> 'pre1,234post'");
return 0;
}

View file

@ -37,7 +37,7 @@ Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int, char**)
{
UnitTest t (225);
UnitTest t (198);
// Ensure environment has no influence.
unsetenv ("TASKDATA");
@ -258,37 +258,6 @@ int main (int, char**)
t.is (longestLine ("one\ntwo three four"), 14, "longestLine (one\\ntwo three four) --> 14");
t.is (longestLine ("one\ntwo\nthree\nfour"), 5, "longestLine (one\\ntwo\\nthree\\nfour) --> 5");
// std::string commify (const std::string& data)
t.is (commify (""), "", "commify '' -> ''");
t.is (commify ("1"), "1", "commify '1' -> '1'");
t.is (commify ("12"), "12", "commify '12' -> '12'");
t.is (commify ("123"), "123", "commify '123' -> '123'");
t.is (commify ("1234"), "1,234", "commify '1234' -> '1,234'");
t.is (commify ("12345"), "12,345", "commify '12345' -> '12,345'");
t.is (commify ("123456"), "123,456", "commify '123456' -> '123,456'");
t.is (commify ("1234567"), "1,234,567", "commify '1234567' -> '1,234,567'");
t.is (commify ("12345678"), "12,345,678", "commify '12345678' -> '12,345,678'");
t.is (commify ("123456789"), "123,456,789", "commify '123456789' -> '123,456,789'");
t.is (commify ("1234567890"), "1,234,567,890", "commify '1234567890' -> '1,234,567,890'");
t.is (commify ("1.0"), "1.0", "commify '1.0' -> '1.0'");
t.is (commify ("12.0"), "12.0", "commify '12.0' -> '12.0'");
t.is (commify ("123.0"), "123.0", "commify '123.0' -> '123.0'");
t.is (commify ("1234.0"), "1,234.0", "commify '1234.0' -> '1,234.0'");
t.is (commify ("12345.0"), "12,345.0", "commify '12345.0' -> '12,345.0'");
t.is (commify ("123456.0"), "123,456.0", "commify '123456.0' -> '123,456.0'");
t.is (commify ("1234567.0"), "1,234,567.0", "commify '1234567.0' -> '1,234,567.0'");
t.is (commify ("12345678.0"), "12,345,678.0", "commify '12345678.0' -> '12,345,678.0'");
t.is (commify ("123456789.0"), "123,456,789.0", "commify '123456789.0' -> '123,456,789.0'");
t.is (commify ("1234567890.0"), "1,234,567,890.0", "commify '1234567890.0' -> '1,234,567,890.0'");
t.is (commify ("pre"), "pre", "commify 'pre' -> 'pre'");
t.is (commify ("pre1234"), "pre1,234", "commify 'pre1234' -> 'pre1,234'");
t.is (commify ("1234post"), "1,234post", "commify '1234post' -> '1,234post'");
t.is (commify ("pre1234post"), "pre1,234post", "commify 'pre1234post' -> 'pre1,234post'");
// std::string lowerCase (const std::string& input)
t.is (lowerCase (""), "", "lowerCase '' -> ''");
t.is (lowerCase ("pre01_:POST"), "pre01_:post", "lowerCase 'pre01_:POST' -> 'pre01_:post'");
// bool nontrivial (const std::string&);
t.notok (nontrivial (""), "nontrivial '' -> false");
t.notok (nontrivial (" "), "nontrivial ' ' -> false");