release: Storybook v0.2.0 - Major syntax and features update
BREAKING CHANGES: - Relationship syntax now requires blocks for all participants - Removed self/other perspective blocks from relationships - Replaced 'guard' keyword with 'if' for behavior tree decorators Language Features: - Add tree-sitter grammar with improved if/condition disambiguation - Add comprehensive tutorial and reference documentation - Add SBIR v0.2.0 binary format specification - Add resource linking system for behaviors and schedules - Add year-long schedule patterns (day, season, recurrence) - Add behavior tree enhancements (named nodes, decorators) Documentation: - Complete tutorial series (9 chapters) with baker family examples - Complete reference documentation for all language features - SBIR v0.2.0 specification with binary format details - Added locations and institutions documentation Examples: - Convert all examples to baker family scenario - Add comprehensive working examples Tooling: - Zed extension with LSP integration - Tree-sitter grammar for syntax highlighting - Build scripts and development tools Version Updates: - Main package: 0.1.0 → 0.2.0 - Tree-sitter grammar: 0.1.0 → 0.2.0 - Zed extension: 0.1.0 → 0.2.0 - Storybook editor: 0.1.0 → 0.2.0
This commit is contained in:
10
zed-storybook/.gitignore
vendored
Normal file
10
zed-storybook/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Binaries (built by build-extension.sh for local testing)
|
||||
bin/
|
||||
|
||||
# Rust build artifacts
|
||||
target/
|
||||
Cargo.lock
|
||||
|
||||
# Zed extension artifacts
|
||||
*.wasm
|
||||
grammars/ # Downloaded and compiled by Zed during extension build
|
||||
12
zed-storybook/Cargo.toml
Normal file
12
zed-storybook/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "zed-storybook"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
description = "Zed extension for Storybook DSL"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
zed_extension_api = "0.2.0"
|
||||
149
zed-storybook/README.md
Normal file
149
zed-storybook/README.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Storybook Extension for Zed
|
||||
|
||||
This extension provides language support for the Storybook narrative DSL in [Zed](https://zed.dev).
|
||||
|
||||
## Features
|
||||
|
||||
- **Syntax highlighting** for all Storybook constructs
|
||||
- **Markdown support** in prose blocks (inline markdown highlighting)
|
||||
- **Document outline** showing characters, templates, relationships, etc.
|
||||
- **Bracket matching** including special `---` prose block markers
|
||||
- **Auto-indentation** with proper block handling
|
||||
- **LSP integration** (when storybook-lsp is installed)
|
||||
- Real-time diagnostics
|
||||
- Hover documentation
|
||||
- Go-to-definition
|
||||
- Find references
|
||||
- Autocomplete
|
||||
- Document formatting
|
||||
|
||||
## Installation
|
||||
|
||||
### For Development (from this repository)
|
||||
|
||||
1. Build the extension (includes LSP server):
|
||||
```bash
|
||||
cd zed-storybook
|
||||
./build-extension.sh
|
||||
```
|
||||
|
||||
2. Install the extension in Zed:
|
||||
- Open Zed
|
||||
- Run command: `zed: install dev extension` (Cmd+Shift+P)
|
||||
- Select the `zed-storybook` directory
|
||||
|
||||
3. Test:
|
||||
- Open a `.sb` file in Zed
|
||||
- The LSP should activate automatically
|
||||
- Try hovering over symbols to see rich information!
|
||||
|
||||
**Note:** The `build-extension.sh` script builds the LSP server and copies the binary into `bin/storybook-lsp` for local testing. The extension will automatically find it there.
|
||||
|
||||
### For Users (once published)
|
||||
|
||||
1. Open Zed
|
||||
2. Open the command palette (Cmd+Shift+P)
|
||||
3. Search for "Extensions: Install Extensions"
|
||||
4. Search for "Storybook"
|
||||
5. Click Install
|
||||
|
||||
## Usage
|
||||
|
||||
Once installed, the extension will automatically activate for `.sb` files.
|
||||
|
||||
### Syntax Highlighting
|
||||
|
||||
The extension provides rich syntax highlighting:
|
||||
- **Keywords** (character, template, relationship, etc.) in purple
|
||||
- **Strings** in yellow
|
||||
- **Numbers** in light purple
|
||||
- **Comments** in gray
|
||||
- **Prose blocks** with Markdown syntax highlighting inside
|
||||
|
||||
### Prose Blocks with Markdown
|
||||
|
||||
Prose blocks support full Markdown syntax:
|
||||
|
||||
```storybook
|
||||
character Alice {
|
||||
---backstory
|
||||
Alice was a **curious** girl who loved:
|
||||
- Reading books
|
||||
- Asking questions
|
||||
- *Adventures*
|
||||
|
||||
She often wondered about the world.
|
||||
---
|
||||
}
|
||||
```
|
||||
|
||||
The markdown inside prose blocks will be highlighted appropriately.
|
||||
|
||||
### LSP Features
|
||||
|
||||
If you have `storybook-lsp` installed, you'll get:
|
||||
|
||||
- **Real-time validation** - Errors and warnings as you type
|
||||
- **Hover information** - Documentation and type info on hover
|
||||
- **Go to definition** - Jump to character/template definitions
|
||||
- **Find references** - See where entities are used
|
||||
- **Autocomplete** - Suggestions for field names, entity names, etc.
|
||||
|
||||
## Configuration
|
||||
|
||||
The extension uses these default settings:
|
||||
- Tab size: 4 spaces
|
||||
- Line comments: `//`
|
||||
- Block comments: `/* */`
|
||||
- Auto-close brackets: Yes
|
||||
|
||||
You can customize these in Zed's settings.
|
||||
|
||||
## Language Server
|
||||
|
||||
The extension looks for `storybook-lsp` in your PATH. To install it:
|
||||
|
||||
```bash
|
||||
# From the storybook repository
|
||||
cargo install --path storybook --bin storybook-lsp
|
||||
```
|
||||
|
||||
## File Association
|
||||
|
||||
The extension automatically activates for files with the `.sb` extension.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Extension not loading
|
||||
|
||||
1. Check that the extension is in `~/.local/share/zed/extensions/installed/storybook`
|
||||
2. Restart Zed
|
||||
3. Check the Zed log for errors (Zed > View > Toggle Terminal > "Extensions" tab)
|
||||
|
||||
### LSP not working
|
||||
|
||||
1. Verify `storybook-lsp` is in your PATH:
|
||||
```bash
|
||||
which storybook-lsp
|
||||
```
|
||||
2. Check Zed's LSP log for errors
|
||||
3. Ensure you have the latest version installed
|
||||
|
||||
### Syntax highlighting issues
|
||||
|
||||
1. Ensure the file has the `.sb` extension
|
||||
2. Try reloading the window (Cmd+Shift+P > "Reload Window")
|
||||
3. Check that the grammar is correctly installed
|
||||
|
||||
## Development
|
||||
|
||||
To modify or contribute to this extension:
|
||||
|
||||
1. Clone the repository
|
||||
2. Make your changes
|
||||
3. Test with `cargo build`
|
||||
4. Submit a pull request
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
54
zed-storybook/build-extension.sh
Executable file
54
zed-storybook/build-extension.sh
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🔨 Building Storybook LSP Extension..."
|
||||
|
||||
# Get the directory where this script lives
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
REPO_ROOT="$SCRIPT_DIR/.."
|
||||
|
||||
echo "📍 Working in: $SCRIPT_DIR"
|
||||
|
||||
# Build the LSP server
|
||||
echo ""
|
||||
echo "1️⃣ Building LSP server..."
|
||||
cd "$REPO_ROOT"
|
||||
cargo build --release --bin storybook-lsp
|
||||
|
||||
# Create bin directory in extension
|
||||
echo ""
|
||||
echo "2️⃣ Copying binary to extension..."
|
||||
mkdir -p "$SCRIPT_DIR/bin"
|
||||
|
||||
# Detect platform and copy the appropriate binary
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
cp "$REPO_ROOT/target/release/storybook-lsp" "$SCRIPT_DIR/bin/storybook-lsp"
|
||||
echo " ✓ Copied macOS binary"
|
||||
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
cp "$REPO_ROOT/target/release/storybook-lsp" "$SCRIPT_DIR/bin/storybook-lsp"
|
||||
echo " ✓ Copied Linux binary"
|
||||
elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
|
||||
cp "$REPO_ROOT/target/release/storybook-lsp.exe" "$SCRIPT_DIR/bin/storybook-lsp.exe"
|
||||
echo " ✓ Copied Windows binary"
|
||||
else
|
||||
echo " ⚠️ Unknown platform: $OSTYPE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make it executable
|
||||
chmod +x "$SCRIPT_DIR/bin/storybook-lsp"* 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "✅ Build complete!"
|
||||
echo ""
|
||||
echo "📦 Extension is ready at: $SCRIPT_DIR"
|
||||
echo "🚀 To install in Zed:"
|
||||
echo " 1. Open Zed"
|
||||
echo " 2. Run: zed: install dev extension"
|
||||
echo " 3. Select: $SCRIPT_DIR"
|
||||
echo ""
|
||||
echo "🧪 To test:"
|
||||
echo " 1. Open a .sb file in Zed"
|
||||
echo " 2. The LSP should activate automatically"
|
||||
echo " 3. Try hovering over symbols to see rich information!"
|
||||
echo ""
|
||||
16
zed-storybook/extension.toml
Normal file
16
zed-storybook/extension.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
id = "storybook"
|
||||
name = "Storybook"
|
||||
description = "Language support for Storybook narrative DSL"
|
||||
version = "0.2.0"
|
||||
schema_version = 1
|
||||
authors = ["Storybook Contributors"]
|
||||
repository = "https://github.com/r3t-studios/storybook"
|
||||
|
||||
[grammars.storybook]
|
||||
repository = "https://github.com/r3t-studios/storybook"
|
||||
rev = "mainline"
|
||||
path = "tree-sitter-storybook"
|
||||
|
||||
[language_servers.storybook-lsp]
|
||||
name = "Storybook LSP"
|
||||
languages = ["Storybook"]
|
||||
5
zed-storybook/languages/storybook/config.toml
Normal file
5
zed-storybook/languages/storybook/config.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
name = "Storybook"
|
||||
grammar = "storybook"
|
||||
path_suffixes = ["sb"]
|
||||
line_comments = ["// "]
|
||||
block_comment = ["/*", "*/"]
|
||||
171
zed-storybook/languages/storybook/highlights.scm
Normal file
171
zed-storybook/languages/storybook/highlights.scm
Normal file
@@ -0,0 +1,171 @@
|
||||
; Highlights query for Storybook DSL
|
||||
; Maps grammar nodes to standard highlight groups
|
||||
|
||||
; Comments
|
||||
(line_comment) @comment.line
|
||||
(block_comment) @comment.block
|
||||
|
||||
; Keywords - Declaration keywords
|
||||
[
|
||||
"character"
|
||||
"template"
|
||||
"life_arc"
|
||||
"schedule"
|
||||
"behavior"
|
||||
"institution"
|
||||
"relationship"
|
||||
"location"
|
||||
"species"
|
||||
"enum"
|
||||
"state"
|
||||
] @keyword.declaration
|
||||
|
||||
; Keywords - Control flow and modifiers
|
||||
[
|
||||
"and"
|
||||
"or"
|
||||
"not"
|
||||
"on"
|
||||
"enter"
|
||||
"strict"
|
||||
] @keyword.control
|
||||
|
||||
; Keywords - Import/module
|
||||
[
|
||||
"use"
|
||||
"include"
|
||||
"from"
|
||||
] @keyword.import
|
||||
|
||||
; Keywords - Special
|
||||
[
|
||||
"as"
|
||||
"self"
|
||||
"remove"
|
||||
"append"
|
||||
"is"
|
||||
] @keyword.special
|
||||
|
||||
; Boolean literals
|
||||
[
|
||||
"true"
|
||||
"false"
|
||||
] @constant.builtin.boolean
|
||||
|
||||
; Numbers
|
||||
(integer) @constant.numeric.integer
|
||||
(float) @constant.numeric.float
|
||||
(time) @constant.numeric.time
|
||||
(duration) @constant.numeric.duration
|
||||
|
||||
; Strings
|
||||
(string) @string
|
||||
|
||||
; Identifiers in different contexts
|
||||
(character name: (identifier) @type.character)
|
||||
(template name: (identifier) @type.template)
|
||||
(life_arc name: (identifier) @type.life_arc)
|
||||
(schedule name: (identifier) @type.schedule)
|
||||
(behavior name: (identifier) @type.behavior)
|
||||
(institution name: (identifier) @type.institution)
|
||||
(relationship name: (identifier) @type.relationship)
|
||||
(location name: (identifier) @type.location)
|
||||
(species name: (identifier) @type.species)
|
||||
(enum_declaration name: (identifier) @type.enum)
|
||||
(arc_state name: (identifier) @type.state)
|
||||
|
||||
; Field names
|
||||
(field name: (dotted_path) @property)
|
||||
|
||||
; Species reference
|
||||
(character species: (identifier) @type.builtin)
|
||||
|
||||
; Paths and identifiers
|
||||
(path) @namespace
|
||||
(identifier) @variable
|
||||
|
||||
; Prose blocks - tag and content
|
||||
(prose_block tag: (identifier) @tag)
|
||||
(prose_block marker: (prose_marker) @punctuation.delimiter)
|
||||
(prose_content) @markup.raw
|
||||
|
||||
; Operators
|
||||
[
|
||||
">"
|
||||
">="
|
||||
"<"
|
||||
"<="
|
||||
"->"
|
||||
"is"
|
||||
] @operator
|
||||
|
||||
; Punctuation
|
||||
[
|
||||
"{"
|
||||
"}"
|
||||
] @punctuation.bracket
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
] @punctuation.bracket
|
||||
|
||||
[
|
||||
"["
|
||||
"]"
|
||||
] @punctuation.bracket
|
||||
|
||||
[
|
||||
":"
|
||||
"::"
|
||||
";"
|
||||
","
|
||||
"."
|
||||
".."
|
||||
"@"
|
||||
] @punctuation.delimiter
|
||||
|
||||
; Behavior tree keywords
|
||||
[
|
||||
"choose"
|
||||
"then"
|
||||
"if"
|
||||
"when"
|
||||
] @keyword.control.behavior
|
||||
|
||||
; Decorator keywords
|
||||
[
|
||||
"repeat"
|
||||
"invert"
|
||||
"retry"
|
||||
"timeout"
|
||||
"cooldown"
|
||||
"succeed_always"
|
||||
"fail_always"
|
||||
] @keyword.decorator
|
||||
|
||||
; Behavior tree nodes
|
||||
(selector_node) @function.behavior.selector
|
||||
(sequence_node) @function.behavior.sequence
|
||||
(condition_node) @function.behavior.condition
|
||||
(if_decorator_node) @function.behavior.decorator
|
||||
(decorator_node) @function.behavior.decorator
|
||||
(action_node (identifier) @function.action)
|
||||
|
||||
; Transitions
|
||||
(transition "->" @operator.transition)
|
||||
(transition target: (identifier) @type.state)
|
||||
|
||||
; Schedule blocks
|
||||
(schedule_block activity: (identifier) @function.activity)
|
||||
|
||||
; Override operations
|
||||
(override "@" @keyword.override)
|
||||
(override_op "remove" @keyword.override)
|
||||
(override_op "append" @keyword.override)
|
||||
|
||||
; Template clause
|
||||
(template_clause "from" @keyword.import)
|
||||
|
||||
; Error handling
|
||||
(ERROR) @error
|
||||
89
zed-storybook/src/lib.rs
Normal file
89
zed-storybook/src/lib.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use zed_extension_api::{self as zed, Result};
|
||||
use std::{env, fs};
|
||||
|
||||
struct StorybookExtension {
|
||||
cached_binary_path: Option<String>,
|
||||
}
|
||||
|
||||
impl StorybookExtension {
|
||||
fn language_server_binary_path(
|
||||
&mut self,
|
||||
language_server_id: &zed::LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<String> {
|
||||
// Return cached path if we have it
|
||||
if let Some(path) = &self.cached_binary_path {
|
||||
if fs::metadata(path).is_ok() {
|
||||
return Ok(path.clone());
|
||||
}
|
||||
}
|
||||
|
||||
zed::set_language_server_installation_status(
|
||||
language_server_id,
|
||||
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
|
||||
);
|
||||
|
||||
// 1. Check system PATH (works for local dev when installed via cargo)
|
||||
if let Some(path) = worktree.which("storybook-lsp") {
|
||||
self.cached_binary_path = Some(path.clone());
|
||||
|
||||
zed::set_language_server_installation_status(
|
||||
language_server_id,
|
||||
&zed::LanguageServerInstallationStatus::None,
|
||||
);
|
||||
|
||||
return Ok(path);
|
||||
}
|
||||
|
||||
// 2. Check extension's bin directory (for bundled binaries)
|
||||
if let Ok(current_dir) = env::current_dir() {
|
||||
let bundled_binary = current_dir.join("bin/storybook-lsp");
|
||||
if bundled_binary.exists() {
|
||||
let path_str = bundled_binary.to_string_lossy().to_string();
|
||||
self.cached_binary_path = Some(path_str.clone());
|
||||
|
||||
zed::set_language_server_installation_status(
|
||||
language_server_id,
|
||||
&zed::LanguageServerInstallationStatus::None,
|
||||
);
|
||||
|
||||
return Ok(path_str);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. TODO: Download from GitHub releases
|
||||
|
||||
zed::set_language_server_installation_status(
|
||||
language_server_id,
|
||||
&zed::LanguageServerInstallationStatus::Failed(
|
||||
"storybook-lsp not found. Install with: cargo install --path storybook --bin storybook-lsp".to_string()
|
||||
),
|
||||
);
|
||||
|
||||
Err("storybook-lsp binary not found".into())
|
||||
}
|
||||
}
|
||||
|
||||
impl zed::Extension for StorybookExtension {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
cached_binary_path: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn language_server_command(
|
||||
&mut self,
|
||||
language_server_id: &zed::LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<zed::Command> {
|
||||
let binary_path = self.language_server_binary_path(language_server_id, worktree)?;
|
||||
|
||||
Ok(zed::Command {
|
||||
command: binary_path,
|
||||
args: vec![],
|
||||
env: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
zed::register_extension!(StorybookExtension);
|
||||
Reference in New Issue
Block a user