usecli 0.1.68__tar.gz → 0.1.70__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.
- {usecli-0.1.68 → usecli-0.1.70}/PKG-INFO +1 -1
- {usecli-0.1.68 → usecli-0.1.70}/pyproject.toml +1 -1
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/__init__.py +26 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/base_command.py +1 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/ui/list.py +65 -23
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/services/command_service.py +35 -0
- {usecli-0.1.68 → usecli-0.1.70}/LICENSE +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/README.md +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/README.md +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/custom/README.md +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/custom/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/base/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/base/about_command.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/base/help_command.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/base/inspire_command.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/base/internal/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/base/internal/fzf_command.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/core/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/core/utils.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/make/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/make/make_command.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/make/make_theme_command.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/init_command.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/config/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/config/colors.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/error/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/error/handler.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/error/utils.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/exceptions/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/exceptions/base.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/exceptions/config.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/exceptions/usage.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/exceptions/validation.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/ui/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/ui/title.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/ui/title.txt +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/validators/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/validators/network.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/validators/numeric.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/validators/path.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/core/validators/string.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/services/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/templates/command.py.j2 +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/templates/theme.toml.j2 +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/templates/usecli.config.toml.j2 +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/ayu_dark.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/catppuccin_frappe.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/catppuccin_latte.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/catppuccin_macchiato.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/catppuccin_mocha.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/default.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/dracula.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/gruvbox_dark.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/nord.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/themes/tokyo_night.toml +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/utils/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/utils/interactive/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/utils/interactive/terminal_menu.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/menu.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/params.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/shared/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/shared/config/__init__.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/shared/config/globals.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/shared/config/manager.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/ui.py +0 -0
- {usecli-0.1.68 → usecli-0.1.70}/src/usecli/usecli.config.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "usecli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.70"
|
|
4
4
|
description = "A powerful Python CLI framework for building beautiful, developer-friendly command-line tools."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{ name = "Edward Boswell", email = "thememium@gmail.com" }]
|
|
@@ -331,6 +331,32 @@ class _FilteredListCommand:
|
|
|
331
331
|
def __init__(self, prefix_filter: str) -> None:
|
|
332
332
|
self.prefix_filter = prefix_filter
|
|
333
333
|
self.name = "filtered-list"
|
|
334
|
+
self.allow_extra_args = True
|
|
335
|
+
self.allow_interspersed_args = True
|
|
336
|
+
self.ignore_unknown_options = True
|
|
337
|
+
self.hidden = False
|
|
338
|
+
self.deprecated = False
|
|
339
|
+
self.params = []
|
|
340
|
+
self.callback = None
|
|
341
|
+
self.help = None
|
|
342
|
+
self.epilog = None
|
|
343
|
+
self.short_help = None
|
|
344
|
+
self.no_args_is_help = False
|
|
345
|
+
self.context_settings = {}
|
|
346
|
+
|
|
347
|
+
def get_short_help_str(self, limit=45):
|
|
348
|
+
return ""
|
|
349
|
+
|
|
350
|
+
def make_context(self, info_name: str, args: list[str], **kwargs: object):
|
|
351
|
+
from click import Context
|
|
352
|
+
|
|
353
|
+
ctx = Context(self, info_name=info_name, **kwargs) # type: ignore[arg-type]
|
|
354
|
+
return ctx
|
|
355
|
+
|
|
356
|
+
def invoke(self, ctx):
|
|
357
|
+
from usecli.cli.core.ui.list import list_commands
|
|
358
|
+
|
|
359
|
+
list_commands(_get_app(), prefix_filter=self.prefix_filter)
|
|
334
360
|
|
|
335
361
|
def __call__(self, *args, **kwargs):
|
|
336
362
|
from usecli.cli.core.ui.list import list_commands
|
|
@@ -57,7 +57,8 @@ def list_commands(app: typer.Typer, prefix_filter: str | None = None) -> None:
|
|
|
57
57
|
prefix_filter: Optional prefix to filter commands by name.
|
|
58
58
|
"""
|
|
59
59
|
project_name = get_project_name()
|
|
60
|
-
|
|
60
|
+
if not prefix_filter:
|
|
61
|
+
print_title(title=project_name)
|
|
61
62
|
|
|
62
63
|
click_group = typer.main.get_command(app)
|
|
63
64
|
|
|
@@ -122,7 +123,6 @@ def list_commands(app: typer.Typer, prefix_filter: str | None = None) -> None:
|
|
|
122
123
|
option_flags.append(flags)
|
|
123
124
|
|
|
124
125
|
help_flags = "--help, -h"
|
|
125
|
-
all_option_flags = [help_flags] + option_flags
|
|
126
126
|
group_entries: list[CommandEntry] = []
|
|
127
127
|
for group_name, group_help in groups.items():
|
|
128
128
|
aliases = group_alias_registry.get(group_name, list[str]())
|
|
@@ -158,31 +158,73 @@ def list_commands(app: typer.Typer, prefix_filter: str | None = None) -> None:
|
|
|
158
158
|
all_display_names = [cmd["display_name"] for cmd in commands] + [
|
|
159
159
|
entry["display_name"] for entry in group_entries
|
|
160
160
|
]
|
|
161
|
-
all_labels = all_display_names +
|
|
161
|
+
all_labels = all_display_names + [help_flags]
|
|
162
162
|
longest_label_length = max((len(label) for label in all_labels), default=0)
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
if prefix_filter:
|
|
165
|
+
command_name = get_script_command_name(default="usecli")
|
|
166
|
+
interactive_flags = "--interactive, -i"
|
|
167
|
+
filtered_labels = (
|
|
168
|
+
[cmd["display_name"] for cmd in commands]
|
|
169
|
+
+ [entry["display_name"] for entry in group_entries]
|
|
170
|
+
+ [help_flags, interactive_flags]
|
|
171
|
+
)
|
|
172
|
+
longest_label_length = max((len(label) for label in filtered_labels), default=0)
|
|
173
|
+
console.print()
|
|
174
|
+
console.print(f"[bold {COLOR.SECONDARY}]Usage:[/bold {COLOR.SECONDARY}]")
|
|
175
|
+
# Detect colon-separated commands (e.g., "make:command" matching prefix "make")
|
|
176
|
+
has_colon_commands = any(
|
|
177
|
+
":" in cmd["name"] and cmd["name"].startswith(prefix_filter + ":")
|
|
178
|
+
for cmd in commands
|
|
179
|
+
)
|
|
180
|
+
if has_colon_commands:
|
|
181
|
+
# Colon-separated: use make:COMMAND [OPTIONS]
|
|
182
|
+
console.print(
|
|
183
|
+
f" [not bold {COLOR.PRIMARY}]{command_name} {prefix_filter}:COMMAND [OPTIONS][/]"
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
# Space-separated nested groups: use make [COMMAND] [OPTIONS]
|
|
187
|
+
console.print(
|
|
188
|
+
f" [not bold {COLOR.PRIMARY}]{command_name} {prefix_filter} [COMMAND] [OPTIONS][/]"
|
|
189
|
+
)
|
|
190
|
+
console.print()
|
|
191
|
+
console.print(f"[bold {COLOR.SECONDARY}]Options:")
|
|
192
|
+
help_padding = " " * (longest_label_length - len(help_flags) + SPACER_LENGTH)
|
|
193
|
+
console.print(
|
|
194
|
+
f" [{COLOR.OPTION}]{help_flags}[/{COLOR.OPTION}]{help_padding}Show this message and exit."
|
|
195
|
+
)
|
|
196
|
+
interactive_padding = " " * (
|
|
197
|
+
longest_label_length - len(interactive_flags) + SPACER_LENGTH
|
|
198
|
+
)
|
|
199
|
+
console.print(
|
|
200
|
+
f" [{COLOR.OPTION}]{interactive_flags}[/{COLOR.OPTION}]{interactive_padding}Run in interactive mode."
|
|
201
|
+
)
|
|
202
|
+
console.print()
|
|
203
|
+
else:
|
|
204
|
+
console.print(f"[bold {COLOR.SECONDARY}]Usage:[/bold {COLOR.SECONDARY}]")
|
|
205
|
+
console.print(
|
|
206
|
+
f" [not bold {COLOR.PRIMARY}]{command_name} [OPTIONS] [ARGUMENTS][/]"
|
|
207
|
+
)
|
|
208
|
+
console.print()
|
|
167
209
|
|
|
168
|
-
|
|
210
|
+
console.print(f"[bold {COLOR.SECONDARY}]Options:")
|
|
169
211
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
212
|
+
help_padding = " " * (longest_label_length - len(help_flags) + SPACER_LENGTH)
|
|
213
|
+
console.print(
|
|
214
|
+
f" [{COLOR.OPTION}]{help_flags}[/{COLOR.OPTION}]{help_padding}Show this message and exit."
|
|
215
|
+
)
|
|
174
216
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
217
|
+
if display_params:
|
|
218
|
+
for param in display_params:
|
|
219
|
+
flags = ", ".join(param.opts)
|
|
220
|
+
if "--help" in flags:
|
|
221
|
+
continue
|
|
222
|
+
description = _get_option_description(param)
|
|
223
|
+
padding = " " * (longest_label_length - len(flags) + SPACER_LENGTH)
|
|
224
|
+
console.print(
|
|
225
|
+
f" [{COLOR.OPTION}]{flags}[/{COLOR.OPTION}]{padding}{description}"
|
|
226
|
+
)
|
|
227
|
+
console.print()
|
|
186
228
|
|
|
187
229
|
if not prefix_filter:
|
|
188
230
|
console.print(f"[bold {COLOR.SECONDARY}]Available commands:")
|
|
@@ -241,7 +283,7 @@ def list_group_commands(group_app: typer.Typer, group_name: str) -> None:
|
|
|
241
283
|
|
|
242
284
|
console.print(f"[bold {COLOR.SECONDARY}]Usage:[/bold {COLOR.SECONDARY}]")
|
|
243
285
|
console.print(
|
|
244
|
-
f" [{COLOR.PRIMARY}]{command_name} {group_name} [COMMAND] [OPTIONS][/]"
|
|
286
|
+
f" [not bold {COLOR.PRIMARY}]{command_name} {group_name} [COMMAND] [OPTIONS][/]"
|
|
245
287
|
)
|
|
246
288
|
console.print()
|
|
247
289
|
commands_by_name: dict[str, CommandMeta] = {}
|
|
@@ -81,6 +81,10 @@ class CommandService:
|
|
|
81
81
|
if config_version:
|
|
82
82
|
self.version = config_version
|
|
83
83
|
return
|
|
84
|
+
app_version = self._get_application_version()
|
|
85
|
+
if app_version:
|
|
86
|
+
self.version = app_version
|
|
87
|
+
return
|
|
84
88
|
try:
|
|
85
89
|
self.version = get_version("usecli")
|
|
86
90
|
except Exception as error:
|
|
@@ -88,6 +92,30 @@ class CommandService:
|
|
|
88
92
|
raise
|
|
89
93
|
self.version = "0.0.0"
|
|
90
94
|
|
|
95
|
+
def _get_application_version(self) -> str | None:
|
|
96
|
+
"""Get the version from the application's own distribution.
|
|
97
|
+
|
|
98
|
+
Finds the distribution that registered the current console script
|
|
99
|
+
(e.g., 'usepr') and returns its version, so user-built CLIs
|
|
100
|
+
show their own version instead of usecli's.
|
|
101
|
+
"""
|
|
102
|
+
import os
|
|
103
|
+
|
|
104
|
+
from usecli.cli.core.ui.title import get_script_command_name
|
|
105
|
+
from usecli.shared.config.manager import _find_distribution_for_console_script
|
|
106
|
+
|
|
107
|
+
command_name = os.path.basename(sys.argv[0]) if sys.argv else None
|
|
108
|
+
if command_name:
|
|
109
|
+
dist = _find_distribution_for_console_script(command_name)
|
|
110
|
+
if dist is not None:
|
|
111
|
+
return dist.version
|
|
112
|
+
primary_command = get_script_command_name(default=None)
|
|
113
|
+
if primary_command:
|
|
114
|
+
dist = _find_distribution_for_console_script(primary_command)
|
|
115
|
+
if dist is not None:
|
|
116
|
+
return dist.version
|
|
117
|
+
return None
|
|
118
|
+
|
|
91
119
|
def _load_from_dir(self, directory: Path) -> None:
|
|
92
120
|
"""Load command classes from a directory.
|
|
93
121
|
|
|
@@ -149,6 +177,13 @@ class CommandService:
|
|
|
149
177
|
if spec and spec.loader:
|
|
150
178
|
module = importlib.util.module_from_spec(spec)
|
|
151
179
|
sys.modules[module_name] = module
|
|
180
|
+
|
|
181
|
+
from usecli.shared.config.manager import find_project_root
|
|
182
|
+
|
|
183
|
+
project_root = find_project_root(path.parent)
|
|
184
|
+
if project_root and str(project_root) not in sys.path:
|
|
185
|
+
sys.path.insert(0, str(project_root))
|
|
186
|
+
|
|
152
187
|
spec.loader.exec_module(module)
|
|
153
188
|
return module
|
|
154
189
|
return None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{usecli-0.1.68 → usecli-0.1.70}/src/usecli/cli/commands/defaults/base/internal/fzf_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|