cli-todo-jd 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cli_todo_jd-0.3.0/MANIFEST.in +1 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/PKG-INFO +16 -9
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/README.md +14 -8
- cli_todo_jd-0.3.0/cli_todo_jd/cli/cli_entry.py +243 -0
- cli_todo_jd-0.3.0/cli_todo_jd/cli/cli_menu.py +129 -0
- cli_todo_jd-0.3.0/cli_todo_jd/helpers.py +109 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd/main.py +174 -184
- cli_todo_jd-0.3.0/cli_todo_jd/web/app.py +106 -0
- cli_todo_jd-0.3.0/cli_todo_jd/web/templates/index.html +162 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd.egg-info/PKG-INFO +16 -9
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd.egg-info/SOURCES.txt +7 -2
- cli_todo_jd-0.3.0/cli_todo_jd.egg-info/entry_points.txt +4 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd.egg-info/requires.txt +1 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/pyproject.toml +6 -4
- cli_todo_jd-0.2.0/cli_todo_jd/cli_entry.py +0 -113
- cli_todo_jd-0.2.0/cli_todo_jd.egg-info/entry_points.txt +0 -3
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd/__init__.py +0 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd/storage/__init__.py +0 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd/storage/migrate.py +0 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd/storage/schema.py +0 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd.egg-info/dependency_links.txt +0 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/cli_todo_jd.egg-info/top_level.txt +0 -0
- {cli_todo_jd-0.2.0 → cli_todo_jd-0.3.0}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include cli_todo_jd/web/templates/index.html
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cli-todo-jd
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
Requires-Dist: questionary>=2.1.1
|
|
8
8
|
Requires-Dist: rich>=14.2.0
|
|
9
9
|
Requires-Dist: typer>=0.21.1
|
|
10
|
+
Requires-Dist: flask>=3.0.0
|
|
10
11
|
Provides-Extra: dev
|
|
11
12
|
Requires-Dist: pre-commit; extra == "dev"
|
|
12
13
|
Requires-Dist: pytest; extra == "dev"
|
|
@@ -19,23 +20,29 @@ A command line to do list with interactive menu
|
|
|
19
20
|
## What is`cli-todo-jd`?
|
|
20
21
|
|
|
21
22
|
This is a command line interface todo list. Once installed, there are two ways to interact
|
|
22
|
-
with the list
|
|
23
|
+
with the list stored as a sqlite database
|
|
23
24
|
|
|
24
|
-
### `
|
|
25
|
+
### `todo menu`
|
|
25
26
|
|
|
26
|
-
Once installed use `
|
|
27
|
+
Once installed use `todo menu` to launch into the interactive menu. From here you can add,
|
|
27
28
|
remove, list, or clear your todo list. Items in your list are stored (by default) as
|
|
28
|
-
`.todo_list.
|
|
29
|
+
`.todo_list.db`. The menu does also support optional filepaths using `-f` or `--filepath`.
|
|
30
|
+
|
|
31
|
+
### `todo web`
|
|
32
|
+
|
|
33
|
+
Once installed use `todo web` to launch into the interactive web UI. From here you can add,
|
|
34
|
+
remove, list, or clear your todo list. Items in your list are stored (by default) as
|
|
35
|
+
`.todo_list.db`. The menu does also support optional filepaths using `-f` or `--filepath`.
|
|
29
36
|
|
|
30
37
|
|
|
31
38
|
### interacting with todo list without menu
|
|
32
39
|
|
|
33
40
|
Alternately you can interact directly using the following commands (`--filepath can be substituted for -f`)
|
|
34
41
|
|
|
35
|
-
- `
|
|
36
|
-
- `
|
|
37
|
-
- `
|
|
38
|
-
- `
|
|
42
|
+
- `todo add text --filepath optional_path_to_json` used to add an item to your list
|
|
43
|
+
- `todo remove index --filepath optional_path_to_json` used to remove item number `index`
|
|
44
|
+
- `todo list --filepath optional_path_to_json` used to view list
|
|
45
|
+
- `todo clear --filepath optional_path_to_json` used to clear list (prompts y/n to confirm)
|
|
39
46
|
|
|
40
47
|
## Getting started
|
|
41
48
|
|
|
@@ -5,23 +5,29 @@ A command line to do list with interactive menu
|
|
|
5
5
|
## What is`cli-todo-jd`?
|
|
6
6
|
|
|
7
7
|
This is a command line interface todo list. Once installed, there are two ways to interact
|
|
8
|
-
with the list
|
|
8
|
+
with the list stored as a sqlite database
|
|
9
9
|
|
|
10
|
-
### `
|
|
10
|
+
### `todo menu`
|
|
11
11
|
|
|
12
|
-
Once installed use `
|
|
12
|
+
Once installed use `todo menu` to launch into the interactive menu. From here you can add,
|
|
13
13
|
remove, list, or clear your todo list. Items in your list are stored (by default) as
|
|
14
|
-
`.todo_list.
|
|
14
|
+
`.todo_list.db`. The menu does also support optional filepaths using `-f` or `--filepath`.
|
|
15
|
+
|
|
16
|
+
### `todo web`
|
|
17
|
+
|
|
18
|
+
Once installed use `todo web` to launch into the interactive web UI. From here you can add,
|
|
19
|
+
remove, list, or clear your todo list. Items in your list are stored (by default) as
|
|
20
|
+
`.todo_list.db`. The menu does also support optional filepaths using `-f` or `--filepath`.
|
|
15
21
|
|
|
16
22
|
|
|
17
23
|
### interacting with todo list without menu
|
|
18
24
|
|
|
19
25
|
Alternately you can interact directly using the following commands (`--filepath can be substituted for -f`)
|
|
20
26
|
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
- `
|
|
24
|
-
- `
|
|
27
|
+
- `todo add text --filepath optional_path_to_json` used to add an item to your list
|
|
28
|
+
- `todo remove index --filepath optional_path_to_json` used to remove item number `index`
|
|
29
|
+
- `todo list --filepath optional_path_to_json` used to view list
|
|
30
|
+
- `todo clear --filepath optional_path_to_json` used to clear list (prompts y/n to confirm)
|
|
25
31
|
|
|
26
32
|
## Getting started
|
|
27
33
|
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from argparse import ArgumentParser
|
|
4
|
+
from cli_todo_jd.helpers import (
|
|
5
|
+
add_item_to_list,
|
|
6
|
+
remove_item_from_list,
|
|
7
|
+
remove_item_from_list_by_id,
|
|
8
|
+
list_items_on_list,
|
|
9
|
+
clear_list_of_items,
|
|
10
|
+
mark_item_as_done,
|
|
11
|
+
mark_item_as_not_done,
|
|
12
|
+
mark_item_as_done_by_id,
|
|
13
|
+
mark_item_as_not_done_by_id,
|
|
14
|
+
edit_item_in_list_by_id,
|
|
15
|
+
)
|
|
16
|
+
from cli_todo_jd.cli.cli_menu import cli_menu
|
|
17
|
+
from cli_todo_jd.web.app import run_web
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
import typer
|
|
20
|
+
|
|
21
|
+
app = typer.Typer(help="A tiny todo CLI built with Typer.")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@app.command()
|
|
25
|
+
def add(
|
|
26
|
+
text: list[str] = typer.Argument(..., help="Todo item text (no quotes needed)."),
|
|
27
|
+
filepath: Path = typer.Option(
|
|
28
|
+
Path(".todo_list.db"),
|
|
29
|
+
"--filepath",
|
|
30
|
+
"-f",
|
|
31
|
+
help="Path to the JSON file used for storage.",
|
|
32
|
+
),
|
|
33
|
+
) -> None:
|
|
34
|
+
full_text = " ".join(text).strip()
|
|
35
|
+
if not full_text:
|
|
36
|
+
raise typer.BadParameter("Todo item text cannot be empty.")
|
|
37
|
+
|
|
38
|
+
add_item_to_list(full_text, filepath)
|
|
39
|
+
typer.echo(f"Added: {full_text}")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@app.command(name="list")
|
|
43
|
+
def list_(
|
|
44
|
+
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
45
|
+
show_all: bool = typer.Option(
|
|
46
|
+
False, "--all", "-a", help="Show all todos (open + done)."
|
|
47
|
+
),
|
|
48
|
+
show_done: bool = typer.Option(
|
|
49
|
+
False, "--done", "-d", help="Show only completed todos."
|
|
50
|
+
),
|
|
51
|
+
show_open: bool = typer.Option(
|
|
52
|
+
False, "--open", "-o", help="Show only open todos (default)."
|
|
53
|
+
),
|
|
54
|
+
) -> None:
|
|
55
|
+
"""List todos.
|
|
56
|
+
|
|
57
|
+
Examples
|
|
58
|
+
--------
|
|
59
|
+
- todo list
|
|
60
|
+
- todo list --done
|
|
61
|
+
- todo list --all
|
|
62
|
+
- todo list -a
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
# Choose filter. If nothing specified, default to open.
|
|
66
|
+
# If the user specifies multiple flags, error out.
|
|
67
|
+
flags = [show_all, show_done, show_open]
|
|
68
|
+
if sum(1 for f in flags if f) > 1:
|
|
69
|
+
raise typer.BadParameter(
|
|
70
|
+
"Use only one of: --all / -a, --done / -d, --open / -o"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if show_all:
|
|
74
|
+
show = "all"
|
|
75
|
+
elif show_done:
|
|
76
|
+
show = "done"
|
|
77
|
+
else:
|
|
78
|
+
# default is open (or explicit --open)
|
|
79
|
+
show = "open"
|
|
80
|
+
|
|
81
|
+
list_items_on_list(filepath, show=show)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@app.command()
|
|
85
|
+
def remove(
|
|
86
|
+
todo_id: int | None = typer.Argument(None, help="Todo ID to remove (preferred)."),
|
|
87
|
+
index: int | None = typer.Option(
|
|
88
|
+
None,
|
|
89
|
+
"--index",
|
|
90
|
+
"-i",
|
|
91
|
+
help="1-based display index (legacy; use ID instead).",
|
|
92
|
+
),
|
|
93
|
+
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
94
|
+
) -> None:
|
|
95
|
+
if todo_id is None and index is None:
|
|
96
|
+
raise typer.BadParameter("Provide either TODO_ID argument or --index/-i")
|
|
97
|
+
if todo_id is not None and index is not None:
|
|
98
|
+
raise typer.BadParameter("Provide either TODO_ID or --index/-i, not both")
|
|
99
|
+
|
|
100
|
+
if todo_id is not None:
|
|
101
|
+
remove_item_from_list_by_id(todo_id, filepath)
|
|
102
|
+
else:
|
|
103
|
+
remove_item_from_list(index, filepath)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@app.command()
|
|
107
|
+
def clear(
|
|
108
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt."),
|
|
109
|
+
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
110
|
+
) -> None:
|
|
111
|
+
if not yes and not typer.confirm(f"Clear all todos in {filepath}?"):
|
|
112
|
+
typer.echo("Cancelled.")
|
|
113
|
+
raise typer.Exit(code=1)
|
|
114
|
+
|
|
115
|
+
clear_list_of_items(filepath)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@app.command()
|
|
119
|
+
def edit(
|
|
120
|
+
todo_id: int = typer.Argument(..., help="Todo ID to edit."),
|
|
121
|
+
new_text: list[str] = typer.Argument(..., help="New text for the todo item."),
|
|
122
|
+
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
123
|
+
) -> None:
|
|
124
|
+
new_text_stripped = " ".join(new_text).strip()
|
|
125
|
+
if not new_text_stripped:
|
|
126
|
+
raise typer.BadParameter("New todo item text cannot be empty.")
|
|
127
|
+
|
|
128
|
+
edit_item_in_list_by_id(todo_id, new_text_stripped, filepath)
|
|
129
|
+
typer.echo(f'Edited todo ID {todo_id} to: "{new_text_stripped}"')
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@app.command(name="menu")
|
|
133
|
+
def menu_(
|
|
134
|
+
filepath: Path = typer.Option(
|
|
135
|
+
Path(".todo_list.db"),
|
|
136
|
+
"--filepath",
|
|
137
|
+
"-f",
|
|
138
|
+
help="Path to the JSON file used for storage.",
|
|
139
|
+
),
|
|
140
|
+
) -> None:
|
|
141
|
+
cli_menu(filepath)
|
|
142
|
+
typer.echo("Exited menu.")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@app.command()
|
|
146
|
+
def done(
|
|
147
|
+
todo_id: int | None = typer.Argument(
|
|
148
|
+
None, help="Todo ID to mark as done (preferred)."
|
|
149
|
+
),
|
|
150
|
+
index: int | None = typer.Option(
|
|
151
|
+
None,
|
|
152
|
+
"--index",
|
|
153
|
+
"-i",
|
|
154
|
+
help="1-based display index (legacy; use ID instead).",
|
|
155
|
+
),
|
|
156
|
+
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
157
|
+
) -> None:
|
|
158
|
+
if todo_id is None and index is None:
|
|
159
|
+
raise typer.BadParameter("Provide either TODO_ID argument or --index/-i")
|
|
160
|
+
if todo_id is not None and index is not None:
|
|
161
|
+
raise typer.BadParameter("Provide either TODO_ID or --index/-i, not both")
|
|
162
|
+
|
|
163
|
+
if todo_id is not None:
|
|
164
|
+
mark_item_as_done_by_id(todo_id, filepath)
|
|
165
|
+
else:
|
|
166
|
+
mark_item_as_done(index, filepath)
|
|
167
|
+
|
|
168
|
+
list_items_on_list(filepath=filepath, show="all")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@app.command(name="not-done")
|
|
172
|
+
def not_done(
|
|
173
|
+
todo_id: int | None = typer.Argument(
|
|
174
|
+
None, help="Todo ID to mark as not done (preferred)."
|
|
175
|
+
),
|
|
176
|
+
index: int | None = typer.Option(
|
|
177
|
+
None,
|
|
178
|
+
"--index",
|
|
179
|
+
"-i",
|
|
180
|
+
help="1-based display index (legacy; use ID instead).",
|
|
181
|
+
),
|
|
182
|
+
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
183
|
+
) -> None:
|
|
184
|
+
if todo_id is None and index is None:
|
|
185
|
+
raise typer.BadParameter("Provide either TODO_ID argument or --index/-i")
|
|
186
|
+
if todo_id is not None and index is not None:
|
|
187
|
+
raise typer.BadParameter("Provide either TODO_ID or --index/-i, not both")
|
|
188
|
+
|
|
189
|
+
if todo_id is not None:
|
|
190
|
+
mark_item_as_not_done_by_id(todo_id, filepath)
|
|
191
|
+
else:
|
|
192
|
+
mark_item_as_not_done(index, filepath)
|
|
193
|
+
|
|
194
|
+
list_items_on_list(filepath=filepath, show="all")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@app.command()
|
|
198
|
+
def web(
|
|
199
|
+
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
200
|
+
host: str = typer.Option(
|
|
201
|
+
"127.0.0.1", help="Host interface to bind the web server."
|
|
202
|
+
),
|
|
203
|
+
port: int = typer.Option(8000, help="Port to run the web server on."),
|
|
204
|
+
debug: bool = typer.Option(False, help="Run Flask in debug mode."),
|
|
205
|
+
) -> None:
|
|
206
|
+
"""Run a local web UI for your todo list."""
|
|
207
|
+
run_web(filepath, host=host, port=port, debug=debug)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def parser_optional_args(parser: ArgumentParser):
|
|
211
|
+
parser.add_argument(
|
|
212
|
+
"-f",
|
|
213
|
+
"--filepath",
|
|
214
|
+
help="Path to the file to process",
|
|
215
|
+
default="./.todo_list.db",
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def todo_menu():
|
|
220
|
+
parser = ArgumentParser(description="Todo List CLI Menu")
|
|
221
|
+
parser_optional_args(parser)
|
|
222
|
+
args = parser.parse_args()
|
|
223
|
+
|
|
224
|
+
cli_menu(filepath=args.filepath)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def todo_web():
|
|
228
|
+
parser = ArgumentParser(description="Todo List Web Server")
|
|
229
|
+
parser_optional_args(parser)
|
|
230
|
+
parser.add_argument(
|
|
231
|
+
"--host", help="Host interface to bind the web server.", default="127.0.0.1"
|
|
232
|
+
)
|
|
233
|
+
parser.add_argument(
|
|
234
|
+
"--port", help="Port to run the web server on.", default=8000, type=int
|
|
235
|
+
)
|
|
236
|
+
parser.add_argument("--debug", help="Run Flask in debug mode.", action="store_true")
|
|
237
|
+
args = parser.parse_args()
|
|
238
|
+
|
|
239
|
+
run_web(db_path=args.filepath, host=args.host, port=args.port, debug=args.debug)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
if __name__ == "__main__":
|
|
243
|
+
app()
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from questionary import Style
|
|
2
|
+
import questionary
|
|
3
|
+
from cli_todo_jd.helpers import create_list
|
|
4
|
+
|
|
5
|
+
custom_style = Style(
|
|
6
|
+
[
|
|
7
|
+
("qmark", "fg:#ff9d00 bold"),
|
|
8
|
+
("question", "bold"),
|
|
9
|
+
("answer", "fg:#ff9d00 bold"),
|
|
10
|
+
("pointer", "fg:#ff9d00 bold"),
|
|
11
|
+
("highlighted", "fg:#ff9d00 bold"),
|
|
12
|
+
("selected", "fg:#ff9d00 bold"),
|
|
13
|
+
("separator", "fg:#ff9d00 bold"),
|
|
14
|
+
("instruction", ""), # default
|
|
15
|
+
("text", ""),
|
|
16
|
+
("disabled", "fg:#ff9d00 italic"),
|
|
17
|
+
]
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def cli_menu(filepath="./.todo_list.db"):
|
|
22
|
+
"""
|
|
23
|
+
Display the command-line interface menu for the todo list.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
filepath : str, optional
|
|
28
|
+
The file path to the JSON file for storing todos, by default "./.todo_list.db"
|
|
29
|
+
"""
|
|
30
|
+
app = create_list(file_path_to_db=filepath)
|
|
31
|
+
while True:
|
|
32
|
+
action = questionary.select(
|
|
33
|
+
"What would you like to do?",
|
|
34
|
+
choices=[
|
|
35
|
+
"Add todo",
|
|
36
|
+
"List todos",
|
|
37
|
+
"Update todo status",
|
|
38
|
+
"Remove todo",
|
|
39
|
+
"Edit todo",
|
|
40
|
+
"Clear all todos",
|
|
41
|
+
"Exit",
|
|
42
|
+
],
|
|
43
|
+
style=custom_style,
|
|
44
|
+
).ask()
|
|
45
|
+
|
|
46
|
+
if action == "Add todo":
|
|
47
|
+
item = questionary.text("Enter the todo item:", style=custom_style).ask()
|
|
48
|
+
app.add_todo(item)
|
|
49
|
+
elif action == "List todos":
|
|
50
|
+
app.list_todos(show="all")
|
|
51
|
+
elif action == "Update todo status":
|
|
52
|
+
app.reload_todos()
|
|
53
|
+
if not app.todos:
|
|
54
|
+
print("No todos to update.")
|
|
55
|
+
continue
|
|
56
|
+
todo_choice = questionary.select(
|
|
57
|
+
"Select the todo to update:",
|
|
58
|
+
choices=["<Back>"] + app.todos,
|
|
59
|
+
style=custom_style,
|
|
60
|
+
).ask()
|
|
61
|
+
|
|
62
|
+
if todo_choice == "<Back>" or todo_choice is None:
|
|
63
|
+
continue
|
|
64
|
+
|
|
65
|
+
todo_index = app.todos.index(todo_choice) + 1
|
|
66
|
+
status_choice = questionary.select(
|
|
67
|
+
"Mark as:",
|
|
68
|
+
choices=["Done", "Not Done", "<Back>"],
|
|
69
|
+
style=custom_style,
|
|
70
|
+
).ask()
|
|
71
|
+
|
|
72
|
+
if status_choice == "<Back>" or status_choice is None:
|
|
73
|
+
continue
|
|
74
|
+
elif status_choice == "Done":
|
|
75
|
+
app.mark_as_done(todo_index)
|
|
76
|
+
elif status_choice == "Not Done":
|
|
77
|
+
app.mark_as_not_done(todo_index)
|
|
78
|
+
app.list_todos(show="all")
|
|
79
|
+
elif action == "Remove todo":
|
|
80
|
+
app.reload_todos()
|
|
81
|
+
if not app.todos:
|
|
82
|
+
print("No todos to remove.")
|
|
83
|
+
continue
|
|
84
|
+
todo_choice = questionary.select(
|
|
85
|
+
"Select the todo to remove:",
|
|
86
|
+
choices=["<Back>"] + app.todos,
|
|
87
|
+
style=custom_style,
|
|
88
|
+
).ask()
|
|
89
|
+
|
|
90
|
+
if todo_choice == "<Back>" or todo_choice is None:
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
todo_to_remove = app.todos.index(todo_choice) + 1
|
|
94
|
+
app.remove_todo(todo_to_remove)
|
|
95
|
+
elif action == "Edit todo":
|
|
96
|
+
app.reload_todos()
|
|
97
|
+
if not app.todos:
|
|
98
|
+
print("No todos to edit.")
|
|
99
|
+
continue
|
|
100
|
+
todo_choice = questionary.select(
|
|
101
|
+
"Select the todo to edit:",
|
|
102
|
+
choices=["<Back>"] + app.todos,
|
|
103
|
+
style=custom_style,
|
|
104
|
+
).ask()
|
|
105
|
+
|
|
106
|
+
if todo_choice == "<Back>" or todo_choice is None:
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
todo_index = app.todos.index(todo_choice) + 1
|
|
110
|
+
new_text = questionary.text(
|
|
111
|
+
"Enter the new text for the todo:",
|
|
112
|
+
default=todo_choice,
|
|
113
|
+
style=custom_style,
|
|
114
|
+
).ask()
|
|
115
|
+
|
|
116
|
+
if new_text is None:
|
|
117
|
+
continue
|
|
118
|
+
app.edit_entry(todo_index, new_text)
|
|
119
|
+
|
|
120
|
+
elif action == "Clear all todos":
|
|
121
|
+
confirm = questionary.confirm(
|
|
122
|
+
"Are you sure you want to clear all todos?", style=custom_style
|
|
123
|
+
).ask()
|
|
124
|
+
if confirm:
|
|
125
|
+
app.clear_all()
|
|
126
|
+
elif action == "Exit":
|
|
127
|
+
break
|
|
128
|
+
else:
|
|
129
|
+
break
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from cli_todo_jd.main import TodoApp
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def create_list(file_path_to_db: str = "./.todo_list.db"):
|
|
5
|
+
"""
|
|
6
|
+
Create a new todo list.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
file_path_to_db : str, optional
|
|
11
|
+
The file path to the JSON file for storing todos, by default "./.todo_list.db"
|
|
12
|
+
|
|
13
|
+
Returns
|
|
14
|
+
-------
|
|
15
|
+
TodoApp
|
|
16
|
+
An instance of the TodoApp class.
|
|
17
|
+
"""
|
|
18
|
+
app = TodoApp(file_path_to_db=file_path_to_db)
|
|
19
|
+
return app
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def add_item_to_list(item: str, filepath: str):
|
|
23
|
+
"""
|
|
24
|
+
Add a new item to the todo list.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
item : str
|
|
29
|
+
The todo item to add.
|
|
30
|
+
filepath : str
|
|
31
|
+
The file path to the JSON file for storing todos.
|
|
32
|
+
"""
|
|
33
|
+
app = create_list(file_path_to_db=filepath)
|
|
34
|
+
app.add_todo(item)
|
|
35
|
+
app.list_todos()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def list_items_on_list(filepath: str, show: str = "open"):
|
|
39
|
+
"""List items in the todo list.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
filepath:
|
|
44
|
+
The SQLite database path.
|
|
45
|
+
show:
|
|
46
|
+
"open" (default), "done", or "all".
|
|
47
|
+
"""
|
|
48
|
+
app = create_list(file_path_to_db=filepath)
|
|
49
|
+
app.list_todos(show=show)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def remove_item_from_list(index: int, filepath: str):
|
|
53
|
+
"""
|
|
54
|
+
remove an item from the todo list using index
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
index : int
|
|
59
|
+
The index of the todo item to remove.
|
|
60
|
+
filepath : str
|
|
61
|
+
The file path to the JSON file for storing todos.
|
|
62
|
+
"""
|
|
63
|
+
app = create_list(file_path_to_db=filepath)
|
|
64
|
+
app.remove_todo(index)
|
|
65
|
+
app.list_todos()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def clear_list_of_items(filepath: str):
|
|
69
|
+
"""
|
|
70
|
+
Clear all items from the todo list.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
filepath : str
|
|
75
|
+
The file path to the JSON file for storing todos.
|
|
76
|
+
"""
|
|
77
|
+
app = create_list(file_path_to_db=filepath)
|
|
78
|
+
app.clear_all()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def mark_item_as_done(index: int, filepath: str):
|
|
82
|
+
app = create_list(file_path_to_db=filepath)
|
|
83
|
+
app.mark_as_done(index)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def mark_item_as_not_done(index: int, filepath: str):
|
|
87
|
+
app = create_list(file_path_to_db=filepath)
|
|
88
|
+
app.mark_as_not_done(index)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def remove_item_from_list_by_id(todo_id: int, filepath: str):
|
|
92
|
+
app = create_list(file_path_to_db=filepath)
|
|
93
|
+
app.remove_by_id(todo_id)
|
|
94
|
+
app.list_todos(show="all")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def mark_item_as_done_by_id(todo_id: int, filepath: str):
|
|
98
|
+
app = create_list(file_path_to_db=filepath)
|
|
99
|
+
app.mark_done_by_id(todo_id)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def mark_item_as_not_done_by_id(todo_id: int, filepath: str):
|
|
103
|
+
app = create_list(file_path_to_db=filepath)
|
|
104
|
+
app.mark_not_done_by_id(todo_id)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def edit_item_in_list_by_id(todo_id: int, new_text: str, filepath: str):
|
|
108
|
+
app = create_list(file_path_to_db=filepath)
|
|
109
|
+
app.edit_by_id(todo_id, new_text)
|