mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
File Import
- Added format identifier code for task 1.4.3, task 1.5.0, todo.sh 2.0 and CSV. - Implemented import for type text. - Implemented util.cpp:slurp function. - Gathered sample input files for import testing, and later, unit tests.
This commit is contained in:
parent
db7b2dd9fe
commit
99dc72f26f
8 changed files with 239 additions and 24 deletions
222
src/import.cpp
222
src/import.cpp
|
@ -28,24 +28,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
std::string handleImport (TDB& tdb, T& task, Config& conf)
|
|
||||||
{
|
|
||||||
std::stringstream out;
|
|
||||||
|
|
||||||
// Use the description as a file name.
|
|
||||||
std::string file = trim (task.getDescription ());
|
|
||||||
|
|
||||||
if (file.length () > 0)
|
|
||||||
{
|
|
||||||
out << "Not yet implemented." << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::string ("You must specify a file to import.");
|
|
||||||
|
|
||||||
return out.str ();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// todo.sh v2.x
|
// todo.sh v2.x
|
||||||
// file format: (A) Walk the dog +project @context
|
// file format: (A) Walk the dog +project @context
|
||||||
|
@ -69,29 +51,221 @@ std::string handleImport (TDB& tdb, T& task, Config& conf)
|
||||||
// file format: project,priority,description
|
// file format: project,priority,description
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void determineFileType ()
|
enum fileType
|
||||||
{
|
{
|
||||||
|
not_a_clue,
|
||||||
|
task_1_4_3,
|
||||||
|
task_1_5_0,
|
||||||
|
todo_sh_2_0,
|
||||||
|
csv,
|
||||||
|
text
|
||||||
|
};
|
||||||
|
|
||||||
|
static fileType determineFileType (const std::vector <std::string>& lines)
|
||||||
|
{
|
||||||
|
// '7f7a4191-c2f2-487f-8855-7a1eb378c267',' ...
|
||||||
|
// ....:....|....:....|....:....|....:....|
|
||||||
|
// 1 10 20 30 40
|
||||||
|
if (lines.size () > 1 &&
|
||||||
|
lines[1][0] == '\'' &&
|
||||||
|
lines[1][9] == '-' &&
|
||||||
|
lines[1][14] == '-' &&
|
||||||
|
lines[1][19] == '-' &&
|
||||||
|
lines[1][24] == '-' &&
|
||||||
|
lines[1][37] == '\'' &&
|
||||||
|
lines[1][38] == ',' &&
|
||||||
|
lines[1][39] == '\'')
|
||||||
|
{
|
||||||
|
if (lines[0] == "'id','uuid','status','tags','entry','start','due','recur',"
|
||||||
|
"'end','project','priority','fg','bg','description'")
|
||||||
|
return task_1_5_0;
|
||||||
|
|
||||||
|
if (lines[0] == "'id','status','tags','entry','start','due','end','project',"
|
||||||
|
"'priority','fg','bg','description'")
|
||||||
|
return task_1_4_3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// x 2009-03-25 Walk the dog +project @context
|
||||||
|
// This is a test +project @context
|
||||||
|
for (unsigned int i = 0; i < lines.size (); ++i)
|
||||||
|
{
|
||||||
|
// All done tasks begin with "x YYYY-MM-DD".
|
||||||
|
if (lines[i].length () > 12)
|
||||||
|
{
|
||||||
|
if ( lines[i][0] == 'x' &&
|
||||||
|
lines[i][1] == ' ' &&
|
||||||
|
::isdigit (lines[i][2]) &&
|
||||||
|
::isdigit (lines[i][3]) &&
|
||||||
|
::isdigit (lines[i][4]) &&
|
||||||
|
::isdigit (lines[i][5]) &&
|
||||||
|
lines[i][6] == '-' &&
|
||||||
|
::isdigit (lines[i][7]) &&
|
||||||
|
::isdigit (lines[i][8]) &&
|
||||||
|
lines[i][9] == '-' &&
|
||||||
|
::isdigit (lines[i][10]) &&
|
||||||
|
::isdigit (lines[i][11]))
|
||||||
|
return todo_sh_2_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector <std::string> words;
|
||||||
|
split (words, lines[i], ' ');
|
||||||
|
for (unsigned int w = 0; w < words.size (); ++w)
|
||||||
|
{
|
||||||
|
// +project
|
||||||
|
if (words[w].length () > 1 &&
|
||||||
|
words[w][0] == '+' &&
|
||||||
|
::isalnum (words[w][1]))
|
||||||
|
return todo_sh_2_0;
|
||||||
|
|
||||||
|
// @context
|
||||||
|
if (words[w].length () > 1 &&
|
||||||
|
words[w][0] == '@' &&
|
||||||
|
::isalnum (words[w][1]))
|
||||||
|
return todo_sh_2_0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSV - commas on every line.
|
||||||
|
bool commas_on_every_line = true;
|
||||||
|
for (unsigned int i = 0; i < lines.size (); ++i)
|
||||||
|
{
|
||||||
|
if (lines[i].length () > 10 &&
|
||||||
|
lines[i][0] != '#' &&
|
||||||
|
lines[i].find (",") == std::string::npos)
|
||||||
|
{
|
||||||
|
commas_on_every_line = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (commas_on_every_line)
|
||||||
|
return csv;
|
||||||
|
|
||||||
|
// TODO text, possibly with commas.
|
||||||
|
for (unsigned int i = 0; i < lines.size (); ++i)
|
||||||
|
{
|
||||||
|
// TODO priority:{H,M,L}
|
||||||
|
// TODO priorit:{H,M,L}
|
||||||
|
// TODO priori:{H,M,L}
|
||||||
|
// TODO prior:{H,M,L}
|
||||||
|
// TODO prio:{H,M,L}
|
||||||
|
// TODO pri:{H,M,L}
|
||||||
|
// TODO project:.+
|
||||||
|
// TODO projec:.+
|
||||||
|
// TODO proje:.+
|
||||||
|
// TODO proj:.+
|
||||||
|
// TODO pro:.+
|
||||||
|
}
|
||||||
|
|
||||||
|
return not_a_clue;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void importTask_1_5 ()
|
static std::string importTask_1_4_3 (
|
||||||
|
TDB& tdb,
|
||||||
|
Config& conf,
|
||||||
|
const std::vector <std::string>& lines)
|
||||||
{
|
{
|
||||||
|
return "task 1.4.3\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void importTask_1_6 ()
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static std::string importTask_1_5_0 (
|
||||||
|
TDB& tdb,
|
||||||
|
Config& conf,
|
||||||
|
const std::vector <std::string>& lines)
|
||||||
{
|
{
|
||||||
|
return "task 1.5.0\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void importTodoSh_2_0 ()
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static std::string importTodoSh_2_0 (
|
||||||
|
TDB& tdb,
|
||||||
|
Config& conf,
|
||||||
|
const std::vector <std::string>& lines)
|
||||||
{
|
{
|
||||||
|
return "todo.sh 2.0\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void importSingleLine ()
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static std::string importText (
|
||||||
|
TDB& tdb,
|
||||||
|
Config& conf,
|
||||||
|
const std::vector <std::string>& lines)
|
||||||
{
|
{
|
||||||
|
std::vector <std::string> failed;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < lines.size (); ++i)
|
||||||
|
{
|
||||||
|
std::string line = lines[i];
|
||||||
|
|
||||||
|
// Strip comments
|
||||||
|
std::string::size_type pound = line.find ("#");
|
||||||
|
if (pound != std::string::npos)
|
||||||
|
line = line.substr (0, pound);
|
||||||
|
|
||||||
|
// Skip blank lines
|
||||||
|
if (line.length () > 0)
|
||||||
|
{
|
||||||
|
T task;
|
||||||
|
task.parse (std::string ("\"") + lines[i] + "\"");
|
||||||
|
if (! tdb.addT (task))
|
||||||
|
failed.push_back (lines[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream out;
|
||||||
|
out << "Imported "
|
||||||
|
<< (lines.size () - failed.size ())
|
||||||
|
<< " tasks successfully, with "
|
||||||
|
<< failed.size ()
|
||||||
|
<< " errors."
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
std::string bad;
|
||||||
|
join (bad, "\n", failed);
|
||||||
|
return out.str () + "\n" + bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
void importCSV ()
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static std::string importCSV (
|
||||||
|
TDB& tdb,
|
||||||
|
Config& conf,
|
||||||
|
const std::vector <std::string>& lines)
|
||||||
{
|
{
|
||||||
|
return "CSV\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string handleImport (TDB& tdb, T& task, Config& conf)
|
||||||
|
{
|
||||||
|
std::stringstream out;
|
||||||
|
|
||||||
|
// Use the description as a file name.
|
||||||
|
std::string file = trim (task.getDescription ());
|
||||||
|
if (file.length () > 0)
|
||||||
|
{
|
||||||
|
// Load the file.
|
||||||
|
std::vector <std::string> lines;
|
||||||
|
slurp (file, lines, true);
|
||||||
|
|
||||||
|
// Determine which type it might be, then attempt an import.
|
||||||
|
switch (determineFileType (lines))
|
||||||
|
{
|
||||||
|
case task_1_4_3: out << importTask_1_4_3 (tdb, conf, lines); break;
|
||||||
|
case task_1_5_0: out << importTask_1_5_0 (tdb, conf, lines); break;
|
||||||
|
case todo_sh_2_0: out << importTodoSh_2_0 (tdb, conf, lines); break;
|
||||||
|
case csv: out << importCSV (tdb, conf, lines); break;
|
||||||
|
case text: out << importText (tdb, conf, lines); break;
|
||||||
|
|
||||||
|
case not_a_clue:
|
||||||
|
out << "?";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("You must specify a file to import.");
|
||||||
|
|
||||||
|
return out.str ();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
4
src/import/freeform.csv
Normal file
4
src/import/freeform.csv
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
'id','priority','description'
|
||||||
|
1,H,'this is a test'
|
||||||
|
2,,'another task'
|
||||||
|
|
|
3
src/import/line.txt
Normal file
3
src/import/line.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
This is a test priority:H project:A
|
||||||
|
Another task
|
||||||
|
|
2
src/import/task-1.4.3.csv
Normal file
2
src/import/task-1.4.3.csv
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
'id','status','tags','entry','start','due','end','project','priority','fg','bg','description'
|
||||||
|
'545629d2-24a3-4a32-8894-57e708b98354','pending','',1238037900,,,,'A','M',,,'foo bar '
|
|
2
src/import/task-1.5.0.csv
Normal file
2
src/import/task-1.5.0.csv
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
'id','uuid','status','tags','entry','start','due','recur','end','project','priority','fg','bg','description'
|
||||||
|
'7f7a4191-c2f2-487f-8855-7a1eb378c267','pending','',1238037947,,,,,'A','M',,,'foo bar'
|
|
2
src/import/todo.txt
Normal file
2
src/import/todo.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
x 2009-03-25 Walk the dog +project @context
|
||||||
|
This is a test +project @context
|
|
@ -139,6 +139,8 @@ std::string expandPath (const std::string&);
|
||||||
int flock (int, int);
|
int flock (int, int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool slurp (const std::string&, std::vector <std::string>&, bool trimLines = false);
|
||||||
|
|
||||||
// rules.cpp
|
// rules.cpp
|
||||||
void initializeColorRules (Config&);
|
void initializeColorRules (Config&);
|
||||||
void autoColorize (T&, Text::color&, Text::color&, Config&);
|
void autoColorize (T&, Text::color&, Text::color&, Config&);
|
||||||
|
|
26
src/util.cpp
26
src/util.cpp
|
@ -25,6 +25,7 @@
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -404,3 +405,28 @@ int flock (int fd, int operation)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool slurp (
|
||||||
|
const std::string& file,
|
||||||
|
std::vector <std::string>& contents,
|
||||||
|
bool trimLines /* = false */)
|
||||||
|
{
|
||||||
|
contents.clear ();
|
||||||
|
|
||||||
|
std::ifstream in (file.c_str ());
|
||||||
|
if (in.good ())
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
while (getline (in, line))
|
||||||
|
{
|
||||||
|
if (trimLines) line = trim (line);
|
||||||
|
contents.push_back (line);
|
||||||
|
}
|
||||||
|
|
||||||
|
in.close ();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue