Skip to content

console_ui

Generic Console UI components using Rich.

Provides a themed console interface with consistent styling for interactive CLI tools.

ConsoleUI #

Bases: Console

Generic console UI with themed output and async input methods.

Source code in cogip/utils/console_ui.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
class ConsoleUI(Console):
    """Generic console UI with themed output and async input methods."""

    def __init__(self, theme: Theme | None = None):
        """
        Initialize the console UI.

        Args:
            theme: Custom Rich theme. If None, uses DEFAULT_THEME.
        """
        super().__init__(theme=theme or DEFAULT_THEME)

    def show_panel(
        self,
        content: str,
        *,
        title: str | None = None,
        subtitle: str | None = None,
        border_style: str = "header",
    ) -> None:
        """
        Display a styled panel.

        Args:
            content: Panel content text
            title: Optional panel title
            subtitle: Optional panel subtitle
            border_style: Border style name from theme
        """
        self.print(
            Panel(
                content,
                title=f"[header]{title}[/]" if title else None,
                subtitle=f"[muted]{subtitle}[/]" if subtitle else None,
                border_style=border_style,
                box=ROUNDED,
                padding=(1, 2),
            )
        )

    def show_rule(self, title: str, *, style: str = "muted", title_style: str = "phase") -> None:
        """
        Display a horizontal rule with title.

        Args:
            title: Rule title text
            style: Line style name from theme
            title_style: Title style name from theme
        """
        self.print()
        self.print(Rule(f"[{title_style}]{title}[/]", style=style))
        self.print()

    def show_success(self, message: str) -> None:
        """Display a success message."""
        self.print(f"[success]\u2713 {message}[/]")

    def show_warning(self, message: str) -> None:
        """Display a warning message."""
        self.print(f"[warning]\u26a0 {message}[/]")

    def show_error(self, message: str) -> None:
        """Display an error message."""
        self.print(f"[error]\u2717 {message}[/]")

    def show_info(self, message: str) -> None:
        """Display an info message."""
        self.print(f"[muted]\u2139 {message}[/]")

    def create_table(
        self,
        title: str | None = None,
        columns: list[tuple[str, dict[str, Any]]] | None = None,
    ) -> Table:
        """Create a styled table.

        Args:
            title: Optional table title
            columns: List of (name, kwargs) tuples for columns.
                     kwargs are passed to add_column().

        Returns:
            Configured Table instance ready for add_row() calls.
        """
        table = Table(
            title=f"[phase]{title}[/]" if title else None,
            box=ROUNDED,
            border_style="muted",
            header_style="header",
            show_header=True,
            padding=(0, 1),
        )
        if columns:
            for name, kwargs in columns:
                table.add_column(name, **kwargs)
        return table

    def show_key_value_table(
        self,
        data: list[tuple[str, str]],
        title: str | None = None,
        key_header: str = "Parameter",
        value_header: str = "Value",
    ) -> None:
        """Display a simple key-value table.

        Args:
            data: List of (key, value) tuples
            title: Optional table title
            key_header: Header for key column
            value_header: Header for value column
        """
        table = self.create_table(
            title=title,
            columns=[
                (key_header, {"style": "label"}),
                (value_header, {"style": "value", "justify": "right"}),
            ],
        )
        for key, value in data:
            table.add_row(key, value)
        self.print(table)

    def show_comparison_table(
        self,
        data: list[tuple[str, str, str]],
        title: str | None = None,
        key_header: str = "Parameter",
        before_header: str = "Previous",
        after_header: str = "New",
    ) -> None:
        """Display a before/after comparison table.

        Args:
            data: List of (key, before_value, after_value) tuples
            title: Optional table title
            key_header: Header for key column
            before_header: Header for before column
            after_header: Header for after column
        """
        table = self.create_table(
            title=title,
            columns=[
                (key_header, {"style": "label"}),
                (before_header, {"style": "muted"}),
                (after_header, {"style": "value"}),
            ],
        )
        for key, before, after in data:
            table.add_row(key, before, after)
        self.print(table)

    async def get_string(self, prompt: str, *, default: str | None = None) -> str:
        """
        Get string input from user.

        Args:
            prompt: Prompt message to display
            default: Default value. If None, input is required.
        """
        kwargs: dict[str, Any] = {"console": self}
        if default is not None:
            kwargs["default"] = default
        return await asyncio.to_thread(lambda: Prompt.ask(f"[prompt]{prompt}[/]", **kwargs))

    async def get_integer(self, prompt: str, *, default: int | None = None) -> int:
        """
        Get integer input from user.

        Displays a confirmation message with the chosen value.

        Args:
            prompt: Prompt message to display
            default: Default value. If None, input is required.
        """
        kwargs: dict[str, Any] = {"console": self}
        if default is not None:
            kwargs["default"] = default
        value = await asyncio.to_thread(lambda: IntPrompt.ask(f"[prompt]{prompt}[/]", **kwargs))
        self.show_info(f"Chosen: {value}")
        return value

    async def get_float(self, prompt: str, *, default: float | None = None) -> float:
        """
        Get float input from user.

        Args:
            prompt: Prompt message to display
            default: Default value. If None, input is required.
        """
        kwargs: dict[str, Any] = {"console": self}
        if default is not None:
            kwargs["default"] = default
        return await asyncio.to_thread(lambda: FloatPrompt.ask(f"[prompt]{prompt}[/]", **kwargs))

    async def confirm(self, message: str, *, default: bool = True) -> bool:
        """
        Ask for confirmation.

        Args:
            message: Confirmation message to display
            default: Default value when user presses Enter
        """
        return await asyncio.to_thread(lambda: Confirm.ask(f"[header]{message}[/]", default=default, console=self))

    async def wait_for_enter(self, message: str) -> None:
        """
        Wait for user to press Enter.

        Args:
            message: Message to display before waiting
        """
        await asyncio.to_thread(lambda: self.input(f"[prompt]{message}[/] [muted][[Enter]][/] "))

    def create_progress_tracker(
        self,
        columns: list[ProgressColumn] | None = None,
    ) -> CustomProgressTracker:
        """
        Create a progress tracker with manual lifecycle control.

        Features:
        - Custom display columns
        - Custom updatable fields
        - Manual start/update/stop control

        Args:
            columns: Custom Rich Progress columns. If None, uses default columns
                    (spinner, description, bar, percentage, elapsed time).

        Returns:
            CustomProgressTracker instance (call .start() to begin tracking)
        """
        return CustomProgressTracker(self, columns)

