Skip to content

Commit 73d3a48

Browse files
committed
Common commands, core commands
1 parent db882e6 commit 73d3a48

File tree

15 files changed

+148
-42
lines changed

15 files changed

+148
-42
lines changed

example/app/cli.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import sys
2+
3+
import click
4+
5+
from plain.cli import register_cli
6+
7+
from .users.models import User
8+
9+
10+
@register_cli("app")
11+
@click.group()
12+
def cli():
13+
"""App related commands"""
14+
pass
15+
16+
17+
@cli.command()
18+
@click.argument("email")
19+
def enable_admin_user(email):
20+
"""Enable admin privileges for a user."""
21+
result = User.query.filter(email=email).update(is_admin=True)
22+
if result:
23+
click.echo(f"User {email} is now an admin.")
24+
else:
25+
click.echo(f"No user found with email {email}.")
26+
sys.exit(1)

plain-code/plain/code/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from plain.cli import register_cli
1212
from plain.cli.print import print_event
13-
from plain.cli.runtime import without_runtime_setup
13+
from plain.cli.runtime import common_command, without_runtime_setup
1414

1515
from .biome import Biome
1616

@@ -118,6 +118,7 @@ def maybe_exit(return_code: int) -> None:
118118
maybe_exit(result.returncode)
119119

120120

121+
@common_command
121122
@without_runtime_setup
122123
@register_cli("fix", shortcut_for="code")
123124
@cli.command()

plain-dev/plain/dev/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import click
99

1010
from plain.cli import register_cli
11+
from plain.cli.runtime import common_command
1112
from plain.runtime import APP_PATH, PLAIN_TEMP_PATH
1213

1314
from .alias import AliasManager
@@ -80,6 +81,7 @@ def _auto_start_services() -> None:
8081
sys.exit(1)
8182

8283

84+
@common_command
8385
@register_cli("dev")
8486
@click.group(cls=DevGroup, invoke_without_command=True)
8587
@click.pass_context

plain-models/plain/models/backups/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
import click
88

99
from plain.cli import register_cli
10+
from plain.cli.runtime import common_command
1011

1112
from .core import DatabaseBackups
1213

1314

15+
@common_command
1416
@register_cli("backups", shortcut_for="models")
1517
@click.group("backups")
1618
def cli() -> None:

plain-models/plain/models/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import click
1010

1111
from plain.cli import register_cli
12+
from plain.cli.runtime import common_command
1213
from plain.packages import packages_registry
1314
from plain.runtime import settings
1415
from plain.utils.text import Truncator
@@ -136,6 +137,7 @@ def list_models(package_labels: tuple[str, ...], app_only: bool) -> None:
136137
click.echo(f" package: {pkg_name}\n")
137138

138139

