Skip to content

Commit

Permalink
Accept multiple bullet types at once; some new ones
Browse files Browse the repository at this point in the history
Add OrgMode/GFM style bullets [ ], [x], [-];
square root symbol for completed tasks;
close #122 close #123
  • Loading branch information
vovkkk committed Jan 23, 2014
1 parent 95673cd commit a83fe56
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 72 deletions.
6 changes: 3 additions & 3 deletions PlainTasks (Linux).sublime-settings
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"open_tasks_bullet": "☐", // options: - | ❍ | ❑ | ■ | □ | ☐ | ▪ | ▫ | – | — ≡ → ›
"done_tasks_bullet": "✔", // options: + | ✓ | ✔
"cancelled_tasks_bullet": "✘", // options: x | ✘
"open_tasks_bullet": "☐", // options: - | ❍ | ❑ | ■ | □ | ☐ | ▪ | ▫ | – | — ≡ → › | [ ]
"done_tasks_bullet": "✔", // options: + | ✓ | ✔ | √ | [x]
"cancelled_tasks_bullet": "✘", // options: x | ✘ | [-]
"before_tasks_bullet_margin": 1,
"date_format": "(%y-%m-%d %H:%M)",
"done_tag": true, // related to @cancelled as well
Expand Down
6 changes: 3 additions & 3 deletions PlainTasks (OSX).sublime-settings
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"open_tasks_bullet": "☐", // options: - | ❍ | ❑ | ■ | □ | ☐ | ▪ | ▫ | – | — ≡ → ›
"done_tasks_bullet": "✔", // options: + | ✓ | ✔
"cancelled_tasks_bullet": "✘", // options: x | ✘
"open_tasks_bullet": "☐", // options: - | ❍ | ❑ | ■ | □ | ☐ | ▪ | ▫ | – | — ≡ → › | [ ]
"done_tasks_bullet": "✔", // options: + | ✓ | ✔ | √ | [x]
"cancelled_tasks_bullet": "✘", // options: x | ✘ | [-]
"before_tasks_bullet_margin": 1,
"date_format": "(%y-%m-%d %H:%M)",
"done_tag": true, // related to @cancelled as well
Expand Down
6 changes: 3 additions & 3 deletions PlainTasks (Windows).sublime-settings
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"open_tasks_bullet": "☐", // options: - | ❍ | ❑ | ■ | □ | ☐ | ▪ | ▫ | – | — ≡ → ›
"done_tasks_bullet": "✔", // options: + | ✓ | ✔
"cancelled_tasks_bullet": "✘", // options: x | ✘
"open_tasks_bullet": "☐", // options: - | ❍ | ❑ | ■ | □ | ☐ | ▪ | ▫ | – | — ≡ → › | [ ]
"done_tasks_bullet": "✔", // options: + | ✓ | ✔ | √ | [x]
"cancelled_tasks_bullet": "✘", // options: x | ✘ | [-]
"before_tasks_bullet_margin": 1,
"date_format": "(%y-%m-%d %H:%M)",
"done_tag": true, // related to @cancelled as well
Expand Down
97 changes: 43 additions & 54 deletions PlainTasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ def runCommand(self, edit):
for region in selections:
line = self.view.line(region)
line_contents = self.view.substr(line).rstrip()
has_bullet = re.match('^(\s*)(' + re.escape(self.open_tasks_bullet) + '|' + re.escape(self.done_tasks_bullet) + '|' + re.escape(self.canc_tasks_bullet) + ')', self.view.substr(line))
not_empty_line = re.match('^(\s*)(\S.+)$', self.view.substr(line))
empty_line = re.match('^(\s+)$', self.view.substr(line))
current_scope = self.view.scope_name(line.a)
if has_bullet:
grps = has_bullet.groups()
if 'item' in current_scope:
grps = not_empty_line.groups()
line_contents = self.view.substr(line) + '\n' + grps[0] + self.open_tasks_bullet + ' '
elif 'header' in current_scope and not self.view.settings().get('header_to_task'):
grps = not_empty_line.groups()
Expand Down Expand Up @@ -90,23 +89,24 @@ def runCommand(self, edit):
except:
done_line_end = ' %s%s%s' % (self.done_tag, self.before_date_space, datetime.now().strftime(self.date_format))
offset = len(done_line_end)
if self.taskpaper_compatible:
rom = '^(\s*)-(\s*[^\b]*\s*)(?!\s@(done|cancelled)).*$'
rdm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@done).*$'
rcm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@cancelled).*$'
else:
rom = '^(\s*)(?:\[\s\]|.)(\s*.*)$'
rdm = '^(\s*)(?:\[x\]|.)(\s*[^\b]*?\s*)(?=\s@done|@project|\s\(|$).*$'
rcm = '^(\s*)(?:\[\-\]|.)(\s*[^\b]*?\s*)(?=\s@cancelled|@project|\s\(|$).*$'
started = '^\s*[^\b]*?\s*@started(\([\d\w,\.:\-\/ @]*\)).*$'
for region in self.view.sel():
line = self.view.line(region)
line_contents = self.view.substr(line).rstrip()
if self.taskpaper_compatible:
rom = '^(\s*)-(\s*[^\b]*\s*)(?!\s@(done|cancelled)).*$'
rdm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@done).*$'
rcm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@cancelled).*$'
else:
rom = '^(\s*)' + re.escape(self.open_tasks_bullet) + '(\s*.*)$'
rdm = '^(\s*)' + re.escape(self.done_tasks_bullet) + '(\s*[^\b]*?\s*)(?=\s@done|@project|\s\(|$).*$'
rcm = '^(\s*)' + re.escape(self.canc_tasks_bullet) + '(\s*[^\b]*?\s*)(?=\s@cancelled|@project|\s\(|$).*$'
started = '^\s*[^\b]*?\s*@started(\([\d\w,\.:\-\/ @]*\)).*$'
open_matches = re.match(rom, line_contents, re.U)
done_matches = re.match(rdm, line_contents, re.U)
canc_matches = re.match(rcm, line_contents, re.U)
started_matches = re.match(started, line_contents, re.U)
if open_matches and not (done_matches or canc_matches):
current_scope = self.view.scope_name(line.a)
if 'pending' in current_scope:
grps = open_matches.groups()
eol = self.view.insert(edit, line.end(), done_line_end)
replacement = u'%s%s%s' % (grps[0], self.done_tasks_bullet, grps[1].rstrip())
Expand All @@ -115,12 +115,12 @@ def runCommand(self, edit):
start = datetime.strptime(started_matches.group(1), self.date_format)
end = datetime.strptime(done_line_end.replace(' @done ', ''), self.date_format)
self.view.insert(edit, line.end() + eol, ' @lasted(%s)' % str(end - start))
elif done_matches:
elif 'completed' in current_scope:
grps = done_matches.groups()
replacement = u'%s%s%s' % (grps[0], self.open_tasks_bullet, grps[1].rstrip())
self.view.replace(edit, line, replacement)
offset = -offset
elif canc_matches:
elif 'cancelled' in current_scope:
grps = canc_matches.groups()
self.view.insert(edit, line.end(), done_line_end)
replacement = u'%s%s%s' % (grps[0], self.done_tasks_bullet, grps[1].rstrip())
Expand All @@ -141,23 +141,24 @@ def runCommand(self, edit):
except:
canc_line_end = ' %s%s%s' % (self.canc_tag,self.before_date_space, datetime.now().strftime(self.date_format))
offset = len(canc_line_end)
if self.taskpaper_compatible:
rom = '^(\s*)-(\s*[^\b]*\s*)(?!\s@(done|cancelled)).*$'
rdm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@done).*$'
rcm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@cancelled).*$'
else:
rom = '^(\s*)(?:\[\s\]|.)(\s*.*)$'
rdm = '^(\s*)(?:\[x\]|.)(\s*[^\b]*?\s*)(?=\s@done|@project|\s\(|$).*$'
rcm = '^(\s*)(?:\[\-\]|.)(\s*[^\b]*?\s*)(?=\s@cancelled|@project|\s\(|$).*$'
started = '^\s*[^\b]*?\s*@started(\([\d\w,\.:\-\/ @]*\)).*$'
for region in self.view.sel():
line = self.view.line(region)
line_contents = self.view.substr(line).rstrip()
if self.taskpaper_compatible:
rom = '^(\s*)-(\s*[^\b]*\s*)(?!\s@(done|cancelled)).*$'
rdm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@done).*$'
rcm = '^(\s*)-(\s*[^\b]*?\s*)(?=\s@cancelled).*$'
else:
rom = '^(\s*)' + re.escape(self.open_tasks_bullet) + '(\s*.*)$'
rdm = '^(\s*)' + re.escape(self.done_tasks_bullet) + '(\s*[^\b]*?\s*)(?=\s@done|@project|\s\(|$).*$'
rcm = '^(\s*)' + re.escape(self.canc_tasks_bullet) + '(\s*[^\b]*?\s*)(?=\s@cancelled|@project|\s\(|$).*$'
started = '^\s*[^\b]*?\s*@started(\([\d\w,\.:\-\/ @]*\)).*$'
open_matches = re.match(rom, line_contents, re.U)
done_matches = re.match(rdm, line_contents, re.U)
canc_matches = re.match(rcm, line_contents, re.U)
started_matches = re.match(started, line_contents, re.U)
if open_matches and not (done_matches or canc_matches):
current_scope = self.view.scope_name(line.a)
if 'pending' in current_scope:
grps = open_matches.groups()
eol = self.view.insert(edit, line.end(), canc_line_end)
replacement = u'%s%s%s' % (grps[0], self.canc_tasks_bullet, grps[1].rstrip())
Expand All @@ -166,13 +167,13 @@ def runCommand(self, edit):
start = datetime.strptime(started_matches.group(1), self.date_format)
end = datetime.strptime(canc_line_end.replace(' @cancelled ', ''), self.date_format)
self.view.insert(edit, line.end() + eol, ' @wasted(%s)' % str(end - start))
elif done_matches:
elif 'completed' in current_scope:
pass
# grps = done_matches.groups()
# replacement = u'%s%s%s' % (grps[0], self.canc_tasks_bullet, grps[1].rstrip())
# self.view.replace(edit, line, replacement)
# offset = -offset
elif canc_matches:
elif 'cancelled' in current_scope:
grps = canc_matches.groups()
replacement = u'%s%s%s' % (grps[0], self.open_tasks_bullet, grps[1].rstrip())
self.view.replace(edit, line, replacement)
Expand All @@ -186,31 +187,19 @@ def runCommand(self, edit):

