cli-todo-jd 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
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/cli/cli_entry.py +243 -0
- cli_todo_jd/cli/cli_menu.py +129 -0
- cli_todo_jd/helpers.py +109 -0
- cli_todo_jd/main.py +174 -184
- cli_todo_jd/web/app.py +106 -0
- cli_todo_jd/web/templates/index.html +162 -0
- {cli_todo_jd-0.2.0.dist-info → cli_todo_jd-0.3.0.dist-info}/METADATA +16 -9
- cli_todo_jd-0.3.0.dist-info/RECORD +15 -0
- cli_todo_jd-0.3.0.dist-info/entry_points.txt +4 -0
- cli_todo_jd/cli_entry.py +0 -113
- cli_todo_jd-0.2.0.dist-info/RECORD +0 -11
- cli_todo_jd-0.2.0.dist-info/entry_points.txt +0 -3
- {cli_todo_jd-0.2.0.dist-info → cli_todo_jd-0.3.0.dist-info}/WHEEL +0 -0
- {cli_todo_jd-0.2.0.dist-info → cli_todo_jd-0.3.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>cli-todo-jd</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: dark;
|
|
10
|
+
--bg: #0b0f17;
|
|
11
|
+
--panel: #121a26;
|
|
12
|
+
--border: #263244;
|
|
13
|
+
--text: #e6edf3;
|
|
14
|
+
--muted: #9fb0c0;
|
|
15
|
+
--accent: #6ea8fe;
|
|
16
|
+
--danger: #ff6b6b;
|
|
17
|
+
--ok: #2ecc71;
|
|
18
|
+
--warn: #ffcc66;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
body {
|
|
22
|
+
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
|
23
|
+
margin: 2rem;
|
|
24
|
+
background: var(--bg);
|
|
25
|
+
color: var(--text);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
a { color: var(--accent); }
|
|
29
|
+
|
|
30
|
+
.row { display: flex; gap: 0.5rem; align-items: center; }
|
|
31
|
+
.toolbar { display: flex; gap: 0.75rem; align-items: center; margin-bottom: 1rem; flex-wrap: wrap; }
|
|
32
|
+
|
|
33
|
+
.card {
|
|
34
|
+
background: var(--panel);
|
|
35
|
+
border: 1px solid var(--border);
|
|
36
|
+
border-radius: 12px;
|
|
37
|
+
padding: 1rem;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
table { width: 100%; border-collapse: collapse; }
|
|
41
|
+
th, td { text-align: left; padding: 0.6rem; border-bottom: 1px solid var(--border); }
|
|
42
|
+
th { color: var(--muted); font-weight: 600; }
|
|
43
|
+
|
|
44
|
+
.done { text-decoration: line-through; color: var(--muted); }
|
|
45
|
+
|
|
46
|
+
.badge {
|
|
47
|
+
display: inline-block;
|
|
48
|
+
padding: 0.15rem 0.55rem;
|
|
49
|
+
border-radius: 999px;
|
|
50
|
+
font-size: 0.8rem;
|
|
51
|
+
border: 1px solid var(--border);
|
|
52
|
+
}
|
|
53
|
+
.badge-open { background: rgba(255, 204, 102, 0.12); color: var(--warn); }
|
|
54
|
+
.badge-done { background: rgba(46, 204, 113, 0.12); color: var(--ok); }
|
|
55
|
+
|
|
56
|
+
button {
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
background: #1b2636;
|
|
59
|
+
color: var(--text);
|
|
60
|
+
border: 1px solid var(--border);
|
|
61
|
+
border-radius: 10px;
|
|
62
|
+
padding: 0.4rem 0.7rem;
|
|
63
|
+
}
|
|
64
|
+
button:hover { border-color: #3a4a64; }
|
|
65
|
+
|
|
66
|
+
input[type=text] {
|
|
67
|
+
width: 100%;
|
|
68
|
+
max-width: 32rem;
|
|
69
|
+
padding: 0.55rem 0.7rem;
|
|
70
|
+
background: #0f1622;
|
|
71
|
+
color: var(--text);
|
|
72
|
+
border: 1px solid var(--border);
|
|
73
|
+
border-radius: 10px;
|
|
74
|
+
outline: none;
|
|
75
|
+
}
|
|
76
|
+
input[type=text]:focus { border-color: var(--accent); }
|
|
77
|
+
|
|
78
|
+
select {
|
|
79
|
+
background: #0f1622;
|
|
80
|
+
color: var(--text);
|
|
81
|
+
border: 1px solid var(--border);
|
|
82
|
+
border-radius: 10px;
|
|
83
|
+
padding: 0.4rem 0.6rem;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
hr { border: 0; border-top: 1px solid var(--border); margin: 1rem 0; }
|
|
87
|
+
|
|
88
|
+
.muted { color: var(--muted); font-size: 0.9rem; }
|
|
89
|
+
.danger { color: var(--danger); }
|
|
90
|
+
</style>
|
|
91
|
+
</head>
|
|
92
|
+
<body>
|
|
93
|
+
<h1>Todo</h1>
|
|
94
|
+
|
|
95
|
+
<div class="toolbar">
|
|
96
|
+
<form method="get" action="/" class="row">
|
|
97
|
+
<label>View:</label>
|
|
98
|
+
<select name="show" onchange="this.form.submit()">
|
|
99
|
+
<option value="open" {% if show == 'open' %}selected{% endif %}>Open</option>
|
|
100
|
+
<option value="done" {% if show == 'done' %}selected{% endif %}>Done</option>
|
|
101
|
+
<option value="all" {% if show == 'all' %}selected{% endif %}>All</option>
|
|
102
|
+
</select>
|
|
103
|
+
</form>
|
|
104
|
+
|
|
105
|
+
<span class="muted">DB: {{ config['TODO_DB_PATH'] }}</span>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div class="card" style="margin-bottom: 1rem;">
|
|
109
|
+
<form method="post" action="/add" class="row">
|
|
110
|
+
<input type="text" name="item" placeholder="Add a todo..." autocomplete="off" />
|
|
111
|
+
<button type="submit">Add</button>
|
|
112
|
+
</form>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<div class="card">
|
|
116
|
+
{% if not todos %}
|
|
117
|
+
<p class="muted">No todos.</p>
|
|
118
|
+
{% else %}
|
|
119
|
+
<table>
|
|
120
|
+
<thead>
|
|
121
|
+
<tr>
|
|
122
|
+
<th style="width: 6rem;">ID</th>
|
|
123
|
+
<th>Item</th>
|
|
124
|
+
<th style="width: 8rem;">Status</th>
|
|
125
|
+
<th style="width: 14rem;">Actions</th>
|
|
126
|
+
</tr>
|
|
127
|
+
</thead>
|
|
128
|
+
<tbody>
|
|
129
|
+
{% for t in todos %}
|
|
130
|
+
<tr>
|
|
131
|
+
<td>{{ t['id'] }}</td>
|
|
132
|
+
<td class="{% if t['done'] %}done{% endif %}">{{ t['item'] }}</td>
|
|
133
|
+
<td>
|
|
134
|
+
{% if t['done'] %}
|
|
135
|
+
<span class="badge badge-done">done</span>
|
|
136
|
+
{% else %}
|
|
137
|
+
<span class="badge badge-open">open</span>
|
|
138
|
+
{% endif %}
|
|
139
|
+
</td>
|
|
140
|
+
<td>
|
|
141
|
+
<form method="post" action="/toggle/{{ t['id'] }}" style="display:inline">
|
|
142
|
+
<button type="submit">Toggle</button>
|
|
143
|
+
</form>
|
|
144
|
+
<form method="post" action="/delete/{{ t['id'] }}" style="display:inline" onsubmit="return confirm('Delete this todo?');">
|
|
145
|
+
<button type="submit" class="danger">Delete</button>
|
|
146
|
+
</form>
|
|
147
|
+
</td>
|
|
148
|
+
</tr>
|
|
149
|
+
{% endfor %}
|
|
150
|
+
</tbody>
|
|
151
|
+
</table>
|
|
152
|
+
{% endif %}
|
|
153
|
+
|
|
154
|
+
<hr />
|
|
155
|
+
|
|
156
|
+
<form method="post" action="/clear" onsubmit="return confirm('Clear ALL todos?');" class="row">
|
|
157
|
+
<input type="hidden" name="confirm" value="yes" />
|
|
158
|
+
<button type="submit" class="danger">Clear all</button>
|
|
159
|
+
</form>
|
|
160
|
+
</div>
|
|
161
|
+
</body>
|
|
162
|
+
</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
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
cli_todo_jd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
cli_todo_jd/helpers.py,sha256=99CXN-i_k8FZgmxprJ-aw-O_wM-t2PIhTngjluxHd3w,2655
|
|
3
|
+
cli_todo_jd/main.py,sha256=065lH4-lhD1r568E2V__bUxCv_Ta8-tCZMHd4zkPyq4,15020
|
|
4
|
+
cli_todo_jd/cli/cli_entry.py,sha256=o4vkuRq0w2JQF34zqWxF6IqrwcelnMlvYyjKdVFuPZM,7250
|
|
5
|
+
cli_todo_jd/cli/cli_menu.py,sha256=2pzcG9X5xA8-3KdqOklZTOquFh7KDw3pI7vhXMwNOBU,4156
|
|
6
|
+
cli_todo_jd/storage/__init__.py,sha256=u0jMfDuUIEy9mor1dVeIiAE0Cap6FL77tW9GlsyskYU,210
|
|
7
|
+
cli_todo_jd/storage/migrate.py,sha256=Ij_0OwTvibow79KVilf2O2nfMuohj0raarVV7OcjwbY,3063
|
|
8
|
+
cli_todo_jd/storage/schema.py,sha256=r5BTtcRn8J72_b8NJlryYnd_aiuy0y00eX01QavKE98,1824
|
|
9
|
+
cli_todo_jd/web/app.py,sha256=5RBABRdsEMtsNid0r7RpwWQ9IMToYsuR0LPfpbl5tA0,3602
|
|
10
|
+
cli_todo_jd/web/templates/index.html,sha256=7jG9OejO9Cf9Y0Yx5KmE5z_vWo7ivx4X6hiWrVvoizA,5086
|
|
11
|
+
cli_todo_jd-0.3.0.dist-info/METADATA,sha256=5sP1pRaY3omt4j42QGi0A8-zciBmt1igcm7ced3mfS8,3320
|
|
12
|
+
cli_todo_jd-0.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
+
cli_todo_jd-0.3.0.dist-info/entry_points.txt,sha256=9AycU3OqgPkmeF5oRwjls2t6P_zRJNGgEScZskA5Rm8,149
|
|
14
|
+
cli_todo_jd-0.3.0.dist-info/top_level.txt,sha256=hOnYr7w1JdQs6MlD1Uzjt24Ca8nvriOWNNq6NaqgHqM,12
|
|
15
|
+
cli_todo_jd-0.3.0.dist-info/RECORD,,
|
cli_todo_jd/cli_entry.py
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from argparse import ArgumentParser
|
|
4
|
-
from cli_todo_jd.main import (
|
|
5
|
-
add_item_to_list,
|
|
6
|
-
remove_item_from_list,
|
|
7
|
-
list_items_on_list,
|
|
8
|
-
clear_list_of_items,
|
|
9
|
-
cli_menu,
|
|
10
|
-
mark_item_as_done,
|
|
11
|
-
mark_item_as_not_done,
|
|
12
|
-
)
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
import typer
|
|
15
|
-
|
|
16
|
-
app = typer.Typer(help="A tiny todo CLI built with Typer.")
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@app.command()
|
|
20
|
-
def add(
|
|
21
|
-
text: list[str] = typer.Argument(..., help="Todo item text (no quotes needed)."),
|
|
22
|
-
filepath: Path = typer.Option(
|
|
23
|
-
Path(".todo_list.db"),
|
|
24
|
-
"--filepath",
|
|
25
|
-
"-f",
|
|
26
|
-
help="Path to the JSON file used for storage.",
|
|
27
|
-
),
|
|
28
|
-
) -> None:
|
|
29
|
-
full_text = " ".join(text).strip()
|
|
30
|
-
if not full_text:
|
|
31
|
-
raise typer.BadParameter("Todo item text cannot be empty.")
|
|
32
|
-
|
|
33
|
-
add_item_to_list(full_text, filepath)
|
|
34
|
-
typer.echo(f"Added: {full_text}")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@app.command(name="list")
|
|
38
|
-
def list_(
|
|
39
|
-
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
40
|
-
) -> None:
|
|
41
|
-
list_items_on_list(filepath)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@app.command()
|
|
45
|
-
def remove(
|
|
46
|
-
index: int = typer.Argument(..., help="1-based index of item to remove."),
|
|
47
|
-
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
48
|
-
) -> None:
|
|
49
|
-
remove_item_from_list(index, filepath)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@app.command()
|
|
53
|
-
def clear(
|
|
54
|
-
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt."),
|
|
55
|
-
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
56
|
-
) -> None:
|
|
57
|
-
if not yes and not typer.confirm(f"Clear all todos in {filepath}?"):
|
|
58
|
-
typer.echo("Cancelled.")
|
|
59
|
-
raise typer.Exit(code=1)
|
|
60
|
-
|
|
61
|
-
clear_list_of_items(filepath)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@app.command(name="menu")
|
|
65
|
-
def menu_(
|
|
66
|
-
filepath: Path = typer.Option(
|
|
67
|
-
Path(".todo_list.db"),
|
|
68
|
-
"--filepath",
|
|
69
|
-
"-f",
|
|
70
|
-
help="Path to the JSON file used for storage.",
|
|
71
|
-
),
|
|
72
|
-
) -> None:
|
|
73
|
-
cli_menu(filepath)
|
|
74
|
-
typer.echo("Exited menu.")
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
@app.command()
|
|
78
|
-
def done(
|
|
79
|
-
index: int = typer.Argument(..., help="1-based index of item to mark as done."),
|
|
80
|
-
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
81
|
-
) -> None:
|
|
82
|
-
mark_item_as_done(index, filepath)
|
|
83
|
-
list_(filepath=filepath)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@app.command()
|
|
87
|
-
def not_done(
|
|
88
|
-
index: int = typer.Argument(..., help="1-based index of item to mark as done."),
|
|
89
|
-
filepath: Path = typer.Option(Path(".todo_list.db"), "--filepath", "-f"),
|
|
90
|
-
) -> None:
|
|
91
|
-
mark_item_as_not_done(index, filepath)
|
|
92
|
-
list_(filepath=filepath)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def parser_optional_args(parser: ArgumentParser):
|
|
96
|
-
parser.add_argument(
|
|
97
|
-
"-f",
|
|
98
|
-
"--filepath",
|
|
99
|
-
help="Path to the file to process",
|
|
100
|
-
default="./.todo_list.db",
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def todo_menu():
|
|
105
|
-
parser = ArgumentParser(description="Todo List CLI Menu")
|
|
106
|
-
parser_optional_args(parser)
|
|
107
|
-
args = parser.parse_args()
|
|
108
|
-
|
|
109
|
-
cli_menu(filepath=args.filepath)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if __name__ == "__main__":
|
|
113
|
-
app()
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
cli_todo_jd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
cli_todo_jd/cli_entry.py,sha256=sKp-aIWVldH8DiXv22bokjlIiJcAZshKHdLEqjM09HA,2877
|
|
3
|
-
cli_todo_jd/main.py,sha256=AN22ojW0iIXArJQmtEjQ1jSdAb7Z-xr8i4NIEE4xAQ0,13965
|
|
4
|
-
cli_todo_jd/storage/__init__.py,sha256=u0jMfDuUIEy9mor1dVeIiAE0Cap6FL77tW9GlsyskYU,210
|
|
5
|
-
cli_todo_jd/storage/migrate.py,sha256=Ij_0OwTvibow79KVilf2O2nfMuohj0raarVV7OcjwbY,3063
|
|
6
|
-
cli_todo_jd/storage/schema.py,sha256=r5BTtcRn8J72_b8NJlryYnd_aiuy0y00eX01QavKE98,1824
|
|
7
|
-
cli_todo_jd-0.2.0.dist-info/METADATA,sha256=rra5GQZYrK8xCKX3pUaW0wnmw_pujlKR8bpOIVH-a1U,2982
|
|
8
|
-
cli_todo_jd-0.2.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
9
|
-
cli_todo_jd-0.2.0.dist-info/entry_points.txt,sha256=BIfrMKcC340A79aXHg34nnhiDsXh7c9hPck1k-Rb28c,95
|
|
10
|
-
cli_todo_jd-0.2.0.dist-info/top_level.txt,sha256=hOnYr7w1JdQs6MlD1Uzjt24Ca8nvriOWNNq6NaqgHqM,12
|
|
11
|
-
cli_todo_jd-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|