cl-preset 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.
cl_preset/interactive.py CHANGED
@@ -93,12 +93,12 @@ class InteractiveCLI:
93
93
 
94
94
  return strategies
95
95
 
96
- def select_strategy(self) -> dict | None:
96
+ def select_strategies(self) -> list[dict] | None:
97
97
  """
98
- Show interactive strategy selection prompt.
98
+ Show interactive multi-select strategy selection prompt.
99
99
 
100
100
  Returns:
101
- Selected strategy dictionary or None if cancelled
101
+ List of selected strategy dictionaries or None if cancelled
102
102
  """
103
103
  strategies = self.get_available_strategies()
104
104
 
@@ -119,26 +119,27 @@ class InteractiveCLI:
119
119
  )
120
120
  choices.append(choice)
121
121
 
122
- # Add cancel option
123
- choices.append(questionary.Separator())
124
- choices.append(questionary.Choice(title="Cancel", value="cancel"))
122
+ # Add instruction separator
123
+ choices.insert(0, questionary.Separator("= Use space to select, enter to continue ="))
125
124
 
126
- selected_name = questionary.select(
127
- "Select a strategy to install:",
125
+ selected_names = questionary.checkbox(
126
+ "Select strategies to install (multiple selection allowed):",
128
127
  choices=choices,
129
128
  qmark=">",
130
129
  pointer=">",
130
+ validate=lambda x: len(x) > 0 or "At least one strategy must be selected",
131
131
  ).ask()
132
132
 
133
- if selected_name == "cancel" or selected_name is None:
133
+ if selected_names is None or len(selected_names) == 0:
134
134
  return None
135
135
 
136
- # Find the selected strategy
136
+ # Find the selected strategies
137
+ selected_strategies = []
137
138
  for strategy in strategies:
138
- if strategy["name"] == selected_name:
139
- return strategy
139
+ if strategy["name"] in selected_names:
140
+ selected_strategies.append(strategy)
140
141
 
141
- return None
142
+ return selected_strategies
142
143
 
143
144
  def select_scope(self) -> PresetScope | None:
144
145
  """
@@ -293,9 +294,9 @@ class InteractiveCLI:
293
294
  """Run the interactive CLI flow."""
294
295
  self.show_welcome()
295
296
 
296
- # Step 1: Select strategy
297
- strategy = self.select_strategy()
298
- if strategy is None:
297
+ # Step 1: Select strategies (multiple)
298
+ strategies = self.select_strategies()
299
+ if strategies is None or len(strategies) == 0:
299
300
  self.console.print("[dim]Cancelled.[/dim]")
300
301
  return
301
302
 
@@ -309,37 +310,73 @@ class InteractiveCLI:
309
310
 
310
311
  self.console.print()
311
312
 
312
- # Step 3: Install/Apply
313
- strategy_type = strategy.get("type", "")
314
- strategy_name = strategy["name"]
313
+ # Step 3: Install/Apply all selected strategies
314
+ results = []
315
+ for strategy in strategies:
316
+ strategy_type = strategy.get("type", "")
317
+ strategy_name = strategy["name"]
315
318
 
316
- if strategy_type == "preset":
317
- self.console.print(f"[cyan]Installing {strategy_name} to {scope.value} scope...[/cyan]")
318
- success = self.install_preset(strategy, scope)
319
- else: # git-strategy
320
- self.console.print(
321
- f"[cyan]Applying git strategy {strategy_name} to {scope.value} scope...[/cyan]"
319
+ if strategy_type == "preset":
320
+ self.console.print(
321
+ f"[cyan]Installing {strategy_name} to {scope.value} scope...[/cyan]"
322
+ )
323
+ success = self.install_preset(strategy, scope)
324
+ else: # git-strategy
325
+ self.console.print(
326
+ f"[cyan]Applying git strategy {strategy_name} to {scope.value} scope...[/cyan]"
327
+ )
328
+ success = self.apply_git_strategy(strategy, scope)
329
+
330
+ results.append(
331
+ {
332
+ "name": strategy_name,
333
+ "type": strategy_type,
334
+ "success": success,
335
+ }
322
336
  )
323
- success = self.apply_git_strategy(strategy, scope)
337
+ self.console.print()
324
338
 
325
- self.console.print()
339
+ # Step 4: Show summary
340
+ successful = [r for r in results if r["success"]]
341
+ failed = [r for r in results if not r["success"]]
342
+
343
+ if len(successful) == len(results):
344
+ # All successful
345
+ success_text = "[bold green]All strategies installed successfully![/bold green]\n\n"
346
+ for r in results:
347
+ success_text += f" [cyan]{r['name']}[/cyan] ([dim]{r['type']}[/dim])\n"
326
348
 
327
- # Step 4: Show result
328
- if success:
329
349
  self.console.print(
330
350
  Panel(
331
- "[bold green]Strategy installed successfully![/bold green]\n\n"
332
- f"Type: [cyan]{strategy_type}[/cyan]\n"
333
- f"Name: [cyan]{strategy_name}[/cyan]\n"
334
- f"Scope: [cyan]{scope.value}[/cyan]",
335
- title="Success",
351
+ success_text,
352
+ title=f"Success ({len(successful)}/{len(results)})",
336
353
  border_style="green",
337
354
  )
338
355
  )
356
+ elif len(successful) > 0:
357
+ # Partial success
358
+ summary_text = f"[bold yellow]Partial success: {len(successful)}/{len(results)} installed[/bold yellow]\n\n"
359
+
360
+ summary_text += "[green]Successfully installed:[/green]\n"
361
+ for r in successful:
362
+ summary_text += f" [cyan]{r['name']}[/cyan]\n"
363
+
364
+ summary_text += "\n[red]Failed to install:[/red]\n"
365
+ for r in failed:
366
+ summary_text += f" [cyan]{r['name']}[/cyan]\n"
367
+
368
+ self.console.print(
369
+ Panel(
370
+ summary_text,
371
+ title="Partial Success",
372
+ border_style="yellow",
373
+ )
374
+ )
339
375
  else:
376
+ # All failed
340
377
  self.console.print(
341
378
  Panel(
342
- "[bold red]Installation failed.[/bold red]\n\n"
379
+ "[bold red]All installations failed.[/bold red]\n\n"
343
380
  "Please check the error messages above and try again.",
344
381
  title="Error",
345
382
  border_style="red",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cl-preset
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: A package for managing Claude Code configuration presets and strategies
5
5
  Project-URL: Homepage, https://github.com/yarang/cl-preset
6
6
  Project-URL: Documentation, https://github.com/yarang/cl-preset#readme
@@ -1,13 +1,13 @@
1
1
  cl_preset/__init__.py,sha256=rGIQS-1vuBzwnPj7NtC2N8hRIoMHUmSEMbWfnhjHjKQ,462
2
2
  cl_preset/cli.py,sha256=f-WqvlfomDQbAaCmSfWLMtfs9KP-jm9E66NZEJC80OM,16003
3
3
  cl_preset/git_strategy.py,sha256=FuiNUMaTwAyNA5nS8EvLhAntldJOBgRMO5FrUUgJ1K4,17375
4
- cl_preset/interactive.py,sha256=O20q7GLjNvtY-4voRsqHIBM_b484IYuxOu8InzviWh8,11509
4
+ cl_preset/interactive.py,sha256=EVUE8a0cMtLpEr3joI6vtTYypXoTp7QKdEMP9pP3f0w,13069
5
5
  cl_preset/manager.py,sha256=OojhbTxXZ0cPt44PPZE1NqSBAXsGssB6ZuYyfoKwPa4,6192
6
6
  cl_preset/models.py,sha256=UWx68lb0ac3VFCRpj3zOqc7qGwJpbX2EZcw_OYHBKWg,2241
7
7
  cl_preset/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  cl_preset/templates/git_strategy_template.yaml,sha256=2oF97WOHq2crSRoaLzWodBvzANmQ-9FPzM-A0jui2iw,1328
9
- cl_preset-0.2.0.dist-info/METADATA,sha256=ohb0hWBIjOvk0zXFQkBr7Uf8QCnl11u8AEzTuQwwEAo,9782
10
- cl_preset-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
11
- cl_preset-0.2.0.dist-info/entry_points.txt,sha256=JAW_u5lrqylE516FDGO5audUKuCsxGYypQ7d6cA_9uY,49
12
- cl_preset-0.2.0.dist-info/licenses/LICENSE,sha256=5b1_XulzMGBmVHcNKAHMo0Mqfqm5xJix4O5AErotK0o,1069
13
- cl_preset-0.2.0.dist-info/RECORD,,
9
+ cl_preset-0.3.0.dist-info/METADATA,sha256=rBTcmCH3TGHv3IRp2DvVZozFFdKK5rGfvhTMWXwICuQ,9782
10
+ cl_preset-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
11
+ cl_preset-0.3.0.dist-info/entry_points.txt,sha256=JAW_u5lrqylE516FDGO5audUKuCsxGYypQ7d6cA_9uY,49
12
+ cl_preset-0.3.0.dist-info/licenses/LICENSE,sha256=5b1_XulzMGBmVHcNKAHMo0Mqfqm5xJix4O5AErotK0o,1069
13
+ cl_preset-0.3.0.dist-info/RECORD,,