class PlainTasksArchiveCommand(PlainTasksBase):
def runCommand(self, edit):
if self.taskpaper_compatible:
rdm = '^(\s*)-(\s*[^\n]*?\s*)(?=\s@done)[\(\)\d\w,\.:\-\/ @]*\s*[^\n]$'
rcm = '^(\s*)-(\s*[^\n]*?\s*)(?=\s@cancelled)[\(\)\d\w,\.:\-\/ @]*\s*[^\n]$'
else:
rdm = '^(\s*)' + re.escape(self.done_tasks_bullet) + '\s+.*$'
rcm = '^(\s*)' + re.escape(self.canc_tasks_bullet) + '\s+.*$'
rds = 'meta.item.todo.completed'
rcs = 'meta.item.todo.cancelled'

# finding archive section
archive_pos = self.view.find(self.archive_name, 0, sublime.LITERAL)

done_tasks = []
done_task = self.view.find(rdm, 0)
# print(done_task)
while done_task and (not archive_pos or done_task < archive_pos):
done_tasks.append(done_task)
self.get_task_note(done_task, done_tasks)
done_task = self.view.find(rdm, done_task.end() + 1)

canc_tasks = []
canc_task = self.view.find(rcm, 0)
# print(canc_task)
while canc_task and (not archive_pos or canc_task < archive_pos):
canc_tasks.append(canc_task)
self.get_task_note(canc_task, canc_tasks)
canc_task = self.view.find(rcm, canc_task.end() + 1)
done_tasks = filter(lambda i: i < archive_pos, self.view.find_by_selector(rds))
for i in done_tasks:
self.get_task_note(i, done_tasks)

