opal

๐Ÿ’Ž Opal

Next-Generation Terminal User Interface (TUI) & CLI DSL Framework for Crystal

CI Docs Crystal License: MIT

Pure Crystal. Zero external C library dependencies (no ncurses). Native Windows, Linux, and macOS support.


๐ŸŒŸ What is Opal?

Opal is an all-in-one terminal framework for Crystal designed to build world-class command-line interfaces, micro-interactive prompts, and full-screen terminal applications.

It merges the best paradigms from modern terminal engineering into a cohesive, idiomatic Crystal DSL:

  • ๐Ÿต The Elm Architecture (TEA) โ€” Pure, predictable state management inspired by Bubble Tea.
  • ๐ŸŽจ Declarative Fluent Styling & Themes โ€” Lipgloss-inspired composable styling, borders, 24-bit TrueColor, visual string width, and curated themes (Catppuccin, Dracula, TokyoNight, Nord, Gruvbox).
  • โšก Flicker-Free Delta Rendering โ€” Blessed-inspired double buffering that computes minimal character delta updates for 60fps full-screen performance.
  • ๐Ÿ› ๏ธ Expressive CLI App DSL โ€” Clap/Commander-style subcommands, typed flags, choices, global flag propagation, and shell completion (bash, zsh, fish).
  • ๐Ÿ“ Multi-Field Form & Wizard DSL โ€” All fields visible simultaneously, tab navigation, live inline validation, and instant submission.
  • ๐Ÿ” Live Fuzzy Search & Filter โ€” Instant keystroke matching with rune highlighting and split preview pane (Opal.filter).
  • ๐Ÿ“Š Rich Data Visualizations โ€” Unicode block Sparklines, horizontal/vertical BarCharts, percentage Gauges, and hierarchical Trees.
  • ๐ŸชŸ Layer Blending, Modals & Toasts โ€” Buffer blit, backdrop dimming, centered confirmation dialogs, and non-blocking toast queues.
  • ๐Ÿ“– Terminal Markdown Viewer โ€” Styled headers, blockquotes, lists, and syntax colorized code blocks.
  • ๐Ÿ”ฎ Ghost-Text Autocomplete & Input DSL โ€” Modern fish/zsh-style inline ghost text autocomplete on Tab, flexible interactive line editing, and declarative key bindings.
  • ๐Ÿ–ฑ๏ธ Hit-Test Mouse Routing DSL โ€” SGR extended mouse tracking with declarative click, drag, and scroll zones.
  • ๐Ÿ”— OSC 8 Links & OSC 52 Clipboard โ€” Native clickable terminal hyperlinks and desktop clipboard copying across SSH and local sessions.

๐Ÿ“ฆ Installation

Add Opal to your project's shard.yml:

dependencies:
  opal:
    github: sol-vin/opal
    version: ~> 0.1.0

Then install dependencies:

shards install

Require Opal in your Crystal code:

require "opal"

๐Ÿ“‘ Table of Contents


๐Ÿš€ Quick Start

1. Build an Interactive Setup Wizard with Opal.form

require "opal"

result = Opal.form("Project Setup") do |f|
  f.text "name", "Project Name:", default: "my-app", required: true
  f.password "token", "API Token:", min_length: 8
  f.select "db", "Database:", ["PostgreSQL", "SQLite", "MySQL"]
  f.multi_select "addons", "Addons:", ["Redis", "Elasticsearch", "GraphQL"]
  f.confirm "deploy", "Auto-deploy to staging?", default: true
end

if config = result
  puts "Created project #{config["name"]} using #{config["db"]}!"
end

2. Live Fuzzy Filter with Split Preview

require "opal"

branches = ["main", "staging", "feat/auth", "feat/fuzzy-finder", "fix/timeout"]

selected = Opal.filter(
  items: branches,
  title: "Git Switcher",
  preview: ->(b : String) { "Branch #{b}\nStatus: Clean\nUpdated: 5m ago" }
)

puts "Switched to branch: #{selected}" if selected

๐Ÿ“ Multi-Field Form & Wizard DSL

Traditional CLI prompts ask one question at a time and prevent reviewing earlier inputs. Opal.form presents an interactive card where all fields are visible simultaneously, users navigate using Tab / Shift+Tab, and live validation catches mistakes instantly.

