Skip to content

Commit 2f55782

Browse files
committed
second pass
1 parent 69e0de3 commit 2f55782

4 files changed

Lines changed: 136 additions & 196 deletions

File tree

codeflash/cli_cmds/cmd_init.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import git
1414
import tomlkit
1515
from git import InvalidGitRepositoryError, Repo
16-
from inquirer_textual.common.Choice import Choice # type: ignore[import-untyped]
16+
from inquirer_textual.common.Choice import Choice
1717
from pydantic.dataclasses import dataclass
1818
from rich.console import Group
1919
from rich.panel import Panel
@@ -450,13 +450,12 @@ def collect_setup_info() -> CLISetupInfo:
450450
#
451451
# # Ask about benchmark framework
452452
# benchmark_framework_options = ["pytest-benchmark", "asv (Airspeed Velocity)", "custom/other"]
453-
# benchmark_framework = inquirer_wrapper(
454-
# inquirer.list_input,
455-
# message="Which benchmark framework do you use?",
453+
# result = prompts.select(
454+
# "Which benchmark framework do you use?",
456455
# choices=benchmark_framework_options,
457-
# default=benchmark_framework_options[0],
458-
# carousel=True,
456+
# default=benchmark_framework_options[0]
459457
# )
458+
# benchmark_framework = result.value
460459

461460
formatter_panel = Panel(
462461
Text(
@@ -571,12 +570,10 @@ def check_for_toml_or_setup_file() -> str | None:
571570
ph("cli-no-pyproject-toml-or-setup-py")
572571

573572
# Create a pyproject.toml file because it doesn't exist
574-
result = prompts.confirm("Create pyproject.toml in the current directory?", default=True)
575-
if result.command is None:
573+
result = prompts.select("Create pyproject.toml in the current directory?", choices=["Yes", "No"], default="Yes")
574+
if result.command is None or result.value == "No":
576575
apologize_and_exit()
577-
create_toml = result.value
578-
if create_toml:
579-
create_empty_pyproject_toml(pyproject_toml_path)
576+
create_empty_pyproject_toml(pyproject_toml_path)
580577
click.echo()
581578
return cast("str", project_name)
582579

@@ -643,27 +640,31 @@ def install_github_actions(override_formatter_check: bool = False) -> None: # n
643640

644641
# Check if the workflow file already exists
645642
if optimize_yaml_path.exists():
646-
result = prompts.confirm(
647-
f"GitHub Actions workflow already exists at {optimize_yaml_path}. Overwrite?", default=False
643+
result = prompts.select(
644+
f"GitHub Actions workflow already exists at {optimize_yaml_path}. Overwrite?",
645+
choices=["No", "Yes"],
646+
default="No",
648647
)
649-
if result.command is None or not result.value:
648+
if result.command is None or result.value == "No":
650649
skip_panel = Panel(
651650
Text("⏩️ Skipping workflow creation.", style="yellow"), title="⏩️ Skipped", border_style="yellow"
652651
)
653652
console.print(skip_panel)
654653
ph("cli-github-workflow-skipped")
655654
return
656-
ph("cli-github-optimization-confirm-workflow-overwrite", {"confirm_overwrite": result.value})
655+
ph("cli-github-optimization-confirm-workflow-overwrite", {"confirm_overwrite": result.value == "Yes"})
657656

658-
result = prompts.confirm("Set up GitHub Actions for continuous optimization?", default=True)
659-
if result.command is None or not result.value:
657+
result = prompts.select(
658+
"Set up GitHub Actions for continuous optimization?", choices=["Yes", "No"], default="Yes"
659+
)
660+
if result.command is None or result.value == "No":
660661
skip_panel = Panel(
661662
Text("⏩️ Skipping GitHub Actions setup.", style="yellow"), title="⏩️ Skipped", border_style="yellow"
662663
)
663664
console.print(skip_panel)
664665
ph("cli-github-workflow-skipped")
665666
return
666-
ph("cli-github-optimization-confirm-workflow-creation", {"confirm_creation": result.value})
667+
ph("cli-github-optimization-confirm-workflow-creation", {"confirm_creation": result.value == "Yes"})
667668
workflows_path.mkdir(parents=True, exist_ok=True)
668669
from importlib.resources import files
669670

@@ -683,8 +684,8 @@ def install_github_actions(override_formatter_check: bool = False) -> None: # n
683684
console.print(benchmark_panel)
684685
console.print()
685686

686-
result = prompts.confirm("Run GitHub Actions in benchmark mode?", default=True)
687-
benchmark_mode = result.value if result.command is not None else False
687+
result = prompts.select("Run GitHub Actions in benchmark mode?", choices=["Yes", "No"], default="Yes")
688+
benchmark_mode = (result.value == "Yes") if result.command is not None else False
688689

689690
optimize_yml_content = (
690691
files("codeflash").joinpath("cli_cmds", "workflows", "codeflash-optimize.yaml").read_text(encoding="utf-8")
Lines changed: 74 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,94 @@
1-
"""Themed prompts wrapper for inquirer-textual with CodeFlash styling.
2-
3-
This module provides themed prompt functions that match the original CodeFlash
4-
inquirer theme (yellow question marks, bright blue selections, cyan defaults).
5-
"""
6-
71
from __future__ import annotations
82

9-
from inquirer_textual.common.Choice import Choice # type: ignore[import-untyped]
10-
from inquirer_textual.common.Result import Result # type: ignore[import-untyped]
11-
from inquirer_textual.InquirerApp import InquirerApp # type: ignore[import-untyped]
12-
from inquirer_textual.widgets.InquirerCheckbox import InquirerCheckbox # type: ignore[import-untyped]
13-
from inquirer_textual.widgets.InquirerConfirm import InquirerConfirm # type: ignore[import-untyped]
14-
from inquirer_textual.widgets.InquirerSelect import InquirerSelect # type: ignore[import-untyped]
15-
from inquirer_textual.widgets.InquirerText import InquirerText # type: ignore[import-untyped]
3+
from typing import TYPE_CHECKING
164

5+
from inquirer_textual.InquirerApp import InquirerApp
6+
from inquirer_textual.widgets.InquirerCheckbox import InquirerCheckbox
7+
from inquirer_textual.widgets.InquirerConfirm import InquirerConfirm
8+
from inquirer_textual.widgets.InquirerSelect import InquirerSelect
9+
from inquirer_textual.widgets.InquirerText import InquirerText
1710

18-
class CodeflashThemedApp(InquirerApp): # type: ignore[misc]
19-
"""Custom themed InquirerApp matching the original CodeFlash theme colors."""
11+
if TYPE_CHECKING:
12+
from inquirer_textual.common.Choice import Choice
2013

21-
def get_theme_variable_defaults(self) -> dict[str, str]:
22-
"""Return CodeFlash theme colors.
2314

24-
Original CodeFlash theme from inquirer:
25-
- Question mark: yellow
26-
- Brackets: bright blue
27-
- Default: bright cyan
28-
- Selection: bright blue
29-
- Checkbox selected: ✅
30-
- Checkbox unselected: ⬜
31-
"""
32-
return {
33-
# Question mark color - yellow like the original
34-
"select-question-mark": "#e5c07b", # Gold/yellow
35-
# List item highlight - bright blue like the original selection
36-
"select-list-item-highlight-foreground": "#61afef", # Bright blue
37-
# Input/text color - cyan like the original
38-
"input-color": "#61afef", # Bright blue (used for inputs and selections)
39-
# Additional contrast colors
40-
"input-selection-background": "#3e4451", # Subtle background for selected items
15+
class CodeflashThemedApp(InquirerApp):
16+
CSS = """
17+
App {
18+
background: #1e293b;
19+
}
20+
Screen {
21+
border-top: none;
22+
border-bottom: none;
23+
background: transparent;
24+
height: auto;
25+
}
26+
ListView {
27+
background: transparent;
28+
border: none;
29+
}
30+
ListItem {
31+
background: transparent;
32+
padding: 0 1;
33+
color: #f1f5f9;
34+
}
35+
ListItem.-highlight {
36+
background: #334155;
37+
color: $select-list-item-highlight-foreground;
38+
}
39+
Label {
40+
background: transparent;
41+
color: #f8fafc;
42+
}
43+
Static {
44+
background: transparent;
45+
color: #f8fafc;
46+
}
47+
Input {
48+
background: #334155;
49+
border: solid $primary;
50+
color: #f8fafc;
51+
}
52+
Input:focus {
53+
border: solid $accent;
4154
}
42-
43-
44-
def select(
45-
message: str, choices: list[str | Choice], default: str | Choice | None = None, mandatory: bool = True
46-
) -> Result[str | Choice]: # type: ignore[type-arg]
47-
"""Display a select prompt with CodeFlash theming.
48-
49-
Args:
50-
message: The prompt message to display
51-
choices: List of choices (strings or Choice objects)
52-
default: Default choice to pre-select
53-
mandatory: Whether a response is mandatory
54-
55-
Returns:
56-
Result object containing the selected value and command
57-
5855
"""
59-
widget = InquirerSelect(message, choices, default, mandatory)
60-
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False) # type: ignore[assignment]
61-
return app.run(inline=True) # type: ignore[return-value]
62-
63-
64-
def confirm(message: str, default: bool = False, mandatory: bool = True) -> Result[bool]: # type: ignore[type-arg]
65-
"""Display a confirm prompt with CodeFlash theming.
6656

67-
Args:
68-
message: The prompt message to display
69-
default: Default value (True for yes, False for no)
70-
mandatory: Whether a response is mandatory
71-
72-
Returns:
73-
Result object containing the boolean value and command
57+
def get_theme_variable_defaults(self) -> dict[str, str]:
58+
return {
59+
"select-question-mark": "#FFC143",
60+
"select-list-item-highlight-foreground": "#2563EB",
61+
"input-color": "#3B82F6",
62+
"input-selection-background": "#1e293b",
63+
"accent": "#FFC143",
64+
"primary": "#2563EB",
65+
"secondary": "#414372",
66+
}
7467

75-
"""
76-
widget = InquirerConfirm(message, default=default, mandatory=mandatory)
77-
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False) # type: ignore[assignment]
78-
return app.run(inline=True) # type: ignore[return-value]
7968

69+
def select( # noqa: ANN201
70+
message: str, choices: list[str | Choice], default: str | Choice | None = None
71+
): # type: ignore[no-untyped-def]
72+
widget = InquirerSelect(message, choices, default, mandatory=True)
73+
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False)
74+
return app.run(inline=True)
8075

81-
def text(message: str) -> Result[str]: # type: ignore[type-arg]
82-
"""Display a text input prompt with CodeFlash theming.
8376

84-
Args:
85-
message: The prompt message to display
77+
def confirm(message: str, *, default: bool = False): # noqa: ANN201 # type: ignore[no-untyped-def]
78+
widget = InquirerConfirm(message, default=default, mandatory=True)
79+
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False)
80+
return app.run(inline=True)
8681

87-
Returns:
88-
Result object containing the text value and command
8982

90-
"""
83+
def text(message: str): # noqa: ANN201 # type: ignore[no-untyped-def]
9184
widget = InquirerText(message)
92-
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False) # type: ignore[assignment]
93-
return app.run(inline=True) # type: ignore[return-value]
85+
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False)
86+
return app.run(inline=True)
9487

9588

96-
def checkbox(
89+
def checkbox( # noqa: ANN201
9790
message: str, choices: list[str | Choice], enabled: list[str | Choice] | None = None
98-
) -> Result[list[str | Choice]]: # type: ignore[type-arg]
99-
"""Display a checkbox prompt with CodeFlash theming.
100-
101-
Args:
102-
message: The prompt message to display
103-
choices: List of choices (strings or Choice objects)
104-
enabled: List of pre-selected choices
105-
106-
Returns:
107-
Result object containing the list of selected values and command
108-
109-
"""
91+
): # type: ignore[no-untyped-def]
11092
widget = InquirerCheckbox(message, choices, enabled)
111-
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False) # type: ignore[assignment]
112-
return app.run(inline=True) # type: ignore[return-value]
93+
app: CodeflashThemedApp = CodeflashThemedApp(widget, shortcuts=None, show_footer=False)
94+
return app.run(inline=True)

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ install_types = true
200200
plugins = ["pydantic.mypy"]
201201

202202
[[tool.mypy.overrides]]
203-
module = ["jedi", "jedi.api.classes", "inquirer", "inquirer.themes", "inquirer_textual", "inquirer_textual.common.Choice", "numba"]
203+
module = ["jedi", "jedi.api.classes", "numba"]
204204
ignore_missing_imports = true
205205

206206
[tool.pydantic-mypy]
@@ -282,7 +282,6 @@ workspace = { members = ["codeflash-benchmark"] }
282282

283283
[tool.uv.sources]
284284
codeflash-benchmark = { workspace = true }
285-
inquirer-textual = { path = "../inquirer-textual", editable = true }
286285

287286
[tool.uv-dynamic-versioning]
288287
enable = true

0 commit comments

Comments
 (0)