__init__(theme=None) #

Initialize the console UI.

Parameters:

Name Type Description Default
theme Theme | None

Custom Rich theme. If None, uses DEFAULT_THEME.

None
Source code in cogip/utils/console_ui.py
158
159
160
161
162
163
164
165
def __init__(self, theme: Theme | None = None):
    """
    Initialize the console UI.

    Args:
        theme: Custom Rich theme. If None, uses DEFAULT_THEME.
    """
    super().__init__(theme=theme or DEFAULT_THEME)

confirm(message, *, default=True) async #

Ask for confirmation.

Parameters:

Name Type Description Default
message str

Confirmation message to display

required
default bool

Default value when user presses Enter

True
Source code in cogip/utils/console_ui.py
350
351
352
353
354
355
356
357
358
async def confirm(self, message: str, *, default: bool = True) -> bool:
    """
    Ask for confirmation.

    Args:
        message: Confirmation message to display
        default: Default value when user presses Enter
    """
    return await asyncio.to_thread(lambda: Confirm.ask(f"[header]{message}[/]", default=default, console=self))

create_progress_tracker(columns=None) #

Create a progress tracker with manual lifecycle control.

Features: - Custom display columns - Custom updatable fields - Manual start/update/stop control

Parameters:

Name Type Description Default
columns list[ProgressColumn] | None

Custom Rich Progress columns. If None, uses default columns (spinner, description, bar, percentage, elapsed time).

None

Returns:

Type Description
CustomProgressTracker

CustomProgressTracker instance (call .start() to begin tracking)

Source code in cogip/utils/console_ui.py
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
def create_progress_tracker(
    self,
    columns: list[ProgressColumn] | None = None,
) -> CustomProgressTracker:
    """
    Create a progress tracker with manual lifecycle control.

    Features:
    - Custom display columns
    - Custom updatable fields
    - Manual start/update/stop control

    Args:
        columns: Custom Rich Progress columns. If None, uses default columns
                (spinner, description, bar, percentage, elapsed time).

    Returns:
        CustomProgressTracker instance (call .start() to begin tracking)
    """
    return CustomProgressTracker(self, columns)

create_table(title=None, columns=None) #