result = Opal.form("New Microservice") do |f|
  f.text "service", "Service Name:", required: true
  f.text "port", "HTTP Port:", default: "8080"
  f.password "secret", "Secret Key:", min_length: 6
  f.select "tier", "Hosting Tier:", ["Small", "Medium", "Large"]
  f.multi_select "plugins", "Plugins:", ["Metrics", "Tracing", "Auth"]
  f.confirm "enabled", "Enable service immediately?", default: true

  # Custom real-time validation
  f.validate "port" do |val|
    (val.to_i? && (1024..65535).includes?(val.to_i)) ? nil : "Port must be 1024-65535"
  end
end

๐Ÿ” Live Fuzzy Search & Filter

Fast, keystroke-responsive fuzzy filtering inspired by fzf:

  • Instant substring matching with word boundary bonuses.
  • Highlights matched characters in bold cyan.
  • Split preview pane for viewing item details.
choice = Opal.filter(
  items: Dir["src/**/*.cr"],
  title: "Fuzzy File Finder",
  preview: ->(path : String) { File.read(path).lines.first(15).join("\n") }
)

๐Ÿ“Š Data Visualizations

Render rich dashboards and metrics without graphics libraries:

Sparklines

# Output:  โ–‚โ–„โ–‡โ–‡โ–ˆโ–†โ–„โ–ƒโ–‚โ–‚
puts Opal::UI::Sparkline.render_to_string([10.0, 15.0, 25.0, 80.0, 95.0, 60.0])

BarCharts, Gauges & Trees in UI Trees

Opal.render_ui(width: 70, height: 20) do |ui|
  ui.vstack(spacing: 1) do |v|
    # Percentage Gauge
    v.gauge 0.76, label: "Disk Usage", color: :yellow

    # Horizontal Bar Chart
    v.barchart(title: "Memory Allocation") do |bc|
      bc.bar "Web", 420, color: :green
      bc.bar "Worker", 850, color: :cyan
      bc.bar "DB", 1200, color: :red
    end

    # Hierarchical Tree
    v.tree(title: "Service Graph") do |t|
      t.node("API Gateway", icon: "๐ŸŒ") do |gateway|
        gateway.add("Auth Service", icon: "๐Ÿ”’")
        gateway.add("Search Node", icon: "๐Ÿ”")
      end
    end
  end
end

๐ŸชŸ Buffer Blitting, Modals & Toasts

Floating Modal Dialog

Center a dialog box over any screen buffer with automatic background dimming:

modal = Opal::UI::Modal.new(
  title: "Confirm Deletion",
  message: "Are you sure you want to drop database 'prod'?",
  buttons: ["Cancel", "Confirm Drop"],
  selected_button: 1
)
modal.render(buffer, 0, 0, 80, 24)

Toast Notifications

Stack floating alerts in the top-right corner with auto-dismiss timers:

toasts = Opal::UI::ToastManager.new
toasts.add("Build Succeeded", "All 124 tests passed", level: :success, duration_ms: 3000)
toasts.add("Disk Warning", "Free space below 10%", level: :warning)

toasts.render_overlay(buffer, position: :top_right)

๐Ÿ“– Terminal Markdown Viewer

Convert Markdown documents into styled ANSI terminal text:

doc = <<-MD
# Opal Framework v1.0
Welcome to **Opal**! Build *beautiful* CLIs in Crystal.

### Features
- Zero external C dependencies
- 60fps delta rendering

```crystal
require "opal"
puts "Hello world!"

"Simplicity is prerequisite for reliability." MD

puts Opal.render_markdown(doc, width: 80)


---

## ๐ŸŽจ Theme Engine & Semantic Colors

Opal includes pre-registered designer palettes and semantic color tokens:

```crystal
# Switch theme dynamically
Opal.theme = :catppuccin_mocha # :dracula, :nord, :tokyo_night, :gruvbox, etc.

# Semantic color tokens
theme = Opal.theme
style = Opal.style
  .foreground(theme.primary)
  .background(theme.surface)
  .border_foreground(theme.border)

๐Ÿ” Command Palette Overlay

Press Ctrl+P or Ctrl+K to summon an instant Spotlight action launcher:

palette = Opal::UI::CommandPalette.new
palette.add("git:commit", "Commit changes", category: "Git", shortcut: "ctrl+c") { commit_flow }
palette.add("file:open", "Open file picker", category: "File", shortcut: "ctrl+o") { open_picker }

๐Ÿ”— OSC 8 Hyperlinks & OSC 52 Clipboard

# Clickable hyperlink in modern terminals
puts Opal.hyperlink("View Source on GitHub", "https://github.com/sol-vin/opal")

# Copy directly to OS desktop clipboard over SSH and local sessions
Opal.copy_to_clipboard("API_KEY_SECRET_12345")

โฑ๏ธ Animation & Easing Engine

