Skip to content

Commit 7e837d1

Browse files
zhujian0805claude
andcommitted
refactor: break down large functions in prompts_commands.py
- Refactored show_prompt_status() function into 6 smaller helper functions - Refactored uninstall_prompt() function into 4 smaller helper functions - Added comprehensive unit tests for all refactored functions - Improved code maintainability and test coverage (71%) - All existing functionality preserved and verified 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ebaabcd commit 7e837d1

File tree

3 files changed

+415
-129
lines changed

3 files changed

+415
-129
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ dist
1818
.venv
1919
.claude/*
2020
codebuddy_usage.md
21+
.coverage

code_assistant_manager/cli/prompts_commands.py

Lines changed: 174 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,25 @@ def uninstall_prompt(
841841

842842
target_levels = resolve_level_targets(level, VALID_LEVELS, default="user")
843843

844+
# Collect all target files to uninstall
845+
all_targets = _collect_uninstall_targets(target_apps, target_levels, project_dir)
846+
847+
if not all_targets:
848+
typer.echo(f"{Colors.YELLOW}No matching prompt files found{Colors.RESET}")
849+
return
850+
851+
# Confirm uninstallation unless force is specified
852+
if not force:
853+
_confirm_uninstall(all_targets)
854+
855+
# Perform the actual uninstallation
856+
_perform_uninstall(all_targets)
857+
858+
859+
def _collect_uninstall_targets(
860+
target_apps: List[str], target_levels: List[str], project_dir: Optional[Path]
861+
):
862+
"""Collect all target files that need to be uninstalled."""
844863
targets = []
845864
copilot_targets = []
846865

@@ -861,35 +880,42 @@ def uninstall_prompt(
861880
continue
862881

863882
if app == "codebuddy":
864-
if lvl == "project":
865-
base_dir = lvl_project_dir or Path.cwd()
866-
codebuddy_path = base_dir / "CODEBUDDY.md"
867-
agents_path = base_dir / "AGENTS.md"
868-
# Prefer CODEBUDDY.md, but report AGENTS.md too
869-
target = codebuddy_path if codebuddy_path.exists() else agents_path
870-
if target.exists():
871-
targets.append(("codebuddy", lvl, target, lvl_project_dir))
872-
elif lvl == "user":
873-
user_path = Path.home() / ".codebuddy" / "CODEBUDDY.md"
874-
if user_path.exists():
875-
targets.append(("codebuddy", lvl, user_path, None))
883+
_collect_codebuddy_targets(app, lvl, lvl_project_dir, targets)
876884
continue
877885

878886
file_path = get_prompt_file_path(app, lvl, lvl_project_dir)
879-
if not file_path:
880-
continue
881-
targets.append((app, lvl, file_path, lvl_project_dir))
882-
883-
all_targets = targets + copilot_targets
887+
if file_path:
888+
targets.append((app, lvl, file_path, lvl_project_dir))
884889

885-
if not all_targets:
886-
typer.echo(f"{Colors.YELLOW}No matching prompt files found{Colors.RESET}")
887-
return
890+
return targets + copilot_targets
888891

889-
if not force:
890-
summary = ", ".join(f"{app}:{lvl}" for app, lvl, *_ in all_targets)
891-
typer.confirm(f"Uninstall prompt files for {summary}?", abort=True)
892892

893+
def _collect_codebuddy_targets(
894+
app: str, lvl: str, lvl_project_dir: Optional[Path], targets: List
895+
):
896+
"""Collect CodeBuddy target files for uninstallation."""
897+
if lvl == "project":
898+
base_dir = lvl_project_dir or Path.cwd()
899+
codebuddy_path = base_dir / "CODEBUDDY.md"
900+
agents_path = base_dir / "AGENTS.md"
901+
# Prefer CODEBUDDY.md, but report AGENTS.md too
902+
target = codebuddy_path if codebuddy_path.exists() else agents_path
903+
if target.exists():
904+
targets.append(("codebuddy", lvl, target, lvl_project_dir))
905+
elif lvl == "user":
906+
user_path = Path.home() / ".codebuddy" / "CODEBUDDY.md"
907+
if user_path.exists():
908+
targets.append(("codebuddy", lvl, user_path, None))
909+
910+
911+
def _confirm_uninstall(all_targets):
912+
"""Show confirmation dialog for uninstallation."""
913+
summary = ", ".join(f"{app}:{lvl}" for app, lvl, *_ in all_targets)
914+
typer.confirm(f"Uninstall prompt files for {summary}?", abort=True)
915+
916+
917+
def _perform_uninstall(all_targets):
918+
"""Perform the actual file uninstallation."""
893919
for app, lvl, file_path, _ in all_targets:
894920
if not file_path.exists():
895921
typer.echo(
@@ -955,7 +981,17 @@ def show_prompt_status(
955981
"""Show prompt status for all apps."""
956982
manager = _get_prompt_manager()
957983

958-
# Show default prompt first
984+
# Show default prompt section
985+
_show_default_prompt_section(manager)
986+
987+
levels_to_show = resolve_level_targets(level, VALID_LEVELS, default="all")
988+
989+
for lvl in levels_to_show:
990+
_show_level_section(manager, lvl, project_dir)
991+
992+
993+
def _show_default_prompt_section(manager: PromptManager):
994+
"""Show the default prompt status section."""
959995
default_prompt = manager.get_default()
960996
if default_prompt:
961997
typer.echo(f"\n{Colors.BOLD}Default Prompt:{Colors.RESET}")
@@ -966,122 +1002,135 @@ def show_prompt_status(
9661002
f"\n{Colors.BOLD}Default Prompt:{Colors.RESET} {Colors.YELLOW}(none set){Colors.RESET}"
9671003
)
9681004

969-
levels_to_show = resolve_level_targets(level, VALID_LEVELS, default="all")
9701005

971-
for lvl in levels_to_show:
972-
typer.echo(
973-
f"\n{Colors.BOLD}Prompt Status ({lvl.capitalize()} Level):{Colors.RESET}\n"
974-
)
1006+
def _show_level_section(manager: PromptManager, lvl: str, project_dir: Optional[Path]):
1007+
"""Show prompt status for a specific level."""
1008+
typer.echo(
1009+
f"\n{Colors.BOLD}Prompt Status ({lvl.capitalize()} Level):{Colors.RESET}\n"
1010+
)
9751011

976-
# Determine which apps to show for this level
977-
apps_for_level = USER_LEVEL_APPS if lvl == "user" else VALID_APP_TYPES
1012+
# Determine which apps to show for this level
1013+
apps_for_level = USER_LEVEL_APPS if lvl == "user" else VALID_APP_TYPES
9781014

979-
for app_type in apps_for_level:
980-
# Handle Copilot specially
981-
if app_type == "copilot":
982-
_show_copilot_status(manager, project_dir)
983-
continue
1015+
for app_type in apps_for_level:
1016+
_show_app_status(manager, app_type, lvl, project_dir)
9841017

985-
if app_type == "codebuddy":
986-
# Show CodeBuddy status for user or project level
987-
if lvl == "user":
988-
file_path = Path.home() / ".codebuddy" / "CODEBUDDY.md"
989-
try:
990-
live_content = manager.get_live_content(
991-
"codebuddy", level="user", project_dir=None
992-
)
993-
except Exception:
994-
live_content = None
995-
else:
996-
base_dir = project_dir or Path.cwd()
997-
codebuddy_file = base_dir / "CODEBUDDY.md"
998-
agents_file = base_dir / "AGENTS.md"
999-
file_path = (
1000-
codebuddy_file if codebuddy_file.exists() else agents_file
1001-
)
1002-
try:
1003-
live_content = manager.get_live_content(
1004-
"codebuddy", level="project", project_dir=project_dir
1005-
)
1006-
except Exception:
1007-
live_content = None
1008-
1009-
typer.echo(f"{Colors.BOLD}CodeBuddy:{Colors.RESET}")
1010-
typer.echo(f" {Colors.CYAN}File:{Colors.RESET} {file_path}")
10111018

1012-
linked_prompt = None
1013-
if live_content:
1014-
for prompt_id, prompt in manager.get_all().items():
1015-
if prompt.content.strip() == live_content.strip():
1016-
linked_prompt = prompt
1017-
break
1019+
def _show_app_status(
1020+
manager: PromptManager, app_type: str, lvl: str, project_dir: Optional[Path]
1021+
):
1022+
"""Show status for a specific app at a specific level."""
1023+
# Handle Copilot specially
1024+
if app_type == "copilot":
1025+
_show_copilot_status(manager, project_dir)
1026+
return
10181027

1019-
if linked_prompt:
1020-
typer.echo(
1021-
f" {Colors.BLUE}Linked Prompt:{Colors.RESET} {linked_prompt.name} ({linked_prompt.id})"
1022-
)
1028+
if app_type == "codebuddy":
1029+
_show_codebuddy_status(manager, lvl, project_dir)
1030+
return
10231031

1024-
if file_path.exists():
1025-
content = file_path.read_text(encoding="utf-8")
1026-
if content.strip():
1027-
lines = content.strip().split("\n")
1028-
preview = (
1029-
lines[0][:50] + "..." if len(lines[0]) > 50 else lines[0]
1030-
)
1031-
typer.echo(f" {Colors.GREEN}Content:{Colors.RESET} {preview}")
1032-
typer.echo(f" {Colors.CYAN}Lines:{Colors.RESET} {len(lines)}")
1033-
else:
1034-
typer.echo(f" {Colors.YELLOW}Content:{Colors.RESET} (empty)")
1035-
else:
1036-
typer.echo(
1037-
f" {Colors.YELLOW}Content:{Colors.RESET} (file not found)"
1038-
)
1032+
# Handle regular apps
1033+
_show_regular_app_status(manager, app_type, lvl, project_dir)
10391034

1040-
typer.echo()
1041-
continue
10421035

1043-
file_path = get_prompt_file_path(
1044-
app_type, lvl, project_dir if lvl == "project" else None
1036+
def _show_codebuddy_status(
1037+
manager: PromptManager, lvl: str, project_dir: Optional[Path]
1038+
):
1039+
"""Show CodeBuddy status for user or project level."""
1040+
if lvl == "user":
1041+
file_path = Path.home() / ".codebuddy" / "CODEBUDDY.md"
1042+
try:
1043+
live_content = manager.get_live_content(
1044+
"codebuddy", level="user", project_dir=None
10451045
)
1046+
except Exception:
1047+
live_content = None
1048+
else:
1049+
base_dir = project_dir or Path.cwd()
1050+
codebuddy_file = base_dir / "CODEBUDDY.md"
1051+
agents_file = base_dir / "AGENTS.md"
1052+
file_path = codebuddy_file if codebuddy_file.exists() else agents_file
1053+
try:
1054+
live_content = manager.get_live_content(
1055+
"codebuddy", level="project", project_dir=project_dir
1056+
)
1057+
except Exception:
1058+
live_content = None
10461059

1047-
typer.echo(f"{Colors.BOLD}{app_type.capitalize()}:{Colors.RESET}")
1048-
typer.echo(f" {Colors.CYAN}File:{Colors.RESET} {file_path}")
1060+
typer.echo(f"{Colors.BOLD}CodeBuddy:{Colors.RESET}")
1061+
typer.echo(f" {Colors.CYAN}File:{Colors.RESET} {file_path}")
10491062

1050-
# Check which prompt is linked to this file
1051-
linked_prompt = None
1052-
try:
1053-
live_content = manager.get_live_content(
1054-
app_type,
1055-
level=lvl,
1056-
project_dir=project_dir if lvl == "project" else None,
1057-
)
1058-
if live_content:
1059-
# Find which stored prompt matches this content
1060-
for prompt_id, prompt in manager.get_all().items():
1061-
if prompt.content.strip() == live_content.strip():
1062-
linked_prompt = prompt
1063-
break
1064-
except Exception:
1065-
pass
1063+
linked_prompt = None
1064+
if live_content:
1065+
for prompt_id, prompt in manager.get_all().items():
1066+
if prompt.content.strip() == live_content.strip():
1067+
linked_prompt = prompt
1068+
break
10661069

1067-
if linked_prompt:
1068-
typer.echo(
1069-
f" {Colors.BLUE}Linked Prompt:{Colors.RESET} {linked_prompt.name} ({linked_prompt.id})"
1070-
)
1070+
if linked_prompt:
1071+
typer.echo(
1072+
f" {Colors.BLUE}Linked Prompt:{Colors.RESET} {linked_prompt.name} ({linked_prompt.id})"
1073+
)
10711074

1072-
if file_path and file_path.exists():
1073-
content = file_path.read_text(encoding="utf-8")
1074-
if content.strip():
1075-
lines = content.strip().split("\n")
1076-
preview = lines[0][:50] + "..." if len(lines[0]) > 50 else lines[0]
1077-
typer.echo(f" {Colors.GREEN}Content:{Colors.RESET} {preview}")
1078-
typer.echo(f" {Colors.CYAN}Lines:{Colors.RESET} {len(lines)}")
1079-
else:
1080-
typer.echo(f" {Colors.YELLOW}Content:{Colors.RESET} (empty)")
1081-
else:
1082-
typer.echo(f" {Colors.YELLOW}Content:{Colors.RESET} (file not found)")
1075+
if file_path.exists():
1076+
content = file_path.read_text(encoding="utf-8")
1077+
if content.strip():
1078+
lines = content.strip().split("\n")
1079+
preview = lines[0][:50] + "..." if len(lines[0]) > 50 else lines[0]
1080+
typer.echo(f" {Colors.GREEN}Content:{Colors.RESET} {preview}")
1081+
typer.echo(f" {Colors.CYAN}Lines:{Colors.RESET} {len(lines)}")
1082+
else:
1083+
typer.echo(f" {Colors.YELLOW}Content:{Colors.RESET} (empty)")
1084+
else:
1085+
typer.echo(f" {Colors.YELLOW}Content:{Colors.RESET} (file not found)")
10831086

1084-
typer.echo()
1087+
typer.echo()
1088+
1089+
1090+
def _show_regular_app_status(
1091+
manager: PromptManager, app_type: str, lvl: str, project_dir: Optional[Path]
1092+
):
1093+
"""Show status for regular apps (non-copilot, non-codebuddy)."""
1094+
file_path = get_prompt_file_path(
1095+
app_type, lvl, project_dir if lvl == "project" else None
1096+
)
1097+
1098+
typer.echo(f"{Colors.BOLD}{app_type.capitalize()}:{Colors.RESET}")
1099+
typer.echo(f" {Colors.CYAN}File:{Colors.RESET} {file_path}")
1100+
1101+
# Check which prompt is linked to this file
1102+
linked_prompt = None
1103+
try:
1104+
live_content = manager.get_live_content(
1105+
app_type,
1106+
level=lvl,
1107+
project_dir=project_dir if lvl == "project" else None,
1108+
)
1109+
if live_content:
1110+
# Find which stored prompt matches this content
1111+
for prompt_id, prompt in manager.get_all().items():
1112+
if prompt.content.strip() == live_content.strip():
1113+
linked_prompt = prompt
1114+
break
1115+
except Exception:
1116+
pass
1117+
1118+
if linked_prompt:
1119+
typer.echo(
1120+
f" {Colors.BLUE}Linked Prompt:{Colors.RESET} {linked_prompt.name} ({linked_prompt.id})"
1121+
)
1122+
1123+
if file_path and file_path.exists():
1124+
content = file_path.read_text(encoding="utf-8")
1125+
if content.strip():
1126+
lines = content.strip().split("\n")
1127+
preview = lines[0][:50] + "..." if len(lines[0]) > 50 else lines[0]
1128+
typer.echo(f" {Colors.GREEN}Content:{Colors.RESET} {preview}")
1129+
typer.echo(f" {Colors.CYAN}Lines:{Colors.RESET} {len(lines)}")
1130+
else:
1131+
typer.echo(f" {Colors.YELLOW}Content:{Colors.RESET} (empty)")
1132+
else:
1133+
typer.echo(f" {Colors.YELLOW}Content:{Colors.RESET} (file not found)")
10851134

10861135

10871136
def _show_copilot_status(manager: PromptManager, project_dir: Optional[Path]):

0 commit comments

Comments
 (0)