Skip to content

Commit dfbc05a

Browse files
committed
fix(cinit): correct target link directory handling in link_rules command
- remove questionary dependency for theme setup - add handling for target link directory creation - update console messages to reflect changes - ensure source directory exists in add_rule and edit_rule functions
1 parent c030abf commit dfbc05a

File tree

1 file changed

+65
-27
lines changed

1 file changed

+65
-27
lines changed

tools/cinit.py

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ def _get_console(): # --> Console # noqa: F821 ANN202
3939
@functools.lru_cache(maxsize=1)
4040
def _get_console_stderr(): # --> Console # noqa: F821 ANN202
4141
"""Lazy load rich stderr console."""
42-
import questionary # Needed for theme
4342
from rich.console import Console
44-
console_stderr = Console(stderr=True, theme=questionary.themes.THEME)
43+
console_stderr = Console(stderr=True)
4544
return console_stderr
4645

4746

@@ -88,24 +87,42 @@ def _create_symlink(rule_name: str, source_dir: Path, dest_dir: Path) -> bool:
8887

8988

9089
@app.command("link")
91-
def link_rules() -> None:
90+
def link_rules() -> None: # noqa: C901 PLR0912
9291
"""Interactively select and symlink rules from ~/.cursor/rules/ to the current directory."""
9392
# Import required libraries here
9493
import questionary
9594

9695
console = _get_console()
9796
console_stderr = _get_console_stderr()
9897

98+
target_link_dir = TARGET_DIR / ".cursor" / "rules" # Define specific target subdir
99+
99100
console.print("[bold cyan]Link Cursor Rules[/]")
100101
console.print(f"Source directory: [dim]{RULES_SOURCE_DIR}[/]")
101-
console.print(f"Target directory: [dim]{TARGET_DIR}[/]")
102+
console.print(f"Target link directory: [dim]{target_link_dir}[/]")
102103

104+
# Ensure source directory exists, create if not
103105
if not RULES_SOURCE_DIR.is_dir():
106+
console.print(f"[info]Source directory {RULES_SOURCE_DIR} not found. Creating it...[/]")
107+
try:
108+
RULES_SOURCE_DIR.mkdir(parents=True, exist_ok=True)
109+
console.print(f"[success]Created directory: {RULES_SOURCE_DIR}[/]")
110+
except OSError as e:
111+
console_stderr.print(
112+
f"[bold red]Error:[/] Could not create source directory {RULES_SOURCE_DIR}: {e}"
113+
)
114+
raise typer.Exit(code=1) from e
115+
116+
# Ensure target link directory exists, create if not
117+
try:
118+
target_link_dir.mkdir(parents=True, exist_ok=True)
119+
except OSError as e:
104120
console_stderr.print(
105-
f"[bold red]Error:[/] Rules source directory not found: {RULES_SOURCE_DIR}"
121+
f"[bold red]Error:[/] Could not create target link directory {target_link_dir}: {e}"
106122
)
107-
raise typer.Exit(code=1)
123+
raise typer.Exit(code=1) from e
108124

125+
# List available rules (logic remains the same)
109126
try:
110127
available_rules = sorted([item.name for item in RULES_SOURCE_DIR.iterdir()])
111128
except OSError as e:
@@ -120,14 +137,15 @@ def link_rules() -> None:
120137
)
121138
raise typer.Exit()
122139