Create a styled table.

Parameters:

Name Type Description Default
title str | None

Optional table title

None
columns list[tuple[str, dict[str, Any]]] | None

List of (name, kwargs) tuples for columns. kwargs are passed to add_column().

None

Returns:

Type Description
Table

Configured Table instance ready for add_row() calls.

Source code in cogip/utils/console_ui.py
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
def create_table(
    self,
    title: str | None = None,
    columns: list[tuple[str, dict[str, Any]]] | None = None,
) -> Table:
    """Create a styled table.

    Args:
        title: Optional table title
        columns: List of (name, kwargs) tuples for columns.
                 kwargs are passed to add_column().

    Returns:
        Configured Table instance ready for add_row() calls.
    """
    table = Table(
        title=f"[phase]{title}[/]" if title else None,
        box=ROUNDED,
        border_style="muted",
        header_style="header",
        show_header=True,
        padding=(0, 1),
    )
    if columns:
        for name, kwargs in columns:
            table.add_column(name, **kwargs)
    return table

get_float(prompt, *, default=None) async #

Get float input from user.

Parameters:

Name Type Description Default
prompt str

Prompt message to display

required
default float | None

Default value. If None, input is required.

None
Source code in cogip/utils/console_ui.py
337
338
339
340
341
342
343
344
345
346
347
348
async def get_float(self, prompt: str, *, default: float | None = None) -> float:
    """
    Get float input from user.

    Args:
        prompt: Prompt message to display
        default: Default value. If None, input is required.
    """
    kwargs: dict[str, Any] = {"console": self}
    if default is not None:
        kwargs["default"] = default
    return await asyncio.to_thread(lambda: FloatPrompt.ask(f"[prompt]{prompt}[/]", **kwargs))

get_integer(prompt, *, default=None) async #

Get integer input from user.

Displays a confirmation message with the chosen value.

Parameters:

Name Type Description Default
prompt str

Prompt message to display

required
default int | None

Default value. If None, input is required.

None
Source code in cogip/utils/console_ui.py
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
async def get_integer(self, prompt: str, *, default: int | None = None) -> int:
    """
    Get integer input from user.

    Displays a confirmation message with the chosen value.

    Args:
        prompt: Prompt message to display
        default: Default value. If None, input is required.
    """
    kwargs: dict[str, Any] = {"console": self}
    if default is not None:
        kwargs["default"] = default
    value = await asyncio.to_thread(lambda: IntPrompt.ask(f"[prompt]{prompt}[/]", **kwargs))
    self.show_info(f"Chosen: {value}")
    return value

get_string(prompt, *, default=None) async #

Get string input from user.

Parameters:

Name Type Description Default
prompt str

Prompt message to display

required
default str | None

Default value. If None, input is required.

None
Source code in cogip/utils/console_ui.py
307
308
309
310
311
312
313
314
315
316
317
318
async def get_string(self, prompt: str, *, default: str | None = None) -> str:
    """
    Get string input from user.

    Args:
        prompt: Prompt message to display
        default: Default value. If None, input is required.
    """
    kwargs: dict[str, Any] = {"console": self}
    if default is not None:
        kwargs["default"] = default
    return await asyncio.to_thread(lambda: Prompt.ask(f"[prompt]{prompt}[/]", **kwargs))

show_comparison_table(data, title=None, key_header='Parameter', before_header='Previous', after_header='New') #

Display a before/after comparison table.

Parameters:

Name Type Description Default
data list[tuple[str, str, str]]

List of (key, before_value, after_value) tuples

required
title str | None

Optional table title

None
key_header str

Header for key column

'Parameter'
before_header str

Header for before column

'Previous'
after_header str

Header for after column

'New'
Source code in cogip/utils/console_ui.py
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
def show_comparison_table(
    self,
    data: list[tuple[str, str, str]],
    title: str | None = None,
    key_header: str = "Parameter",
    before_header: str = "Previous",
    after_header: str = "New",
) -> None:
    """Display a before/after comparison table.

    Args:
        data: List of (key, before_value, after_value) tuples
        title: Optional table title
        key_header: Header for key column
        before_header: Header for before column
        after_header: Header for after column
    """
    table = self.create_table(
        title=title,
        columns=[
            (key_header, {"style": "label"}),
            (before_header, {"style": "muted"}),
            (after_header, {"style": "value"}),
        ],
    )
    for key, before, after in data:
        table.add_row(key, before, after)
    self.print(table)

