From d694d764ca9e079c542f0f865b5664139ea6f912 Mon Sep 17 00:00:00 2001 From: Dmitry Tomp Date: Fri, 26 May 2023 10:53:34 +0900 Subject: [PATCH 1/4] First version --- ftplugin/orgmode/liborgmode/headings.py | 3 ++ ftplugin/orgmode/liborgmode/orgdate.py | 42 +++++++++++++++++++++++++ ftplugin/orgmode/plugins/Agenda.py | 29 ++++++++++------- syntax/orgagenda.vim | 12 +++++++ 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/ftplugin/orgmode/liborgmode/headings.py b/ftplugin/orgmode/liborgmode/headings.py index d0d1d083..75969862 100644 --- a/ftplugin/orgmode/liborgmode/headings.py +++ b/ftplugin/orgmode/liborgmode/headings.py @@ -460,6 +460,9 @@ def parse_title(heading_line): else: new_heading.active_date = None + if new_heading.tags: + with open('/tmp/orgdebug.txt', 'a') as f: + print('Found tags', new_heading, file=f) return new_heading def update_subtasks(self, total=0, on=0): diff --git a/ftplugin/orgmode/liborgmode/orgdate.py b/ftplugin/orgmode/liborgmode/orgdate.py index b2365069..d842e8e3 100644 --- a/ftplugin/orgmode/liborgmode/orgdate.py +++ b/ftplugin/orgmode/liborgmode/orgdate.py @@ -175,6 +175,24 @@ def __init__(self, active, year, month, day): self.active = active pass + def _cast_to_datetime_to_compare(self): + now = datetime.datetime.now() + today = now.date() + time_to_add = now.time() if today == self else datetime.time(0, 0) if today < self else datetime.time(23, 59) + return datetime.datetime.combine(self, time_to_add) + + def __le__(self, other): + return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__le__(other) + + def __lt__(self, other): + return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__lt__(other) + + def __ge__(self, other): + return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__ge__(other) + + def __gt__(self, other): + return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__gt__(other) + def __new__(cls, active, year, month, day): return datetime.date.__new__(cls, year, month, day) @@ -190,6 +208,12 @@ def __unicode__(self): def __str__(self): return u_encode(self.__unicode__()) + def timestr(self): + return '--:--' + + def date(self): + return self + def strftime(self, fmt): return u_decode(datetime.date.strftime(self, u_encode(fmt))) @@ -210,6 +234,18 @@ def __init__(self, active, year, month, day, hour, mins): def __new__(cls, active, year, month, day, hour, minute): return datetime.datetime.__new__(cls, year, month, day, hour, minute) + def __le__(self, other): + return super(OrgDateTime, self).__le__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) + + def __lt__(self, other): + return super(OrgDateTime, self).__lt__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) + + def __ge__(self, other): + return super(OrgDateTime, self).__ge__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) + + def __gt__(self, other): + return super(OrgDateTime, self).__gt__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) + def __unicode__(self): u""" Return a string representation. @@ -222,6 +258,12 @@ def __unicode__(self): def __str__(self): return u_encode(self.__unicode__()) + def timestr(self): + return self.strftime('%H:%M') + + def date(self): + return OrgDate(self.active, self.year, self.month, self.day) + def strftime(self, fmt): return u_decode(datetime.datetime.strftime(self, u_encode(fmt))) diff --git a/ftplugin/orgmode/plugins/Agenda.py b/ftplugin/orgmode/plugins/Agenda.py index ed5faa65..017c7f21 100644 --- a/ftplugin/orgmode/plugins/Agenda.py +++ b/ftplugin/orgmode/plugins/Agenda.py @@ -171,32 +171,39 @@ def list_next_week_for(cls, agenda_documents): # It's easy to jump to the right document this way cls.line2doc = {} # format text for agenda - last_date = raw_agenda[0].active_date - final_agenda = [u'Week Agenda:', unicode(last_date)] + last_date = None + final_agenda = [u'Week Agenda:'] for i, h in enumerate(raw_agenda): # insert date information for every new date (not datetime) - if unicode(h.active_date)[1:11] != unicode(last_date)[1:11]: + active_date_no_time = h.active_date.date() + if active_date_no_time != last_date: today = date.today() # insert additional "TODAY" string - if h.active_date.year == today.year and \ - h.active_date.month == today.month and \ - h.active_date.day == today.day: - section = unicode(h.active_date) + u" TODAY" + if active_date_no_time == today: + section = unicode(active_date_no_time) + u" TODAY" today_row = len(final_agenda) + 1 else: - section = unicode(h.active_date) + section = unicode(active_date_no_time) final_agenda.append(section) # update last_date - last_date = h.active_date + last_date = active_date_no_time + + p = h + tags = [] + while p is not None: + tags += p.tags + p = p.parent bufname = os.path.basename(vim.buffers[h.document.bufnr].name) bufname = bufname[:-4] if bufname.endswith(u'.org') else bufname - formatted = u" %(bufname)s (%(bufnr)d) %(todo)s %(title)s" % { + formatted = u" %(bufname)s (%(bufnr)d) %(todo)s %(timestr)s %(title)s %(tags)s" % { 'bufname': bufname, 'bufnr': h.document.bufnr, 'todo': h.todo, - 'title': h.title + 'timestr': h.active_date.timestr(), + 'title': h.title, + 'tags': ':' + ':'.join(tags) + ':' if tags else '' } final_agenda.append(formatted) cls.line2doc[len(final_agenda)] = (get_bufname(h.document.bufnr), h.document.bufnr, h.start) diff --git a/syntax/orgagenda.vim b/syntax/orgagenda.vim index 3ea4fad5..1207c6c8 100644 --- a/syntax/orgagenda.vim +++ b/syntax/orgagenda.vim @@ -5,6 +5,18 @@ syn match org_todo_key /\[\zs[^]]*\ze\]/ hi def link org_todo_key Identifier +" ['Title', 'Constant', 'Statement', 'Type', 'Special'] +syn match org_tag_1 /:[a-iA-I][^: ]*:/hs=s+1,me=e-1 +syn match org_tag_2 /:[j-rJ-R][^: ]*:/hs=s+1,me=e-1 +syn match org_tag_3 /:[s-zS-Z0][^: ]*:/hs=s+1,me=e-1 +syn match org_tag_4 /:[1-9_][^: ]*:/hs=s+1,me=e-1 +syn match org_tag_5 /:[\W][^: ]*:/hs=s+1,me=e-1 +hi def link org_tag_1 Title +hi def link org_tag_2 Constant +hi def link org_tag_3 Statement +hi def link org_tag_4 Type +hi def link org_tag_5 Special + let s:todo_headings = '' let s:i = 1 while s:i <= g:org_heading_highlight_levels From 4a9fb702d997c3f21e6276ec8a18aeff0eac6cd2 Mon Sep 17 00:00:00 2001 From: Dmitry Tomp Date: Tue, 13 Jun 2023 16:27:56 +0900 Subject: [PATCH 2/4] Prepare for a PR --- ftplugin/orgmode/liborgmode/agenda.py | 27 +++++++++++++++++++--- ftplugin/orgmode/liborgmode/headings.py | 3 --- ftplugin/orgmode/liborgmode/orgdate.py | 30 ------------------------- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/ftplugin/orgmode/liborgmode/agenda.py b/ftplugin/orgmode/liborgmode/agenda.py index d19e8c7d..0bc31694 100644 --- a/ftplugin/orgmode/liborgmode/agenda.py +++ b/ftplugin/orgmode/liborgmode/agenda.py @@ -16,7 +16,28 @@ from orgmode.liborgmode.agendafilter import is_within_week_and_active_todo from orgmode.liborgmode.agendafilter import contains_active_todo from orgmode.liborgmode.agendafilter import contains_active_date +from orgmode.liborgmode.orgdate import OrgDateTime, OrgTimeRange +import datetime +def agenda_sorting_key(heading): + orgtime = heading.active_date + if orgtime is None or isinstance(orgtime, OrgDateTime): + return orgtime + if isinstance(orgtime, OrgTimeRange): + return orgtime.start + + # Then it is an OrgDate. OrgDate cannot be compared with datetime-based Org* values + # by default, so it will be converted in such a way that: + # * OrgDate value of _today_ will be displayed after today's passed events and before + # today's upcoming scheduled events. + # * OrgDate value of a past day will be displayed after all other items of the same + # day. + # * OrgDate value of a future day will be displayed before all other items of the same + # day. + now = datetime.datetime.now() + today = now.date() + time_to_add = now.time() if today == orgtime else datetime.time(0, 0) if today < orgtime else datetime.time(23, 59) + return datetime.datetime.combine(orgtime, time_to_add) class AgendaManager(object): u"""Simple parsing of Documents to create an agenda.""" @@ -34,7 +55,7 @@ def get_todo(self, documents): # filter and return headings filtered.extend(filter_items(document.all_headings(), [contains_active_todo])) - return sorted(filtered) + return sorted(filtered, key=agenda_sorting_key) def get_next_week_and_active_todo(self, documents): u""" @@ -46,7 +67,7 @@ def get_next_week_and_active_todo(self, documents): # filter and return headings filtered.extend(filter_items(document.all_headings(), [is_within_week_and_active_todo])) - return sorted(filtered) + return sorted(filtered, key=agenda_sorting_key) def get_timestamped_items(self, documents): u""" @@ -58,4 +79,4 @@ def get_timestamped_items(self, documents): # filter and return headings filtered.extend(filter_items(document.all_headings(), [contains_active_date])) - return sorted(filtered) + return sorted(filtered, key=agenda_sorting_key) diff --git a/ftplugin/orgmode/liborgmode/headings.py b/ftplugin/orgmode/liborgmode/headings.py index 75969862..d0d1d083 100644 --- a/ftplugin/orgmode/liborgmode/headings.py +++ b/ftplugin/orgmode/liborgmode/headings.py @@ -460,9 +460,6 @@ def parse_title(heading_line): else: new_heading.active_date = None - if new_heading.tags: - with open('/tmp/orgdebug.txt', 'a') as f: - print('Found tags', new_heading, file=f) return new_heading def update_subtasks(self, total=0, on=0): diff --git a/ftplugin/orgmode/liborgmode/orgdate.py b/ftplugin/orgmode/liborgmode/orgdate.py index d842e8e3..5ac229c5 100644 --- a/ftplugin/orgmode/liborgmode/orgdate.py +++ b/ftplugin/orgmode/liborgmode/orgdate.py @@ -175,24 +175,6 @@ def __init__(self, active, year, month, day): self.active = active pass - def _cast_to_datetime_to_compare(self): - now = datetime.datetime.now() - today = now.date() - time_to_add = now.time() if today == self else datetime.time(0, 0) if today < self else datetime.time(23, 59) - return datetime.datetime.combine(self, time_to_add) - - def __le__(self, other): - return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__le__(other) - - def __lt__(self, other): - return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__lt__(other) - - def __ge__(self, other): - return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__ge__(other) - - def __gt__(self, other): - return (super(OrgDate, self) if not isinstance(other, datetime.datetime) else self._cast_to_datetime_to_compare()).__gt__(other) - def __new__(cls, active, year, month, day): return datetime.date.__new__(cls, year, month, day) @@ -234,18 +216,6 @@ def __init__(self, active, year, month, day, hour, mins): def __new__(cls, active, year, month, day, hour, minute): return datetime.datetime.__new__(cls, year, month, day, hour, minute) - def __le__(self, other): - return super(OrgDateTime, self).__le__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) - - def __lt__(self, other): - return super(OrgDateTime, self).__lt__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) - - def __ge__(self, other): - return super(OrgDateTime, self).__ge__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) - - def __gt__(self, other): - return super(OrgDateTime, self).__gt__(other._cast_to_datetime_to_compare() if isinstance(other, OrgDate) else other) - def __unicode__(self): u""" Return a string representation. From 7e738f9beea1e2c856c9a73abf13cf62421bf9ad Mon Sep 17 00:00:00 2001 From: Dmitry Tomp Date: Tue, 13 Jun 2023 17:20:52 +0900 Subject: [PATCH 3/4] Add date function --- ftplugin/orgmode/liborgmode/orgdate.py | 3 +++ syntax/orgagenda.vim | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ftplugin/orgmode/liborgmode/orgdate.py b/ftplugin/orgmode/liborgmode/orgdate.py index 5ac229c5..91fdc03c 100644 --- a/ftplugin/orgmode/liborgmode/orgdate.py +++ b/ftplugin/orgmode/liborgmode/orgdate.py @@ -304,3 +304,6 @@ def __unicode__(self): def __str__(self): return u_encode(self.__unicode__()) + + def date(self): + return OrgDate(self.active, self.start.year, self.start.month, self.start.day) diff --git a/syntax/orgagenda.vim b/syntax/orgagenda.vim index 1207c6c8..32f66cdc 100644 --- a/syntax/orgagenda.vim +++ b/syntax/orgagenda.vim @@ -5,7 +5,7 @@ syn match org_todo_key /\[\zs[^]]*\ze\]/ hi def link org_todo_key Identifier -" ['Title', 'Constant', 'Statement', 'Type', 'Special'] +" Multi-colored tags in agenda syn match org_tag_1 /:[a-iA-I][^: ]*:/hs=s+1,me=e-1 syn match org_tag_2 /:[j-rJ-R][^: ]*:/hs=s+1,me=e-1 syn match org_tag_3 /:[s-zS-Z0][^: ]*:/hs=s+1,me=e-1 From 938b7083cdc58f2b88a1b94d3f37474921286869 Mon Sep 17 00:00:00 2001 From: Dmitry Tomp Date: Tue, 13 Jun 2023 17:27:41 +0900 Subject: [PATCH 4/4] Add comment --- ftplugin/orgmode/liborgmode/agenda.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ftplugin/orgmode/liborgmode/agenda.py b/ftplugin/orgmode/liborgmode/agenda.py index 0bc31694..149be99b 100644 --- a/ftplugin/orgmode/liborgmode/agenda.py +++ b/ftplugin/orgmode/liborgmode/agenda.py @@ -26,8 +26,8 @@ def agenda_sorting_key(heading): if isinstance(orgtime, OrgTimeRange): return orgtime.start - # Then it is an OrgDate. OrgDate cannot be compared with datetime-based Org* values - # by default, so it will be converted in such a way that: + # It is an OrgDate. OrgDate cannot be compared with datetime-based Org* values by + # default, so it will be converted in such a way that: # * OrgDate value of _today_ will be displayed after today's passed events and before # today's upcoming scheduled events. # * OrgDate value of a past day will be displayed after all other items of the same