Smooth transitions, progress bars, and color interpolation:

# Easing functions
t = Opal::Animation.ease(:ease_in_out_cubic, 0.5)

# Color interpolation (e.g. green to red as CPU load increases)
normal_color = Opal::Color.green
alert_color  = Opal::Color.red
current_c    = Opal::Color.lerp(normal_color, alert_color, 0.75)

๐Ÿ› ๏ธ CLI Application DSL

app = Opal.cli("deployer", "Cloud deployment manager", "0.4.0") do
  option "-v", "--verbose", "Enable debug logging", type: :bool

  command "deploy", "Deploy application containers" do
    argument "service", "Service name to deploy"
    option "-c", "--concurrency=NUM", "Max concurrency", type: :int, default: 3

    run do |ctx|
      svc = ctx.argument("service")
      puts "Deploying #{svc} (concurrency: #{ctx.int("concurrency")})..."
    end
  end
end

app.run(ARGV)

๐Ÿต The Elm Architecture (TEA)

Build reactive terminal applications with pure state transitions:

record CounterModel, count : Int32 = 0 do
  include Opal::Tea::Model

  def init : Opal::Tea::Cmd
    Opal::Tea::Cmd.none
  end

  def update(msg : Opal::Tea::Msg) : {Opal::Tea::Model, Opal::Tea::Cmd}
    case msg
    when Opal::Tea::KeyMsg
      case msg.key
      when "up", "k"   then {CounterModel.new(count + 1), Opal::Tea::Cmd.none}
      when "down", "j" then {CounterModel.new(count - 1), Opal::Tea::Cmd.none}
      when "q"         then {self, Opal::Tea::Cmd.quit}
      else {self, Opal::Tea::Cmd.none}
      end
    else
      {self, Opal::Tea::Cmd.none}
    end
  end

  def view : String
    "Counter: #{count} (Press โ†‘/k, โ†“/j, q to quit)"
  end
end

Opal::Tea::Program.new(CounterModel.new).run

๐Ÿงช Testing with MockDriver

Test full TUI interactions headlessly without opening an actual terminal:

require "spec"
require "opal"

describe "Counter" do
  it "increments on keypress" do
    model = CounterModel.new
    new_model, cmd = model.update(Opal::Tea::KeyMsg.new("k"))
    new_model.as(CounterModel).count.should eq(1)
  end
end

๐Ÿ“‚ Examples

Explore all runnable examples in the examples/ directory:

  • 01_lapis_revamp.cr โ€” Comprehensive CLI developer toolchain with subcommands, typed options, and table reports.
  • 02_interactive_prompts.cr โ€” Setup wizard showing ask, confirm, select, multi_select, spinner, and progress.
  • 03_tea_counter.cr โ€” Classic Elm Architecture counter application with keyboard controls.
  • 04_system_dashboard.cr โ€” Live full-screen system monitor dashboard with charts, tables, and async metrics updates.
  • 05_autocomplete_and_input.cr โ€” Interactive REPL showcasing Tab autocompletion, inline ghost-text hints, keymaps, mouse routing, and terminal inspection.
  • 06_rich_form_wizard.cr โ€” Multi-field form wizard with live validation, password masking, select menus, and checkboxes.
  • 07_fuzzy_finder.cr โ€” Live fuzzy search list with rune highlighting and split preview pane.
  • 08_dataviz_dashboard.cr โ€” Rich analytics dashboard with Sparklines, BarCharts, Gauges, Trees, and Themes.
  • 09_markdown_and_overlays.cr โ€” Terminal Markdown viewer, Modal dialogs, and floating Toast notifications.

Run any example:

crystal run examples/06_rich_form_wizard.cr
crystal run examples/08_dataviz_dashboard.cr
crystal run examples/09_markdown_and_overlays.cr

๐ŸŒ Cross-Platform Support

Platform Terminal Backend Colors Mouse Support
Linux POSIX termios, VT100, SGR TrueColor, 256, ANSI 16 Yes (SGR 1006)
macOS POSIX termios, VT100, SGR TrueColor, 256, ANSI 16 Yes (SGR 1006)
Windows Win32 Console API (ENABLE_VIRTUAL_TERMINAL_PROCESSING) + ANSI VT100 TrueColor, 256, ANSI 16 Yes (SGR 1006)

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

Repository

opal

Owner
Statistic
  • 0
  • 0
  • 0
  • 3
  • 0
  • about 11 hours ago
  • September 29, 2026
License

MIT License

Links
Synced at

Tue, 29 Sep 2026 12:40:50 GMT

Languages