Skip to content

Commit

Permalink
Merge pull request #170 from kraanzu/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
kraanzu authored Jan 25, 2024
2 parents b1ea932 + 0234b50 commit 9b25fd6
Show file tree
Hide file tree
Showing 17 changed files with 126 additions and 37 deletions.
File renamed without changes.
18 changes: 16 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

# 2.0.2
## 2.2.0

### Added
- Add support for changing the default urgency of a todo with `TODO.initial_urgency`
- Add support for changing urgency colors with `TODO.urgency1_color` to `TODO.urgency4_color`
- Add shortcut for recursively expanding and closing todos (Ctrl + Z)
- Add `WORKSPACE.start_expanded` and `TODO.start_expanded` to launch with the Workspace and Todo tree fully expanded
- Dooit can now also be launched with `python -m dooit`

### Fixed

- App crashes when an opened workspace is deleted (closes https://github.com/kraanzu/dooit/issues/169)
- App crash on adding a workspace (closes https://github.com/kraanzu/dooit/issues/167)

## 2.0.2

### Added
- Add `DATE_FORMAT` and `TIME_FORMAT` to allow users to customize due date https://github.com/kraanzu/dooit/issues/141 (Also [see this](https://github.com/kraanzu/dooit/wiki/Configuration#general))

# 2.0.1
## 2.0.1

### Added
- Add `USE_DAY_FIRST` settings to allow users to switch between day and month
Expand Down
15 changes: 0 additions & 15 deletions dooit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +0,0 @@
import argparse
from importlib.metadata import version
from dooit.ui.tui import Dooit


def main():
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--version", help="Show version", action="store_true")
args = parser.parse_args()

if args.version:
ver = version("dooit")
print(f"dooit - {ver}")
else:
Dooit().run()
19 changes: 19 additions & 0 deletions dooit/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import argparse
from importlib.metadata import version
from dooit.ui.tui import Dooit


def main():
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--version", help="Show version", action="store_true")
args = parser.parse_args()

if args.version:
ver = version("dooit")
print(f"dooit - {ver}")
else:
Dooit().run()


if __name__ == "__main__":
main()
16 changes: 9 additions & 7 deletions dooit/api/model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List, Literal, Optional
from typing import Any, ClassVar, Dict, List, Literal, Optional
from typing_extensions import Self
from uuid import uuid4
from dataclasses import dataclass
Expand Down Expand Up @@ -56,6 +56,7 @@ class Model:
Model class to for the base tree structure
"""

class_kind: ClassVar[str]
fields: List
sortable_fields: List[SortMethodType]

Expand All @@ -76,14 +77,9 @@ def __init__(
def uuid(self) -> str:
return self._uuid

@classmethod
@property
def class_kind(cls) -> str:
return cls.__name__.lower()

@property
def kind(self):
return self.__class__.__name__.lower()
return self.class_kind

@property
def nest_level(self):
Expand Down Expand Up @@ -310,3 +306,9 @@ def get_all_todos(self) -> List:
arr.extend(i.get_all_todos())

return arr

def __init_subclass__(cls) -> None:
cls.class_kind = cls.__name__.lower()


Model.__init_subclass__()
10 changes: 10 additions & 0 deletions dooit/api/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ def edit(self, key: str, value: str) -> Result:
def toggle_complete(self) -> bool:
return self._status.toggle_done()

def set_urgency(self, value: int) -> None:
self._urgency.set(value)

def decrease_urgency(self) -> None:
self._urgency.decrease()

Expand Down Expand Up @@ -157,6 +160,13 @@ def from_data(self, data: List, overwrite_uuid: bool = True) -> None:
self.fill_from_data(data[0], overwrite_uuid)
if len(data) > 1:
for i in data[1]:
# Skips todos with no description and no children
if len(i) == 1 and not i[0]['description']:
continue
# Don't skip the todo as the children might have data that would be lost otherwise
elif len(i) > 1 and not i[0]['description']:
i[0]['description'] = '<Empty>'

child_todo = self.add_child(kind="todo", index=len(self.todos))
child_todo.from_data(i, overwrite_uuid)

Expand Down
1 change: 1 addition & 0 deletions dooit/ui/widgets/help_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def generate_kb_table(
"move to top": "Move to top of list",
"move to bottom": "Move to bottom of list",
"toggle expand": "Toggle-expand highlighted item",
"toggle expand recursive": "Toggle-expand highlighted item and all it's children",
"toggle expand parent": "Toggle-expand parent item",
"remove item": "Remove highlighted node",
"add sibling": "Add sibling todo/workspace",
Expand Down
14 changes: 9 additions & 5 deletions dooit/ui/widgets/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
YELLOW = config_man.get("yellow")
GREEN = config_man.get("green")
ORANGE = config_man.get("orange")
COLOR_URGENCY_1 = config_man.get(TODOS.get('urgency1_color'))
COLOR_URGENCY_2 = config_man.get(TODOS.get('urgency2_color'))
COLOR_URGENCY_3 = config_man.get(TODOS.get('urgency3_color'))
COLOR_URGENCY_4 = config_man.get(TODOS.get('urgency4_color'))

DATE_FORMAT = config_man.get("DATE_FORMAT")
TIME_FORMAT = config_man.get("TIME_FORMAT")
Expand Down Expand Up @@ -143,13 +147,13 @@ def draw(self) -> str:
urgency = int(self.model.urgency)
icon = TODOS.get(f"urgency{urgency}_icon")
if urgency == 1:
color = GREEN
color = COLOR_URGENCY_1
elif urgency == 2:
color = YELLOW
elif urgency == 2:
color = ORANGE
color = COLOR_URGENCY_2
elif urgency == 3:
color = COLOR_URGENCY_3
else:
color = RED
color = COLOR_URGENCY_4

return self._render_text_with_color(icon, color)

Expand Down
3 changes: 2 additions & 1 deletion dooit/ui/widgets/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Node(Widget):
pointer_icon = ">"
_expand = False
ModelType: Type[Union[Workspace, Todo]]
_default_display = False

def __init__(self, model, force_display: bool = True):
super().__init__(id=model.uuid)
Expand Down Expand Up @@ -95,7 +96,7 @@ def draw(self) -> Iterator[Widget]:

def compose(self) -> ComposeResult:
if not self.force_display and self.model.nest_level:
self.display = False
self.display = self._default_display

for widget in self.draw():
yield widget
Expand Down
2 changes: 1 addition & 1 deletion dooit/ui/widgets/simple_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ async def keypress(self, key: str) -> None:
# await self._insert_text()
# except Exception:
# return
elif key.startswith('events.Paste:'):
elif key.startswith("events.Paste:"):
await self._insert_text(key[13:])

elif len(key) == 1:
Expand Down
6 changes: 6 additions & 0 deletions dooit/ui/widgets/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

EDITING = config_man.get("TODO").get("editing")
POINTER_ICON = config_man.get("TODO").get("pointer")
EXPANDED = config_man.get("TODO").get("start_expanded")


class TodoGrid(Widget):
Expand All @@ -36,6 +37,7 @@ class TodoGrid(Widget):
class TodoWidget(Node):
ModelType = Todo
pointer_icon = POINTER_ICON
_default_display = EXPANDED

def setup_children(self):
self.status = Status(model=self.model)
Expand All @@ -48,6 +50,10 @@ def setup_children(self):
def _get_model_children(self) -> List[ModelType]:
return self.model.todos

async def set_urgency(self, val: int):
self.model.set_urgency(val)
await self.refresh_value()

async def increase_urgency(self):
self.model.increase_urgency()
await self.refresh_value()
Expand Down
9 changes: 9 additions & 0 deletions dooit/ui/widgets/todo_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
from dooit.api.workspace import Workspace
from dooit.ui.events.events import SwitchTab
from dooit.ui.widgets.todo import TodoWidget
from dooit.utils.conf_reader import config_man
from .tree import Tree

INITIAL_URGENCY = config_man.get("TODO").get("initial_urgency")


class TodoTree(Tree):
"""
Expand All @@ -31,6 +34,12 @@ def model_class_kind(self) -> Literal["todo"]:
def get_children(self, parent: Model) -> List[ModelType]:
return parent.todos

async def add_node(
self, type_: Literal["child", "sibling"], edit: bool = True
) -> None:
await super().add_node(type_, edit=edit)
await self.current.set_urgency(INITIAL_URGENCY)

async def switch_pane(self) -> None:
self.post_message(SwitchTab())

Expand Down
36 changes: 32 additions & 4 deletions dooit/ui/widgets/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ async def force_refresh(self, model: Optional[Model] = None):
async def notify(self, message: str) -> None:
self.post_message(Notify(message))

def next_node(self) -> Optional[WidgetType]:
def next_node(self, is_sibling=False) -> Optional[WidgetType]:
nodes = self.visible_nodes
if not nodes:
return
Expand All @@ -224,7 +224,17 @@ def next_node(self) -> Optional[WidgetType]:
if idx == len(nodes) - 1:
return

return nodes[idx + 1]
next_node = nodes[idx + 1]

while is_sibling:
try:
next_node = nodes[idx + 1]
except IndexError:
return None
if next_node in self.current.siblings:
return next_node
idx += 1
return next_node

def prev_node(self) -> Optional[WidgetType]:
nodes = self.visible_nodes
Expand Down Expand Up @@ -302,6 +312,10 @@ async def add_node(
if type_ == "child"
else self.node.add_sibling()
)
# Neccessary to call this after node creation,
# otherwise the parent node won't show the child_hint until the program
# is restarted or the node gets collapsed and uncollapsed
await self.current.refresh_value()

widget = self.WidgetType(new_node)
if type_ == "sibling":
Expand All @@ -321,7 +335,9 @@ async def remove_item(self) -> None:

widget = self.current

if node := self.next_node():
# We only want to get sibling and not children, otherwise selecting the new
# self.current will crash as it was deleted with its parent
if node := self.next_node(is_sibling=True):
self.current = node
elif node := self.prev_node():
self.current = node
Expand Down Expand Up @@ -369,13 +385,25 @@ async def add_child(self) -> None:
async def add_sibling(self) -> None:
await self.add_node("sibling")

async def toggle_expand(self) -> None:
async def toggle_expand(self, recursive: bool = False) -> None:
if not self.current:
return

self.current.toggle_expand()

if recursive:
nodes = [*self.current.children]
while nodes:
node = nodes.pop()
if isinstance(node, TodoWidget):
nodes.extend(node.children)
node.toggle_expand()

self._rebuild_cache = True

async def toggle_expand_recursive(self) -> None:
await self.toggle_expand(recursive=True)

async def toggle_expand_parent(self) -> None:
if not self.current:
return
Expand Down
2 changes: 2 additions & 0 deletions dooit/ui/widgets/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

EDITING = config_man.get("WORKSPACE").get("editing")
POINTER_ICON = config_man.get("WORKSPACE").get("pointer")
EXPANDED = config_man.get("WORKSPACE").get("start_expanded")


class WorkspaceGrid(Widget):
Expand All @@ -32,6 +33,7 @@ class WorkspaceWidget(Node):

ModelType = Workspace
pointer_icon = POINTER_ICON
_default_display = EXPANDED

def setup_children(self) -> None:
self.description = Description(self.model)
Expand Down
7 changes: 7 additions & 0 deletions dooit/utils/default_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ def stylize(art):
"editing": cyan,
"pointer": ">",
"children_hint": "+", # "[{count}]", # vars: count
"start_expanded": False,
}
EMPTY_WORKSPACE = [
":(",
Expand Down Expand Up @@ -170,6 +171,12 @@ def stylize(art):
"urgency2_icon": "B",
"urgency3_icon": "C",
"urgency4_icon": "D",
"start_expanded": False,
"initial_urgency": 1,
"urgency1_color": "green",
"urgency2_color": "yellow",
"urgency3_color": "orange",
"urgency4_color": "red",
}

EMPTY_TODO = [
Expand Down
1 change: 1 addition & 0 deletions dooit/utils/keybinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def __init__(self, func_name: str, params: List[str]) -> None:
"shift down": ["J", "<shift+down>"],
"edit description": "i",
"toggle expand": "z",
"toggle expand recursive": "<ctrl+z>",
"toggle expand parent": "Z",
"add child": "A",
"add sibling": "a",
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "dooit"
version = "2.1.1"
version = "2.2.0"
description = "A TUI todo manager"
authors = ["kraanzu <kraanzu@gmail.com>"]
maintainers = ["kraanzu <kraanzu@gmail.com>"]
Expand Down Expand Up @@ -29,4 +29,4 @@ requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry.scripts]
dooit = 'dooit.__init__:main'
dooit = 'dooit.__main__:main'

0 comments on commit 9b25fd6

Please sign in to comment.