canc_tasks = filter(lambda i: i < archive_pos, self.view.find_by_selector(rcs))
for i in canc_tasks:
self.get_task_note(i, canc_tasks)

all_tasks = done_tasks + canc_tasks
all_tasks.sort()
Expand All @@ -227,11 +216,9 @@ def runCommand(self, edit):

# adding tasks to archive section
for task in all_tasks:
if self.taskpaper_compatible:
match_task = re.match('^\s*(-)(\s*[^\n]*?)', self.view.substr(task), re.U)
else:
match_task = re.match('^\s*(' + re.escape(self.done_tasks_bullet) + '|' + re.escape(self.canc_tasks_bullet) + ')(\s+.*$)', self.view.substr(task), re.U)
if match_task:
match_task = re.match('^\s*(\[[x-]\]|.)(\s+.*$)', self.view.substr(task), re.U)
current_scope = self.view.scope_name(task.a)
if rds in current_scope or rcs in current_scope:
pr = self.get_task_project(task, projects)
if self.project_postfix:
eol = (self.before_tasks_bullet_spaces + self.view.substr(task).lstrip() +
Expand Down Expand Up @@ -293,7 +280,9 @@ def get_task_project(self, task, projects):
def get_task_note(self, task, tasks):
note_line = task.end() + 1
while self.view.scope_name(note_line) == 'text.todo notes.todo ':
tasks.append(self.view.line(note_line))
note = self.view.line(note_line)
if note not in tasks:
tasks.append(note)
note_line = self.view.line(note_line).end() + 1


Expand Down
8 changes: 4 additions & 4 deletions PlainTasks.tmLanguage
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
</dict>
</dict>
<key>match</key>
<string>^\s*(?:(\+|✓|✔|☑)\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*))|(?:(-)\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*\@done.*))\s*\n*</string>
<string>^\s*(?:(\+|✓|✔|☑|√|\[x\])\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*))|(?:(-)\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*\@done.*))\s*\n*</string>
<key>name</key>
<string>meta.item.todo.completed</string>
</dict>
Expand Down Expand Up @@ -96,14 +96,14 @@
</dict>
</dict>
<key>match</key>
<string>^\s*(?:(✘|x)\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*))|(?:(-)\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*\@cancelled.*))\s*\n*</string>
<string>^\s*(?:(✘|x|\[-\])\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*))|(?:(-)\s+((?:[^\@]|(?&lt;!\s)\@|\@(?=\s))*)(.*\@cancelled.*))\s*\n*</string>
<key>name</key>
<string>meta.item.todo.cancelled</string>
</dict>