140+
@common_command
139141
@register_cli("makemigrations", shortcut_for="models")
140142
@cli.command()
141143
@click.argument("package_labels", nargs=-1)
@@ -341,6 +343,7 @@ def write_migration_files(
341343
write_migration_files(changes)
342344

343345

346+
@common_command
344347
@register_cli("migrate", shortcut_for="models")
345348
@cli.command()
346349
@click.argument("package_label", required=False)

plain-pytest/plain/pytest/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
from dotenv import load_dotenv
77

88
from plain.cli import register_cli
9+
from plain.cli.runtime import common_command
910

1011

12+
@common_command
1113
@register_cli("test")
1214
@click.command(
1315
context_settings={

plain/plain/cli/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .registry import register_cli
2+
from .runtime import common_command
23

3-
__all__ = ["register_cli"]
4+
__all__ = ["register_cli", "common_command"]

plain/plain/cli/build.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
import plain.runtime
1111
from plain.assets.compile import compile_assets, get_compiled_path
12+
from plain.cli.runtime import common_command
1213

1314

15+
@common_command
1416
@click.command()
1517
@click.option(
1618
"--keep-original/--no-keep-original",

plain/plain/cli/core.py

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -141,50 +141,65 @@ def list_commands(self, ctx: Context) -> list[str]:
141141
return super().list_commands(ctx)
142142

143143
def format_commands(self, ctx: Context, formatter: Any) -> None:
144-
"""Format commands with separate sections for shortcuts and regular commands."""
144+
"""Format commands with separate sections for common, core, and package commands."""
145145
self._ensure_registry_loaded()
146146

147-
# Get all commands from both sources
147+
# Get all commands from both sources, tracking their source
148148
commands = []
149-
for source in self.sources:
149+
for source_index, source in enumerate(self.sources):
150150
for name in source.list_commands(ctx):
151151
cmd = source.get_command(ctx, name)
152152
if cmd is not None:
153-
commands.append((name, cmd))
153+
# source_index 0 = plain_cli (core), 1+ = registry (packages)
154+
commands.append((name, cmd, source_index))
154155

155156
if not commands:
156157
return
157158

158-
# Get metadata about shortcuts from the registry
159+
# Get metadata from the registry (for shortcuts)
159160
shortcuts_metadata = cli_registry.get_shortcuts()
160161

161-
# Separate shortcuts from regular commands
162-
shortcuts = []
163-
regular_commands = []
164-
165-
for name, cmd in commands:
166-
if name in shortcuts_metadata:
167-
# This is a shortcut
168-
help_text = cmd.get_short_help_str(limit=200)
169-
shortcut_for = shortcuts_metadata[name].shortcut_for
170-
if shortcut_for:
171-
# Add italic styling to the alias information (more concise)
172-
alias_info = click.style(f"(→ {shortcut_for})", italic=True)
173-
help_text = f"{help_text} {alias_info}"
174-
shortcuts.append((name, help_text))
162+
# Separate commands into common, core, and package
163+
common_commands = []
164+
core_commands = []
165+
package_commands = []
166+
167+
for name, cmd, source_index in commands:
168+
help_text = cmd.get_short_help_str(limit=200)
169+
170+
# Check if command is marked as common via decorator
171+
is_common = getattr(cmd, "is_common_command", False)
172+
173+
if is_common:
174+
# This is a common command
175+
# Add arrow notation if it's also a shortcut
176+
if name in shortcuts_metadata:
177+
shortcut_for = shortcuts_metadata[name].shortcut_for
178+
if shortcut_for:
179+
alias_info = click.style(f"(→ {shortcut_for})", italic=True)
180+
help_text = f"{help_text} {alias_info}"
181+
common_commands.append((name, help_text))
182+
elif source_index == 0:
183+
# Package command (from registry, inserted at index 0)
184+
package_commands.append((name, help_text))
175185
else:
176-
# Regular command or group
177-
regular_commands.append((name, cmd.get_short_help_str(limit=200)))
178-
179-
# Write shortcuts section if any exist
180-
if shortcuts:
181-
with formatter.section("Shortcuts"):
182-
formatter.write_dl(sorted(shortcuts))
183-
184-
# Write regular commands section
185-
if regular_commands:
186-
with formatter.section("Commands"):
187-
formatter.write_dl(sorted(regular_commands))
186+
# Core command (from plain_cli, at index 1)
187+
core_commands.append((name, help_text))
188+
189+
# Write common commands section if any exist
190+
if common_commands:
191+
with formatter.section("Common Commands"):
192+
formatter.write_dl(sorted(common_commands))
193+
194+
# Write core commands section if any exist
195+
if core_commands:
196+
with formatter.section("Core Commands"):
197+
formatter.write_dl(sorted(core_commands))
198+
199+
# Write package commands section if any exist
200+
if package_commands:
201+
with formatter.section("Package Commands"):
202+
formatter.write_dl(sorted(package_commands))
188203

189204

190205
cli = PlainCommandCollection()

plain/plain/cli/formatting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class PlainHelpFormatter(click.HelpFormatter):
1111
def write_heading(self, heading: str) -> None:
12-
styled_heading = click.style(heading, underline=True)
12+
styled_heading = click.style(heading, dim=True)
1313
self.write(f"{'':>{self.current_indent}}{styled_heading}\n")
1414

1515
def write_usage(self, prog: str, args: str = "", prefix: str = "Usage: ") -> None:

0 commit comments

Comments
 (0)