diff --git a/README.md b/README.md index 2484aad..21d35bc 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ repository below the directories you give it, at any depth. ## Demo - + ![cdd demo](demo/demo.gif) ## Install diff --git a/demo/demo.gif b/demo/demo.gif index db6f8e1..b25fab1 100644 Binary files a/demo/demo.gif and b/demo/demo.gif differ diff --git a/demo/demo.tape b/demo/demo.tape index 4822cc8..f8f0e35 100644 --- a/demo/demo.tape +++ b/demo/demo.tape @@ -1,7 +1,8 @@ # Records demo/demo.gif against the environment built by demo/setup.sh. -# Run `demo/setup.sh` first; it never touches your real home or History. +# setup.sh puts stand-in projects in ~/Code and ~/Work and cdd's own state +# in ~/.cache/cdd-demo, so it never touches your real config or History. # -# demo/setup.sh && vhs demo/demo.tape +# demo/setup.sh && vhs demo/demo.tape; demo/teardown.sh # # Use VHS v0.11.0 (go install github.com/charmbracelet/vhs@v0.11.0). # v0.12.0 cancels its own context before rendering and silently writes @@ -15,26 +16,102 @@ Set Width 1200 Set Height 640 Set Padding 20 Set Theme "Catppuccin Mocha" -Set TypingSpeed 60ms - -Env XDG_CONFIG_HOME "/tmp/cdd-demo/xdg/config" -Env XDG_DATA_HOME "/tmp/cdd-demo/xdg/data" -Env HOME "/tmp/cdd-demo/home" +Set TypingSpeed 90ms +# Hidden setup. cdd's state points at the demo +# directory (Env values are literal, so the shell does it), the demo bin +# comes first on PATH so cdd is the one built from this checkout and nothing +# opens for real, and the prompt is neutral: no username or hostname. Hide -Type "set -gx PATH /tmp/cdd-demo/bin $PATH" Enter +Set TypingSpeed 5ms +Type "set -gx XDG_CONFIG_HOME $HOME/.cache/cdd-demo/config" Enter +Type "set -gx XDG_DATA_HOME $HOME/.cache/cdd-demo/data" Enter +Type "set -gx XDG_STATE_HOME $HOME/.cache/cdd-demo/state" Enter +Type "set -gx PATH $HOME/.cache/cdd-demo/bin $PATH" Enter +Type "set -g fish_greeting" Enter Type "set -g fish_autosuggestion_enabled 0" Enter +Type "set -g fish_prompt_pwd_dir_length 0" Enter +Type "function fish_prompt; echo -n (prompt_pwd)' ❯ '; end" Enter +Type "function pwd; builtin pwd | string replace -- $HOME '~'; end" Enter Type "cdd init fish | source" Enter -Type "cd ~/notes" Enter +Type "cd ~/Code/go" Enter Type "clear" Enter +Set TypingSpeed 90ms Show -Type "cdd" Sleep 800ms Enter -Sleep 2.5s -Down Sleep 600ms -Down Sleep 600ms -Type "grg" Sleep 1.5s +Sleep 1s +Type "# find every git repo under these dirs" Enter +Sleep 1s +Type "cdd scan ~/Code ~/Work" Sleep 500ms Enter +Sleep 2s + +Type "# open the Picker: note the key hints" Enter +Sleep 1s +Type "cdd" Sleep 500ms Enter +Sleep 3.5s +Type "oss kube" +Sleep 3s Enter -Sleep 800ms -Type "pwd" Enter +Sleep 500ms +Type "# Enter jumped: where am I?" Enter +Sleep 500ms +Type "pwd" Sleep 500ms Enter +Sleep 2s + +Type "# my own Action: ctrl+l runs lazygit" Enter +Sleep 1s +Type "cdd" Sleep 500ms Enter +Sleep 1.5s +Ctrl+l +Sleep 3.5s + +Type "# ctrl+y copies the path, ctrl+g opens the remote" Enter +Sleep 1s +Type "cdd" Sleep 500ms Enter +Sleep 1.5s +Ctrl+y +Sleep 2.5s +Ctrl+g +Sleep 1.5s +Escape +Sleep 500ms +Type "# (the opener is a stub: nothing really opened)" Enter +Sleep 500ms +Type "cat ~/.cache/cdd-demo/opened.log" Sleep 500ms Enter +Sleep 2.5s + +Type "# add a directory that is not a git repo" Enter +Sleep 1s +Type "cdd add ~/Work/notes" Sleep 500ms Enter +Sleep 1.5s +Type "cdd" Sleep 500ms Enter +Sleep 1.5s +Type "notes" Sleep 2.5s +Escape +Sleep 500ms + +Type "# ctrl+d forgets a Project after y/n" Enter +Sleep 1s +Type "cdd" Sleep 500ms Enter +Sleep 1.5s +Type "rust" +Sleep 1s +Ctrl+d +Sleep 2.5s +Type "y" +Sleep 2.5s +Escape +Sleep 500ms + +# Hidden: config init refuses to replace the config the demo used so far. +Hide +Type "rm $XDG_CONFIG_HOME/cdd/config.toml" Enter +Type "clear" Enter +Show +Type "# write a commented example config" Enter +Sleep 1s +Type "cdd config init" Sleep 500ms Enter +Sleep 1.5s +Type "head -20 ~/.cache/cdd-demo/config/cdd/config.toml" Sleep 500ms Enter +Sleep 5s diff --git a/demo/setup.sh b/demo/setup.sh index 3c8f2aa..85bb0b6 100755 --- a/demo/setup.sh +++ b/demo/setup.sh @@ -1,94 +1,113 @@ #!/usr/bin/env bash -# Builds a self-contained demo environment for recording cdd, so the -# recording never touches your real home, config, or History. +# Builds the demo environment that demo/demo.tape records against. # -# demo/setup.sh # builds /tmp/cdd-demo -# DEMO_DIR=~/x demo/setup.sh +# demo/setup.sh && vhs demo/demo.tape; demo/teardown.sh # -# Layout it creates: -# $DEMO_DIR/home a fake home with git repositories at several depths -# $DEMO_DIR/xdg/config XDG_CONFIG_HOME holding cdd/config.toml -# $DEMO_DIR/xdg/data XDG_DATA_HOME holding cdd/history -# $DEMO_DIR/bin/cdd the binary built from this checkout +# It creates, in your REAL home directory: +# ~/Code ~/Work stand-in projects: empty `git init` dirs with one +# dated commit and an origin remote, plus ~/Work/notes +# (not a repository, for `cdd add`) +# ~/.cache/cdd-demo cdd's config, History and projects file (XDG_*_HOME +# point here, so your real ones are never touched), and +# bin/ holding the cdd built from this checkout and +# stubs for xdg-open, open, lazygit and the clipboard +# +# It refuses to run if any of those three directories already exists, and +# demo/teardown.sh deletes exactly those three and nothing else. set -euo pipefail -DEMO_DIR="${DEMO_DIR:-/tmp/cdd-demo}" -ROOT="$DEMO_DIR/home" -CONFIG="$DEMO_DIR/xdg/config" -DATA="$DEMO_DIR/xdg/data" -BIN="$DEMO_DIR/bin" -REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)" +CODE="$HOME/Code" +WORK="$HOME/Work" +DEMO_DIR="$HOME/.cache/cdd-demo" +for d in "$CODE" "$WORK" "$DEMO_DIR"; do + if [ -e "$d" ] || [ -L "$d" ]; then + echo "setup.sh: $d already exists; refusing to run" >&2 + exit 1 + fi +done -rm -rf "$DEMO_DIR" -mkdir -p "$ROOT" "$CONFIG/cdd" "$DATA/cdd" "$BIN" +REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)" +CONFIG="$DEMO_DIR/config" +DATA="$DEMO_DIR/data" # created by cdd on first write +STATE="$DEMO_DIR/state" +BIN="$DEMO_DIR/bin" +mkdir -p "$DEMO_DIR" "$DATA" "$CODE" "$WORK" "$CONFIG/cdd" "$STATE" "$BIN" +touch "$DEMO_DIR/.created-by-setup" # teardown deletes nothing without it # --- Projects ----------------------------------------------------------- -# Each Project is a git repository unless noted. Commit dates are spread -# out so `cdd scan` seeds a varied History. git_demo() { git -c user.name=demo -c user.email=demo@example.com -c commit.gpgsign=false "$@"; } -repo() { # repo - local dir="$ROOT/$1"; mkdir -p "$dir" - git_demo -C "$dir" init -q -b main - echo "# ${1##*/}" > "$dir/$3" - local when; when="$(ago "$2")" - GIT_AUTHOR_DATE="$when" GIT_COMMITTER_DATE="$when" git_demo -C "$dir" -c init.defaultBranch=main add -A - GIT_AUTHOR_DATE="$when" GIT_COMMITTER_DATE="$when" git_demo -C "$dir" commit -q -m "initial commit" -} - ago() { # ago -> ISO timestamp, GNU or BSD date date -u -d "$1 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \ || date -u -v-"$1"d +%Y-%m-%dT%H:%M:%SZ } -repo Developer/domain/kryft.dev 1 README.md -repo Developer/domain/wowaitech.com 3 README.md -repo Developer/tools/cdd 0 main.go -repo Developer/tools/grg 6 main.go -repo Developer/tools/lab/bubbletea-play 5 main.go -repo work/internal 2 README.md -repo work/clients/acme/api 9 README.md -repo dotfiles 40 README.md -repo uni/2025/compilers 20 notes.md - -# clean vs. dirty vs. untracked vs. ahead -echo "wip" >> "$ROOT/Developer/domain/wowaitech.com/README.md" # modified -touch "$ROOT/Developer/tools/grg/scratch.go" # untracked -echo "wip" >> "$ROOT/work/internal/README.md"; touch "$ROOT/work/internal/new.txt" # both - -upstream="$DEMO_DIR/upstream.git" -git_demo init -q --bare "$upstream" -git_demo -C "$ROOT/Developer/domain/kryft.dev" remote add origin "$upstream" -git_demo -C "$ROOT/Developer/domain/kryft.dev" push -q -u origin main -echo "more" >> "$ROOT/Developer/domain/kryft.dev/README.md" -git_demo -C "$ROOT/Developer/domain/kryft.dev" commit -q -am "second commit" # ahead by 1 - -mkdir -p "$ROOT/notes/2026" # not a repository, never listed -repo Developer/tools/cdd/vendor/inner 1 README.md # inside a repository, never listed -repo .cache/some-tool 1 README.md # hidden, never listed - -# --- Config and History --------------------------------------------------- -# No config.toml: cdd needs none. - -# --- Binary and seeded History -------------------------------------------- -( cd "$REPO_DIR" && go build -o "$BIN/cdd" ./cmd/cdd ) -HOME="$ROOT" XDG_CONFIG_HOME="$CONFIG" XDG_DATA_HOME="$DATA" "$BIN/cdd" scan +repo() { # repo + local dir="$1" when; when="$(ago "$2")" + mkdir -p "$dir" + git_demo -C "$dir" init -q -b main + echo "# ${dir##*/}" > "$dir/README.md" + git_demo -C "$dir" add -A + GIT_AUTHOR_DATE="$when" GIT_COMMITTER_DATE="$when" git_demo -C "$dir" commit -q -m "initial commit" + git_demo -C "$dir" remote add origin "$3" +} -# A few real Jumps on top of the Scan so the ordering shows both sources. -hist="$DATA/cdd/history" -printf '%s\tjump\t%s\n' "$(ago 0)" "$ROOT/Developer/tools/cdd" >> "$hist" -printf '%s\tjump\t%s\n' "$(ago 1)" "$ROOT/Developer/domain/kryft.dev" >> "$hist" -printf '%s\tjump\t%s\n' "$(ago 2)" "$ROOT/work/internal" >> "$hist" +repo "$CODE/next.js" 1 git@github.com:vercel/next.js.git +repo "$CODE/go" 2 git@github.com:golang/go.git +repo "$CODE/react" 4 git@github.com:facebook/react.git +repo "$CODE/rust" 7 git@github.com:rust-lang/rust.git +repo "$CODE/oss/kubernetes" 3 git@github.com:kubernetes/kubernetes.git +repo "$CODE/oss/deno" 9 git@github.com:denoland/deno.git +repo "$WORK/acme/api" 0 git@github.com:acme/api.git +repo "$WORK/acme/web" 5 git@github.com:acme/web.git +repo "$WORK/globex/billing" 6 git@github.com:globex/billing.git +mkdir -p "$WORK/notes" # not a repository: shown by `cdd add` + +# --- Binary and stubs ---------------------------------------------------- +# Nothing in the demo opens a browser, a file manager or a real lazygit. +( cd "$REPO_DIR" && go build -o "$BIN/cdd.real" ./cmd/cdd ) + +# cdd, with $HOME shown as ~ in what it prints, so the recording does not +# show the username. The Picker (`cdd pick`) is passed straight through. +cat > "$BIN/cdd" <&1 | sed "s|$HOME|~|g" ;; + *) exec "$BIN/cdd.real" "\$@" ;; +esac +SH + +for opener in xdg-open open; do + cat > "$BIN/$opener" <> "$DEMO_DIR/opened.log" +SH +done +for clip in wl-copy xclip xsel pbcopy; do + printf '#!/bin/sh\ncat > /dev/null\n' > "$BIN/$clip" +done +cat > "$BIN/lazygit" <<'SH' +#!/bin/sh +printf '\n lazygit (demo stand-in)\n\n' +printf ' Status main, up to date with origin/main\n' +printf ' Files nothing to commit, working tree clean\n' +printf ' Branches * main\n' +printf ' Commits initial commit\n\n' +sleep 1.5 +SH +chmod +x "$BIN"/* + +# --- Config, History and the demo's own Action ----------------------------- +cat > "$CONFIG/cdd/config.toml" <<'TOML' +[actions.lazygit] +key = "ctrl+l" +run = "lazygit" +TOML cat <&2 + exit 1 +fi +rm -rf -- "$HOME/Code" "$HOME/Work" "$DEMO_DIR" +echo "Removed ~/Code, ~/Work and ~/.cache/cdd-demo"