diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/README.markdown b/README.markdown index 7220c9f..d677ce5 100644 --- a/README.markdown +++ b/README.markdown @@ -2,6 +2,11 @@ As it was suggested on issue [#28](https://github.com/freitass/todo.txt-vim/issues/28) (and as recommended by vim's documentation), all mappings were changed to use `` instead of ``. If you don't have `maplocalleader` set on your environment then yours is probably `\`. For more information on that regard, please take a look at `:h `. +### (Jan 2016) Note: Overdue date highlight and Python Optional dependency + +A new feature was added to highlight dates in overdue tasks as an Error (as suggested on issue [#44][https://github.com/freitass/todo.txt-vim/issues/44]). It depends on a Python library, however, and as such will only be able to work if your version of Vim was compiled with the `+python` option (as most common versions do). + +If your Vim installation does **not** have Python support, this plugin **will work just fine** but this feature will be disabled. ### Quick install @@ -17,6 +22,7 @@ Sorting tasks: `s+` Sort the file on +Projects `s@` Sort the file on @Contexts `sd` Sort the file on dates +`sdd` Sort the file on due dates Edit priority: `j` Decrease the priority of the current line diff --git a/syntax/python/dateregex/dateregex/__init__.py b/syntax/python/dateregex/dateregex/__init__.py new file mode 100644 index 0000000..cfbc141 --- /dev/null +++ b/syntax/python/dateregex/dateregex/__init__.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# File: __init__.py +# Author: Guilherme Victal +# Description: Dateregex library entry point +# License: Vim license +# Website: http://github.com/freitass/todo.txt-vim +# Version: 0.1 + +from after import regex_date_after +from before import regex_date_before diff --git a/syntax/python/dateregex/dateregex/after.py b/syntax/python/dateregex/dateregex/after.py new file mode 100644 index 0000000..8a13574 --- /dev/null +++ b/syntax/python/dateregex/dateregex/after.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# File: after.py +# Author: Guilherme Victal +# Description: Generates regexes after a certain date +# License: Vim license +# Website: http://github.com/freitass/todo.txt-vim +# Version: 0.1 + +from datetime import date, timedelta, MAXYEAR + + +def _year_regex_after(year): + if int(year) > MAXYEAR: + return None + + year_regex = r'(\d+\d{%s}' % len(year) + for idx, digit in enumerate(year): + if digit != '9': + regex = '|' + year[0:idx] + regex += '9' if digit == '8' else '[%s-9]' % str(int(digit) + 1) + if idx < len(year) - 1: + regex += '\d{%s}' % (len(year) - (idx + 1)) + year_regex += regex + + year_regex += ')' + return '-'.join((year_regex, r'\d{2}', r'\d{2}')) + + +def _month_regex_after(year, month): + if month == '12': + return None + + digit1, digit2 = month + if digit1 == '1': + month_regex = r'12' if month == '11' else r'1[12]' + else: + month_regex = r'1[0-2]' + if digit2 != '9': + if digit2 == '8': + month_regex = r'(' + month_regex + r'|09)' + else: + month_regex = r'(' + month_regex + r'|0[%s-9])' + month_regex = month_regex % str(int(digit2) + 1) + return '-'.join((year, month_regex, r'\d{2}')) + +def _day_regex_after(year, month, day): + last_month_day = str((date(int(year), (int(month) + 1) % 12, 1) + - date.resolution).day) + if day == last_month_day: + return None + day_regex = r'(' + digit1, digit2 = day + last_digit1, last_digit2 = last_month_day + if digit1 == last_digit1: + day_regex = last_month_day if int(digit2) == int(last_digit2) - 1 else last_digit1 + r'[%s-%s]' % (str(int(digit2) + 1), last_digit2) + else: + day_regex = r'(' + day_regex += last_digit1 if int(digit1) == int(last_digit1) - 1 else r'[%s-%s]' % (str(int(digit1) + 1), last_digit1) + day_regex +=r'\d' + if digit2 < '9': + day_regex += '|' + digit1 + day_regex += '9' if digit2 == '8' else r'[%s-9]' % str(int(digit2) + 1) + + day_regex += ')' + return '-'.join((year, month, day_regex)) + + +def regex_date_after(given_date): + year, month, day = given_date.isoformat().split('-') + + year_regex = _year_regex_after(year) + month_regex = _month_regex_after(year, month) + day_regex = _day_regex_after(year, month, day) + + date_regex = '(' + year_regex if year_regex else '(' + date_regex += ('|' + month_regex) if month_regex else '' + date_regex += ('|' + day_regex) if day_regex else '' + date_regex += ')' + return date_regex + + +def __main(): + import re + date_regex = regex_date_after(date(1999,12,31)) + print(date_regex) + pattern = re.compile(date_regex) + + + d = date.today() + date.resolution + assert pattern.match(date.strftime(d, '%Y-%m-%d')) is not None + print(date.strftime(d, '%Y-%m-%d') + ' is okay') + d += date.resolution + +if __name__ == '__main__': + __main() diff --git a/syntax/python/dateregex/dateregex/before.py b/syntax/python/dateregex/dateregex/before.py new file mode 100644 index 0000000..8a3402e --- /dev/null +++ b/syntax/python/dateregex/dateregex/before.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# File: before.py +# Author: Guilherme Victal +# Description: Generates regexes before a certain date +# License: Vim license +# Website: http://github.com/freitass/todo.txt-vim +# Version: 0.1 + +from datetime import date, timedelta, MINYEAR + +def _year_regex_before(year): + if int(year) <= MINYEAR: + return None + year_regex = r'(' + year_regex += r'\d{1,%s}' % str(len(year) - 1) if len(year) > 1 else '' + for idx, digit in enumerate(year): + if digit != '0': + regex = '|' + year[0:idx] + regex += '0' if digit == '1' else '[0-%s]' % str(int(digit) - 1) + if idx < len(year) - 1: + regex += '\d{%s}' % (len(year) - (idx + 1)) + year_regex += regex + + year_regex += ')' + return '-'.join((year_regex, r'\d{2}', r'\d{2}')) + +def _month_regex_before(year, month): + if month == '01': + return None + + digit1, digit2 = month + if digit1 == '0': + month_regex = '01' if month == '02' else r'0[1-%s]' % str(int(digit2) - 1) + elif month == '10': + month_regex = r'0\d' + elif month == '11': + month_regex = r'(0\d|10)' + else: + month_regex = r'(0\d|1[01])' + + return '-'.join((year, month_regex, r'\d{2}')) + +def _day_regex_before(year, month, day): + if day == '01': + return None + last_month_day = str((date(int(year), (int(month) + 1) % 12, 1) + - date.resolution).day) + last_digit1, last_digit2 = last_month_day + + digit1, digit2 = day + if digit1 == '0': + day_regex = '01' if day == '02' else r'0[1-%s]' % str(int(digit2) - 1) + else: + day_regex = r'(' + day_regex += '0' if digit1 == '1' else r'[0-%s]' % str(int(digit1) - 1) + day_regex += r'\d' + if digit2 != '0': + day_regex += '|' + day_regex += digit1 + day_regex += '0' if digit2 == '1' else r'[0-%s]' % str(int(digit2) - 1) + day_regex += ')' + + return '-'.join((year, month, day_regex)) + + + + +def regex_date_before(given_date): + year, month, day = given_date.isoformat().split('-') + + year_regex = _year_regex_before(year) + month_regex = _month_regex_before(year, month) + day_regex = _day_regex_before(year, month, day) + + date_regex = '(' + year_regex if year_regex else '(' + date_regex += ('|' + month_regex) if month_regex else '' + date_regex += ('|' + day_regex) if day_regex else '' + date_regex += ')' + return date_regex diff --git a/syntax/python/todo.py b/syntax/python/todo.py new file mode 100644 index 0000000..36d0d9d --- /dev/null +++ b/syntax/python/todo.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +# File: todo.py +# Description: Todo.txt overdue date syntax script +# License: Vim license +# Website: http://github.com/freitass/todo.txt-vim +# Version: 0.1 + +import vim +import os +import sys +from datetime import date + +dateregex_dir = os.path.join(vim.eval('s:script_dir'), 'dateregex') +if os.path.isdir(dateregex_dir): + sys.path.insert(0, dateregex_dir) + +def add_due_date_syntax_highlight(): + try: + from dateregex import regex_date_before + except ImportError: + print("dateregex module not found. Overdue dates won't be highlighted") + return + + regex = regex_date_before(date.today()) + regex = r'(^|<)due:%s(>|$)' % regex + + vim.command("syntax match OverDueDate '\\v%s'" % regex) + vim.command("highlight default link OverDueDate Error") + +add_due_date_syntax_highlight() diff --git a/syntax/todo.vim b/syntax/todo.vim index eabcd9f..f7c5105 100644 --- a/syntax/todo.vim +++ b/syntax/todo.vim @@ -9,33 +9,34 @@ if exists("b:current_syntax") finish endif -syntax match TodoDone '^[xX]\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityA '^([aA])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityB '^([bB])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityC '^([cC])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityD '^([dD])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityE '^([eE])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityF '^([fF])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityG '^([gG])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityH '^([hH])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityI '^([iI])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityJ '^([jJ])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityK '^([kK])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityL '^([lL])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityM '^([mM])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityN '^([nN])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityO '^([oO])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityP '^([pP])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityQ '^([qQ])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityR '^([rR])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityS '^([sS])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityT '^([tT])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityU '^([uU])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityV '^([vV])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityW '^([wW])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityX '^([xX])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityY '^([yY])\s.\+$' contains=TodoDate,TodoProject,TodoContext -syntax match TodoPriorityZ '^([zZ])\s.\+$' contains=TodoDate,TodoProject,TodoContext +syntax match TodoDone '^[xX]\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityA '^([aA])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityB '^([bB])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityC '^([cC])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityD '^([dD])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityE '^([eE])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityF '^([fF])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityG '^([gG])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityH '^([hH])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityI '^([iI])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityJ '^([jJ])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityK '^([kK])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityL '^([lL])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityM '^([mM])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityN '^([nN])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityO '^([oO])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityP '^([pP])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityQ '^([qQ])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityR '^([rR])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityS '^([sS])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityT '^([tT])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityU '^([uU])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityV '^([vV])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityW '^([wW])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityX '^([xX])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityY '^([yY])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate +syntax match TodoPriorityZ '^([zZ])\s.\+$' contains=TodoDate,TodoProject,TodoContext,OverDueDate + syntax match TodoDate '\d\{2,4\}-\d\{2\}-\d\{2\}' contains=NONE syntax match TodoProject '\(^\|\W\)+[^[:blank:]]\+' contains=NONE syntax match TodoContext '\(^\|\W\)@[^[:blank:]]\+' contains=NONE @@ -49,4 +50,12 @@ highlight default link TodoDate PreProc highlight default link TodoProject Special highlight default link TodoContext Special +if has('python') + let b:curdir = expand(':p:h') + let s:script_dir = b:curdir . "/python/" + execute "pyfile " . s:script_dir. "todo.py" +else + echom "Your version of vim has no python support. Overdue dates won't be highlighted" +endif + let b:current_syntax = "todo"