diff --git a/README.md b/README.md index d5c3b99f4..ecd894c47 100644 --- a/README.md +++ b/README.md @@ -330,7 +330,7 @@ See the [docs](docs/Custom_Command_Keybindings.md) For when you really want to just get rid of anything that shows up when you run `git status` (and yes that includes dirty submodules) [kidpix style](https://www.youtube.com/watch?v=Ur7_A4JusMU) -![nuke_working_tree-compressed](https://github.com/jesseduffield/lazygit/assets/8456633/06facd9c-166c-4ff5-b011-12e584ff8163) +![Nuke working tree](../assets/demo/nuke_working_tree-compressed.gif) ### Amend old commit diff --git a/demo/record_demo.sh b/demo/record_demo.sh index 0ef379377..97d5c2f36 100755 --- a/demo/record_demo.sh +++ b/demo/record_demo.sh @@ -1,15 +1,44 @@ #!/bin/sh -TEST=$1 - set -e -if [ -z "$TEST" ] +TYPE=$1 +TEST=$2 + +usage() { + echo "Usage: $0 [gif|mp4] " + echo "e.g. using full path: $0 gif pkg/integration/tests/demo/nuke_working_tree.go" + exit 1 +} + +if [ "$#" -ne 2 ] then - echo "Usage: $0 " + usage +fi + +if [ "$TYPE" != "gif" ] && [ "$TYPE" != "mp4" ] +then + usage exit 1 fi +if [ -z "$TEST" ] +then + usage +fi + +WORKTREE_PATH=$(git worktree list | grep assets | awk '{print $1}') + +if [ -z "$WORKTREE_PATH" ] +then + echo "Could not find assets worktree. You'll need to create a worktree for the assets branch using the following command:" + echo "git worktree add .worktrees/assets assets" + echo "The assets branch has no shared history with the main branch: it exists to store assets which are too large to store in the main branch." + exit 1 +fi + +OUTPUT_DIR="$WORKTREE_PATH/demo" + if ! command -v terminalizer &> /dev/null then echo "terminalizer could not be found" @@ -24,18 +53,29 @@ then exit 1 fi -# get last part of the test path and set that as the output name +# Get last part of the test path and set that as the output name # example test path: pkg/integration/tests/01_basic_test.go # For that we want: NAME=01_basic_test NAME=$(echo "$TEST" | sed -e 's/.*\///' | sed -e 's/\..*//') +# Add the demo to the tests list (if missing) so that it can be run go generate pkg/integration/tests/tests.go -mkdir -p demo/output +mkdir -p "$OUTPUT_DIR" -terminalizer -c demo/config.yml record --skip-sharing -d "go run cmd/integration_test/main.go cli --slow $TEST" "demo/output/$NAME" -terminalizer render "demo/output/$NAME" -o "demo/output/$NAME.gif" -COMPRESSED_PATH="demo/output/$NAME-compressed.gif" -gifsicle --colors 256 --use-col=web -O3 < "demo/output/$NAME.gif" > "$COMPRESSED_PATH" +# First we record the demo into a yaml representation +terminalizer -c demo/config.yml record --skip-sharing -d "go run cmd/integration_test/main.go cli --slow $TEST" "$OUTPUT_DIR/$NAME" +# Then we render it into a gif +terminalizer render "$OUTPUT_DIR/$NAME" -o "$OUTPUT_DIR/$NAME.gif" + +# Then we convert it to either an mp4 or gif based on the command line argument +if [ "$TYPE" = "mp4" ] +then + COMPRESSED_PATH="$OUTPUT_DIR/$NAME.mp4" + ffmpeg -y -i "$OUTPUT_DIR/$NAME.gif" -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" "$COMPRESSED_PATH" +else + COMPRESSED_PATH="$OUTPUT_DIR/$NAME-compressed.gif" + gifsicle --colors 256 --use-col=web -O3 < "$OUTPUT_DIR/$NAME.gif" > "$COMPRESSED_PATH" +fi echo "Demo recorded to $COMPRESSED_PATH" diff --git a/docs/dev/Demo_Recordings.md b/docs/dev/Demo_Recordings.md index 11924c199..1068e688f 100644 --- a/docs/dev/Demo_Recordings.md +++ b/docs/dev/Demo_Recordings.md @@ -12,6 +12,8 @@ Ideally we'd run this whole thing through docker but we haven't got that working npm i -g terminalizer # for gif compression npm i -g gifsicle +# for mp4 conversion +brew install ffmpeg # font with icons wget https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/DejaVuSansMono.tar.xz && \ @@ -37,16 +39,44 @@ You can use the same flow as we use with integration tests when you're writing a It's good to add captions explaining what task if being performed. Use the existing demos as a guide. +### Setting up the assets worktree + +We store assets (which includes demo recordings) in the `assets` branch, which is a branch that shares no history with the main branch and exists purely for storing assets. Storing them separately means we don't clog up the code branches with large binaries. + +The scripts and demo definitions live in the code branches but the output lives in the assets branch so to be able to create a video from a demo you'll need to create a linked worktree for the assets branch which you can do with: + +```sh +git worktree add .worktrees/assets assets +``` + +Outputs will be stored in `.worktrees/assets/demos/`. We'll store three separate things: +* the yaml of the recording +* the original gif +* either the compressed gif or the mp4 depending on the output you chose (see below) + ### Recording the demo Once you're happy with your demo you can record it using: ```sh -scripts/record_demo.sh +scripts/record_demo.sh [gif|mp4] # e.g. -scripts/record_demo.sh pkg/integration/tests/demo/interactive_rebase.go +scripts/record_demo.sh gif pkg/integration/tests/demo/interactive_rebase.go ``` -### Storing demos +~~The gif format is for use in the first video of the readme (it has a larger size but has auto-play and looping)~~ +~~The mp4 format is for everything else (no looping, requires clicking, but smaller size).~~ -This part is subject to change. I'm thinking of storing all gifs in the `assets` branch. But yet to finalize on that. -For now, feel free to upload `demo/demo-compressed.gif` to GitHub by dragging and dropping it in a file in the browser (e.g. the README). +Turns out that you can't store mp4s in a repo and link them from a README so we're gonna just use gifs across the board for now. + +### Including demos in README/docs + +If you've followed the above steps you'll end up with your output in your assets worktree. + +Within that worktree, stage all three output files and raise a PR against the assets branch. + +Then back in the code branch, in the doc, you can embed the recording like so: +```md +![Nuke working tree](../assets/demo/interactive_rebase-compressed.gif) +``` + +This means we can update assets without needing to update the docs that embed them.