Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 301 additions & 0 deletions DEVTOOLS_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
# Scenic DevTools Guide

## Overview

The new Scenic DevTools provide a unified interface for inspecting and debugging Scenic applications, with a focus on semantic content that supports development, testing, automation, and accessibility.

## Key Improvements

### 1. Unified `inspect_viewport()` Function

The new `inspect_viewport()` replaces both `scene_tree()` and `inspect_app()` with a single, powerful function that provides:

```elixir
# Import the tools
import Scenic.DevTools

# Full inspection (default)
inspect_viewport()

# Options for focused inspection
inspect_viewport(show: :semantic) # Just semantic content
inspect_viewport(show: :scenes) # Just scene hierarchy
inspect_viewport(show: :graphs) # Just graphs
inspect_viewport(verbose: true) # Detailed view
inspect_viewport(graph: "abc123") # Specific graph
```

### 2. Semantic-First Design

The tools are built around the semantic layer, making it easy to:
- Find elements by their semantic type
- Access content directly without parsing visual output
- Build automation and accessibility features

### 3. Generic Semantic Functions

```elixir
# Find elements by type
find(:button)
find(:text_buffer)
find(:menu)

# See what types are in use
types()

# View all semantic content
semantic()

# Get raw data for advanced queries
raw_semantic()
```

### 4. Application-Specific Functions

Text editor applications (like Quillex) extend the DevTools with specialized functions:

```elixir
# Import both modules
import Scenic.DevTools
import Quillex.DevTools

# Text buffer functions (Quillex-specific)
buffers() # List all text buffers with preview
buffer(1) # Show full content of buffer by index
buffer("uuid") # Show buffer by ID
buffer("file.ex") # Show buffer by filename

# Other editor-specific tools
cursor_info() # Show cursor position and context
selection_info() # Show current selection
buffer_stats() # Detailed buffer statistics
syntax_info() # Language/syntax detection
```

## Semantic Annotation Best Practices

### Adding Semantic Data

When building Scenic graphs, add semantic annotations to make elements queryable:

```elixir
@graph Graph.build()
# Text buffer with semantic info
|> text(buffer_content,
id: :buffer_text,
semantic: Semantic.text_buffer(buffer_id: buffer.uuid))

# Button with semantic info
|> rect({100, 40},
id: :save_button,
semantic: Semantic.button("Save"))

# Custom semantic data
|> group(
semantic: %{
type: :code_editor,
language: :elixir,
file_path: "lib/myfile.ex",
editable: true
})
```

### Semantic Helper Functions

The `Scenic.Semantic` module provides helpers for common patterns:

```elixir
Semantic.button("Label") # Clickable button
Semantic.text_buffer(buffer_id: id) # Text editor buffer
Semantic.text_input(name, opts) # Input field
Semantic.menu(name, opts) # Menu container
Semantic.menu_item(label, opts) # Menu item
Semantic.annotate(type, attrs) # Generic annotation
```

### Custom Semantic Types

You can create custom semantic types for your application:

```elixir
# In your component
|> rect({100, 100},
semantic: %{
type: :code_cell, # Custom type
language: :elixir,
cell_id: 42,
execution_state: :ready
})

# Query it later
find(:code_cell)
```

## Usage Examples

### During Development

```elixir
iex> import Scenic.DevTools

# Get overview of your app
iex> inspect_viewport()

╔═══ Scenic ViewPort Inspector ═══╗
║ ViewPort: :main_viewport
║ Size: 800×600
║ Root: Elixir.MyApp.Scene.Root
╚═════════════════════════════════╝

🎬 Scene Hierarchy:
─────────────────
🎬 _main_ (RootScene)
├── 📄 editor_1 (EditorScene)
└── 📄 sidebar (SidebarScene)

📊 Graphs & Semantic Content:
────────────────────────────

🏷️ With Semantic Data:
📋 "abc123..." (scene: editor_1)
Elements: 3
📝 text_buffer: 1 buffer
🔘 button: Save, Cancel

📈 Semantic Summary:
──────────────────
📝 text_buffer: 1 (1 buffer)
🔘 button: 2 (Save, Cancel)

💡 Quick Commands:
• inspect_viewport(show: :semantic) # Just semantic content
• find(:button) # Find by type
• types() # List all types
• semantic() # All semantic content
```

### Finding Elements

```elixir
iex> find(:button)

🔘 Found 3 button element(s):

Graph "abc123...":
• "Save"
• "Cancel"

Graph "def456...":
• "Submit"
```

### Application-Specific Buffer Access (Quillex)

```elixir
# Import Quillex-specific tools
iex> import Quillex.DevTools

# See all buffers
iex> buffers()

📝 Text Buffers:
[1] Buffer abc12345... (main.ex): "defmodule MyApp do..."
[2] Buffer def67890... (notes.md): "# TODO: implement feature"

# Inspect specific buffer
iex> buffer(1)

📝 Buffer Details:
ID: abc12345-6789-0123-4567-890123456789
File: lib/main.ex
Editable: true

Stats: 25 lines, 89 words, 487 chars
Cursor: Line 5, Column 12

--- Content ---
defmodule MyApp do
use Application

def start(_type, _args) do
# ...
end
end
--- End ---
```

## Application-Specific Extensions

Applications can extend the DevTools with domain-specific functionality:

```elixir
defmodule MyApp.DevTools do
# Import base DevTools
import Scenic.DevTools

# Add app-specific tools
def show_active_document() do
# Use semantic queries to find active document
case find(:document) do
# Custom logic here
end
end

def list_open_files() do
# Query semantic data for file information
raw_semantic()
|> extract_file_info()
|> display_files()
end
end
```

## Integration with Testing

The DevTools are designed to work seamlessly with testing frameworks:

```elixir
defmodule MyAppTest do
use ExUnit.Case
alias Scenic.Semantic.Query

test "save button saves the document" do
# Start your scene
{:ok, scene, viewport} = start_scene()

# Use semantic queries
{:ok, save_button} = Query.get_button_by_label(viewport, "Save")
{:ok, buffer_text} = Query.get_buffer_text(viewport, buffer_id)

# Simulate interaction
send_event(scene, {:click, save_button.id})

# Verify results
assert file_saved?()
end
end
```

## Tips and Tricks

1. **Use verbose mode for debugging**: `inspect_viewport(verbose: true)` shows additional details

2. **Filter by graph**: `inspect_viewport(graph: "partial_id")` to focus on specific components

3. **Combine with IEx helpers**: The DevTools work great with IEx's autocomplete and history

4. **Add semantic data incrementally**: Start with key interactive elements, add more as needed

5. **Use consistent semantic types**: Stick to common types like `:button`, `:text_buffer`, `:menu` when possible

6. **Include metadata**: Add extra fields like `file_path`, `cursor_position`, `language` to semantic data

## Future Enhancements

The semantic layer and DevTools are designed to support future features:

- **Accessibility**: Screen readers can use semantic data
- **Automation**: UI testing frameworks can find elements reliably
- **AI Integration**: Language models can understand UI structure
- **Remote Debugging**: Inspect apps running on other devices
- **Time-Travel Debugging**: Record and replay semantic state changes
Loading
Loading