show_error(message) #

Display an error message.

Source code in cogip/utils/console_ui.py
216
217
218
def show_error(self, message: str) -> None:
    """Display an error message."""
    self.print(f"[error]\u2717 {message}[/]")

show_info(message) #

Display an info message.

Source code in cogip/utils/console_ui.py
220
221
222
def show_info(self, message: str) -> None:
    """Display an info message."""
    self.print(f"[muted]\u2139 {message}[/]")

show_key_value_table(data, title=None, key_header='Parameter', value_header='Value') #

Display a simple key-value table.

Parameters:

Name Type Description Default
data list[tuple[str, str]]

List of (key, value) tuples

required
title str | None

Optional table title

None
key_header str

Header for key column

'Parameter'
value_header str

Header for value column

'Value'
Source code in cogip/utils/console_ui.py
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def show_key_value_table(
    self,
    data: list[tuple[str, str]],
    title: str | None = None,
    key_header: str = "Parameter",
    value_header: str = "Value",
) -> None:
    """Display a simple key-value table.

    Args:
        data: List of (key, value) tuples
        title: Optional table title
        key_header: Header for key column
        value_header: Header for value column
    """
    table = self.create_table(
        title=title,
        columns=[
            (key_header, {"style": "label"}),
            (value_header, {"style": "value", "justify": "right"}),
        ],
    )
    for key, value in data:
        table.add_row(key, value)
    self.print(table)

show_panel(content, *, title=None, subtitle=None, border_style='header') #

Display a styled panel.

Parameters:

Name Type Description Default
content str

Panel content text

required
title str | None

Optional panel title

None
subtitle str | None

Optional panel subtitle

None
border_style str

Border style name from theme

'header'
Source code in cogip/utils/console_ui.py
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
def show_panel(
    self,
    content: str,
    *,
    title: str | None = None,
    subtitle: str | None = None,
    border_style: str = "header",
) -> None:
    """
    Display a styled panel.

    Args:
        content: Panel content text
        title: Optional panel title
        subtitle: Optional panel subtitle
        border_style: Border style name from theme
    """
    self.print(
        Panel(
            content,
            title=f"[header]{title}[/]" if title else None,
            subtitle=f"[muted]{subtitle}[/]" if subtitle else None,
            border_style=border_style,
            box=ROUNDED,
            padding=(1, 2),
        )
    )

show_rule(title, *, style='muted', title_style='phase') #

Display a horizontal rule with title.

Parameters:

Name Type Description Default
title str

Rule title text

required
style str

Line style name from theme

'muted'
title_style str

Title style name from theme

'phase'
Source code in cogip/utils/console_ui.py
195
196
197
198
199
200
201
202
203
204
205
206
def show_rule(self, title: str, *, style: str = "muted", title_style: str = "phase") -> None:
    """
    Display a horizontal rule with title.

    Args:
        title: Rule title text
        style: Line style name from theme
        title_style: Title style name from theme
    """
    self.print()
    self.print(Rule(f"[{title_style}]{title}[/]", style=style))
    self.print()

show_success(message) #

Display a success message.

Source code in cogip/utils/console_ui.py
208
209
210
def show_success(self, message: str) -> None:
    """Display a success message."""
    self.print(f"[success]\u2713 {message}[/]")

show_warning(message) #

Display a warning message.

Source code in cogip/utils/console_ui.py
212
213
214
def show_warning(self, message: str) -> None:
    """Display a warning message."""
    self.print(f"[warning]\u26a0 {message}[/]")

wait_for_enter(message) async #

Wait for user to press Enter.

Parameters:

Name Type Description Default
message str

Message to display before waiting

required
Source code in cogip/utils/console_ui.py
360
361
362
363
364
365
366
367
async def wait_for_enter(self, message: str) -> None:
    """
    Wait for user to press Enter.

    Args:
        message: Message to display before waiting
    """
    await asyncio.to_thread(lambda: self.input(f"[prompt]{message}[/] [muted][[Enter]][/] "))

CustomProgressTracker #

Progress tracker with manual lifecycle and custom columns/fields.

Features: - Manual start/update/stop control - Custom Rich columns - Custom task fields that can be updated

Example

