├── TODO ├── ChangeLog ├── output.org ├── MANIFEST.in ├── PyOrgMode ├── __init__.py ├── headlines.org ├── no_headline.org ├── agenda.org ├── tags.org ├── test_scheduled_output.org ├── test_clock.py ├── test_no_headline.py ├── test_parser.py ├── test.py ├── test_headlines.py ├── test_simple-agenda.py ├── test_dates.py ├── test_tags.py ├── test.org └── PyOrgMode.py ├── .gitignore ├── setup.py ├── AUTHORS ├── README.org ├── PyOrgMode_test.py └── LICENSE /TODO: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /output.org: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | 3 | -------------------------------------------------------------------------------- /PyOrgMode/__init__.py: -------------------------------------------------------------------------------- 1 | from .PyOrgMode import * -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | MANIFEST 4 | dist 5 | build 6 | 7 | -------------------------------------------------------------------------------- /PyOrgMode/headlines.org: -------------------------------------------------------------------------------- 1 | * This is a headline 2 | **This is not a headline 3 | ** This is a headline too 4 | -------------------------------------------------------------------------------- /PyOrgMode/no_headline.org: -------------------------------------------------------------------------------- 1 | This is an orgmode file with no headlines *test* 2 | 3 | *Test* 4 | 5 | edtedp 6 | 7 | Test 8 | -------------------------------------------------------------------------------- /PyOrgMode/agenda.org: -------------------------------------------------------------------------------- 1 | * Test 2 | ** Element 1 3 | SCHEDULED: <2011-02-08> 4 | ** Element 2 5 | ** Element 3 6 | DEADLINE: <2011-02-08> 7 | *** Test 8 | *** Element 4 9 | SCHEDULED: <2011-02-08> 10 | **** Couic 11 | -------------------------------------------------------------------------------- /PyOrgMode/tags.org: -------------------------------------------------------------------------------- 1 | * First header :onetag: 2 | * TODO Second header :onetag:twotag: 3 | * TODO Third header :onetag:twotag:threetag: 4 | 5 | -------------------------------------------------------------------------------- /PyOrgMode/test_scheduled_output.org: -------------------------------------------------------------------------------- 1 | * Element 1 2 | SCHEDULED: <2011-02-08> 3 | * Element 3 4 | DEADLINE: <2011-02-08> 5 | ** Test 6 | ** Element 4 7 | SCHEDULED: <2011-02-08> 8 | *** Couic 9 | * Element 4 10 | SCHEDULED: <2011-02-08> 11 | ** Couic 12 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name = 'PyOrgMode', 5 | packages = ['PyOrgMode'], # this must be the same as the name above 6 | version = '0.1', 7 | description = 'Library to interact with org-mode from python', 8 | author = 'Jonathan BISSON', 9 | author_email = 'Jonathan.BISSON@bjonnh.net', 10 | url = 'https://github.com/bjonnh/PyOrgMode', # use the URL to the github repo 11 | keywords = ['org-mode'], 12 | classifiers = [], 13 | ) 14 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | 2 | Jonathan BISSON : initiator of the project 3 | Antti KAIHOLA 4 | m3wolf (github) 5 | bordercore (github) 6 | wroberts (github) 7 | gonvaled (github) 8 | 10nin (github) 9 | CodeMonk (github) 10 | midraal (github) 11 | whacked (github) 12 | maxandersen (github) 13 | CodeMonk (github) 14 | midraal (github) 15 | Seamus Tuohy (@elationfoundation on github) 16 | clemente (github) 17 | kbarber2 (github) 18 | sp1ff (github) 19 | -------------------------------------------------------------------------------- /PyOrgMode/test_clock.py: -------------------------------------------------------------------------------- 1 | import PyOrgMode 2 | import unittest 3 | 4 | 5 | class TestClockElement(unittest.TestCase): 6 | def test_duration_format(self): 7 | """Durations are formatted identically to org-mode""" 8 | 9 | for hour in '0', '1', '5', '10', '12', '13', '19', '23': 10 | for minute in '00', '01', '29', '40', '59': 11 | orig_str = '%s:%s' % (hour, minute) 12 | orgdate_element = PyOrgMode.OrgDate(orig_str) 13 | formatted_str = orgdate_element.get_value() 14 | self.assertEqual(formatted_str, orig_str) 15 | 16 | 17 | if __name__ == '__main__': 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /PyOrgMode/test_no_headline.py: -------------------------------------------------------------------------------- 1 | 2 | """Tests for parsing a file containing no headline 3 | but that contains a bold element (thanks whacked) 4 | You need the fr_FR.UTF-8 locale to run these tests 5 | """ 6 | 7 | import locale 8 | import PyOrgMode 9 | try: 10 | import unittest2 as unittest 11 | except ImportError: 12 | import unittest 13 | 14 | 15 | class TestExampleOrgFile(unittest.TestCase): 16 | def test_noheadline_org(self): 17 | test = PyOrgMode.OrgDataStructure() 18 | test.load_from_file("no_headline.org") 19 | 20 | locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') 21 | test.save_to_file("output.org") 22 | with open("no_headline.org") as f: 23 | original = [line for line in f] 24 | with open("output.org") as f: 25 | saved = [line for line in f] 26 | self.assertEqual(saved, original) 27 | 28 | 29 | if __name__ == '__main__': 30 | unittest.main() 31 | -------------------------------------------------------------------------------- /PyOrgMode/test_parser.py: -------------------------------------------------------------------------------- 1 | 2 | import PyOrgMode 3 | import tempfile 4 | import unittest 5 | 6 | 7 | class TestParser(unittest.TestCase): 8 | """Test the org file parser with a simple org structure""" 9 | 10 | def setUp(self): 11 | """Parse the org structure from a temporary file""" 12 | orgfile = tempfile.NamedTemporaryFile() 13 | orgfile.write('\n'.join(( 14 | '* one', 15 | '* two', 16 | '** two point one', 17 | '* three', 18 | '')).encode('UTF-8')) 19 | orgfile.flush() 20 | self.tree = PyOrgMode.OrgDataStructure() 21 | try: 22 | self.tree.load_from_file(orgfile.name) 23 | finally: 24 | orgfile.close() 25 | 26 | def test_has_three_top_level_headings(self): 27 | """The example has three top-level headings""" 28 | self.assertEqual(len(self.tree.root.content), 3) 29 | 30 | def test_second_item_has_a_subheading(self): 31 | """The second top-level heading has one subheading""" 32 | self.assertEqual(len(self.tree.root.content[1].content), 1) 33 | 34 | 35 | if __name__ == '__main__': 36 | unittest.main() 37 | -------------------------------------------------------------------------------- /PyOrgMode/test.py: -------------------------------------------------------------------------------- 1 | 2 | """Tests for parsing and outputting a simple .org test file 3 | 4 | You need the fr_FR.UTF-8 locale to run these tests 5 | """ 6 | 7 | import locale 8 | import PyOrgMode 9 | try: 10 | import unittest2 as unittest 11 | except ImportError: 12 | import unittest 13 | 14 | 15 | def _normalize_ignored(line): 16 | """Normalize a line to ignore differences which aren't yet handled""" 17 | line = line.replace(':ORDERED: t', ':ORDERED: t') 18 | return line 19 | 20 | 21 | def _normalize_output_ignored(line): 22 | line = line.replace(':TAG1:TAG2:', ':TAG1::TAG2:') 23 | line = _normalize_ignored(line) 24 | return line 25 | 26 | 27 | class TestExampleOrgFile(unittest.TestCase): 28 | def test_test_org(self): 29 | test = PyOrgMode.OrgDataStructure() 30 | locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') 31 | test.load_from_file("test.org") 32 | test.save_to_file("output.org") 33 | with open("test.org") as f: 34 | original = [_normalize_ignored(line) for line in f] 35 | with open("output.org") as f: 36 | saved = [_normalize_output_ignored(line) for line in f] 37 | 38 | self.assertEqual(saved, original) 39 | 40 | 41 | if __name__ == '__main__': 42 | unittest.main() 43 | -------------------------------------------------------------------------------- /PyOrgMode/test_headlines.py: -------------------------------------------------------------------------------- 1 | 2 | """Tests for headline validity 3 | """ 4 | 5 | import PyOrgMode 6 | try: 7 | import unittest2 as unittest 8 | except ImportError: 9 | import unittest 10 | 11 | 12 | class TestHeadlineValidity(unittest.TestCase): 13 | def setUp(self): 14 | self.tree = PyOrgMode.OrgDataStructure() 15 | self.tree.add_todo_state('TODO') 16 | self.tree.load_from_file("headlines.org") 17 | self.todolist = self.tree.extract_todo_list() 18 | 19 | def test_recognize_heading(self): 20 | """The file has three top-level headings""" 21 | node = self.tree.root.content[0] 22 | self.assertIsInstance(node.content[1], 23 | PyOrgMode.OrgNode.Element) 24 | 25 | def test_not_recognize_starredtext_asheading(self): 26 | """The file has three top-level headings""" 27 | node = self.tree.root.content[0] 28 | self.assertNotIsInstance(node.content[0], 29 | PyOrgMode.OrgNode.Element) 30 | 31 | def test_links_in_headline(self): 32 | """Links and priorities are distinguished in headlines""" 33 | link = '[[http://github.com][Github]]' 34 | tree = PyOrgMode.OrgDataStructure() 35 | tree.load_from_string('* ' + link + ' :tag:') 36 | node = tree.root.content[0] 37 | self.assertTrue(node.heading.rstrip() == link) 38 | self.assertTrue('tag' in node.tags) 39 | 40 | if __name__ == '__main__': 41 | unittest.main() 42 | -------------------------------------------------------------------------------- /PyOrgMode/test_simple-agenda.py: -------------------------------------------------------------------------------- 1 | import PyOrgMode 2 | import copy 3 | try: 4 | import unittest2 as unittest 5 | except ImportError: 6 | import unittest 7 | 8 | 9 | def Get_Scheduled_Elements(element, data=[]): 10 | """Grab the data from all scheduled elements for all the tree defined by 11 | 'element' recursively. Returns all the elements as an array. 12 | """ 13 | if hasattr(element, "content"): 14 | for child in element.content: 15 | if hasattr(child, "TYPE"): 16 | if child.TYPE == "SCHEDULE_ELEMENT": 17 | # This element is scheduled, we are creating a copy of it 18 | data.append(copy.deepcopy(child.parent)) 19 | Get_Scheduled_Elements(child, data) 20 | return data 21 | 22 | 23 | class TestAgenda(unittest.TestCase): 24 | def test_agenda(self): 25 | # Creating the input and output files data structures 26 | input_file = PyOrgMode.OrgDataStructure() 27 | output_file = PyOrgMode.OrgDataStructure() 28 | 29 | # Loading from agenda.org file 30 | input_file.load_from_file("agenda.org") 31 | 32 | # Get the scheduled elements (those with SCHEDULE, DEADLINE in them, 33 | # not in the node name) 34 | scheduled_elements = Get_Scheduled_Elements(input_file.root) 35 | 36 | # Assign these element to the root (reparent each elements recursively, 37 | # relevel them cleanly) 38 | output_file.root.append_clean(scheduled_elements) 39 | 40 | output_file.save_to_file("test_scheduled_output.org") 41 | with open("test_scheduled_output.org") as f: 42 | saved = f.readlines() 43 | 44 | self.assertEqual(saved, ['* Element 1\n', 45 | ' SCHEDULED: <2011-02-08>\n', 46 | '* Element 3\n', 47 | ' DEADLINE: <2011-02-08>\n', 48 | '** Test\n', 49 | '** Element 4\n', 50 | ' SCHEDULED: <2011-02-08>\n', 51 | '*** Couic\n', 52 | '* Element 4\n', 53 | ' SCHEDULED: <2011-02-08>\n', 54 | '** Couic\n']) 55 | 56 | 57 | if __name__ == '__main__': 58 | unittest.main() 59 | -------------------------------------------------------------------------------- /PyOrgMode/test_dates.py: -------------------------------------------------------------------------------- 1 | 2 | import PyOrgMode 3 | import unittest 4 | 5 | 6 | class TestDates(unittest.TestCase): 7 | """Test the org file parser with several date formats""" 8 | 9 | def test_baredate(self): 10 | """ 11 | Tests parsing dates without time. 12 | """ 13 | datestr = '<2013-11-20 Wed>' 14 | date = PyOrgMode.OrgDate(datestr) 15 | self.assertEqual(tuple(date.value), (2013, 11, 20, 0, 0, 0, 2, 324, -1)) 16 | self.assertEqual(date.get_value(), datestr) 17 | 18 | def test_datetime(self): 19 | """ 20 | Tests parsing dates with time. 21 | """ 22 | datestr = '<2011-12-12 Mon 09:00>' 23 | date = PyOrgMode.OrgDate(datestr) 24 | self.assertEqual(tuple(date.value), (2011, 12, 12, 9, 0, 0, 0, 346, -1)) 25 | self.assertEqual(date.get_value(), datestr) 26 | 27 | def test_datenoweekday(self): 28 | """ 29 | Tests parsing simple dates without weekdays. 30 | """ 31 | datestr = '<2013-11-20>' 32 | date = PyOrgMode.OrgDate(datestr) 33 | self.assertEqual(tuple(date.value), (2013, 11, 20, 0, 0, 0, 2, 324, -1)) 34 | self.assertEqual(date.get_value(), datestr) 35 | 36 | def test_localizeddatetime_unicode(self): 37 | """ 38 | Tests parsing dates with localized weekday name that uses non-ASCII. 39 | """ 40 | datestr = '<2011-12-12 Пнд 09:00>' # Понедельник = Monday (Russian) 41 | date = PyOrgMode.OrgDate(datestr) 42 | self.assertEqual(tuple(date.value), (2011, 12, 12, 9, 0, 0, 0, 346, -1)) 43 | self.assertEqual(date.get_value(), '<2011-12-12 Mon 09:00>') 44 | 45 | def test_localizeddatetime_dot(self): 46 | """ 47 | Tests parsing dates with localized weekday name that includes a dot. 48 | """ 49 | datestr = '<2011-12-12 al. 09:00>' # astelehena = Monday (Basque) 50 | date = PyOrgMode.OrgDate(datestr) 51 | self.assertEqual(tuple(date.value), (2011, 12, 12, 9, 0, 0, 0, 346, -1)) 52 | self.assertEqual(date.get_value(), '<2011-12-12 Mon 09:00>') 53 | 54 | def test_timerange(self): 55 | """ 56 | Tests parsing time ranges on the same day. 57 | """ 58 | datestr = '<2012-06-28 Thu 12:00-13:00>' 59 | date = PyOrgMode.OrgDate(datestr) 60 | self.assertEqual(tuple(date.value), (2012, 6, 28, 12, 0, 0, 3, 180, -1)) 61 | self.assertEqual(tuple(date.end), (2012, 6, 28, 13, 0, 0, 3, 180, -1)) 62 | self.assertEqual(date.get_value(), datestr) 63 | 64 | def test_daterange(self): 65 | """ 66 | Tests parsing date ranges. 67 | """ 68 | datestr = '<2012-07-20 Fri>--<2012-07-31 Tue>' 69 | date = PyOrgMode.OrgDate(datestr) 70 | self.assertEqual(tuple(date.value), (2012, 7, 20, 0, 0, 0, 4, 202, -1)) 71 | self.assertEqual(tuple(date.end), (2012, 7, 31, 0, 0, 0, 1, 213, -1)) 72 | self.assertEqual(date.get_value(), datestr) 73 | 74 | def test_daterangewithtimes(self): 75 | """ 76 | Tests parsing date ranges with times. 77 | """ 78 | datestr = '<2012-07-20 Fri 09:00>--<2012-07-31 Tue 14:00>' 79 | date = PyOrgMode.OrgDate(datestr) 80 | self.assertEqual(tuple(date.value), (2012, 7, 20, 9, 0, 0, 4, 202, -1)) 81 | self.assertEqual(tuple(date.end), (2012, 7, 31, 14, 0, 0, 1, 213, -1)) 82 | self.assertEqual(date.get_value(), datestr) 83 | 84 | if __name__ == '__main__': 85 | unittest.main() 86 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+BABEL: :comments no 2 | #+VERSION: 0.03a 3 | 4 | **PyOrgMode is currently, and probably for ever, unmaintained ** 5 | 6 | There is a new project that is well documented and may cover most, if not more of what PyOrgMode was covering: [[https://github.com/karlicoss/orgparse][Karlicoss' OrgParse]]. 7 | 8 | * PyOrgMode 9 | PyOrgMode is a small python library able to do simple tasks with your org files. It allows you to generate org files or treat them in an automated fashion. 10 | 11 | This project is not my top priority, but I'm more than happy to receive pull requests. Don't worry, even if it takes some time, I go through all of them ;) 12 | 13 | I'd like to thank all the people that contributes (see AUTHORS file). 14 | 15 | ** Quick Start 16 | 17 | *** Installation 18 | 19 | Download the git repo and then install the package. 20 | #+BEGIN_SRC sh 21 | git clone https://github.com/bjonnh/PyOrgMode.git 22 | cd PyOrgMode/ 23 | sudo python setup.py install 24 | #+END_SRC 25 | 26 | *** Import an Org-Mode file 27 | 28 | Import PyOrgMode 29 | 30 | #+BEGIN_SRC python 31 | import PyOrgMode 32 | #+END_SRC 33 | 34 | Create an Org data structure to hold the org-mode file. 35 | 36 | #+BEGIN_SRC python 37 | base = PyOrgMode.OrgDataStructure() 38 | #+END_SRC 39 | 40 | Load the org-mode file. 41 | 42 | #+BEGIN_SRC python 43 | base.load_from_file("test.org") 44 | #+END_SRC 45 | 46 | *** Create an org-mode file 47 | Create an Org data structure to hold the org-mode file. 48 | #+BEGIN_SRC python 49 | base = PyOrgMode.OrgDataStructure() 50 | #+END_SRC 51 | 52 | Create a new TODO item 53 | #+BEGIN_SRC python 54 | new_todo = PyOrgMode.OrgNode.Element() 55 | new_todo.heading = "I am a new todo item" 56 | new_todo.tags=["things", "important"] 57 | new_todo.level = 1 58 | new_todo.todo = "TODO" 59 | #+END_SRC 60 | 61 | Add a scheduled item and a deadline to the item. 62 | #+BEGIN_SRC python 63 | _sched = PyOrgMode.OrgSchedule() 64 | _sched._append(new_todo, _sched.Element(scheduled="<2015-08-01 Sat 12:00-13:00>")) 65 | _sched._append(new_todo, _sched.Element(deadline="<2015-08-01 Sat 12:00-13:00>")) 66 | #+END_SRC 67 | 68 | Create a logbook drawer 69 | #+BEGIN_SRC python 70 | _props = PyOrgMode.OrgDrawer.Element("LOGBOOK") 71 | # Add a properties drawer 72 | _props.append(PyOrgMode.OrgDrawer.Element("- State \"SOMEDAY\" from \"TODO\" [2015-07-01 Wed 09:45]")) 73 | # Append the properties to the new todo item 74 | new_todo.append_clean(_props) 75 | #+END_SRC 76 | 77 | Create a properties drawer 78 | #+BEGIN_SRC python 79 | _props = PyOrgMode.OrgDrawer.Element("PROPERTIES") 80 | # Add a properties drawer 81 | _props.append(PyOrgMode.OrgDrawer.Property("FRUITS", "pineapples")) 82 | _props.append(PyOrgMode.OrgDrawer.Property("NAMES", "bob, sally")) 83 | # Append the properties to the new todo item 84 | new_todo.append_clean(_props) 85 | #+END_SRC 86 | 87 | Append the todo item to the base object 88 | #+BEGIN_SRC python 89 | base.root.append_clean(new_todo) 90 | #+END_SRC 91 | 92 | Save the org object to a file 93 | #+BEGIN_SRC python 94 | base.save_to_file("output.org") 95 | #+END_SRC 96 | 97 | ** Tools 98 | [[elisp:org-babel-tangle][Tangle]] (Export the files) 99 | ** Documentation 100 | *** Authors 101 | :PROPERTIES: 102 | :ID: 5b9ea3e5-f67b-4be7-9c55-6f1923b04e79 103 | :END: 104 | #+srcname: authors 105 | #+begin_src ascii :tangle AUTHORS :exports code 106 | Jonathan BISSON : initiator of the project 107 | Antti KAIHOLA 108 | m3wolf (github) 109 | bordercore (github) 110 | wroberts (github) 111 | gonvaled (github) 112 | 10nin (github) 113 | CodeMonk (github) 114 | midraal (github) 115 | whacked (github) 116 | maxandersen (github) 117 | CodeMonk (github) 118 | midraal (github) 119 | Seamus Tuohy (@elationfoundation on github) 120 | clemente (github) 121 | kbarber2 (github) 122 | sp1ff (github) 123 | inducer (github) 124 | #+end_src 125 | -------------------------------------------------------------------------------- /PyOrgMode/test_tags.py: -------------------------------------------------------------------------------- 1 | 2 | """Tests for parsing a file containing no headline 3 | but that contains a bold element (thanks whacked) 4 | You need the fr_FR.UTF-8 locale to run these tests 5 | """ 6 | 7 | import PyOrgMode 8 | import re 9 | import tempfile 10 | try: 11 | import unittest2 as unittest 12 | except ImportError: 13 | import unittest 14 | 15 | 16 | class TestExampleOrgFile(unittest.TestCase): 17 | def setUp(self): 18 | self.tree = PyOrgMode.OrgDataStructure() 19 | self.tree.add_todo_state('TODO') 20 | self.tree.load_from_file("tags.org") 21 | self.todolist = self.tree.extract_todo_list() 22 | 23 | def test_has_three_top_level_headings(self): 24 | """The file has three top-level headings""" 25 | self.assertEqual(len(self.tree.root.content), 3) 26 | 27 | def test_the_first_item_has_one_tag(self): 28 | node = self.tree.root.content[0] 29 | self.assertEqual(len(node.tags), 1) 30 | self.assertEqual(node.heading.strip(), "First header") 31 | 32 | def test_the_second_item_has_two_tags(self): 33 | """The file has three top-level headings""" 34 | node = self.tree.root.content[1] 35 | 36 | self.assertEqual(len(node.tags), 2) 37 | self.assertEqual(node.tags, ["onetag", "twotag"]) 38 | self.assertEqual(node.heading.strip(), "Second header") 39 | 40 | def test_third_item_has_three_tags(self): 41 | """The file has three top-level headings""" 42 | node = self.tree.root.content[2] 43 | self.assertEqual(len(node.tags), 3) 44 | self.assertEqual(node.heading.strip(), "Third header") 45 | self.assertEqual(node.output(), "* TODO Third header " + 46 | " :onetag:twotag:threetag:\n\n") 47 | 48 | 49 | class TestTagInheritance(unittest.TestCase): 50 | def setUp(self): 51 | """Setup a temp file against which to test.""" 52 | orgfile = tempfile.NamedTemporaryFile() 53 | orgfile.write("""#+TITLE: test 54 | #+FILETAGS: :a:b:c: 55 | * one 56 | * two 57 | ** TODO 2.1 58 | * three 59 | """.encode('UTF-8')) 60 | orgfile.flush() 61 | self.tree = PyOrgMode.OrgDataStructure() 62 | try: 63 | self.tree.load_from_file(orgfile.name) 64 | finally: 65 | orgfile.close() 66 | 67 | def test_file_tags(self): 68 | assert self.tree.root.tags == ['a', 'b', 'c'] 69 | todos = self.tree.extract_todo_list() 70 | assert len(todos) == 1 and '2.1' == todos[0].heading 71 | assert todos[0].node.get_all_tags() == ['a', 'b', 'c'] 72 | assert todos[0].node.get_all_tags(None) == [] 73 | assert todos[0].node.get_all_tags(True, ['a']) == ['b', 'c'] 74 | assert todos[0].node.get_all_tags(re.compile('[ab]')) == ['a', 'b'] 75 | 76 | 77 | class TestFileTagsPlugin(unittest.TestCase): 78 | 79 | def test_filetags1(self): 80 | tree = PyOrgMode.OrgDataStructure() 81 | tree.load_from_string("""#+TITLE: test 82 | #+FILETAGS: :a:b:c: 83 | * one 84 | * two 85 | * three 86 | """) 87 | assert tree.root.tags == ['a', 'b', 'c'] 88 | 89 | def test_filetags2(self): 90 | tree = PyOrgMode.OrgDataStructure() 91 | tree.load_from_string("""#+TITLE: test 92 | #+FILETAGS: a:b:c: 93 | * one 94 | * two 95 | * three 96 | """) 97 | assert tree.root.tags == ['a', 'b', 'c'] 98 | 99 | def test_filetags3(self): 100 | tree = PyOrgMode.OrgDataStructure() 101 | tree.load_from_string("""#+TITLE: test 102 | #+FILETAGS: a:b:c 103 | * one 104 | * two 105 | * three 106 | """) 107 | assert tree.root.tags == ['a', 'b', 'c'] 108 | 109 | def test_filetags4(self): 110 | tree = PyOrgMode.OrgDataStructure() 111 | tree.load_from_string("""#+TITLE: test 112 | #+FILETAGS: a:b 113 | * one 114 | * two 115 | * three 116 | """) 117 | assert tree.root.tags == ['a', 'b'] 118 | 119 | def test_filetags5(self): 120 | tree = PyOrgMode.OrgDataStructure() 121 | tree.load_from_string("""#+TITLE: test 122 | #+FILETAGS: a 123 | * one 124 | * two 125 | * three 126 | """) 127 | assert tree.root.tags == ['a'] 128 | 129 | 130 | if __name__ == '__main__': 131 | unittest.main() 132 | -------------------------------------------------------------------------------- /PyOrgMode/test.org: -------------------------------------------------------------------------------- 1 | * Table test 2 | | elsbl | lesél | lseilép | 3 | |----------+-------+---------| 4 | | dlitsléb | 10 | 20 | 5 | | eietl | letil | lielt | 6 | * Scheduling Test 7 | ** DEADLINE SCHEDULED CLOCK combo 8 | SCHEDULED: <2011-04-01 ven.> DEADLINE: <2011-04-04 lun.> CLOSED: [2011-04-05 mar. 19:20] 9 | ** DEADLINE 10 | DEADLINE: <2010-10-10> 11 | ** SCHEDULED 12 | SCHEDULED: <2010-10-10> 13 | ** CLOCK 14 | CLOCK: [2011-02-27 dim. 19:50]--[2011-02-27 dim. 19:51] => 0:01 15 | CLOCK: [2011-02-27 dim. 19:50]--[2011-02-27 dim. 19:50] => 0:00 16 | CLOCK: [2011-02-27 dim. 19:50]--[2011-02-27 dim. 19:50] => 0:00 17 | :PROPERTIES: 18 | :ORDERED: t 19 | :CLOCKSUM: 0 20 | :END: 21 | Test 22 | * TAGS TEST :TAG1::TAG2: 23 | ** TAGS :TAG1: 24 | ** TAGS :TAG1::TAG2: 25 | 26 | 27 | * Priority 28 | ** [#A] A :a: 29 | ** [#B] B :b: 30 | ** [#C] C :c: 31 | * Autre format de ces prises de notes: 32 | :PROPERTIES: 33 | :ID: 1 34 | et 35 | :END: 36 | - [[http://www.piprime.fr/files/articles/emacs/org/org.org][code source au format org]] 37 | - [[http://www.piprime.fr/files/articles/emacs/org/org.pdf][le pdf généré à partir de l'export en LaTeX]] 38 | - [[http://www.piprime.fr/files/articles/emacs/org/org.pdf][l'export en LaTeX]] pour les très curieux ;-) 39 | - [[http://www.piprime.fr/files/articles/emacs/org/org.png][Une copie d'écran]] et [[http://www.piprime.fr/files/articles/emacs/org/org1.png][une deuxième]] montrant le rendu du fichier org.org en cours d'édition dans Emacs. 40 | 41 | * Introduction 42 | ** Résumé 43 | [[http://orgmode.org/][Org]] est un mode pour /Emacs/ qui permet entre autre de prendre des notes, de maintenir 44 | des /TODOs/ ainsi que de planifier efficacement des projets complexes. 45 | Plus d'information dans [[http://orgmode.org/manual/Summary.html][la documentation officielle]] 46 | ** Installation et configuration 47 | Org fait parti d'/Emacs/ depuis la version 22, je ne détaillerais donc pas son installation. 48 | La configuration de base préconisée par la documentation officielle suit: 49 | #+begin_src emacs-lisp 50 | (require 'org-install) 51 | (add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) 52 | (define-key global-map "\C-cl" 'org-store-link) 53 | (define-key global-map "\C-ca" 'org-agenda) 54 | (setq org-log-done t) 55 | #+end_src 56 | 57 | 58 | * Structure des documents 59 | ** /Outlines/ 60 | /Org/ est implémenté au-dessus du mode [[http://www.gnu.org/software/emacs/manual/html_node/emacs/Outline-Mode.html][Outline Mode]] qui permet 61 | d'éditer des lignes longues. Cela permet aux documents d'être 62 | organisé dans une structure hiérarchique donnant ainsi une meilleure 63 | représentation des notes et des idées. 64 | /Org/ simplifie notablement l'usage du mode /outline/ en rassemblant 65 | toutes les fonctionnalités de masquage/affichage en une seule 66 | commande =org-cycle=, qui est accessible via le raccourci . 67 | 68 | ** Sections 69 | Les sections d'un document sont hiérarchisées à l'aide 70 | d'étoiles. Par exemple: 71 | 72 | : * Section 1 73 | : ** Sous-section 1 74 | : *** Sous-sous-section 1 75 | : Du texte… 76 | : *** Sous-sous-section 2 77 | : Du texte… 78 | : 79 | : ** Sous-section 2 80 | : *** Sous-sous-section 1 81 | : Du texte… 82 | : *** Sous-sous-section 2 83 | : Du texte… 84 | : 85 | : * Section 2 86 | : etc… 87 | 88 | Si l'on préfère une vue de ce type… 89 | 90 | : * Top level headline 91 | : * Second level 92 | : * 3rd level 93 | : some text 94 | : * 3rd level 95 | : more text 96 | : * Another top level headline 97 | : 98 | …on peut, à partir de /Emacs 23.1.50.3/ et /Org 6.29/, utiliser le 99 | mode =org-indent-mode= ou mettre dans le fichier où l'on désire ce 100 | comportement la ligne de configuration =#+STARTUP: indent=. Plus 101 | d'information sur ce type de vue se trouve à la section 102 | [[http://orgmode.org/manual/Clean-view.html#Clean-view][A cleaner outline view]] de la documentation officielle. 103 | ** Rotation cyclique de la visibilité 104 | Il est possible de cacher certaines parties du texte dans le buffer 105 | afin d'en dégager la structure. Les deux principaux raccourcis pour 106 | cela sont == (rotation sur le nœud courant) et == (rotation 107 | sur l'ensemble du buffer). 108 | Pour voir l'ensemble du buffer, on peut utiliser =C-u C-u C-u = 109 | Enfin, lors de la première visite d'un buffer il est possible de 110 | paramétré le type de contenu que l'on veut voir par défaut: 111 | 112 | : #+STARTUP: overview 113 | : #+STARTUP: content 114 | : #+STARTUP: showall 115 | : #+STARTUP: showeverything 116 | 117 | Plus d'information sur ces fonctionnalités à la section 118 | [[http://orgmode.org/manual/Visibility-cycling.html#Visibility-cycling][Visibility cycling]] de la documentation officielle. 119 | 120 | ** Les raccourcis de déplacement 121 | Les commandes suivantes permettent de naviguer rapidement dans le 122 | buffer. 123 | 124 | - *C-c C-n* :: 125 | Section suivante ; 126 | - *C-c C-p* :: 127 | Section précédente ; 128 | - *C-c C-f* :: 129 | Section suivante de même niveau ; 130 | - *C-c C-b* :: 131 | Section précédente de même niveau ; 132 | - *C-c C-u* :: 133 | Retourne au niveau le plus haut. 134 | - *C-c C-j* :: 135 | Place le document dans un buffer temporaire où l'on 136 | peut naviguer rapidement à l'aide de touches prédéfinies rappelées 137 | ci-dessous. Cette fonctionnalité est très appréciable pour de 138 | gros documents. 139 | 140 | : Cycle visibility. 141 | : / Next/previous visible headline. 142 | : Select this location. 143 | : / Do a Sparse-tree search. 144 | : The following keys work if you turn off org-goto-auto-isearch. 145 | : n / p Next/previous visible headline. 146 | : f / b Next/previous headline same level. 147 | : u One level up. 148 | : 0-9 Digit argument. 149 | : q Quit. 150 | 151 | ** Les raccourcis d'édition 152 | Voici la description sommaire des *principaux* raccourcis d'édition. Pour une 153 | description complète et exhaustive on peut toujours se référer à la section 154 | [[http://orgmode.org/manual/Structure-editing.html#Structure-editing][Structure editing]] de la documentation officielle. 155 | 156 | - *M-* :: 157 | Insère une nouvelle rubrique (section, description etc) de même niveau que le niveau actuel. 158 | - *C-* :: 159 | Comme *M-*, sauf que la rubrique est ajoutée au niveau 160 | inférieur. 161 | - *M-S-* :: 162 | Insère un nouveau /TODO/ au même niveau que le niveau actuel. 163 | - *C-S-* :: 164 | Comme *M-S-* mais au niveau inférieur. 165 | - ** :: (dans un nouvelle entrée vide) 166 | Dans une nouvelle entrée, sans encore de texte, le premier 167 | ** fait devenir l'entrée un enfant de la précédente. Le ** suivant la fait 168 | devenir… je n'ai pas compris (voir la doc ou essayer). 169 | - *M-* :: 170 | Descend *tout* le niveau courant d'un niveau. 171 | - *M-* :: 172 | Augmente *tout* le niveau courant d'un niveau. 173 | - *M-S-* :: 174 | Descend seulement l'entrée courante d'un niveau. 175 | - *M-S-* :: 176 | Augmente seulement l'entrée courante d'un niveau. 177 | - *M-S-* :: 178 | Déplace l'entrée courante au-dessus de l'entrée de même niveau. 179 | - *M-S-* :: 180 | Idem vers le bas. 181 | - *C-c C-x C-w* :: 182 | Supprime l'entrée courante et la place dans le /kill ring/. 183 | - *C-c C-x M-w* :: 184 | Copie l'entrée courante dans le /kill ring/. 185 | - *C-c C-x C-y* :: 186 | Colle une entrée depuis le /kill ring/. 187 | - *C-c C-x c* :: 188 | Clone une entrée. 189 | - *C-c C-w* :: 190 | Déplace l'entrée courante ou la région à un autre endroit. Voir [[http://orgmode.org/manual/Refiling-notes.html#Refiling-notes][Refiling notes]]. 191 | - *C-c ^* :: 192 | Trie les entrées de même niveau. 193 | 194 | ** Arbres partiels 195 | /Org/ est capable de construire un arbre partiel à partir d'une 196 | information donnée de tel manière que la totalité du document soit 197 | replié à l'exception des parties contenant l'information cherchée. 198 | Essayez le et vous comprendrez ; les commandes pour construire un 199 | arbre partiel sont accessibles par *C-c /*, en particulier 200 | *C-c / r* permet de construire un aperçu des correspondances à une 201 | expression rationnelle donnée. 202 | 203 | Pour un usage répété d'une recherche, il est possible de définir une 204 | touche d'accès rapide accessible via le répartiteur d'agenda (vois 205 | [[agenda-dispatcher][Agenda Dispatcher]] pour plus d'information). 206 | #+BEGIN_SRC emacs-lisp 207 | (setq org-agenda-custom-commands 208 | '(("f" occur-tree "FIXME"))) 209 | #+END_SRC 210 | définie le « rat Courci » *C-c a f* pour créer un aperçu de 211 | l'arborescence qui trouve une correspondance avec /FIXME/. 212 | 213 | Les différentes commandes possibles seront expliquées ultérieurement, 214 | lorsque seront expliqué les notions de /tags/ et de /properties/. 215 | 216 | Enfin, pour imprimer un arbre partiel tel qu'il apparaît, on peut 217 | utiliser la commande =ps-print-buffer-with-faces= car elle n'imprime 218 | pas les parties invisibles. On peut aussi utiliser *C-c C-e v* pour 219 | exporter seulement la partie visible puis imprimer le résultat. 220 | 221 | Pour plus d'information sur cette section, se reporter à la partie 222 | [[http://orgmode.org/manual/Sparse-trees.html#Sparse-trees][Sparse trees]] de la documentation officielle. 223 | 224 | ** Les listes 225 | Il est possible de formater des listes à la main. En effet /Org/ 226 | reconnaît les listes non ordonnées, les listes numérotées et les 227 | descriptions. 228 | - Les listes à puces sont marquées avec les symbole '-' ou '+', 229 | éventuellement * (malgré que ce soit déconseillé) ; 230 | - les listes numérotées commences par un numéro suivit d'un 231 | point « 1. 2. etc » ou d'une parenthèse « 1) 2) etc ». 232 | - les descriptions sont identiques au listes non ordonnées mais 233 | la description est suivi du séparateur :: 234 | 235 | Voici un exemple de listes: 236 | : ** Lord of the Rings 237 | : My favorite scenes are (in this order) 238 | : 1. The attack of the Rohirrim 239 | : 2. Eowyn's fight with the witch king 240 | : + this was already my favorite scene in the book 241 | : + I really like Miranda Otto. 242 | : 3. Peter Jackson being shot by Legolas 243 | : - on DVD only 244 | : He makes a really funny face when it happens. 245 | : But in the end, no individual scenes matter but the film as a whole. 246 | : Important actors in this film are: 247 | : - Elijah Wood :: He plays Frodo 248 | : - Sean Austin :: He plays Sam, Frodo's friend. I still remember 249 | : him very well from his role as Mikey Walsh in The Goonies. 250 | 251 | Il existe beaucoup de raccourcis claviers très utiles pour manipuler 252 | les listes mais le plus important d'entre eux est sûrement *M-* 253 | qui permet de passer à la ligne en ajoutant une nouvelle entrée à la 254 | liste. 255 | 256 | Pour plus d'information sur les listes et les raccourcis associés, se 257 | reporter à la section [[http://orgmode.org/manual/Plain-lists.html#Plain-lists][Plain lists]] de la documentation officielle. 258 | ** Drawers [[#marqueurs]] 259 | TODO http://orgmode.org/manual/Drawers.html#Drawers 260 | ** Blocks 261 | ** Footnotes 262 | ** The Orgstruct minor mode 263 | 264 | 265 | * Tables <> 266 | ** The built-in table editor 267 | ** Column width and alignment 268 | ** Column groups 269 | ** The Orgtbl minor mode 270 | ** The spreadsheet 271 | *** References 272 | *** Formula syntax for Calc 273 | *** Emacs Lisp forms as formulas 274 | *** Field formulas 275 | *** Column formulas 276 | *** Editing and debugging formulas 277 | *** Updating the table 278 | *** Advanced features 279 | ** Org-Plot 280 | 281 | 282 | * Hyperlinks 283 | **Link format 284 | ** Internal links 285 | *** Radio targets 286 | ** External links 287 | ** Handling links 288 | ** Using links outside Org 289 | ** Link abbreviations 290 | ** Search options in file links 291 | ** Custom Searches 292 | 293 | 294 | * TODO Items 295 | ** Basic TODO functionality 296 | ** Extended use of TODO keywords 297 | *** TODO keywords as workflow states 298 | *** TODO keywords as types 299 | *** Multiple keyword sets in one file 300 | *** Fast access to TODO states 301 | *** Setting up keywords for individual files 302 | *** Faces for TODO keywords 303 | *** TODO dependencies 304 | ** Progress logging 305 | *** Closing items 306 | *** Tracking TODO state changes 307 | *** Tracking your habits 308 | ** Priorities 309 | ** Breaking tasks down into subtasks 310 | ** Checkboxes 311 | 312 | 313 | * Tags 314 | ** Tag inheritance 315 | ** Setting tags 316 | ** Tag searches 317 | 318 | 319 | * Propriétés et colonnes 320 | ** Syntaxe des propriétés 321 | Les propriétés sont des paires clé-valeur. Elles doivent être 322 | insérées entre des marqueurs spéciaux (voir [[#marqueurs][Marqueurs]]) dont le nom 323 | est /PROPERTIES/. Chaque propriété est spécifiée sur une seule ligne, avec la 324 | clé (entouré par deux-points) suivie de sa valeur. Voici un 325 | exemple : 326 | 327 | : * CD collection 328 | : ** Classic 329 | : *** Goldberg Variations 330 | : :PROPERTIES: 331 | : :Title: Goldberg Variations 332 | : :Composer: J.S. Bach 333 | : :Artist: Glen Gould 334 | : :Publisher: Deutsche Grammophon 335 | : :NDisks: 1 336 | : :END: 337 | 338 | Il est possible de définir les valeurs autorisées pour une 339 | propriété donnée, disons ':xyz:', en définissant une propriété 340 | ':xyz_ALL:'. Cette propriété particulière est héritée sur la 341 | suite de l'arborescence. Lorsque les valeurs autorisées sont 342 | définies, il devient plus facile d'insérer les propriétés et cela 343 | évite les erreurs de frappe. 344 | Pour l'exemple, pour une collection de CD, on peut prédéfinir 345 | les éditeurs et le nombre de disques dans une boîte comme ceci: 346 | 347 | : * CD collection 348 | : :PROPERTIES: 349 | : :NDisks_ALL: 1 2 3 4 350 | : :Publisher_ALL: "Deutsche Grammophon" Philips EMI 351 | : :END: 352 | 353 | Si l'on souhaite définir des propriétés héritées sur l'ensemble du 354 | fichier, utilisez une ligne comme 355 | 356 | : #+PROPERTY: NDisks_ALL 1 2 3 4 357 | 358 | Les valeurs de propriétés définies dans le variable global 359 | 'org-global-properties' sont héritées dans tous les fichiers Org. 360 | 361 | Les raccourcis claviers suivant facilite le travail avec les 362 | propriétés: 363 | 364 | - *M-* :: 365 | Après un « : » en début de ligne, complète avec toutes les clefs 366 | de propriétés accessible dans le fichier courant. 367 | - *C-c C-x p* :: 368 | Sollicite la saisie du nom d'une propriétés et de sa valeur. 369 | - *C-c C-c* :: 370 | Quand le curseur est sur un marqueur de propriétés, cela exécute 371 | des commandes de la propriété. 372 | - *C-c C-c s* :: 373 | Définit une propriété dans l'entrée actuelle. Propriété et valeur 374 | peuvent être insérés à l'aide du complètement de code. 375 | - *S-/* :: 376 | Place la propriété du point courant à la valeur possible précédente/suivante. 377 | - *C-c C-c d* :: 378 | Supprime une propriété de l'entrée courante. 379 | - *C-c C-c D* :: 380 | Supprime une propriété dans toutes les entrées du ficher courant. 381 | - *C-c C-c c* :: 382 | Compute the property at point, using the operator and scope from 383 | the nearest column format definition. (si quelqu'un comprend…) 384 | 385 | ** Propriétés spéciales 386 | Des propriétés spéciales fournissent une méthode alternative d'accès aux 387 | caractéristiques du mode Org, comme l'état « TODO » ou la priorité d'une 388 | entrée, examinées dans les chapitres précédents. Cette interface existe 389 | pour pouvoir inclure ces états dans une vue en colonne (voir 390 | [[*Vue en colonne][Vue en colonne]]), ou de les utiliser dans des requêtes. Les noms des 391 | propriétés suivantes sont particulières et ne devraient pas être 392 | utilisés comme clés dans un marqueur de propriété : 393 | 394 | : TODO The TODO keyword of the entry. 395 | : TAGS The tags defined directly in the headline. 396 | : ALLTAGS All tags, including inherited ones. 397 | : CATEGORY The category of an entry. 398 | : PRIORITY The priority of the entry, a string with a single letter. 399 | : DEADLINE The deadline time string, without the angular brackets. 400 | : SCHEDULED The scheduling timestamp, without the angular brackets. 401 | : CLOSED When was this entry closed? 402 | : TIMESTAMP The first keyword-less timestamp in the entry. 403 | : TIMESTAMP_IA The first inactive timestamp in the entry. 404 | : CLOCKSUM The sum of CLOCK intervals in the subtree. org-clock-sum 405 | : must be run first to compute the values. 406 | : ITEM The content of the entry. 407 | 408 | 409 | ** Property searches 410 | ** Property Inheritance 411 | 412 | ** Vue en colonne 413 | Par exemple la structure suivante: 414 | : ** My project 415 | : :PROPERTIES: 416 | : :COLUMNS: %20ITEM %9Approved(Approved?){X} %Owner %11Status %10Time_Spent{:} 417 | : :Owner_ALL: Tammy Mark Karl Lisa Don 418 | : :Status_ALL: "In progress" "Not started yet" "Finished" "" 419 | : :Approved_ALL: "[ ]" "[X]" 420 | : :END: 421 | : 422 | : *** Item 1 423 | : :PROPERTIES: 424 | : :Owner: Tammy 425 | : :Time_spent: 1:45 426 | : :Status: Finished 427 | : :END: 428 | : 429 | : *** Item 2 430 | : :PROPERTIES: 431 | : :Owner: Tammy 432 | : :Status: In progress 433 | : :Time_spent: 0:15 434 | : :END: 435 | : 436 | : *** Item 3 437 | : :PROPERTIES: 438 | : :Owner: Lisa 439 | : :Status: Not started yet 440 | : :Approved: [X] 441 | : :END: 442 | 443 | Donnera ceci dans une vue en colonne: 444 | 445 | [[file:res/column1-r.png]] 446 | 447 | En mode replié: 448 | 449 | [[file:res/column2-r.png]] 450 | 451 | Pour plus d'information, voir [[http://orgmode.org/worg/org-tutorials/org-column-view-tutorial.php][ce tutoriel]]. 452 | 453 | *** Defining columns 454 | **** Scope of column definitions 455 | **** Column attributes 456 | *** Using column view 457 | *** Capturing column view 458 | ** The Property 459 | 460 | * Dates and Times 461 | 462 | ** Timestamps, deadlines, and scheduling 463 | ** Creating timestamps 464 | *** The date/time prompt 465 | *** Custom time format 466 | ** Deadlines and scheduling 467 | *** Inserting deadlines or schedules 468 | *** Repeated tasks 469 | ** Clocking work time 470 | ** Resolving idle time 471 | ** Effort estimates 472 | ** Taking notes with a relative timer 473 | 474 | 475 | * Capture - Refile - Archive 476 | ** Remember 477 | *** Setting up Remember for Org 478 | *** Remember templates 479 | *** Storing notes 480 | ** Attachments 481 | ** RSS feeds 482 | ** Protocols for external access 483 | ** Refiling notes 484 | ** Archiving 485 | *** Moving a tree to the archive file 486 | *** Internal archiving 487 | 488 | 489 | * Agenda Views 490 | 491 | ** Agenda files 492 | ** The agenda dispatcher <> 493 | ** The built-in agenda views 494 | *** The weekly/daily agenda 495 | *** The global TODO list 496 | *** Matching tags and properties 497 | *** Timeline for a single file 498 | *** Search view 499 | *** Stuck projects 500 | ** Presentation and sorting 501 | *** Categories 502 | *** Time-of-day specifications 503 | *** Sorting of agenda items 504 | ** Commands in the agenda buffer 505 | ** Custom agenda views 506 | *** Storing searches 507 | *** Block agenda 508 | *** Setting options for custom commands 509 | ** Exporting Agenda Views 510 | ** Using column view in the agenda 511 | 512 | 513 | * Markup for rich export 514 | ** Structural markup elements 515 | ** Images and Tables 516 | ** Literal examples 517 | ** Include files 518 | ** Macro replacement 519 | ** Embedded LaTeX 520 | *** Special symbols 521 | *** Subscripts and superscripts 522 | *** LaTeX fragments 523 | *** Previewing LaTeX fragments 524 | *** Using CDLaTeX to enter math 525 | 526 | 527 | * Exporting 528 | ** Selective export 529 | ** Export options 530 | ** The export dispatcher 531 | ** ASCII export 532 | ** HTML export 533 | *** HTML export commands 534 | *** Quoting HTML tags 535 | *** Links in HTML export 536 | *** Tables 537 | *** Images in HTML export 538 | *** Text areas in HTML export 539 | *** CSS support 540 | *** Javascript supported display of web pages 541 | ** LaTeX and PDF export 542 | *** LaTeX export commands 543 | *** Quoting LaTeX code 544 | *** Sectioning structure 545 | *** Tables in LaTeX export 546 | *** Images in LaTeX export 547 | *** Beamer class export 548 | ** DocBook export 549 | *** DocBook export commands 550 | *** Quoting DocBook code 551 | *** Recursive sections 552 | *** Tables in DocBook export 553 | *** Images in DocBook export 554 | *** Special characters in DocBook export 555 | ** Freemind export 556 | ** XOXO export 557 | ** iCalendar export 558 | 559 | 560 | * Publishing 561 | ** Configuration 562 | *** The variable org-publish-project-alist 563 | *** Sources and destinations for files 564 | *** Selecting files 565 | *** Publishing action 566 | *** Options for the HTML/LaTeX exporters 567 | *** Links between published files 568 | *** Project page index 569 | ** Uploading files 570 | ** Sample configuration 571 | *** Example: simple publishing configuration 572 | *** Example: complex publishing configuration 573 | ** Triggering publication 574 | 575 | 576 | * Miscellaneous 577 | ** Completion 578 | ** Speed keys 579 | ** Customization 580 | ** Summary of in-buffer settings 581 | ** The very busy C-c C-c key 582 | ** A cleaner outline view 583 | ** Using Org on a tty 584 | ** Interaction with other packages 585 | *** Packages that Org cooperates with 586 | *** Packages that lead to conflicts with Org mode 587 | 588 | 589 | * Appendix A Hacking 590 | ** Hooks 591 | ** Add-on packages 592 | ** Adding hyperlink types 593 | ** Context-sensitive commands 594 | ** Tables and lists in arbitrary syntax 595 | *** Radio tables 596 | *** A LaTeX example of radio tables 597 | *** Translator functions 598 | *** Radio lists 599 | ** Dynamic blocks 600 | ** Special agenda views 601 | ** Extracting agenda information 602 | ** Using the property API 603 | ** Using the mapping API 604 | 605 | 606 | * Appendix B MobileOrg 607 | ** Setting up the staging area 608 | ** Pushing to MobileOrg 609 | ** Pulling from MobileOrg 610 | 611 | 612 | * Appendix C History and Acknowledgments 613 | 614 | * Concept Index 615 | 616 | * Key Index 617 | 618 | * Variable Index 619 | -------------------------------------------------------------------------------- /PyOrgMode_test.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | ############################################################################## 3 | # 4 | # PyOrgMode, a python module for treating with orgfiles 5 | # Copyright (C) 2010 Jonathan BISSON (bissonjonathan on the google thing). 6 | # All Rights Reserved 7 | # 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | # 21 | ############################################################################## 22 | 23 | """ 24 | The PyOrgMode class is able to read,modify and create orgfiles. The internal 25 | representation of the file allows the use of orgfiles easily in your projects. 26 | """ 27 | 28 | import re 29 | import string 30 | import copy 31 | import time 32 | 33 | class OrgDate: 34 | """Functions for date management""" 35 | 36 | format = 0 37 | TIMED = 1 38 | DATED = 2 39 | WEEKDAYED = 4 40 | ACTIVE = 8 41 | INACTIVE = 16 42 | RANGED = 32 43 | REPEAT = 64 44 | 45 | # TODO: Timestamp with repeater interval 46 | DICT_RE = {'start': '[[<]', 47 | 'end': '[]>]', 48 | 'date': '([0-9]{4})-([0-9]{2})-([0-9]{2})(\s+([\w]+))?', 49 | 'time': '([0-9]{2}):([0-9]{2})', 50 | 'repeat': '[\+\.]{1,2}\d+[dwmy]'} 51 | 52 | def __init__(self,value=None): 53 | """ 54 | Initialisation of an OrgDate element. 55 | """ 56 | if value != None: 57 | self.set_value(value) 58 | 59 | def parse_datetime(self, s): 60 | """ 61 | Parses an org-mode date time string. 62 | Returns (timed, weekdayed, time_struct, repeat). 63 | """ 64 | search_re = '(?P{date})(\s+(?P