From c1d55f17fb4e0a0480c50fe9bb93d26ff33d3eb9 Mon Sep 17 00:00:00 2001 From: Adam Goldsmith Date: Fri, 6 Nov 2015 10:51:07 -0500 Subject: [PATCH] Initial commit --- .gitignore | 1 + sub.py | 85 +++++++++++++++++++++++++++++++++++ test.py | 75 +++++++++++++++++++++++++++++++ test_data/test1/sub/test1.txt | 1 + test_data/test1/todo.txt | 1 + test_data/test2/sub/test1.txt | 1 + test_data/test2/sub/test2.txt | 1 + test_data/test2/todo.txt | 2 + test_data/todo.cfg | 0 9 files changed, 167 insertions(+) create mode 100644 .gitignore create mode 100755 sub.py create mode 100755 test.py create mode 100644 test_data/test1/sub/test1.txt create mode 100644 test_data/test1/todo.txt create mode 100644 test_data/test2/sub/test1.txt create mode 100644 test_data/test2/sub/test2.txt create mode 100644 test_data/test2/todo.txt create mode 100644 test_data/todo.cfg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a348e50 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/__pycache__/ diff --git a/sub.py b/sub.py new file mode 100755 index 0000000..a0270c1 --- /dev/null +++ b/sub.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +import os +import sys +import re +import subprocess +import tempfile + +suffixes = {"sub": ".txt", + "note": ".md"} + +def getItem(num): + with open(os.getenv("TODO_FILE"), "r") as todoFile: + return todoFile.readlines()[num-1] + +def getSub(item): + if "/:" not in item: + return None + try: + sub=re.findall("[^ ]+/:[.A-Za-z0-9_]+", item)[0] + except IndexError: + return None + return sub.split("/:") + +def addSub(num, sub, edit=True): + with open(os.getenv("TODO_FILE"), "r") as todoFile: + lines = todoFile.readlines() + if getSub(lines[num-1]) is not None and getSub(lines[num-1])[0] != sub: + sys.exit("The item already has a sub \"" + sub + "\":" + "\n" + lines[num-1][:-1]) + if not os.path.exists(os.path.join(os.getenv("TODO_DIR"), sub)): + os.mkdir(os.path.join(os.getenv("TODO_DIR"), sub)) + f, name = tempfile.mkstemp(suffixes[sub], "", os.path.join(os.getenv("TODO_DIR"), sub)) + lines[num-1] = lines[num-1][:-1] + " " + sub + "/:" + os.path.basename(name) + "\n" + with open(os.getenv("TODO_FILE"), "w") as todoFile: + todoFile.writelines(lines) + if edit: + editSub(num) + +def editSub(num): + sub = getSub(getItem(num)) + if sub is None: + sys.exit("This item does not have a sub") + editor = os.getenv("EDITOR").split() + subprocess.call(editor + [os.path.join(os.getenv("TODO_DIR"), sub[0], sub[1])]) + +def showSub(item, indent=0, color=True): + sub = getSub(item) + if sub is None: + sys.exit("This item does not have a sub") + command = ["todo.sh", "listfile", os.path.join(sub[0], sub[1])] + if not color: + command.insert(1, "-p") + p = subprocess.Popen(command, stdout=subprocess.PIPE) + output = p.communicate()[0].decode("utf-8") + output = '\n'.join(" "*indent + i for i in output.splitlines()[:-2]) + "\n" + return output + +def showAll(out=sys.stdout, color=True): + command = ["todo.sh", "list"] + if not color: + command.insert(1, "-p") + p = subprocess.Popen(command, stdout=subprocess.PIPE) + lines = p.communicate()[0].decode("utf-8").splitlines() + for line in lines: + out.write(line + "\n") + if getSub(line) is not None: + out.write(showSub(line, indent=2, color=color)) + +def main(argv): + if len(argv) < 3: + showAll() + elif argv[2] == "add": + if len(argv) != 5: + sys.exit("Usage: " + argv[1] + " add [itemNum] [subName]") + itemNum = int(argv[3]) + addSub(itemNum, argv[4]) + elif argv[2] == "edit": + if len(argv) != 4: + sys.exit("Usage: " + argv[1] + " edit [itemNum]") + itemNum = int(argv[3]) + editSub(itemNum) + else: + sys.exit("Command not recognized") + +if __name__ == '__main__': + main(sys.argv) diff --git a/test.py b/test.py new file mode 100755 index 0000000..df12cf1 --- /dev/null +++ b/test.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 + +import unittest +import sub +import os + +TEST_DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_data") + +class TestGetSub(unittest.TestCase): + def test_no_sub(self): + self.assertEqual(sub.getSub("(Z) gibberish"), None) + + def test_sub_at_bol(self): + self.assertEqual(sub.getSub("sub/:test gibberish"), ["sub", "test"]) + + def test_sub_at_eol(self): + self.assertEqual(sub.getSub("(Z) gibberish sub/:test"), ["sub", "test"]) + + def test_sub_mid_line(self): + self.assertEqual(sub.getSub("(Z) sub/:test gibberish"), ["sub", "test"]) + + def test_sub_missing_folder(self): + self.assertEqual(sub.getSub("(Z) gibberish /:test"), None) + + def test_sub_missing_file(self): + self.assertEqual(sub.getSub("(Z) sub/: gibberish"), None) + +def setup_environment(path): + os.environ["TODO_DIR"] = os.path.join(TEST_DATA_DIR, path) + os.environ["TODO_FILE"] = os.path.join(TEST_DATA_DIR, path, "todo.txt") + os.environ["DONE_FILE"] = os.path.join(TEST_DATA_DIR, path, "done.txt") + os.environ["REPORT_FILE"] = os.path.join(TEST_DATA_DIR, path, "report.txt") + os.environ["TODOTXT_CFG_FILE"] = os.path.join(TEST_DATA_DIR, "todo.cfg") + +class TestShowSub(unittest.TestCase): + def test_show(self): + setup_environment("test1") + + output = sub.showSub("(Z) gibberish sub/:test1.txt\n", color=False) + self.assertEqual(output, "1 this is test 1\n") + +class TestShowAll(unittest.TestCase): + def test_show_all_one(self): + self.show_all_tester("test1", "1 (Z) gibberish sub/:test1.txt\n 1 this is test 1\n--\nTODO: 1 of 1 tasks shown\n") + + def test_show_all_two(self): + self.show_all_tester("test2", "1 (Z) gibberish sub/:test1.txt\n 1 this is test 1\n2 (Z) more gibberish sub/:test2.txt\n 1 this is test 2\n--\nTODO: 2 of 2 tasks shown\n") + + def show_all_tester(self, path, expected_output): + from io import StringIO + setup_environment(path) + + out = StringIO() + sub.showAll(out=out, color=False) + output = out.getvalue() + self.assertEqual(output, expected_output) + +class TestAdd(unittest.TestCase): + def setUp(self): + import shutil + shutil.rmtree(os.path.join(TEST_DATA_DIR, "test3")) + os.mkdir(os.path.join(TEST_DATA_DIR, "test3")) + + def test_add_sub(self): + with open(os.path.join(TEST_DATA_DIR, "test3/todo.txt"), "w") as f: + f.write("(Z) gibberish") + setup_environment("test3") + sub.addSub(1, "sub", False) + out = sub.getSub(sub.getItem(1)) + self.assertTrue(out is not None) + fileExists = os.path.isfile(os.path.join(os.getenv("TODO_DIR"), out[0], out[1])) + self.assertTrue(fileExists) + +if __name__ == '__main__': + unittest.main() diff --git a/test_data/test1/sub/test1.txt b/test_data/test1/sub/test1.txt new file mode 100644 index 0000000..49a7eca --- /dev/null +++ b/test_data/test1/sub/test1.txt @@ -0,0 +1 @@ +this is test 1 diff --git a/test_data/test1/todo.txt b/test_data/test1/todo.txt new file mode 100644 index 0000000..04c7e19 --- /dev/null +++ b/test_data/test1/todo.txt @@ -0,0 +1 @@ +(Z) gibberish sub/:test1.txt diff --git a/test_data/test2/sub/test1.txt b/test_data/test2/sub/test1.txt new file mode 100644 index 0000000..49a7eca --- /dev/null +++ b/test_data/test2/sub/test1.txt @@ -0,0 +1 @@ +this is test 1 diff --git a/test_data/test2/sub/test2.txt b/test_data/test2/sub/test2.txt new file mode 100644 index 0000000..d46e3c0 --- /dev/null +++ b/test_data/test2/sub/test2.txt @@ -0,0 +1 @@ +this is test 2 diff --git a/test_data/test2/todo.txt b/test_data/test2/todo.txt new file mode 100644 index 0000000..6464339 --- /dev/null +++ b/test_data/test2/todo.txt @@ -0,0 +1,2 @@ +(Z) gibberish sub/:test1.txt +(Z) more gibberish sub/:test2.txt diff --git a/test_data/todo.cfg b/test_data/todo.cfg new file mode 100644 index 0000000..e69de29