tracker = console.create_progress_tracker(columns=[ SpinnerColumn(), TextColumn("{task.description}"), BarColumn(), TextColumn("Status: {task.fields[status]}"), ]) tracker.start("Processing", total=100, status="starting") for i in range(100): tracker.update(completed=i, status=f"item {i}") tracker.stop()

Source code in cogip/utils/console_ui.py
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
class CustomProgressTracker:
    """
    Progress tracker with manual lifecycle and custom columns/fields.

    Features:
    - Manual start/update/stop control
    - Custom Rich columns
    - Custom task fields that can be updated

    Example:
        tracker = console.create_progress_tracker(columns=[
            SpinnerColumn(),
            TextColumn("{task.description}"),
            BarColumn(),
            TextColumn("Status: {task.fields[status]}"),
        ])
        tracker.start("Processing", total=100, status="starting")
        for i in range(100):
            tracker.update(completed=i, status=f"item {i}")
        tracker.stop()
    """

    def __init__(
        self,
        console: Console,
        columns: list[ProgressColumn] | None = None,
    ):
        """
        Initialize the progress tracker.

        Args:
            console: Console instance for output
            columns: Custom Rich Progress columns. If None, uses default columns.
        """
        self._console = console
        self._columns = columns or [
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            BarColumn(),
            TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
            TimeElapsedColumn(),
        ]
        self._progress: Progress | None = None
        self._task_id: TaskID | None = None

    def start(
        self,
        description: str,
        total: float = 100,
        **fields: float,
    ) -> None:
        """
        Start the progress display.

        Args:
            description: Task description
            total: Total value for 100% completion (default: 100 for percentage)
            **fields: Custom fields to display
        """
        if self._progress is not None:
            raise RuntimeError("Progress already started. Call stop() first.")

        self._progress = Progress(*self._columns, console=self._console)
        self._progress.start()
        self._task_id = self._progress.add_task(description, total=total, **fields)

    def update(
        self,
        *,
        completed: float | None = None,
        description: str | None = None,
        **fields: float,
    ) -> None:
        """
        Update progress state.

        Args:
            completed: Current completion value (0 to total)
            description: New description (optional)
            **fields: Updated custom field values
        """
        if self._progress is None or self._task_id is None:
            return

        self._progress.update(
            self._task_id,
            completed=completed,
            description=description,
            **fields,
        )

    def stop(self, complete: bool = True) -> None:
        """
        Stop the progress display.

        Args:
            complete: If True, set progress to 100% before stopping
        """
        if self._progress is None:
            return

        if complete and self._task_id is not None:
            self._progress.update(self._task_id, completed=self._progress.tasks[self._task_id].total)

        self._progress.stop()
        self._progress = None
        self._task_id = None

    @property
    def is_active(self) -> bool:
        """Check if progress is currently active."""
        return self._progress is not None

is_active property #

Check if progress is currently active.

__init__(console, columns=None) #

Initialize the progress tracker.

Parameters:

Name Type Description Default
console Console

Console instance for output

required
columns list[ProgressColumn] | None

Custom Rich Progress columns. If None, uses default columns.

None
Source code in cogip/utils/console_ui.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def __init__(
    self,
    console: Console,
    columns: list[ProgressColumn] | None = None,
):
    """
    Initialize the progress tracker.

    Args:
        console: Console instance for output
        columns: Custom Rich Progress columns. If None, uses default columns.
    """
    self._console = console
    self._columns = columns or [
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        BarColumn(),
        TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
        TimeElapsedColumn(),
    ]
    self._progress: Progress | None = None
    self._task_id: TaskID | None = None

start(description, total=100, **fields) #

Start the progress display.

Parameters:

Name Type Description Default
description str

Task description

required
total float

Total value for 100% completion (default: 100 for percentage)

100
**fields float

Custom fields to display

{}
Source code in cogip/utils/console_ui.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def start(
    self,
    description: str,
    total: float = 100,
    **fields: float,
) -> None:
    """
    Start the progress display.

    Args:
        description: Task description
        total: Total value for 100% completion (default: 100 for percentage)
        **fields: Custom fields to display
    """
    if self._progress is not None:
        raise RuntimeError("Progress already started. Call stop() first.")

    self._progress = Progress(*self._columns, console=self._console)
    self._progress.start()
    self._task_id = self._progress.add_task(description, total=total, **fields)

stop(complete=True) #

Stop the progress display.

Parameters:

