def __init__(self): self.warrior = TaskWarrior() self.config = Config() self.default_limit = self.config.get_default_filter() self.limit = self.default_limit self.show_annotations = [] self.walker = urwid.SimpleListWalker([]) self.list_box = ScrollingListBox(self.walker) self.view = urwid.Frame(urwid.AttrWrap(self.list_box, 'body')) self.refresh() def update_header(): limit = ' | ' + self.limit if self.limit else '' header_text = ['tasky.α', ('dim', limit)] self.view.set_header(urwid.AttrMap(urwid.Text(header_text), 'head')) update_header() loop = urwid.MainLoop(self.view, Tasky.palette, unhandled_input=self.keystroke) self.loop = loop urwid.connect_signal(self.walker, 'modified', update_header) loop.screen.set_terminal_properties(colors=256) loop.run()
def __init__(self): self.warrior = TaskWarrior() self.limit = ''.join(sys.argv[1:]) self.nvim = None self.note_folder = "~/.tasknote/" header = urwid.AttrMap(urwid.Text('tasky.α'), 'head') self.walker = urwid.SimpleListWalker([]) self.list_box = ScrollingListBox(self.walker) self.view = urwid.Frame(urwid.AttrWrap(self.list_box, 'body')) self.required_status = ['pending'] self.refresh() def update_header(): limit = ' | ' + self.limit if self.limit else '' header_text = ['tasky.α', ('dim', limit)] self.view.set_header(urwid.AttrMap(urwid.Text(header_text), 'head')) update_header() loop = urwid.MainLoop(self.view, Tasky.palette, unhandled_input=self.keystroke) urwid.connect_signal(self.walker, 'modified', update_header) loop.screen.set_terminal_properties(colors=256) loop.run()
def __init__(self): self.warrior = TaskWarrior() self.limit = ''.join(sys.argv[1:]) header = urwid.AttrMap(urwid.Text('tasky.α'), 'head') self.walker = urwid.SimpleListWalker([]) self.list_box = ScrollingListBox(self.walker) self.view = urwid.Frame(urwid.AttrWrap(self.list_box, 'body')) self.refresh() def update_header(): limit = ' | ' + self.limit if self.limit else '' header_text = ['tasky.α', ('dim', limit)] self.view.set_header(urwid.AttrMap(urwid.Text(header_text), 'head')) update_header() loop = urwid.MainLoop(self.view, Tasky.palette, unhandled_input=self.keystroke) urwid.connect_signal(self.walker, 'modified', update_header) loop.screen.set_terminal_properties(colors=256) loop.run()
class Tasky(object): palette = [ ('proj', '', '', '', 'dark green', ''), ('proj_focus', '', '', '', 'dark gray', 'dark green'), ('body','', '', '', 'dark blue', ''), ('body_focus', '', '', '', 'dark gray', 'dark cyan'), ('body_emph','', '', '', 'light red', ''), ('body_emph_focus', '', '', '', 'dark gray', 'dark magenta'), ('head', '', '', '', 'light red', 'black'), ('dim', '', '', '', 'g54', 'black') ] def __init__(self): self.warrior = TaskWarrior() self.limit = ''.join(sys.argv[1:]) self.nvim = None self.note_folder = "~/.tasknote/" header = urwid.AttrMap(urwid.Text('tasky.α'), 'head') self.walker = urwid.SimpleListWalker([]) self.list_box = ScrollingListBox(self.walker) self.view = urwid.Frame(urwid.AttrWrap(self.list_box, 'body')) self.required_status = ['pending'] self.refresh() def update_header(): limit = ' | ' + self.limit if self.limit else '' header_text = ['tasky.α', ('dim', limit)] self.view.set_header(urwid.AttrMap(urwid.Text(header_text), 'head')) update_header() loop = urwid.MainLoop(self.view, Tasky.palette, unhandled_input=self.keystroke) urwid.connect_signal(self.walker, 'modified', update_header) loop.screen.set_terminal_properties(colors=256) loop.run() def refresh(self): limit = self.limit or '' self.walker[:] = map(TaskWidget, self.warrior.retrieve_tasks(limit, status=self.required_status)) def attach_nvim(self): Utility.run_command("tmux split-window -h 'NVIM_LISTEN_ADDRESS=/tmp/nvim nvim'") while True: try: time.sleep(1) nvim = attach('socket', path='/tmp/nvim') except: continue break self.nvim = nvim def keystroke(self, input): def exit(): if self.nvim: self.nvim.quit("wq") raise urwid.ExitMainLoop() def undo(): self.warrior.undo() self.refresh() view_action_map = { 'q': exit, 'Q': exit, 'r': self.refresh, 'u': undo, 'i': self.new_task, ':': self.command_mode, '!': self.shell_mode, 'l': self.change_limit, 'A': self.show_all, } task_action_map = { 'enter': (self.edit_task, False), 'e': (self.edit_task, False), 'n': (self.task_note, False), 'c': (self.warrior.complete, True), 'd': (self.warrior.delete, True), ' ': (self.warrior.toggle_active, True) } if input in view_action_map: view_action_map[input]() if input in task_action_map: (action, should_refresh) = task_action_map[input] action(self.selected_task()) if should_refresh: self.refresh() def selected_task(self): return self.list_box.get_focus()[0].task def task_note(self, task): if not self.nvim: self.attach_nvim() if not os.path.isdir(expanduser(self.note_folder)): os.mkdir(expanduser(self.note_folder)) note_file = expanduser(self.note_folder + task.uuid() + ".markdown") if not os.path.isfile(note_file): with open(note_file, 'w+') as fh: header = "# " + task.description() fh.write(header) # Annotate the task to show that it has notes now. Utility.run_command("task %i annotate Notes" % task.id()) # either capture error or write note before changing buffer try: self.nvim.command("e " + note_file) except: self.nvim.command("w") self.nvim.command("e " + note_file) def present_editor(self, prompt, text, handler): self.foot = LineEditor(prompt, text) self.view.set_footer(self.foot) self.view.set_focus('footer') urwid.connect_signal(self.foot, 'done', handler) def command_mode(self): self.present_editor(': ', '', self.command_done) def shell_mode(self): self.present_editor('! ', '', self.shell_done) def change_limit(self): limit = self.limit or '' self.present_editor('Limit: ', limit, self.limit_done) def edit_task(self, task): self.edited_task = task self.present_editor(' >> ', task.description(), self.edit_done) def new_task(self): self.present_editor(' >> ', '', self.new_done) def dismiss_editor(action): def wrapped(self, content): self.view.set_focus('body') urwid.disconnect_signal(self, self.foot, 'done', action) if content is not None: action(self, content) self.view.set_footer(None) return wrapped @dismiss_editor def edit_done(self, content): self.warrior.mod(self.edited_task, content) self.edited_task = None self.refresh() @dismiss_editor def new_done(self, content): limit = self.limit or '' self.warrior.add(content + ' ' + limit) self.refresh() @dismiss_editor def command_done(self, content): Utility.run_command('task ' + content) self.refresh() @dismiss_editor def shell_done(self, content): Utility.run_command("tmux split-window '%s'" % content) @dismiss_editor def limit_done(self, content): self.limit = content self.refresh() def show_all(self): if 'completed' not in self.required_status: self.required_status += ['completed'] self.refresh() else: self.required_status = ['pending'] self.refresh()
class Tasky(object): palette = [('proj', '', '', '', 'dark green', ''), ('proj_focus', '', '', '', 'dark gray', 'dark green'), ('body', '', '', '', 'dark blue', ''), ('body_focus', '', '', '', 'dark gray', 'dark cyan'), ('body_emph', '', '', '', 'light red', ''), ('body_emph_focus', '', '', '', 'dark gray', 'dark magenta'), ('head', '', '', '', 'light red', 'black'), ('dim', '', '', '', 'g54', 'black')] def __init__(self): self.warrior = TaskWarrior() self.limit = ''.join(sys.argv[1:]) header = urwid.AttrMap(urwid.Text('tasky.α'), 'head') self.walker = urwid.SimpleListWalker([]) self.list_box = ScrollingListBox(self.walker) self.view = urwid.Frame(urwid.AttrWrap(self.list_box, 'body')) self.refresh() def update_header(): limit = ' | ' + self.limit if self.limit else '' header_text = ['tasky.α', ('dim', limit)] self.view.set_header(urwid.AttrMap(urwid.Text(header_text), 'head')) update_header() loop = urwid.MainLoop(self.view, Tasky.palette, unhandled_input=self.keystroke) urwid.connect_signal(self.walker, 'modified', update_header) loop.screen.set_terminal_properties(colors=256) loop.run() def refresh(self): limit = self.limit or '' self.walker[:] = map(TaskWidget, self.warrior.pending_tasks(limit)) def keystroke(self, input): def exit(): raise urwid.ExitMainLoop() def undo(): self.warrior.undo() self.refresh() view_action_map = { 'q': exit, 'Q': exit, 'r': self.refresh, 'u': undo, 'i': self.new_task, ':': self.command_mode, '!': self.shell_mode, 'l': self.change_limit } task_action_map = { 'enter': (self.edit_task, False), 'e': (self.edit_task, False), 'n': (self.task_note, False), 'c': (self.warrior.complete, True), 'd': (self.warrior.delete, True), ' ': (self.warrior.toggle_active, True) } if input in view_action_map: view_action_map[input]() if input in task_action_map: (action, should_refresh) = task_action_map[input] action(self.selected_task()) if should_refresh: self.refresh() def selected_task(self): return self.list_box.get_focus()[0].task def task_note(self, task): Utility.run_command("tmux split-window 'tasknote %i'" % task.id()) def present_editor(self, prompt, text, handler): self.foot = LineEditor(prompt, text) self.view.set_footer(self.foot) self.view.set_focus('footer') urwid.connect_signal(self.foot, 'done', handler) def command_mode(self): self.present_editor(': ', '', self.command_done) def shell_mode(self): self.present_editor('! ', '', self.shell_done) def change_limit(self): limit = self.limit or '' self.present_editor('Limit: ', limit, self.limit_done) def edit_task(self, task): self.edited_task = task self.present_editor(' >> ', task.description(), self.edit_done) def new_task(self): self.present_editor(' >> ', '', self.new_done) def dismiss_editor(action): def wrapped(self, content): self.view.set_focus('body') urwid.disconnect_signal(self, self.foot, 'done', action) if content is not None: action(self, content) self.view.set_footer(None) return wrapped @dismiss_editor def edit_done(self, content): self.warrior.mod(self.edited_task, content) self.edited_task = None self.refresh() @dismiss_editor def new_done(self, content): limit = self.limit or '' self.warrior.add(content + ' ' + limit) self.refresh() @dismiss_editor def command_done(self, content): Utility.run_command('task ' + content) self.refresh() @dismiss_editor def shell_done(self, content): Utility.run_command("tmux split-window '%s'" % content) @dismiss_editor def limit_done(self, content): self.limit = content self.refresh()
class Tasky(object): palette = [('proj', '', '', '', 'dark green', ''), ('proj_focus', '', '', '', 'black', 'dark green'), ('body', '', '', '', 'dark blue', ''), ('body_focus', '', '', '', 'black', 'dark cyan'), ('body_emph', '', '', '', 'light red', ''), ('body_emph_focus', '', '', '', 'black', 'dark magenta'), ('head', '', '', '', 'light red', 'black'), ('dim', '', '', '', 'g54', 'black')] def __init__(self): self.warrior = TaskWarrior() self.config = Config() self.default_limit = self.config.get_default_filter() self.limit = self.default_limit self.show_annotations = [] self.walker = urwid.SimpleListWalker([]) self.list_box = ScrollingListBox(self.walker) self.view = urwid.Frame(urwid.AttrWrap(self.list_box, 'body')) self.refresh() def update_header(): limit = ' | ' + self.limit if self.limit else '' header_text = ['tasky.α', ('dim', limit)] self.view.set_header(urwid.AttrMap(urwid.Text(header_text), 'head')) update_header() loop = urwid.MainLoop(self.view, Tasky.palette, unhandled_input=self.keystroke) self.loop = loop urwid.connect_signal(self.walker, 'modified', update_header) loop.screen.set_terminal_properties(colors=256) loop.run() def refresh(self): limit = self.limit or '' self.walker[:] = [ TaskWidget(task, task.uuid() in self.show_annotations) for task in self.warrior.pending_tasks(limit) ] def sync(self): self.warrior.sync() self.refresh() def keystroke(self, input): def exit(): raise urwid.ExitMainLoop() def undo(): self.warrior.undo() self.refresh() view_action_map = { 'q': exit, 'Q': exit, 'r': self.sync, 'u': undo, 'i': self.new_inbox, 't': self.new_task, ':': self.command_mode, '!': self.shell_mode, '/': self.change_limit, '-': self.all, 'b': self.clear_limit, } task_action_map = { 'enter': (self.edit_task, False), 'e': (self.edit_task_detail, True), 'n': (self.task_annotate, True), 'N': (self.task_note, True), 'c': (self.warrior.complete, True), 'd': (self.warrior.delete, True), ' ': (self.warrior.toggle_active, True), 'y': (self.copy_description, False), 'Y': (self.copy_notes, False), 'o': (self.open_browser, False), 'a': (self.toggle_annotations, True), 'A': (self.toggle_all_annotations, True), 'T': (self.new_task_with_defaults, True), 's': (self.sleep_task, True), } config_bind = self.config.get_bind(input) if config_bind and len(config_bind): self.limit = config_bind self.refresh() return if input in view_action_map: view_action_map[input]() return if input in task_action_map: (action, should_refresh) = task_action_map[input] action(self.selected_task()) if should_refresh: self.refresh() def selected_task(self): return self.list_box.get_focus()[0].task def task_annotate(self, task): self.edited_task = task self.present_editor(' >> ', '', self.annotate_done) def task_note(self, task): self.loop.stop() subprocess.check_call(['tasknote %s' % str(task.id())], shell=True) self.loop.start() def present_editor(self, prompt, text, handler): self.foot = LineEditor(prompt, text) self.view.set_footer(self.foot) self.view.set_focus('footer') urwid.connect_signal(self.foot, 'done', handler) def command_mode(self): self.present_editor(': ', '', self.command_done) def shell_mode(self): self.present_editor('! ', '', self.shell_done) def change_limit(self): self.present_editor('Filter: ', '', self.limit_done) def all(self): self.limit = '' self.refresh() def clear_limit(self): self.limit = self.default_limit self.refresh() def copy_description(self, task): Utility.write_to_clipboard(task.description()) def copy_notes(self, task): notes = [note[u'description'] for note in task.annotations()] Utility.write_to_clipboard("\n".join(notes)) def open_browser(self, task): urls = [] if Utility.is_url(task.description()): urls.append(task.description()) possibles = [ v[u'description'] for v in task.annotations() if Utility.is_url(v[u'description']) ] urls.extend(possibles) for url in urls: Utility.run_command('open -a "Google Chrome" %s' % url) def toggle_annotations(self, task): if not len(task.annotations()): return if task.uuid() in self.show_annotations: self.show_annotations.remove(task.uuid()) else: self.show_annotations.append(task.uuid()) def toggle_all_annotations(self, task): if len(self.show_annotations): self.show_annotations = [] else: limit = self.limit or '' self.show_annotations = [ t.uuid() for t in self.warrior.pending_tasks(limit) ] def edit_task(self, task): self.edited_task = task self.present_editor(' >> ', task.description(), self.edit_done) def sleep_task(self, task): self.edited_task = task self.present_editor(' >> ', 'wait:', self.edit_done) def edit_task_detail(self, task): self.loop.stop() subprocess.check_call(['task %s edit' % str(task.id())], shell=True) self.loop.start() def new_task(self, prefilled=''): self.present_editor(' >> ', prefilled, self.new_done) def new_inbox(self): self.new_task('+in ') def new_task_with_defaults(self, task): project = task.project() tags = task.tags_string() prefilled = '' if project: prefilled += 'pro:{} '.format(project) prefilled += '{} '.format(tags) self.new_task(prefilled) def dismiss_editor(action): def wrapped(self, content): self.view.set_focus('body') urwid.disconnect_signal(self, self.foot, 'done', action) if content is not None: action(self, content) self.view.set_footer(None) return wrapped @dismiss_editor def edit_done(self, content): self.warrior.mod(self.edited_task, content) self.edited_task = None self.refresh() @dismiss_editor def new_done(self, content): self.warrior.add(content) self.refresh() @dismiss_editor def command_done(self, content): Utility.run_command('task ' + content) self.refresh() @dismiss_editor def shell_done(self, content): self.loop.stop() subprocess.check_call(['/bin/zsh', '-i', '-c', content]) self.loop.start() @dismiss_editor def limit_done(self, content): self.limit = content self.refresh() @dismiss_editor def annotate_done(self, content): self.warrior.annotate(self.edited_task, content) self.edited_task = None self.refresh()
class Tasky(object): palette = [ ('proj', '', '', '', 'dark green', ''), ('proj_focus', '', '', '', 'dark gray', 'dark green'), ('body','', '', '', 'dark blue', ''), ('body_focus', '', '', '', 'dark gray', 'dark cyan'), ('body_emph','', '', '', 'light red', ''), ('body_emph_focus', '', '', '', 'dark gray', 'dark magenta'), ('head', '', '', '', 'light red', 'black'), ('dim', '', '', '', 'g54', 'black') ] def __init__(self): self.warrior = TaskWarrior() self.limit = ''.join(sys.argv[1:]) header = urwid.AttrMap(urwid.Text('tasky.α'), 'head') self.walker = urwid.SimpleListWalker([]) self.list_box = ScrollingListBox(self.walker) self.view = urwid.Frame(urwid.AttrWrap(self.list_box, 'body')) self.refresh() def update_header(): limit = ' | ' + self.limit if self.limit else '' header_text = ['tasky.α', ('dim', limit)] self.view.set_header(urwid.AttrMap(urwid.Text(header_text), 'head')) update_header() loop = urwid.MainLoop(self.view, Tasky.palette, unhandled_input=self.keystroke) urwid.connect_signal(self.walker, 'modified', update_header) loop.screen.set_terminal_properties(colors=256) loop.run() def refresh(self): limit = self.limit or '' self.walker[:] = map(TaskWidget, self.warrior.pending_tasks(limit)) def keystroke(self, input): def exit(): raise urwid.ExitMainLoop() def undo(): self.warrior.undo() self.refresh() view_action_map = { 'q': exit, 'Q': exit, 'r': self.refresh, 'u': undo, 'i': self.new_task, ':': self.command_mode, '!': self.shell_mode, 'l': self.change_limit } task_action_map = { 'enter': (self.edit_task, False), 'e': (self.edit_task, False), 'n': (self.task_note, False), 'c': (self.warrior.complete, True), 'd': (self.warrior.delete, True), ' ': (self.warrior.toggle_active, True) } if input in view_action_map: view_action_map[input]() if input in task_action_map: (action, should_refresh) = task_action_map[input] action(self.selected_task()) if should_refresh: self.refresh() def selected_task(self): return self.list_box.get_focus()[0].task def task_note(self, task): Utility.run_command("tmux split-window 'tasknote %i'" % task.id()) def present_editor(self, prompt, text, handler): self.foot = LineEditor(prompt, text) self.view.set_footer(self.foot) self.view.set_focus('footer') urwid.connect_signal(self.foot, 'done', handler) def command_mode(self): self.present_editor(': ', '', self.command_done) def shell_mode(self): self.present_editor('! ', '', self.shell_done) def change_limit(self): limit = self.limit or '' self.present_editor('Limit: ', limit, self.limit_done) def edit_task(self, task): self.edited_task = task self.present_editor(' >> ', task.description(), self.edit_done) def new_task(self): self.present_editor(' >> ', '', self.new_done) def dismiss_editor(action): def wrapped(self, content): self.view.set_focus('body') urwid.disconnect_signal(self, self.foot, 'done', action) if content is not None: action(self, content) self.view.set_footer(None) return wrapped @dismiss_editor def edit_done(self, content): self.warrior.mod(self.edited_task, content) self.edited_task = None self.refresh() @dismiss_editor def new_done(self, content): limit = self.limit or '' self.warrior.add(content + ' ' + limit) self.refresh() @dismiss_editor def command_done(self, content): Utility.run_command('task ' + content) self.refresh() @dismiss_editor def shell_done(self, content): Utility.run_command("tmux split-window '%s'" % content) @dismiss_editor def limit_done(self, content): self.limit = content self.refresh()