# Terminal Management

## Overview

ChukTerm provides comprehensive terminal management utilities for handling terminal state, cleanup, and cross-platform operations. The `TerminalManager` class offers a unified interface for terminal operations that work across Windows, macOS, and Linux.

## Core Features

### 1. Screen Clearing
Clear the terminal screen using platform-appropriate commands:

```python
from chuk_term.ui.terminal import clear_screen

# Clear the terminal
clear_screen()

# Or using the manager directly
from chuk_term.ui.terminal import TerminalManager
TerminalManager.clear()
```

- **Windows**: Uses `cls` command
- **Unix/Linux/macOS**: Uses `clear` command

### 2. Terminal Reset
Reset terminal to sane defaults (Unix-like systems only):

```python
from chuk_term.ui.terminal import reset_terminal

# Reset terminal settings
reset_terminal()

# Useful after programs leave terminal in bad state
```

- Runs `stty sane` on Unix-like systems
- No-op on Windows
- Handles errors gracefully with debug logging

### 3. Terminal Size Detection
Get current terminal dimensions:

```python
from chuk_term.ui.terminal import get_terminal_size

# Get size as (columns, rows)
cols, rows = get_terminal_size()

print(f"Terminal size: {cols}×{rows}")

# Check terminal size categories
if cols < 80:
    print("Narrow terminal - content may wrap")
elif cols < 120:
    print("Standard terminal width")
else:
    print("Wide terminal - good for side-by-side views")
```

- Uses `shutil.get_terminal_size()` internally
- Returns default (80, 24) if detection fails

### 4. Terminal Title
Set the terminal window title:

```python
from chuk_term.ui.terminal import set_terminal_title

# Set a custom title
set_terminal_title("ChukTerm - Processing...")

# Update title with status
for i in range(100):
    set_terminal_title(f"Progress: {i+1}%")
    # ... do work ...

set_terminal_title("ChukTerm - Complete")
```

- **Windows**: Uses `title` command
- **Unix/Linux/macOS**: Uses ANSI escape sequence `\033]0;title\007`

### 5. Color Support Detection
Check terminal color capabilities:

```python
from chuk_term.ui.terminal import TerminalManager

# Basic color support
if TerminalManager.supports_color():
    print("\033[32mGreen text\033[0m")  # Use ANSI colors
else:
    print("Plain text")  # No colors

# Advanced color detection
if TerminalManager.supports_truecolor():
    print("24-bit RGB colors supported")
elif TerminalManager.supports_256_colors():
    print("256 colors supported")
else:
    print("Basic 16 colors")

# Get color level
color_level = TerminalManager.get_color_level()
# Returns: 'truecolor', '256', '16', or 'mono'
```

- **supports_color()**: Returns `True` if stdout is a TTY
- **supports_truecolor()**: Checks for 24-bit RGB support via COLORTERM
- **supports_256_colors()**: Checks for 256 color support via TERM
- **get_color_level()**: Returns the highest supported color level

### 6. Cursor Control
Control cursor visibility and position (Unix-like systems):

```python
from chuk_term.ui.terminal import (
    hide_cursor, show_cursor,
    TerminalManager
)

# Hide/show cursor
hide_cursor()
# ... do work without visible cursor ...
show_cursor()

# Save and restore position
TerminalManager.save_cursor_position()
print("Line 1")
print("Line 2")
TerminalManager.restore_cursor_position()  # Back to saved position

# Move cursor
TerminalManager.move_cursor_up(2)    # Move up 2 lines
TerminalManager.move_cursor_down(1)  # Move down 1 line
TerminalManager.clear_line()          # Clear current line
```

- Cursor control uses ANSI escape sequences
- No-op on Windows
- Useful for creating dynamic terminal UIs

### 7. Hyperlinks
Create clickable hyperlinks in supported terminals:

```python
from chuk_term.ui.terminal import hyperlink, TerminalManager

# Create hyperlink with TerminalManager
link = TerminalManager.hyperlink("https://example.com")
print(f"Visit: {link}")

# Custom link text
link = TerminalManager.hyperlink("https://docs.example.com", "Documentation")
print(f"Read the {link}")

# Using Rich for hyperlinks (recommended with Rich output)
from chuk_term.ui.output import get_output
ui = get_output()
ui.print("Visit [link=https://example.com]our website[/link]")
```

Supported terminals include:
- iTerm2 (macOS)
- Kitty
- WezTerm
- Hyper
- Most modern terminal emulators with OSC 8 support

For unsupported terminals, falls back to "text (url)" format.

### 8. Terminal Bell
Sound the terminal bell/beep:

```python
from chuk_term.ui.terminal import bell

# Sound the bell
bell()

# Multiple bells with delay
import time
for i in range(3):
    bell()
    time.sleep(1)
```