Name Type Description Default
complete bool

If True, set progress to 100% before stopping

True
Source code in cogip/utils/console_ui.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
def stop(self, complete: bool = True) -> None:
    """
    Stop the progress display.

    Args:
        complete: If True, set progress to 100% before stopping
    """
    if self._progress is None:
        return

    if complete and self._task_id is not None:
        self._progress.update(self._task_id, completed=self._progress.tasks[self._task_id].total)

    self._progress.stop()
    self._progress = None
    self._task_id = None

update(*, completed=None, description=None, **fields) #

Update progress state.

Parameters:

Name Type Description Default
completed float | None

Current completion value (0 to total)

None
description str | None

New description (optional)

None
**fields float

Updated custom field values

{}
Source code in cogip/utils/console_ui.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
def update(
    self,
    *,
    completed: float | None = None,
    description: str | None = None,
    **fields: float,
) -> None:
    """
    Update progress state.

    Args:
        completed: Current completion value (0 to total)
        description: New description (optional)
        **fields: Updated custom field values
    """
    if self._progress is None or self._task_id is None:
        return

    self._progress.update(
        self._task_id,
        completed=completed,
        description=description,
        **fields,
    )

demo() async #

Demonstrate ConsoleUI features.

Source code in cogip/utils/console_ui.py
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
async def demo() -> None:
    """Demonstrate ConsoleUI features."""
    ui = ConsoleUI()

    # Welcome panel
    ui.show_panel(
        "This demo showcases all features of the ConsoleUI class.\n"
        "Follow the prompts to see each feature in action.",
        title="Console UI Demo",
        subtitle="Interactive demonstration",
    )

    # Status messages
    ui.show_rule("Status Messages")
    ui.show_success("Operation completed successfully")
    ui.show_warning("This is a warning message")
    ui.show_error("This is an error message")
    ui.show_info("This is an informational message")

    # Key-value table
    ui.show_rule("Key-Value Table")
    ui.show_key_value_table(
        [
            ("Robot ID", "1"),
            ("Wheel diameter", "60.0 mm"),
            ("Encoder resolution", "4096 ticks"),
            ("Max speed", "1000 mm/s"),
        ],
        title="Robot Configuration",
    )

    # Comparison table
    ui.show_rule("Comparison Table")
    ui.show_comparison_table(
        [
            ("Left wheel", "59.8 mm", "60.2 mm"),
            ("Right wheel", "60.1 mm", "59.9 mm"),
            ("Track width", "280.0 mm", "281.5 mm"),
        ],
        title="Calibration Results",
        before_header="Before",
        after_header="After",
    )

    # Custom table
    ui.show_rule("Custom Table")
    table = ui.create_table(
        title="Sensor Readings",
        columns=[
            ("Sensor", {"style": "label"}),
            ("Value", {"style": "value", "justify": "right"}),
            ("Status", {"style": "success", "justify": "center"}),
        ],
    )
    table.add_row("Temperature", "25.3°C", "OK")
    table.add_row("Battery", "12.4V", "OK")
    table.add_row("Distance", "150 mm", "OK")
    ui.print(table)

    # Interactive inputs
    ui.show_rule("Interactive Inputs")

    robot_name = await ui.get_string("Robot name", default="PAMI")
    ui.show_info(f"Configuring robot: {robot_name}")

    robot_id = await ui.get_integer("Robot ID (1-4)", default=1)
    ui.show_info(f"Robot ID set to: {robot_id}")

    wheel_diameter = await ui.get_float("Wheel diameter (mm)", default=60.0)
    ui.show_info(f"Wheel diameter: {wheel_diameter:.1f} mm")

    confirmed = await ui.confirm("Do you want to continue?", default=True)
    if confirmed:
        ui.show_success("Continuing...")
    else:
        ui.show_warning("Cancelled by user")

    # Progress tracker demo
    ui.show_rule("Progress Tracker Demo")
    tracker = ui.create_progress_tracker()
    tracker.start("[info]Processing items[/]", total=10)
    for i in range(10):
        time.sleep(0.3)
        tracker.update(completed=i + 1)
    tracker.stop()
    ui.show_success("Progress tracker demo complete")

    # Final panel
    await ui.wait_for_enter("Press Enter to exit")
    ui.show_panel(
        "[success]All features demonstrated successfully![/]",
        title="Demo Complete",
        border_style="success",
    )