<dict>
<key>match</key>
<string>^\s*((?!-|\+|✓|✔|❍|❑|■|□|☐|▪|▫|–|—|_|✘|(x\s+))\S).*((?!:\s*).\s*)$</string>
<string>^\s*((?!-|\+|✓|✔|√|❍|❑|■|□|☐|▪|▫|–|—|\[[\sx-]\]|_|✘|(x\s+))\S).*((?!:\s*).\s*)$</string>
<key>name</key>
<string>notes.todo</string>
</dict>
Expand All @@ -123,7 +123,7 @@
</dict>
</dict>
<key>match</key>
<string>^\s*(-|❍|❑|■|□|☐|▪|▫|–|—)\s+((?:[^\@]|(?&lt;!\s)\@)*)(?!(.*)?(\@done|\@cancelled))</string>
<string>^\s*(-|❍|❑|■|□|☐|▪|▫|–|—|\[\s\])\s+((?:[^\@]|(?&lt;!\s)\@)*)(?!(.*)?(\@done|\@cancelled))</string>
<key>name</key>
<string>meta.item.todo.pending</string>
</dict>
Expand Down
6 changes: 3 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ Here is a list of PlainTasks' specific settings:

| Setting | Default | Options/Description |
| ------------------------------ | ---------------- | ----------------------------------------------------------------------- |
| **open_tasks_bullet** || - ❍ ❑ ■ □ ☐ ▪ ▫ – — ≡ → › |
| **done_tasks_bullet** || ✓ ☑ + |
| **cancelled_tasks_bullet** || x |
| **open_tasks_bullet** || - ❍ ❑ ■ □ ☐ ▪ ▫ – — ≡ → › [ ] |
| **done_tasks_bullet** || ✓ ☑ + [x] |
| **cancelled_tasks_bullet** || x [-] |
| **date_format** | `(%y-%m-%d %H:%M)` | |
| **done_tag** | true | Determines whether done tasks should gain a @done tag or not |
| **before_tasks_bullet_margin** | 1 | Determines the number of spaces (default indent) before the task bullet |
Expand Down
4 changes: 2 additions & 2 deletions TODO.todo
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ TODO:
☐ in archive list, add date in front of done tasks (e.g. 2012-09-06 14:41 Ξ some task) @feature
☐ @today ✭ᴛᴏᴅᴀʏ tags @feature
☐ marking all nested tasks as done should mark the parent as done?
☐ accept multiple bullet types at the same time @feature
☐ other themes?
☐ export to html/ preview in browser @feature
☐ taskpaper compatibility @improvement
☐ mouse interaction @feature

___________________
Archive:
✔ accept multiple bullet types at the same time @feature @done (14-01-23 15:39)
✔ taskpaper compatibility @improvement @done (14-01-23 15:38)
✔ include in the task the date and time of creation (using a shortcut key) @feature @done (13-10-25 14:47) @project(TODO)
✔ in archive list, adding newly archived items to the bottom or top should be configurable @feature @done (13-10-23 21:21) @project(TODO)
✔ Maybe after mark the task as done calculate (the end time - start time) @done (13-10-22 17:50) @project(TODO)
Expand Down

2 comments on commit a83fe56

@aziz
Copy link
Owner

@aziz aziz commented on a83fe56 Jan 23, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is amazing Vova! Thanks dude! yesterday I published two new plugins FileBrowser and DistractionFreeWindow. if you're interested I can give you push access to those too.

@vovkkk
Copy link
Collaborator Author

@vovkkk vovkkk commented on a83fe56 Jan 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, FileBrowser seems interesting.

Please sign in to comment.