- Uses ASCII bell character (`\a`)
- May be disabled in terminal settings
- Some terminals flash instead of beeping

### 9. Alternate Screen Buffer
Use alternate screen like vim, less, or htop:

```python
from chuk_term.ui.terminal import alternate_screen

# Using context manager (recommended)
with alternate_screen():
    # Now in alternate screen
    print("This is in alternate screen")
    print("Original screen content is preserved")
    input("Press Enter to return...")
# Automatically returns to main screen

# Manual control
from chuk_term.ui.terminal import TerminalManager
TerminalManager.enter_alternate_screen()
# ... work in alternate screen ...
TerminalManager.exit_alternate_screen()
```

The alternate screen:
- Preserves main screen content
- Automatically hides cursor in context manager
- Used by full-screen applications
- Clears when exiting

### 10. Terminal Information
Get comprehensive terminal information:

```python
from chuk_term.ui.terminal import get_terminal_info, TerminalManager

# Get all terminal info
info = get_terminal_info()
print(f"Terminal: {info['program']}")
print(f"Type: {info['type']}")
print(f"Size: {info['size']['columns']}×{info['size']['rows']}")
print(f"Encoding: {info['encoding']}")

# Check specific environments
if TerminalManager.is_tmux():
    print("Running in tmux")
if TerminalManager.is_ssh():
    print("Connected via SSH")
if TerminalManager.is_screen():
    print("Running in GNU screen")

# Get terminal program
program = TerminalManager.get_terminal_program()
# Returns: 'iTerm.app', 'Terminal.app', 'unknown', etc.
```

### 11. Progress in Title
Show progress in the terminal title bar:

```python
from chuk_term.ui.terminal import TerminalManager

# Basic progress
for i in range(101):
    TerminalManager.set_title_progress(i)
    # ... do work ...
    time.sleep(0.1)

# Custom prefix
for i in range(101):
    TerminalManager.set_title_progress(i, "Downloading")
    # Shows: "Downloading: [████░░░░░░] 40%"
```

Creates a visual progress bar in the title with percentage.

### 12. Full Terminal Restoration
Restore terminal and clean up all resources:

```python
from chuk_term.ui.terminal import restore_terminal

try:
    # Your application code
    run_app()
finally:
    # Always restore on exit
    restore_terminal()
```

The `restore_terminal()` function performs:
1. Terminal reset (`stty sane` on Unix)
2. Asyncio cleanup (cancels tasks, closes event loops)
3. Garbage collection

## Asyncio Cleanup

The terminal manager provides comprehensive asyncio cleanup to prevent resource leaks:

```python
from chuk_term.ui.terminal import TerminalManager

# Cleanup asyncio resources
TerminalManager.cleanup_asyncio()
```

This function:
- Detects running vs non-running event loops
- Cancels pending tasks gracefully
- Shuts down async generators
- Closes event loops properly
- Handles all errors without raising exceptions

### Cleanup Process

1. **Loop Detection**: Checks for running or existing event loops
2. **Task Cancellation**: Only cancels tasks that aren't done
3. **Graceful Shutdown**: Gives tasks time to cancel cleanly
4. **Generator Cleanup**: Shuts down async generators
5. **Loop Closure**: Closes the event loop if not running

## Usage Examples

### Basic Terminal Operations

```python
from chuk_term.ui.terminal import (
    clear_screen,
    get_terminal_size,
    set_terminal_title,
    TerminalManager
)

# Clear and setup
clear_screen()
set_terminal_title("My Application")

# Get and display size
cols, rows = get_terminal_size()
print(f"Working with {cols}×{rows} terminal")

# Check capabilities
if TerminalManager.supports_color():
    print("✅ Color support detected")
else:
    print("No color support")
```

### Application Lifecycle Management

```python
import asyncio
from chuk_term.ui.terminal import restore_terminal, set_terminal_title

async def main():
    try:
        set_terminal_title("App Running")
        
        # Create background tasks
        tasks = [
            asyncio.create_task(background_work()),
            asyncio.create_task(monitor_input())
        ]
        
        # Run application
        await run_application()
        
    finally:
        # Always restore terminal on exit
        restore_terminal()
        print("Terminal restored successfully")

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        restore_terminal()
```

### Dynamic Terminal Monitoring

```python
import asyncio
from chuk_term.ui.terminal import get_terminal_size

async def monitor_terminal_size():
    """Monitor and react to terminal size changes."""
    last_size = (0, 0)
    
    while True:
        current_size = get_terminal_size()
        
        if current_size != last_size:
            cols, rows = current_size
            print(f"Terminal resized to {cols}×{rows}")
            
            # Adjust UI layout based on new size
            if cols < 80:
                use_compact_layout()
            else:
                use_full_layout()
            
            last_size = current_size
        
        await asyncio.sleep(0.5)
```

