summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-08-03 17:02:40 +1000
committerGitHub <noreply@github.com>2023-08-03 17:02:40 +1000
commit39d24fdeb7386a4555491349cca06ec6b7788552 (patch)
tree3e0d618159d136714f79312a5db9ada7be5a3f6f
parentde28391052c4bd6a3832072112d9d47c81a607d8 (diff)
parentbbb2b32816302e7693e3410fa18cb7180e706326 (diff)
Add more demos to the README (#2866)
-rw-r--r--README.md18
-rwxr-xr-xdemo/record_demo.sh58
-rw-r--r--docs/dev/Demo_Recordings.md40
-rw-r--r--pkg/integration/components/confirmation_driver.go6
-rw-r--r--pkg/integration/tests/demo/amend_old_commit.go62
-rw-r--r--pkg/integration/tests/demo/filter.go93
-rw-r--r--pkg/integration/tests/demo/stage_lines.go85
-rw-r--r--pkg/integration/tests/test_list.go3
8 files changed, 344 insertions, 21 deletions
diff --git a/README.md b/README.md
index d5c3b99f4..af6e15f1c 100644
--- a/README.md
+++ b/README.md
@@ -7,9 +7,9 @@
A simple terminal UI for git commands
<br/>
-[![GitHub Releases](https://img.shields.io/github/downloads/jesseduffield/lazygit/total)](https://github.com/jesseduffield/lazygit/releases) [![Go Report Card](https://goreportcard.com/badge/github.com/jesseduffield/lazygit)](https://goreportcard.com/report/github.com/jesseduffield/lazygit) [![GolangCI](https://golangci.com/badges/github.com/jesseduffield/lazygit.svg)](https://golangci.com) [![GitHub tag](https://img.shields.io/github/tag/jesseduffield/lazygit.svg)](https://github.com/jesseduffield/lazygit/releases/latest) [![homebrew](https://img.shields.io/homebrew/v/lazygit)](https://github.com/Homebrew/homebrew-core/blob/master/Formula/lazygit.rb)
+[![GitHub Releases](https://img.shields.io/github/downloads/jesseduffield/lazygit/total)](https://github.com/jesseduffield/lazygit/releases) [![Go Report Card](https://goreportcard.com/badge/github.com/jesseduffield/lazygit)](https://goreportcard.com/report/github.com/jesseduffield/lazygit) [![GolangCI](https://golangci.com/badges/github.com/jesseduffield/lazygit.svg)](https://golangci.com) [![GitHub tag](https://img.shields.io/github/tag/jesseduffield/lazygit.svg)](https://github.com/jesseduffield/lazygit/releases/latest) [![homebrew](https://img.shields.io/homebrew/v/lazygit)](https://github.com/Homebrew/homebrew-core/blob/master/Formula/lazygit.rb)
-![demo-compressed](https://github.com/jesseduffield/lazygit/assets/8456633/7e77d895-05a9-4571-a55b-240ac80f75eb)
+![commit_and_push](../assets/demo/commit_and_push-compressed.gif)
</div>
@@ -316,25 +316,29 @@ See the [docs](docs/Custom_Command_Keybindings.md)
### Git Bisect
-![demo-compressed](https://github.com/jesseduffield/lazygit/assets/8456633/b2752a77-3bd0-4b65-8e36-e643ae70c396)
+![bisect](../assets/demo/bisect-compressed.gif)
### Cherry-pick
-![cherry_pick-compressed](https://github.com/jesseduffield/lazygit/assets/8456633/2d1205c8-9980-40b0-8b6a-221497099715)
+![cherry_pick](../assets/demo/cherry_pick-compressed.gif)
### Interactive Rebase
-![demo-compressed](https://github.com/jesseduffield/lazygit/assets/8456633/04d6dbe4-845a-41de-8072-0e475765ec63)
+![interactive_rebase](../assets/demo/interactive_rebase-compressed.gif)
### Nuking the working tree
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
-![amend_old_commit-compressed](https://github.com/jesseduffield/lazygit/assets/8456633/de7010c0-6902-4fad-8fe5-7197956ca40d)
+![amend_old_commit](../assets/demo/amend_old_commit-compressed.gif)
+
+### Stage individual lines
+
+![stage_lines](../assets/demo/stage_lines-compressed.gif)
## Contributing
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
+TYPE=$1
+TEST=$2
+
+usage() {
+ echo "Usage: $0 [gif|mp4] <test path>"
+ echo "e.g. using full path: $0 gif pkg/integration/tests/demo/nuke_working_tree.go"
+ exit 1
+}
+
+if [ "$#" -ne 2 ]
+then
+ usage
+fi
+
+if [ "$TYPE" != "gif" ] && [ "$TYPE" != "mp4" ]
+then
+ usage
+ exit 1
+fi
+
if [ -z "$TEST" ]
then
- echo "Usage: $0 <test>"
+ 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"
+
+# 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"
-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"
+# 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 <path>
+scripts/record_demo.sh [gif|mp4] <path>
# 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).~~
+
+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 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).
+This means we can update assets without needing to update the docs that embed them.
diff --git a/pkg/integration/components/confirmation_driver.go b/pkg/integration/components/confirmation_driver.go
index aad5cc248..7934b351c 100644
--- a/pkg/integration/components/confirmation_driver.go
+++ b/pkg/integration/components/confirmation_driver.go
@@ -40,6 +40,12 @@ func (self *ConfirmationDriver) Cancel() {
self.getViewDriver().PressEscape()
}
+func (self *ConfirmationDriver) Wait(milliseconds int) *ConfirmationDriver {
+ self.getViewDriver().Wait(milliseconds)
+
+ return self
+}
+
func (self *ConfirmationDriver) checkNecessaryChecksCompleted() {
if !self.hasCheckedContent || !self.hasCheckedTitle {
self.t.Fail("You must both check the content and title of a confirmation popup by calling Title()/Content() before calling Confirm()/Cancel().")
diff --git a/pkg/integration/tests/demo/amend_old_commit.go b/pkg/integration/tests/demo/amend_old_commit.go
new file mode 100644
index 000000000..b77a62bd1
--- /dev/null
+++ b/pkg/integration/tests/demo/amend_old_commit.go
@@ -0,0 +1,62 @@
+package demo
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var AmendOldCommit = NewIntegrationTest(NewIntegrationTestArgs{
+ Description: "Amend old commit",
+ ExtraCmdArgs: []string{},
+ Skip: false,
+ IsDemo: true,
+ SetupConfig: func(config *config.AppConfig) {
+ // No idea why I had to use version 2: it should be using my own computer's
+ // font and the one iterm uses is version 3.
+ config.UserConfig.Gui.NerdFontsVersion = "2"
+ config.UserConfig.Gui.ShowFileTree = false
+ },
+ SetupRepo: func(shell *Shell) {
+ shell.CreateNCommitsWithRandomMessages(60)
+ shell.NewBranch("feature/demo")
+
+ shell.CloneIntoRemote("origin")
+
+ shell.SetBranchUpstream("feature/demo", "origin/feature/demo")
+
+ shell.UpdateFile("navigation/site_navigation.go", "package navigation\n\nfunc Navigate() {\n\tpanic(\"unimplemented\")\n}")
+ shell.CreateFile("docs/README.md", "my readme content")
+ },
+ Run: func(t *TestDriver, keys config.KeybindingConfig) {
+ t.SetCaptionPrefix("Amend an old commit")
+ t.Wait(1000)
+
+ t.Views().Files().
+ IsFocused().
+ SelectedLine(Contains("site_navigation.go")).
+ PressPrimaryAction()
+
+ t.Views().Commits().
+ Focus().
+ NavigateToLine(Contains("Improve accessibility of site navigation")).
+ Wait(500).
+ Press(keys.Commits.AmendToCommit).
+ Tap(func() {
+ t.ExpectPopup().Confirmation().
+ Title(Equals("Amend commit")).
+ Wait(1000).
+ Content(AnyString()).
+ Confirm()
+
+ t.Wait(1000)
+ }).
+ Press(keys.Universal.Push).
+ Tap(func() {
+ t.ExpectPopup().Confirmation().
+ Title(Equals("Force push")).
+ Content(AnyString()).
+ Wait(1000).
+ Confirm()
+ })
+ },
+})
diff --git a/pkg/integration/tests/demo/filter.go b/pkg/integration/tests/demo/filter.go
new file mode 100644
index 000000000..2e62ba444
--- /dev/null
+++ b/pkg/integration/tests/demo/filter.go
@@ -0,0 +1,93 @@
+package demo
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var Filter = NewIntegrationTest(NewIntegrationTestArgs{
+ Description: "Filter branches",
+ ExtraCmdArgs: []string{},
+ Skip: false,
+ IsDemo: true,
+ SetupConfig: func(config *config.AppConfig) {
+ // No idea why I had to use version 2: it should be using my own computer's
+ // font and the one iterm uses is version 3.
+ config.UserConfig.Gui.NerdFontsVersion = "2"
+ },
+ SetupRepo: func(shell *Shell) {
+ shell.CreateNCommitsWithRandomMessages(30)
+ shell.NewBranch("feature/user-authentication")
+ shell.NewBranch("feature/payment-processing")
+ shell.NewBranch("feature/search-functionality")
+ shell.NewBranch("feature/mobile-responsive")
+ shell.NewBranch("bugfix/fix-login-issue")
+ shell.NewBranch("bugfix/fix-crash-bug")
+ shell.NewBranch("bugfix/fix-validation-error")
+ shell.NewBranch("refactor/improve-performance")
+ shell.NewBranch("refactor/code-cleanup")
+ shell.NewBranch("refactor/extract-method")
+ shell.NewBranch("docs/update-readme")
+ shell.NewBranch("docs/add-user-guide")
+ shell.NewBranch("docs/api-documentation")
+ shell.NewBranch("experiment/new-feature-idea")
+ shell.NewBranch("experiment/try-new-library")
+ shell.NewBranch("chore/update-dependencies")
+ shell.NewBranch("chore/add-test-cases")
+ shell.NewBranch("chore/migrate-database")
+ shell.NewBranch("hotfix/critical-bug")
+ shell.NewBranch("hotfix/security-patch")
+ shell.NewBranch("feature/social-media-integration")
+ shell.NewBranch("feature/email-notifications")
+ shell.NewBranch("feature/admin-panel")
+ shell.NewBranch("feature/analytics-dashboard")
+ shell.NewBranch("bugfix/fix-registration-flow")
+ shell.NewBranch("bugfix/fix-payment-bug")
+ shell.NewBranch("refactor/improve-error-handling")
+ shell.NewBranch("refactor/optimize-database-queries")
+ shell.NewBranch("docs/improve-tutorials")
+ shell.NewBranch("docs/add-faq-section")
+ shell.NewBranch("experiment/try-alternative-algorithm")
+ shell.NewBranch("experiment/implement-design-concept")
+ shell.NewBranch("chore/update-documentation")
+ shell.NewBranch("chore/improve-test-coverage")
+ shell.NewBranch("chore/cleanup-codebase")
+ shell.NewBranch("hotfix/critical-security-vulnerability")
+ shell.NewBranch("hotfix/fix-production-issue")
+ shell.NewBranch("feature/integrate-third-party-api")
+ shell.NewBranch("feature/image-upload-functionality")
+ shell.NewBranch("feature/localization-support")
+ shell.NewBranch("feature/chat-feature")
+ shell.NewBranch("bugfix/fix-broken-link")
+ shell.NewBranch("bugfix/fix-css-styling")
+ shell.NewBranch("refactor/improve-logging")
+ shell.NewBranch("refactor/extract-reusable-component")
+ shell.NewBranch("docs/add-changelog")
+ shell.NewBranch("docs/update-api-reference")
+ shell.NewBranch("experiment/implement-new-design")
+ shell.NewBranch("experiment/try-different-architecture")
+ shell.NewBranch("chore/clean-up-git-history")
+ shell.NewBranch("chore/update-environment-configuration")
+ shell.CreateFileAndAdd("env_config.rb", "EnvConfig.call(false)\n")
+ shell.Commit("Update env config")
+ shell.CreateFileAndAdd("env_config.rb", "# Turns out we need to pass true for this to work\nEnvConfig.call(true)\n")
+ shell.Commit("Fix env config issue")
+ shell.Checkout("docs/add-faq-section")
+ },
+ Run: func(t *TestDriver, keys config.KeybindingConfig) {
+ t.SetCaptionPrefix("Fuzzy filter branches")
+ t.Wait(1000)
+
+ t.Views().Branches().
+ Focus().
+ Wait(500).
+ Press(keys.Universal.StartSearch).
+ Tap(func() {
+ t.Wait(500)
+
+ t.ExpectSearch().Type("environ").Confirm()
+ }).
+ Wait(500).
+ PressEnter()
+ },
+})
diff --git a/pkg/integration/tests/demo/stage_lines.go b/pkg/integration/tests/demo/stage_lines.go
new file mode 100644
index 000000000..6bfa21a98
--- /dev/null
+++ b/pkg/integration/tests/demo/stage_lines.go
@@ -0,0 +1,85 @@
+package demo
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var originalFile = `# Lazygit
+
+Simple terminal UI for git commands
+
+![demo](https://user-images.gh.com/demo.gif)
+
+## Installation
+
+### Homebrew
+
+`
+
+var updatedFile = `# Lazygit
+
+Simple terminal UI for git
+(Not too simple though)
+
+![demo](https://user-images.gh.com/demo.gif)
+
+## Installation
+
+### Homebrew
+
+Just do brew install lazygit and bada bing bada
+boom you have begun on the path of laziness.
+
+`
+
+var StageLines = NewIntegrationTest(NewIntegrationTestArgs{
+ Description: "Stage individual lines",
+ ExtraCmdArgs: []string{},
+ Skip: false,
+ IsDemo: true,
+ SetupConfig: func(config *config.AppConfig) {
+ // No idea why I had to use version 2: it should be using my own computer's
+ // font and the one iterm uses is version 3.
+ config.UserConfig.Gui.NerdFontsVersion = "2"
+ config.UserConfig.Gui.ShowFileTree = false
+ config.UserConfig.Gui.ShowCommandLog = false
+ },
+ SetupRepo: func(shell *Shell) {
+ shell.NewBranch("docs-fix")
+ shell.CreateNCommitsWithRandomMessages(30)
+ shell.CreateFileAndAdd("docs/README.md", originalFile)
+ shell.Commit("Update docs/README")
+ shell.UpdateFile("docs/README.md", updatedFile)
+ },
+ Run: func(t *TestDriver, keys config.KeybindingConfig) {
+ t.SetCaptionPrefix("Stage individual lines")
+ t.Wait(1000)
+
+ t.Views().Files().
+ IsFocused().
+ PressEnter()
+
+ t.Views().Staging().
+ IsFocused().
+ Press(keys.Main.ToggleDragSelect).
+ PressFast(keys.Universal.NextItem).
+ PressFast(keys.Universal.NextItem).
+ Wait(500).
+ PressPrimaryAction().
+ Wait(500).
+ PressEscape()
+
+ t.Views().Files().
+ IsFocused().
+ Press(keys.Files.CommitChanges).
+ Tap(func() {
+ t.ExpectPopup().CommitMessagePanel().
+ Type("Update tagline").
+ Confirm()
+ })
+
+ t.Views().Commits().
+ Focus()
+ },
+})
diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go
index 27cb3513e..75508784e 100644
--- a/pkg/integration/tests/test_list.go
+++ b/pkg/integration/tests/test_list.go
@@ -89,11 +89,14 @@ var tests = []*components.IntegrationTest{
custom_commands.OmitFromHistory,
custom_commands.SuggestionsCommand,
custom_commands.SuggestionsPreset,
+ demo.AmendOldCommit,
demo.Bisect,
demo.CherryPick,
demo.CommitAndPush,
+ demo.Filter,
demo.InteractiveRebase,
demo.NukeWorkingTree,
+ demo.StageLines,
diff.Diff,
diff.DiffAndApplyPatch,
diff.DiffCommits,