Improve storybook story selection (#3653)

This PR builds on top of #3652 by adding a selection prompt to the
storybook to allow you to choose from the available list of stories if
you don't provide one explicitly:

<img width="1387" alt="Screenshot 2023-12-14 at 12 00 26 PM"
src="https://github.com/zed-industries/zed/assets/1486634/640d62a3-1340-45f1-9746-69b513faff62">

This way we don't have to keep generating the `script/storybook` script
whenever stories are added/removed.

#### Usage (through `cargo`):

```sh
# Select from the available stories
cargo run -p storybook2

# Run a specific story
cargo run -p storybook2 -- components/list_item
```

#### Usage (through `script/storybook`):

```sh
# Select from the available stories
./script/storybook

# Run a specific story
./script/storybook list_item
```

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2023-12-14 12:13:02 -05:00 committed by GitHub
parent 08418618ab
commit fd133df896
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 169 deletions

View file

@ -3,23 +3,19 @@ name = "storybook2"
version = "0.1.0"
edition = "2021"
publish = false
default-run = "storybook"
[[bin]]
name = "storybook"
path = "src/bin/storybook2.rs"
[[bin]]
name = "print_storybook_script"
path = "src/bin/print_storybook_script.rs"
path = "src/storybook2.rs"
[dependencies]
anyhow.workspace = true
# TODO: Remove after diagnosing stack overflow.
backtrace-on-stack-overflow = "0.3.0"
clap = { version = "4.4", features = ["derive", "string"] }
editor = { package = "editor2", path = "../editor2" }
chrono = "0.4"
clap = { version = "4.4", features = ["derive", "string"] }
dialoguer = { version = "0.11.0", features = ["fuzzy-select"] }
editor = { package = "editor2", path = "../editor2" }
fuzzy = { package = "fuzzy2", path = "../fuzzy2" }
gpui = { package = "gpui2", path = "../gpui2" }
itertools = "0.11.0"

View file

@ -1,74 +0,0 @@
use std::fs::File;
use std::io::Write;
use strum::IntoEnumIterator;
use storybook2::story_selector::ComponentStory;
// TOOD: Ideally we actually create a more full featured CLI,
// but for the moment I just wanted a easier way to run the stories
fn main() -> std::io::Result<()> {
let path = std::env::current_dir()?;
let out_file = path.join("script").join("storybook");
// the script output file
let mut file = File::create(out_file)?;
// generate the list of components, in `snake_case`
let components = ComponentStory::iter()
.map(|c| c.to_string()) // Converts enum to string in `snake_case`
.collect::<Vec<_>>();
// write the bash script
writeln!(file, "#!/bin/bash")?;
writeln!(file, "")?;
writeln!(file, "options=(")?;
for component in &components {
writeln!(file, " \"{}\"", component)?;
}
writeln!(file, ")")?;
writeln!(file, "")?;
// Check if an argument is provided and if it matches a valid option
writeln!(file, "run_story() {{")?;
writeln!(file, " echo \"Running story: $1\"")?;
writeln!(file, " cargo run -p storybook2 -- \"$1\"")?;
writeln!(file, "}}")?;
writeln!(file, "")?;
writeln!(file, "if [ \"$#\" -gt 0 ]; then")?;
writeln!(file, " story_arg=\"$1\"")?;
writeln!(file, " # Add prefix 'components/' if not present")?;
writeln!(file, " if [[ $story_arg != components/* ]]; then")?;
writeln!(file, " story_arg=\"components/$story_arg\"")?;
writeln!(file, " fi")?;
writeln!(file, " # Check if the provided story is a valid option")?;
writeln!(file, " for opt in \"${{options[@]}}\"; do")?;
writeln!(
file,
" if [[ \"components/$opt\" == \"$story_arg\" ]]; then"
)?;
writeln!(file, " run_story \"$story_arg\"")?;
writeln!(file, " exit")?;
writeln!(file, " fi")?;
writeln!(file, " done")?;
writeln!(file, " echo \"Invalid story name: $1\"")?;
writeln!(file, " exit 1")?;
writeln!(file, "fi")?;
writeln!(file, "")?;
// Existing selection prompt
writeln!(file, "prompt=\"Please select a story:\"")?;
writeln!(file, "PS3=\"$prompt \"")?;
writeln!(file, "select story in \"${{options[@]}}\"; do")?;
writeln!(file, " if [[ -n $story ]]; then")?;
writeln!(file, " run_story \"components/$story\"")?;
writeln!(file, " break")?;
writeln!(file, " else")?;
writeln!(file, " echo \"Invalid option\"")?;
writeln!(file, " fi")?;
writeln!(file, "done")?;
Ok(())
}

View file

@ -1,4 +0,0 @@
pub mod assets;
pub mod stories;
pub mod story_selector;

View file

@ -1,6 +1,11 @@
mod assets;
mod stories;
mod story_selector;
use std::sync::Arc;
use clap::Parser;
use dialoguer::FuzzySelect;
use gpui::{
div, px, size, AnyView, AppContext, Bounds, Div, Render, ViewContext, VisualContext,
WindowBounds, WindowOptions,
@ -8,12 +13,12 @@ use gpui::{
use log::LevelFilter;
use settings2::{default_settings, Settings, SettingsStore};
use simplelog::SimpleLogger;
use strum::IntoEnumIterator;
use theme2::{ThemeRegistry, ThemeSettings};
use ui::prelude::*;
use storybook2::assets::Assets;
pub use storybook2::story_selector::*;
// pub use crate::story_selector::{ComponentStory, StorySelector};
use crate::assets::Assets;
use crate::story_selector::{ComponentStory, StorySelector};
// gpui::actions! {
// storybook,
@ -40,7 +45,17 @@ fn main() {
let args = Args::parse();
let story_selector = args.story.clone();
let story_selector = args.story.clone().unwrap_or_else(|| {
let stories = ComponentStory::iter().collect::<Vec<_>>();
let selection = FuzzySelect::new()
.with_prompt("Choose a story to run:")
.items(&stories)
.interact()
.unwrap();
StorySelector::Component(stories[selection])
});
let theme_name = args.theme.unwrap_or("One Dark".to_string());
let asset_source = Arc::new(Assets);
@ -55,7 +70,7 @@ fn main() {
theme2::init(theme2::LoadThemes::All, cx);
let selector = story_selector.unwrap_or(StorySelector::KitchenSink);
let selector = story_selector;
let theme_registry = cx.global::<ThemeRegistry>();
let mut theme_settings = ThemeSettings::get_global(cx).clone();