## Platform Compatibility

| Feature | Windows | macOS | Linux | Notes |
|---------|---------|-------|-------|-------|
| Clear Screen | ✅ `cls` | ✅ `clear` | ✅ `clear` | Platform-specific commands |
| Terminal Reset | ❌ | ✅ `stty sane` | ✅ `stty sane` | Unix-only feature |
| Size Detection | ✅ | ✅ | ✅ | Falls back to 80×24 |
| Set Title | ✅ `title` | ✅ ANSI | ✅ ANSI | May not work in all terminals |
| Progress in Title | ✅ | ✅ | ✅ | Uses set title functionality |
| Color Support | ✅ | ✅ | ✅ | Based on TTY detection |
| 256/True Color Detection | ✅ | ✅ | ✅ | Via environment variables |
| Cursor Control | ❌ | ✅ ANSI | ✅ ANSI | Unix-only, uses escape sequences |
| Hyperlinks (OSC 8) | ⚠️ | ✅ | ✅ | Terminal-dependent support |
| Terminal Bell | ✅ | ✅ | ✅ | May be disabled in settings |
| Alternate Screen | ❌ | ✅ ANSI | ✅ ANSI | Unix-only feature |
| Terminal Info | ✅ | ✅ | ✅ | Environment detection |
| Asyncio Cleanup | ✅ | ✅ | ✅ | Cross-platform |

## Best Practices

### 1. Always Restore on Exit
```python
try:
    run_application()
finally:
    restore_terminal()
```

### 2. Handle Non-TTY Environments
```python
import sys

if not sys.stdout.isatty():
    print("Warning: Not running in a terminal")
    # Disable color output, interactive features
```

### 3. Test Terminal Capabilities
```python
def setup_ui():
    if TerminalManager.supports_color():
        enable_rich_output()
    else:
        use_plain_text_mode()
    
    cols, rows = get_terminal_size()
    if cols < 80:
        use_narrow_layout()
```

### 4. Graceful Degradation
```python
try:
    set_terminal_title("My App")
except Exception:
    # Some terminals don't support title changes
    pass
```

### 5. Write Theme-Agnostic Code
The UI system automatically handles theme differences. Never check themes in application code:

```python
# ✅ GOOD - Theme-agnostic
from rich.table import Table
from chuk_term.ui.output import get_output

ui = get_output()

# Create table normally
table = Table(show_header=True, title="Status")
table.add_column("Property")
table.add_column("Value")
table.add_row("Size", f"{cols}×{rows}")
table.add_row("Color", "Supported" if has_color else "Not supported")

# Let the UI system handle theme-appropriate rendering
ui.print_table(table)  # Automatically converts to text for minimal/terminal themes

# ❌ BAD - Theme-aware (don't do this!)
if theme.name == "minimal":
    print(f"Size: {cols}×{rows}")
else:
    # Create rich table
    ...
```

The output system automatically:
- Renders Rich tables with full formatting for default/dark/light themes
- Converts tables to aligned plain text for minimal/terminal themes
- Handles all theme-specific formatting internally

## Demo Script

A comprehensive terminal demo script is available:

```bash
# Run the terminal management demo
uv run examples/ui_terminal_demo.py
```

The demo includes:
1. **Terminal Information** - Display comprehensive terminal details
2. **Clear Screen** - Platform-specific screen clearing
3. **Terminal Title** - Dynamic title updates
4. **Terminal Reset** - Reset to sane defaults (Unix)
5. **Size Detection** - Monitor terminal resizing
6. **Color Support** - Check color capabilities (16/256/truecolor)
7. **Cursor Control** - Hide/show, move, save/restore cursor position
8. **Hyperlinks** - Clickable links in supported terminals
9. **Terminal Bell** - System beep/flash demonstration
10. **Alternate Screen** - Full-screen buffer like vim/less
11. **Asyncio Tasks** - Task management and cleanup
12. **Theme Integration** - Terminal features with themes
13. **Stress Test** - Rapid terminal operations

## Error Handling

All terminal operations handle errors gracefully:

- **Missing TTY**: Operations degrade gracefully
- **Permission Errors**: Logged but don't crash
- **Platform Limitations**: Fallback behaviors provided
- **Asyncio Errors**: Caught and logged during cleanup

## Related Documentation

- [UI Themes](./themes.md) - Theme system that works with terminal features
- [Output System](./output.md) - Rich terminal output
- [Prompts](./prompts.md) - Interactive terminal prompts
- [Testing](../testing/UNIT_TESTING.md) - Terminal management tests (99% coverage)