140+
# Select rules (logic remains the same)
123141
try:
124142
selected_rules = questionary.checkbox(
125143
"Select rules to link to the current directory:",
126144
choices=available_rules,
127-
qmark=b"?", # Explicitly encode qmark
145+
qmark="?", # Changed back to string
128146
).ask()
129147
except UnicodeDecodeError:
130-
# Fallback if encoding fails (e.g., terminal issue)
148+
# Fallback should also use string
131149
selected_rules = questionary.checkbox(
132150
"Select rules to link to the current directory:",
133151
choices=available_rules,
@@ -144,20 +162,20 @@ def link_rules() -> None:
144162
console.print("[yellow]No rules selected. Exiting.[/]")
145163
raise typer.Exit()
146164

147-
console.print(f"\nAttempting to link {len(selected_rules)} selected rules:")
165+
console.print(f"\nAttempting to link {len(selected_rules)} selected rules to {target_link_dir}:")
148166
success_count = 0
149167
error_count = 0
150168

169+
# Link selected rules to the target subdir
151170
for rule_name in selected_rules:
152-
if _create_symlink(rule_name, RULES_SOURCE_DIR, TARGET_DIR):
171+
if _create_symlink(rule_name, RULES_SOURCE_DIR, target_link_dir):
153172
success_count += 1
154173
else:
155-
# Note: _create_symlink prints specific errors/skips
156-
# We only count actual errors here, not skips
157-
dest_path = TARGET_DIR / rule_name
174+
dest_path = target_link_dir / rule_name # Check against correct target
158175
if not (dest_path.exists() or dest_path.is_symlink()):
159176
error_count += 1
160177

178+
# Summary (remains the same conceptually)
161179
console.print("\n[bold cyan]Link Summary:[/]")
162180
console.print(f" Successfully linked: [green]{success_count}[/]")
163181
# Skipped count is implicitly len(selected_rules) - success_count - error_count
@@ -239,11 +257,13 @@ def add_rule( # noqa: C901 PLR0912
239257

240258
# 4. Ask to create symlink in current directory
241259
if copy_success or not should_copy: # Ask even if copy was skipped but file exists
242-
if dest_rule_path.exists(): # Ensure source exists before asking to link
260+
if dest_rule_path.exists(): # Ensure source rule exists before asking to link
243261
console.print("") # Spacer
262+
target_link_dir = TARGET_DIR / ".cursor" / "rules" # Define specific target subdir
244263
try:
264+
# Updated confirmation message
245265
create_link = questionary.confirm(
246-
f"Create a symlink for '{rule_name}' in the current directory ({TARGET_DIR})?",
266+
f"Create a symlink for '{rule_name}' in ./.cursor/rules/ ({target_link_dir})?",
247267
default=True,
248268
).ask()
249269
except KeyboardInterrupt:
@@ -254,11 +274,22 @@ def add_rule( # noqa: C901 PLR0912
254274
raise typer.Exit(code=1) from e
255275

256276
if create_link:
257-
console.print(f"Attempting to link '{rule_name}' to {TARGET_DIR}...")
258-
if not _create_symlink(rule_name, RULES_SOURCE_DIR, TARGET_DIR):
259-
# Error/skip message printed by helper
260-
console.print("[yellow]Symlink creation skipped or failed.[/]")
261-
# Don't exit with error if only linking failed after successful add/confirmation
277+
# Ensure target link directory exists, create if not
278+
try:
279+
target_link_dir.mkdir(parents=True, exist_ok=True)
280+
except OSError as e:
281+
console_stderr.print(
282+
f"[bold red]Error:[/] Could not create target link directory {target_link_dir}: {e}"
283+
)
284+
# Don't exit, just report error and skip linking
285+
console.print("[yellow]Symlink creation skipped due to directory error.[/]")
286+
else:
287+
# Attempt to link to the target subdir
288+
console.print(f"Attempting to link '{rule_name}' to {target_link_dir}...")
289+
if not _create_symlink(rule_name, RULES_SOURCE_DIR, target_link_dir):
290+
# Error/skip message printed by helper
291+
console.print("[yellow]Symlink creation skipped or failed.[/]")
292+
# Don't exit with error if only linking failed after successful add/confirmation
262293
else:
263294
console.print("[info]Skipping symlink creation.[/]")
264295
else:
@@ -269,7 +300,7 @@ def add_rule( # noqa: C901 PLR0912
269300

270301

271302
@app.command("edit")
272-
def edit_rule() -> None:
303+
def edit_rule() -> None: # noqa: C901 PLR0912
273304
"""Select a rule from ~/.cursor/rules/ and open it for editing."""
274305
# Import required libraries here
275306
import questionary
@@ -280,11 +311,18 @@ def edit_rule() -> None:
280311
console.print("[bold cyan]Edit Cursor Rule[/]")
281312
console.print(f"Rule directory: [dim]{RULES_SOURCE_DIR}[/]")
282313

314+
# Ensure source directory exists, create if not
283315
if not RULES_SOURCE_DIR.is_dir():
284-
console_stderr.print(
285-
f"[bold red]Error:[/] Rules source directory not found: {RULES_SOURCE_DIR}"
286-
)
287-
raise typer.Exit(code=1)
316+
console.print(f"[info]Source directory {RULES_SOURCE_DIR} not found. Creating it...[/]")
317+
try:
318+
RULES_SOURCE_DIR.mkdir(parents=True, exist_ok=True)
319+
console.print(f"[success]Created directory: {RULES_SOURCE_DIR}[/]")
320+
except OSError as e:
321+
console_stderr.print(
322+
f"[bold red]Error:[/] Could not create source directory {RULES_SOURCE_DIR}: {e}"
323+
)
324+
raise typer.Exit(code=1) from e
325+
# Proceed even if directory was just created (it will be empty)
288326

289327
try:
290328
available_rules = sorted(
@@ -306,10 +344,10 @@ def edit_rule() -> None:
306344
rule_to_edit = questionary.select(
307345
"Select a rule file to edit:",
308346
choices=available_rules,
309-
qmark=b"?", # Explicitly encode qmark
347+
qmark="?", # Changed back to string
310348
).ask()
311349
except UnicodeDecodeError:
312-
# Fallback if encoding fails
350+
# Fallback should also use string
313351
rule_to_edit = questionary.select(
314352
"Select a rule file to edit:",
315353
choices=available_rules,

0 commit comments

Comments
 (0)