Skip to content

Commit 9cab01c

Browse files
committed
misc improvement suggestions in init flow UX
1 parent c288419 commit 9cab01c

File tree

1 file changed

+178
-11
lines changed

1 file changed

+178
-11
lines changed

codeflash/cli_cmds/cmd_init.py

Lines changed: 178 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,181 @@ def should_modify_pyproject_toml() -> bool:
171171
if "tests_root" not in config or config["tests_root"] is None or not Path(config["tests_root"]).is_dir():
172172
return True
173173

174-
return Confirm.ask(
174+
should_reconfigure = Confirm.ask(
175175
"✅ A valid Codeflash config already exists in this project. Do you want to re-configure it?",
176176
default=False,
177177
show_default=True,
178178
)
179+
180+
if not should_reconfigure:
181+
display_current_config(config, config_file_path)
182+
183+
return should_reconfigure
184+
185+
186+
def browse_and_select_directory(start_dir: Path, message: str, title: str) -> Path | None:
187+
"""Interactive directory browser with tab-completion-like functionality."""
188+
current_dir = start_dir
189+
190+
while True:
191+
# Get all subdirectories in current directory
192+
try:
193+
subdirs = []
194+
for item in current_dir.iterdir():
195+
if item.is_dir() and not item.name.startswith('.'):
196+
subdirs.append(item.name)
197+
subdirs.sort()
198+
except PermissionError:
199+
console.print(f"❌ Permission denied accessing {current_dir}")
200+
return None
201+
202+
# Build choices list
203+
choices = []
204+
205+
# Add parent directory option if not at start_dir
206+
if current_dir != start_dir and current_dir.parent != current_dir:
207+
choices.append(("📁 .. (parent directory)", ".."))
208+
209+
# Add current directory selection option
210+
choices.append(("✅ Select this directory", "SELECT"))
211+
212+
# Add subdirectories
213+
for subdir in subdirs:
214+
choices.append((f"📂 {subdir}/", subdir))
215+
216+
# Add option to type custom path
217+
choices.append(("⌨️ Type custom path", "CUSTOM"))
218+
choices.append(("❌ Cancel", "CANCEL"))
219+
220+
# Show current directory in panel
221+
browse_panel = Panel(
222+
Text(f"📍 Current directory: {current_dir}\n\n{message}", style="cyan"),
223+
title=title,
224+
border_style="bright_blue",
225+
)
226+
console.print(browse_panel)
227+
console.print()
228+
229+
# Prompt for selection
230+
questions = [
231+
inquirer.List(
232+
"selection",
233+
message="Navigate or select directory:",
234+
choices=choices,
235+
carousel=True,
236+
)
237+
]
238+
239+
answers = inquirer.prompt(questions, theme=CodeflashTheme())
240+
if not answers:
241+
return None
242+
243+
selection = answers["selection"]
244+
245+
if selection == "SELECT":
246+
return current_dir
247+
elif selection == "CANCEL":
248+
return None
249+
elif selection == "..":
250+
current_dir = current_dir.parent
251+
elif selection == "CUSTOM":
252+
# Allow custom path input
253+
custom_panel = Panel(
254+
Text("Enter a directory path (relative to current directory or absolute):", style="yellow"),
255+
title="🔧 Custom Path",
256+
border_style="bright_yellow",
257+
)
258+
console.print(custom_panel)
259+
console.print()
260+
261+
custom_path = click.prompt("Directory path", type=str).strip()
262+
if custom_path:
263+
try:
264+
if Path(custom_path).is_absolute():
265+
new_dir = Path(custom_path)
266+
else:
267+
new_dir = current_dir / custom_path
268+
269+
new_dir = new_dir.resolve()
270+
if new_dir.exists() and new_dir.is_dir():
271+
current_dir = new_dir
272+
else:
273+
console.print(f"❌ Directory does not exist: {new_dir}")
274+
click.pause()
275+
except Exception as e:
276+
console.print(f"❌ Invalid path: {e}")
277+
click.pause()
278+
else:
279+
# Navigate to subdirectory
280+
try:
281+
new_dir = current_dir / selection
282+
if new_dir.exists() and new_dir.is_dir():
283+
current_dir = new_dir
284+
else:
285+
console.print(f"❌ Directory not accessible: {new_dir}")
286+
click.pause()
287+
except Exception as e:
288+
console.print(f"❌ Error accessing directory: {e}")
289+
click.pause()
290+
291+
292+
def display_current_config(config: dict[str, Any], config_file_path: Path) -> None:
293+
"""Display the current codeflash configuration in a nice format."""
294+
# Create a table for the configuration
295+
config_table = Table(show_header=True, header_style="bold cyan")
296+
config_table.add_column("Setting", style="blue", width=20)
297+
config_table.add_column("Value", style="green")
298+
299+
# Add configuration rows
300+
config_table.add_row("Module Root", str(config.get("module_root", "Not set")))
301+
302+
# Handle tests_root - it could be a string or list
303+
tests_root = config.get("tests_root", "Not set")
304+
if isinstance(tests_root, list):
305+
tests_root_display = ", ".join(tests_root) if tests_root else "Not set"
306+
else:
307+
tests_root_display = str(tests_root)
308+
config_table.add_row("Tests Root", tests_root_display)
309+
310+
config_table.add_row("Test Framework", str(config.get("test_framework", "Not set")))
311+
config_table.add_row("Benchmarks Root", str(config.get("benchmarks_root", "Not set")))
312+
config_table.add_row("Git Remote", str(config.get("git_remote", "origin")))
313+
314+
# Handle formatter commands
315+
formatter_cmds = config.get("formatter_cmds", [])
316+
if isinstance(formatter_cmds, list):
317+
formatter_display = ", ".join(formatter_cmds) if formatter_cmds else "Not set"
318+
else:
319+
formatter_display = str(formatter_cmds)
320+
config_table.add_row("Formatter Commands", formatter_display)
321+
322+
# Handle ignore paths
323+
ignore_paths = config.get("ignore_paths", [])
324+
if isinstance(ignore_paths, list):
325+
ignore_display = ", ".join(ignore_paths) if ignore_paths else "None"
326+
else:
327+
ignore_display = str(ignore_paths)
328+
config_table.add_row("Ignore Paths", ignore_display)
329+
330+
# Display telemetry setting
331+
telemetry_disabled = config.get("disable_telemetry", False)
332+
telemetry_status = "Disabled" if telemetry_disabled else "Enabled"
333+
config_table.add_row("Telemetry", telemetry_status)
334+
335+
# Create the panel
336+
config_panel = Panel(
337+
Group(
338+
Text("📋 Current Codeflash Configuration\n", style="bold cyan", justify="center"),
339+
Text(f"Configuration file: {config_file_path}\n", style="dim"),
340+
config_table
341+
),
342+
title="📋 Current Configuration",
343+
border_style="bright_blue",
344+
padding=(1, 2),
345+
)
346+
347+
console.print(config_panel)
348+
console.print()
179349

180350

181351
# Custom theme for better UX
@@ -336,16 +506,13 @@ def collect_setup_info() -> SetupInfo:
336506
console.print(custom_tests_panel)
337507
console.print()
338508

339-
custom_tests_questions = [
340-
inquirer.Path(
341-
"custom_tests_path", message="Enter the path to your tests directory", path_type=inquirer.Path.DIRECTORY
342-
)
343-
]
344-
345-
custom_tests_answers = inquirer.prompt(custom_tests_questions, theme=CodeflashTheme())
346-
if custom_tests_answers:
347-
tests_root = Path(curdir) / Path(custom_tests_answers["custom_tests_path"])
348-
else:
509+
# Use interactive directory browser instead of simple path input
510+
tests_root = browse_and_select_directory(
511+
curdir,
512+
"Select your tests directory:",
513+
"🧪 Browse for Tests Directory"
514+
)
515+
if not tests_root:
349516
apologize_and_exit()
350517
else:
351518
tests_root = Path(curdir) / Path(cast("str", tests_root_answer))

0 commit comments

Comments
 (0)