def fin(time: Union[str, Arrow], back_from_interrupt=True) -> bool: ensure_working() data = store.load() current = data['work'][-1] item = Item(**data['work'][-1]) end: XArrow = formatted2arrow(time) if item.start > end: print(f'{c.orange("Cannot")} finish {item.name_colored} at {c.time(end.HHmmss)} because it only started at {c.time(item.start.HHmmss)}.') return False if item.start.day < end.day: print(end) if not confirm(f'{item.name_colored} started on {c.time(item.start.MMDDYYHHmmss)}, continue?'): return False current['end'] = time item.end = time ok = store.dump(data) print(f'{c.yellow("Stopped")} working on {item.name_colored} at {c.time(item.end.HHmmss)}') if not ok: return False if back_from_interrupt and len(data['interrupt_stack']) > 0: name = data['interrupt_stack'].pop()['name'] store.dump(data) on(name, time) if len(data['interrupt_stack']) > 0: print('You are now %d deep in interrupts.' % len(data['interrupt_stack'])) else: print("Congrats, you're out of interrupts!") return True
def edit(): if "EDITOR" not in os.environ: raise NoEditor("Please set the 'EDITOR' environment variable") data = store.load() yml = yaml.safe_dump(data, default_flow_style=False, allow_unicode=True) cmd = os.getenv('EDITOR') fd, temp_path = tempfile.mkstemp(prefix='ti.') with open(temp_path, "r+") as f: f.write(yml.replace('\n- ', '\n\n- ')) f.seek(0) subprocess.check_call(cmd + ' ' + temp_path, shell=True) yml = f.read() f.truncate() os.close(fd) os.remove(temp_path) try: data = yaml.load(yml) except: raise InvalidYAML("Oops, that YAML doesn't appear to be valid!") store.dump(data)
def tag(_tag, time="now"): time = human2arrow(time) if time > now(): raise BadTime(f"in the future: {time}") data = store.load() idx = -1 item = Item(**data['work'][idx]) if time < item.start: # Tag something in the past idx = -1 * next(i for i, work in enumerate(reversed(data['work']), 1) if Item(**work).start <= time) item_in_range = Item(**data['work'][idx]) if not confirm(f'{item.name_colored} started only at {c.time(item.start.strftime("%X"))}, ' f'Tag {item_in_range.name_colored} (started at {c.time(item_in_range.start.strftime("%X"))})?'): return item = item_in_range tag_colored = c.b(c.tag(_tag)) if _tag.lower() in [t.lower() for t in item.tags]: print(f'{item.name_colored} already has tag {tag_colored}.') return item.tags.append(_tag) data['work'][idx]['tags'] = item.tags store.dump(data) print(f"Okay, tagged {item.name_colored} with {tag_colored}.")
def interrupt(name, time): ensure_working() fin(time, back_from_interrupt=False) data = store.load() if 'interrupt_stack' not in data: data['interrupt_stack'] = [] interrupt_stack = data['interrupt_stack'] interrupted = data['work'][-1] interrupt_stack.append(interrupted) store.dump(data) on('interrupt: ' + c.green(name), time) print('You are now %d deep in interrupts.' % len(interrupt_stack))
def note(content, time="now"): # ensure_working() time = human2arrow(time) if time > now(): raise BadTime(f"in the future: {time}") breakpoint() content_and_time = content.strip() + f' ({time.HHmmss})' data = store.load() idx = -1 item = Item(**data['work'][idx]) if time < item.start: # Note for something in the past idx, item_in_range = next((i, item) for i, item in enumerate(map(lambda w: Item(**w), reversed(data['work'])), 1) if item.start.full == time.full) idx *= -1 if item_in_range.name == item.name: item = item_in_range else: if not confirm(f'{item.name_colored} started only at {c.time(item.start.strftime("%X"))},\n' f'note to {item_in_range.name_colored} (started at {c.time(item_in_range.start.strftime("%X"))})?'): return item = item_in_range # refactor this out when Note class content_lower = content.lower() for n in item.notes: if n.lower().startswith(content_lower): if not confirm(f'{item.name_colored} already has this note: {c.b(c.note(n))}.\n' 'Add anyway?'): return item.notes.append(content_and_time) data['work'][idx]['notes'] = item.notes store.dump(data) print(f'Noted {c.b(c.note(content_and_time))} to {item.name_colored}')
return on(name, time, _tag) return False entry = { 'name': name, 'start': time, } if _tag: entry.update({'tags': [_tag]}) if _note: entry.update({'notes': [_note]}) work.append(entry) store.dump(data) message = f'{c.green("Started")} working on {c.task(name)} at {c.b(c.time(reformat(time, "HH:mm:ss")))}' if _tag: message += f". tag: {c.tag(_tag)}" if _note: message += f". note: {c.note(_note)}" print(message) def fin(time: Union[str, Arrow], back_from_interrupt=True) -> bool: ensure_working() data = store.load()