1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-01-20 05:19:24 +02:00

refactor cheatsheet generator

This commit is contained in:
Jesse Duffield 2022-03-20 13:59:33 +11:00
parent cb26c7a1f2
commit 340a145bc8
7 changed files with 640 additions and 400 deletions

View File

@ -269,7 +269,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd></kbd>: select next hunk
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>e</kbd>: edit file
<kbd>o</kbd>: open file
<kbd>v</kbd>: toggle drag select
<kbd>V</kbd>: toggle drag select
<kbd>a</kbd>: toggle select hunk

View File

@ -41,6 +41,46 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>[</kbd>: vorige tabblad
</pre>
## Bestanden Paneel (Bestanden)
<pre>
<kbd>ctrl+o</kbd>: kopieer de bestandsnaam naar het klembord
<kbd>ctrl+w</kbd>: Toggle whether or not whitespace changes are shown in the diff view
<kbd>d</kbd>: bekijk 'veranderingen ongedaan maken' opties
<kbd>space</kbd>: toggle staged
<kbd>ctrl+b</kbd>: Filter files (staged/unstaged)
<kbd>c</kbd>: commit veranderingen
<kbd>w</kbd>: commit veranderingen zonder pre-commit hook
<kbd>A</kbd>: wijzig laatste commit
<kbd>C</kbd>: commit veranderingen met de git editor
<kbd>e</kbd>: verander bestand
<kbd>o</kbd>: open bestand
<kbd>i</kbd>: voeg toe aan .gitignore
<kbd>r</kbd>: refresh bestanden
<kbd>s</kbd>: stash-bestanden
<kbd>S</kbd>: bekijk stash opties
<kbd>a</kbd>: toggle staged alle
<kbd>enter</kbd>: stage individuele hunks/lijnen
<kbd>g</kbd>: bekijk upstream reset opties
<kbd>D</kbd>: bekijk reset opties
<kbd>`</kbd>: toggle bestandsboom weergave
<kbd>M</kbd>: open external merge tool (git mergetool)
<kbd>f</kbd>: fetch
</pre>
## Bestanden Paneel (Submodules)
<pre>
<kbd>ctrl+o</kbd>: kopieer submodule naam naar klembord
<kbd>enter</kbd>: enter submodule
<kbd>d</kbd>: remove submodule
<kbd>u</kbd>: update submodule
<kbd>n</kbd>: voeg nieuwe submodule toe
<kbd>e</kbd>: update submodule URL
<kbd>i</kbd>: initialiseer submodule
<kbd>b</kbd>: bekijk bulk submodule opties
</pre>
## Branches Paneel (Branches Tabblad)
<pre>
@ -178,46 +218,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>@</kbd>: open command log menu
</pre>
## Bestanden Paneel (Bestanden)
<pre>
<kbd>ctrl+o</kbd>: kopieer de bestandsnaam naar het klembord
<kbd>ctrl+w</kbd>: Toggle whether or not whitespace changes are shown in the diff view
<kbd>d</kbd>: bekijk 'veranderingen ongedaan maken' opties
<kbd>space</kbd>: toggle staged
<kbd>ctrl+b</kbd>: Filter files (staged/unstaged)
<kbd>c</kbd>: commit veranderingen
<kbd>w</kbd>: commit veranderingen zonder pre-commit hook
<kbd>A</kbd>: wijzig laatste commit
<kbd>C</kbd>: commit veranderingen met de git editor
<kbd>e</kbd>: verander bestand
<kbd>o</kbd>: open bestand
<kbd>i</kbd>: voeg toe aan .gitignore
<kbd>r</kbd>: refresh bestanden
<kbd>s</kbd>: stash-bestanden
<kbd>S</kbd>: bekijk stash opties
<kbd>a</kbd>: toggle staged alle
<kbd>enter</kbd>: stage individuele hunks/lijnen
<kbd>g</kbd>: bekijk upstream reset opties
<kbd>D</kbd>: bekijk reset opties
<kbd>`</kbd>: toggle bestandsboom weergave
<kbd>M</kbd>: open external merge tool (git mergetool)
<kbd>f</kbd>: fetch
</pre>
## Bestanden Paneel (Submodules)
<pre>
<kbd>ctrl+o</kbd>: kopieer submodule naam naar klembord
<kbd>enter</kbd>: enter submodule
<kbd>d</kbd>: remove submodule
<kbd>u</kbd>: update submodule
<kbd>n</kbd>: voeg nieuwe submodule toe
<kbd>e</kbd>: update submodule URL
<kbd>i</kbd>: initialiseer submodule
<kbd>b</kbd>: bekijk bulk submodule opties
</pre>
## Hoofd Paneel (Mergen)
<pre>
@ -269,7 +269,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd></kbd>: selecteer de volgende hunk
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>e</kbd>: verander bestand
<kbd>o</kbd>: open bestand
<kbd>v</kbd>: toggle drag selecteer
<kbd>V</kbd>: toggle drag selecteer
<kbd>a</kbd>: toggle selecteer hunk

View File

@ -41,6 +41,56 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>[</kbd>: previous tab
</pre>
## Commity Panel (Commity)
<pre>
<kbd>ctrl+o</kbd>: copy commit SHA to clipboard
<kbd>ctrl+r</kbd>: reset cherry-picked (copied) commits selection
<kbd>b</kbd>: view bisect options
<kbd>s</kbd>: ściśnij
<kbd>f</kbd>: napraw commit
<kbd>r</kbd>: zmień nazwę commita
<kbd>R</kbd>: zmień nazwę commita w edytorze
<kbd>d</kbd>: usuń commit
<kbd>e</kbd>: edytuj commit
<kbd>p</kbd>: wybierz commit (podczas zmiany bazy)
<kbd>F</kbd>: utwórz commit naprawczy dla tego commita
<kbd>S</kbd>: spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash)
<kbd>ctrl+j</kbd>: przenieś commit 1 w dół
<kbd>ctrl+k</kbd>: przenieś commit 1 w górę
<kbd>A</kbd>: popraw commit zmianami z poczekalni
<kbd>t</kbd>: odwróć commit
<kbd>n</kbd>: create new branch off of commit
<kbd>c</kbd>: kopiuj commit (przebieranie)
<kbd>C</kbd>: kopiuj zakres commitów (przebieranie)
<kbd>v</kbd>: wklej commity (przebieranie)
<kbd>ctrl+l</kbd>: open log menu
<kbd>g</kbd>: zresetuj do tego commita
<kbd>space</kbd>: checkout commit
<kbd>T</kbd>: tag commit
<kbd>ctrl+y</kbd>: copy commit message to clipboard
<kbd>o</kbd>: open commit in browser
<kbd>enter</kbd>: przeglądaj pliki commita
</pre>
## Commity Panel (Reflog Tab)
<pre>
<kbd>ctrl+o</kbd>: copy commit SHA to clipboard
<kbd>space</kbd>: checkout commit
<kbd>g</kbd>: wyświetl opcje resetu
<kbd>c</kbd>: kopiuj commit (przebieranie)
<kbd>C</kbd>: kopiuj zakres commitów (przebieranie)
<kbd>ctrl+r</kbd>: reset cherry-picked (copied) commits selection
<kbd>enter</kbd>: przeglądaj pliki commita
</pre>
## Extras Panel
<pre>
<kbd>@</kbd>: open command log menu
</pre>
## Gałęzie Panel (Branches Tab)
<pre>
@ -109,73 +159,69 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>enter</kbd>: view commits
</pre>
## Pliki commita Panel
## Główne Panel (Patch Building)
<pre>
<kbd>ctrl+o</kbd>: copy the committed file name to the clipboard
</pre>
## Pliki commita Panel (Pliki commita)
<pre>
<kbd>c</kbd>: plik wybierania
<kbd>d</kbd>: porzuć zmiany commita dla tego pliku
<kbd>esc</kbd>: wyście z trybu "linia po linii"
<kbd>o</kbd>: otwórz plik
<kbd></kbd>: poprzednia linia
<kbd></kbd>: następna linia
<kbd></kbd>: poprzedni kawałek
<kbd></kbd>: następny kawałek
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>space</kbd>: add/remove line(s) to patch
<kbd>v</kbd>: toggle drag select
<kbd>V</kbd>: toggle drag select
<kbd>a</kbd>: toggle select hunk
</pre>
## Główne Panel (Poczekalnia)
<pre>
<kbd>esc</kbd>: wróć do panelu plików
<kbd>space</kbd>: toggle line staged / unstaged
<kbd>d</kbd>: delete change (git reset)
<kbd>tab</kbd>: switch to other panel
<kbd>o</kbd>: otwórz plik
<kbd></kbd>: poprzednia linia
<kbd></kbd>: następna linia
<kbd></kbd>: poprzedni kawałek
<kbd></kbd>: następny kawałek
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>e</kbd>: edytuj plik
<kbd>space</kbd>: toggle file included in patch
<kbd>a</kbd>: toggle all files included in patch
<kbd>enter</kbd>: enter file to add selected lines to the patch (or toggle directory collapsed)
<kbd>`</kbd>: toggle file tree view
<kbd>v</kbd>: toggle drag select
<kbd>V</kbd>: toggle drag select
<kbd>a</kbd>: toggle select hunk
<kbd>c</kbd>: Zatwierdź zmiany
<kbd>w</kbd>: zatwierdź zmiany bez skryptu pre-commit
<kbd>C</kbd>: Zatwierdź zmiany używając edytora
</pre>
## Commity Panel (Commity)
## Główne Panel (Scalanie)
<pre>
<kbd>ctrl+o</kbd>: copy commit SHA to clipboard
<kbd>ctrl+r</kbd>: reset cherry-picked (copied) commits selection
<kbd>b</kbd>: view bisect options
<kbd>s</kbd>: ściśnij
<kbd>f</kbd>: napraw commit
<kbd>r</kbd>: zmień nazwę commita
<kbd>R</kbd>: zmień nazwę commita w edytorze
<kbd>d</kbd>: usuń commit
<kbd>e</kbd>: edytuj commit
<kbd>p</kbd>: wybierz commit (podczas zmiany bazy)
<kbd>F</kbd>: utwórz commit naprawczy dla tego commita
<kbd>S</kbd>: spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash)
<kbd>ctrl+j</kbd>: przenieś commit 1 w dół
<kbd>ctrl+k</kbd>: przenieś commit 1 w górę
<kbd>A</kbd>: popraw commit zmianami z poczekalni
<kbd>t</kbd>: odwróć commit
<kbd>n</kbd>: create new branch off of commit
<kbd>c</kbd>: kopiuj commit (przebieranie)
<kbd>C</kbd>: kopiuj zakres commitów (przebieranie)
<kbd>v</kbd>: wklej commity (przebieranie)
<kbd>ctrl+l</kbd>: open log menu
<kbd>g</kbd>: zresetuj do tego commita
<kbd>space</kbd>: checkout commit
<kbd>T</kbd>: tag commit
<kbd>ctrl+y</kbd>: copy commit message to clipboard
<kbd>o</kbd>: open commit in browser
<kbd>enter</kbd>: przeglądaj pliki commita
<kbd>esc</kbd>: wróć do panelu plików
<kbd>M</kbd>: open external merge tool (git mergetool)
<kbd>space</kbd>: wybierz kawałek
<kbd>b</kbd>: wybierz wszystkie kawałki
<kbd></kbd>: poprzedni konflikt
<kbd></kbd>: następny konflikt
<kbd></kbd>: wybierz poprzedni kawałek
<kbd></kbd>: wybierz następny kawałek
<kbd>z</kbd>: cofnij
</pre>
## Commity Panel (Reflog Tab)
## Główne Panel (Zwykłe)
<pre>
<kbd>ctrl+o</kbd>: copy commit SHA to clipboard
<kbd>space</kbd>: checkout commit
<kbd>g</kbd>: wyświetl opcje resetu
<kbd>c</kbd>: kopiuj commit (przebieranie)
<kbd>C</kbd>: kopiuj zakres commitów (przebieranie)
<kbd>ctrl+r</kbd>: reset cherry-picked (copied) commits selection
<kbd>enter</kbd>: przeglądaj pliki commita
<kbd>mouse wheel down</kbd>: przewiń w dół (fn+up)
<kbd>mouse wheel up</kbd>: przewiń w górę (fn+down)
</pre>
## Extras Panel
## Menu Panel
<pre>
<kbd>@</kbd>: open command log menu
<kbd>esc</kbd>: close menu
</pre>
## Pliki Panel (Pliki)
@ -218,70 +264,23 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: view bulk submodule options
</pre>
## Główne Panel (Scalanie)
## Pliki commita Panel
<pre>
<kbd>esc</kbd>: wróć do panelu plików
<kbd>M</kbd>: open external merge tool (git mergetool)
<kbd>space</kbd>: wybierz kawałek
<kbd>b</kbd>: wybierz wszystkie kawałki
<kbd></kbd>: poprzedni konflikt
<kbd></kbd>: następny konflikt
<kbd></kbd>: wybierz poprzedni kawałek
<kbd></kbd>: wybierz następny kawałek
<kbd>z</kbd>: cofnij
<kbd>ctrl+o</kbd>: copy the committed file name to the clipboard
</pre>
## Główne Panel (Zwykłe)
## Pliki commita Panel (Pliki commita)
<pre>
<kbd>mouse wheel down</kbd>: przewiń w dół (fn+up)
<kbd>mouse wheel up</kbd>: przewiń w górę (fn+down)
</pre>
## Główne Panel (Patch Building)
<pre>
<kbd>esc</kbd>: wyście z trybu "linia po linii"
<kbd>c</kbd>: plik wybierania
<kbd>d</kbd>: porzuć zmiany commita dla tego pliku
<kbd>o</kbd>: otwórz plik
<kbd></kbd>: poprzednia linia
<kbd></kbd>: następna linia
<kbd></kbd>: poprzedni kawałek
<kbd></kbd>: następny kawałek
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>space</kbd>: add/remove line(s) to patch
<kbd>v</kbd>: toggle drag select
<kbd>V</kbd>: toggle drag select
<kbd>a</kbd>: toggle select hunk
</pre>
## Główne Panel (Poczekalnia)
<pre>
<kbd>esc</kbd>: wróć do panelu plików
<kbd>space</kbd>: toggle line staged / unstaged
<kbd>d</kbd>: delete change (git reset)
<kbd>tab</kbd>: switch to other panel
<kbd>o</kbd>: otwórz plik
<kbd></kbd>: poprzednia linia
<kbd></kbd>: następna linia
<kbd></kbd>: poprzedni kawałek
<kbd></kbd>: następny kawałek
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>e</kbd>: edytuj plik
<kbd>o</kbd>: otwórz plik
<kbd>v</kbd>: toggle drag select
<kbd>V</kbd>: toggle drag select
<kbd>a</kbd>: toggle select hunk
<kbd>c</kbd>: Zatwierdź zmiany
<kbd>w</kbd>: zatwierdź zmiany bez skryptu pre-commit
<kbd>C</kbd>: Zatwierdź zmiany używając edytora
</pre>
## Menu Panel
<pre>
<kbd>esc</kbd>: close menu
<kbd>space</kbd>: toggle file included in patch
<kbd>a</kbd>: toggle all files included in patch
<kbd>enter</kbd>: enter file to add selected lines to the patch (or toggle directory collapsed)
<kbd>`</kbd>: toggle file tree view
</pre>
## Schowek Panel (Schowek)

View File

@ -41,6 +41,71 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>[</kbd>: 上一个标签
</pre>
## Extras 面板
<pre>
<kbd>@</kbd>: 打开命令日志菜单
</pre>
## 主要 面板 (合并中)
<pre>
<kbd>esc</kbd>: 返回文件面板
<kbd>M</kbd>: 打开合并工具
<kbd>space</kbd>: 选中区块
<kbd>b</kbd>: 选中所有区块
<kbd></kbd>: 选择上一个冲突
<kbd></kbd>: 选择下一个冲突
<kbd></kbd>: 选择顶部块
<kbd></kbd>: 选择底部块
<kbd>z</kbd>: 撤销
</pre>
## 主要 面板 (构建补丁中)
<pre>
<kbd>esc</kbd>: 退出逐行模式
<kbd>o</kbd>: 打开文件
<kbd></kbd>: 选择上一行
<kbd></kbd>: 选择下一行
<kbd></kbd>: 选择上一个区块
<kbd></kbd>: 选择下一个区块
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>space</kbd>: 添加/移除 行到补丁
<kbd>v</kbd>: 切换拖动选择
<kbd>V</kbd>: 切换拖动选择
<kbd>a</kbd>: 切换选择区块
</pre>
## 主要 面板 (正在暂存)
<pre>
<kbd>esc</kbd>: 返回文件面板
<kbd>space</kbd>: 切换行暂存状态
<kbd>d</kbd>: 取消变更 (git reset)
<kbd>tab</kbd>: 切换到其他面板
<kbd>o</kbd>: 打开文件
<kbd></kbd>: 选择上一行
<kbd></kbd>: 选择下一行
<kbd></kbd>: 选择上一个区块
<kbd></kbd>: 选择下一个区块
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>e</kbd>: 编辑文件
<kbd>v</kbd>: 切换拖动选择
<kbd>V</kbd>: 切换拖动选择
<kbd>a</kbd>: 切换选择区块
<kbd>c</kbd>: 提交更改
<kbd>w</kbd>: 提交更改而无需预先提交钩子
<kbd>C</kbd>: 提交更改(使用编辑器编辑提交信息)
</pre>
## 主要 面板 (正常)
<pre>
<kbd>mouse wheel down</kbd>: 向下滚动 (fn+up)
<kbd>mouse wheel up</kbd>: 向上滚动 (fn+down)
</pre>
## 分支 面板 (分支标签)
<pre>
@ -62,29 +127,6 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>enter</kbd>: 查看提交
</pre>
## 分支 面板 (远程分支(在远程页面中))
<pre>
<kbd>space</kbd>: 检出
<kbd>n</kbd>: 新分支
<kbd>M</kbd>: 合并到当前检出的分支
<kbd>r</kbd>: 将已检出的分支变基到该分支
<kbd>d</kbd>: 删除分支
<kbd>u</kbd>: 设置为检出分支的上游
<kbd>esc</kbd>: 返回远程仓库列表
<kbd>g</kbd>: 查看重置选项
<kbd>enter</kbd>: 查看提交
</pre>
## 分支 面板 (远程页面)
<pre>
<kbd>f</kbd>: 抓取远程仓库
<kbd>n</kbd>: 添加新的远程仓库
<kbd>d</kbd>: 删除远程
<kbd>e</kbd>: 编辑远程仓库
</pre>
## 分支 面板 (子提交)
<pre>
@ -109,23 +151,39 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>enter</kbd>: 查看提交
</pre>
## 提交文件 面板
## 分支 面板 (远程分支(在远程页面中))
<pre>
<kbd>ctrl+o</kbd>: 将提交的文件名复制到剪贴板
<kbd>space</kbd>: 检出
<kbd>n</kbd>: 新分支
<kbd>M</kbd>: 合并到当前检出的分支
<kbd>r</kbd>: 将已检出的分支变基到该分支
<kbd>d</kbd>: 删除分支
<kbd>u</kbd>: 设置为检出分支的上游
<kbd>esc</kbd>: 返回远程仓库列表
<kbd>g</kbd>: 查看重置选项
<kbd>enter</kbd>: 查看提交
</pre>
## 提交文件 面板 (提交文件)
## 分支 面板 (远程页面)
<pre>
<kbd>c</kbd>: 检出文件
<kbd>d</kbd>: 放弃对此文件的提交更改
<kbd>o</kbd>: 打开文件
<kbd>e</kbd>: 编辑文件
<kbd>space</kbd>: 补丁中包含的切换文件
<kbd>a</kbd>: toggle all files included in patch
<kbd>enter</kbd>: 输入文件以将所选行添加到补丁中(或切换目录折叠)
<kbd>`</kbd>: 切换文件树视图
<kbd>f</kbd>: 抓取远程仓库
<kbd>n</kbd>: 添加新的远程仓库
<kbd>d</kbd>: 删除远程
<kbd>e</kbd>: 编辑远程仓库
</pre>
## 提交 面板 (Reflog)
<pre>
<kbd>ctrl+o</kbd>: 将提交的 SHA 复制到剪贴板
<kbd>space</kbd>: 检出提交
<kbd>g</kbd>: 查看重置选项
<kbd>c</kbd>: 复制提交(拣选)
<kbd>C</kbd>: 复制提交范围(拣选)
<kbd>ctrl+r</kbd>: 重置已拣选(复制)的提交
<kbd>enter</kbd>: 查看提交的文件
</pre>
## 提交 面板 (提交)
@ -160,22 +218,36 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>enter</kbd>: 查看提交的文件
</pre>
## 提交 面板 (Reflog)
## 提交文件 面板
<pre>
<kbd>ctrl+o</kbd>: 将提交的 SHA 复制到剪贴板
<kbd>space</kbd>: 检出提交
<kbd>g</kbd>: 查看重置选项
<kbd>c</kbd>: 复制提交(拣选)
<kbd>C</kbd>: 复制提交范围(拣选)
<kbd>ctrl+r</kbd>: 重置已拣选(复制)的提交
<kbd>enter</kbd>: 查看提交的文件
<kbd>ctrl+o</kbd>: 将提交的文件名复制到剪贴板
</pre>
## Extras 面板
## 提交文件 面板 (提交文件)
<pre>
<kbd>@</kbd>: 打开命令日志菜单
<kbd>c</kbd>: 检出文件
<kbd>d</kbd>: 放弃对此文件的提交更改
<kbd>o</kbd>: 打开文件
<kbd>e</kbd>: 编辑文件
<kbd>space</kbd>: 补丁中包含的切换文件
<kbd>a</kbd>: toggle all files included in patch
<kbd>enter</kbd>: 输入文件以将所选行添加到补丁中(或切换目录折叠)
<kbd>`</kbd>: 切换文件树视图
</pre>
## 文件 面板 (子模块)
<pre>
<kbd>ctrl+o</kbd>: 将子模块名称复制到剪贴板
<kbd>enter</kbd>: 输入子模块
<kbd>d</kbd>: 删除子模块
<kbd>u</kbd>: 更新子模块
<kbd>n</kbd>: 添加新的子模块
<kbd>e</kbd>: 更新子模块 URL
<kbd>i</kbd>: 初始化子模块
<kbd>b</kbd>: 查看批量子模块选项
</pre>
## 文件 面板 (文件)
@ -205,77 +277,14 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>f</kbd>: 抓取
</pre>
## 文件 面板 (子模块)
## 状态 面板 (状态)
<pre>
<kbd>ctrl+o</kbd>: 将子模块名称复制到剪贴板
<kbd>enter</kbd>: 输入子模块
<kbd>d</kbd>: 删除子模块
<kbd>u</kbd>: 更新子模块
<kbd>n</kbd>: 添加新的子模块
<kbd>e</kbd>: 更新子模块 URL
<kbd>i</kbd>: 初始化子模块
<kbd>b</kbd>: 查看批量子模块选项
</pre>
## 主要 面板 (合并中)
<pre>
<kbd>esc</kbd>: 返回文件面板
<kbd>M</kbd>: 打开合并工具
<kbd>space</kbd>: 选中区块
<kbd>b</kbd>: 选中所有区块
<kbd></kbd>: 选择上一个冲突
<kbd></kbd>: 选择下一个冲突
<kbd></kbd>: 选择顶部块
<kbd></kbd>: 选择底部块
<kbd>z</kbd>: 撤销
</pre>
## 主要 面板 (正常)
<pre>
<kbd>mouse wheel down</kbd>: 向下滚动 (fn+up)
<kbd>mouse wheel up</kbd>: 向上滚动 (fn+down)
</pre>
## 主要 面板 (构建补丁中)
<pre>
<kbd>esc</kbd>: 退出逐行模式
<kbd>o</kbd>: 打开文件
<kbd></kbd>: 选择上一行
<kbd></kbd>: 选择下一行
<kbd></kbd>: 选择上一个区块
<kbd></kbd>: 选择下一个区块
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>space</kbd>: 添加/移除 行到补丁
<kbd>v</kbd>: 切换拖动选择
<kbd>V</kbd>: 切换拖动选择
<kbd>a</kbd>: 切换选择区块
</pre>
## 主要 面板 (正在暂存)
<pre>
<kbd>esc</kbd>: 返回文件面板
<kbd>space</kbd>: 切换行暂存状态
<kbd>d</kbd>: 取消变更 (git reset)
<kbd>tab</kbd>: 切换到其他面板
<kbd>o</kbd>: 打开文件
<kbd></kbd>: 选择上一行
<kbd></kbd>: 选择下一行
<kbd></kbd>: 选择上一个区块
<kbd></kbd>: 选择下一个区块
<kbd>ctrl+o</kbd>: copy the selected text to the clipboard
<kbd>e</kbd>: 编辑文件
<kbd>o</kbd>: 打开文件
<kbd>v</kbd>: 切换拖动选择
<kbd>V</kbd>: 切换拖动选择
<kbd>a</kbd>: 切换选择区块
<kbd>c</kbd>: 提交更改
<kbd>w</kbd>: 提交更改而无需预先提交钩子
<kbd>C</kbd>: 提交更改(使用编辑器编辑提交信息)
<kbd>e</kbd>: 编辑配置文件
<kbd>o</kbd>: 打开配置文件
<kbd>u</kbd>: 检查更新
<kbd>enter</kbd>: 切换到最近的仓库
<kbd>a</kbd>: 显示所有分支的日志
</pre>
## 菜单 面板
@ -293,13 +302,3 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>n</kbd>: 新分支
<kbd>enter</kbd>: 查看提交的文件
</pre>
## 状态 面板 (状态)
<pre>
<kbd>e</kbd>: 编辑配置文件
<kbd>o</kbd>: 打开配置文件
<kbd>u</kbd>: 检查更新
<kbd>enter</kbd>: 切换到最近的仓库
<kbd>a</kbd>: 显示所有分支的日志
</pre>

View File

@ -21,6 +21,8 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/integration"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
type bindingSection struct {
@ -28,6 +30,17 @@ type bindingSection struct {
bindings []*types.Binding
}
type header struct {
// priority decides the order of the headers in the cheatsheet (lower means higher)
priority int
title string
}
type headerWithBindings struct {
header header
bindings []*types.Binding
}
func CommandToRun() string {
return "go run scripts/cheatsheet/main.go generate"
}
@ -49,7 +62,8 @@ func generateAtDir(cheatsheetDir string) {
panic(err)
}
bindingSections := getBindingSections(mApp)
bindings := mApp.Gui.GetCheatsheetKeybindings()
bindingSections := getBindingSections(bindings, mApp.Tr)
content := formatSections(mApp.Tr, bindingSections)
content = fmt.Sprintf("_This file is auto-generated. To update, make the changes in the "+
"pkg/i18n directory and then run `%s` from the project root._\n\n%s", CommandToRun(), content)
@ -68,9 +82,7 @@ func writeString(file *os.File, str string) {
}
}
func localisedTitle(mApp *app.App, str string) string {
tr := mApp.Tr
func localisedTitle(tr *i18n.TranslationSet, str string) string {
contextTitleMap := map[string]string{
"global": tr.GlobalTitle,
"navigation": tr.NavigationTitle,
@ -110,142 +122,66 @@ func localisedTitle(mApp *app.App, str string) string {
return title
}
func formatTitle(title string) string {
return fmt.Sprintf("\n## %s\n\n", title)
}
func formatBinding(binding *types.Binding) string {
if binding.Alternative != "" {
return fmt.Sprintf(" <kbd>%s</kbd>: %s (%s)\n", gui.GetKeyDisplay(binding.Key), binding.Description, binding.Alternative)
}
return fmt.Sprintf(" <kbd>%s</kbd>: %s\n", gui.GetKeyDisplay(binding.Key), binding.Description)
}
func getBindingSections(mApp *app.App) []*bindingSection {
bindingSections := []*bindingSection{}
bindings := mApp.Gui.GetCheatsheetKeybindings()
type contextAndViewType struct {
subtitle string
title string
}
contextAndViewBindingMap := map[contextAndViewType][]*types.Binding{}
outer:
for _, binding := range bindings {
if binding.Tag == "navigation" {
key := contextAndViewType{subtitle: "", title: "navigation"}
existing := contextAndViewBindingMap[key]
if existing == nil {
contextAndViewBindingMap[key] = []*types.Binding{binding}
} else {
if !slices.Some(contextAndViewBindingMap[key], func(navBinding *types.Binding) bool {
return navBinding.Description == binding.Description
}) {
contextAndViewBindingMap[key] = append(contextAndViewBindingMap[key], binding)
}
}
continue outer
}
contexts := []string{}
if len(binding.Contexts) == 0 {
contexts = append(contexts, "")
} else {
contexts = append(contexts, binding.Contexts...)
}
for _, context := range contexts {
key := contextAndViewType{subtitle: context, title: binding.ViewName}
existing := contextAndViewBindingMap[key]
if existing == nil {
contextAndViewBindingMap[key] = []*types.Binding{binding}
} else {
contextAndViewBindingMap[key] = append(contextAndViewBindingMap[key], binding)
}
}
}
type groupedBindingsType struct {
contextAndView contextAndViewType
bindings []*types.Binding
}
groupedBindings := maps.MapToSlice(
contextAndViewBindingMap,
func(contextAndView contextAndViewType, contextBindings []*types.Binding) groupedBindingsType {
return groupedBindingsType{contextAndView: contextAndView, bindings: contextBindings}
},
)
slices.SortFunc(groupedBindings, func(a, b groupedBindingsType) bool {
first := a.contextAndView
second := b.contextAndView
if first.title == "" {
return true
}
if second.title == "" {
return false
}
if first.title == "navigation" {
return true
}
if second.title == "navigation" {
return false
}
return first.title < second.title || (first.title == second.title && first.subtitle < second.subtitle)
func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*bindingSection {
bindingsToDisplay := slices.Filter(bindings, func(binding *types.Binding) bool {
return binding.Description != "" || binding.Alternative != ""
})
for _, group := range groupedBindings {
contextAndView := group.contextAndView
contextBindings := group.bindings
mApp.Log.Info("viewname: " + contextAndView.title + ", context: " + contextAndView.subtitle)
viewName := contextAndView.title
if viewName == "" {
viewName = "global"
}
translatedView := localisedTitle(mApp, viewName)
var title string
if contextAndView.subtitle == "" {
addendum := " " + mApp.Tr.Panel
if viewName == "global" || viewName == "navigation" {
addendum = ""
}
title = fmt.Sprintf("%s%s", translatedView, addendum)
} else {
translatedContextName := localisedTitle(mApp, contextAndView.subtitle)
title = fmt.Sprintf("%s %s (%s)", translatedView, mApp.Tr.Panel, translatedContextName)
}
bindingsByHeader := utils.MuiltiGroupBy(bindingsToDisplay, func(binding *types.Binding) []header {
return getHeaders(binding, tr)
})
for _, binding := range contextBindings {
bindingSections = addBinding(title, bindingSections, binding)
}
}
bindingGroups := maps.MapToSlice(bindingsByHeader, func(header header, hBindings []*types.Binding) headerWithBindings {
uniqBindings := lo.UniqBy(hBindings, func(binding *types.Binding) string {
return binding.Description + gui.GetKeyDisplay(binding.Key)
})
return bindingSections
return headerWithBindings{
header: header,
bindings: uniqBindings,
}
})
slices.SortFunc(bindingGroups, func(a, b headerWithBindings) bool {
if a.header.priority != b.header.priority {
return a.header.priority > b.header.priority
}
return a.header.title < b.header.title
})
return slices.Map(bindingGroups, func(hb headerWithBindings) *bindingSection {
return &bindingSection{
title: hb.header.title,
bindings: hb.bindings,
}
})
}
func addBinding(title string, bindingSections []*bindingSection, binding *types.Binding) []*bindingSection {
if binding.Description == "" && binding.Alternative == "" {
return bindingSections
// a binding may belong to multiple headers if it is applicable to multiple contexts,
// for example the copy-to-clipboard binding.
func getHeaders(binding *types.Binding, tr *i18n.TranslationSet) []header {
if binding.Tag == "navigation" {
return []header{{priority: 2, title: localisedTitle(tr, "navigation")}}
}
for _, section := range bindingSections {
if title == section.title {
section.bindings = append(section.bindings, binding)
return bindingSections
}
if binding.ViewName == "" {
return []header{{priority: 3, title: localisedTitle(tr, "global")}}
}
section := &bindingSection{
title: title,
bindings: []*types.Binding{binding},
if len(binding.Contexts) == 0 {
translatedView := localisedTitle(tr, binding.ViewName)
title := fmt.Sprintf("%s %s", translatedView, tr.Panel)
return []header{{priority: 1, title: title}}
}
return append(bindingSections, section)
return slices.Map(binding.Contexts, func(context string) header {
translatedView := localisedTitle(tr, binding.ViewName)
translatedContextName := localisedTitle(tr, context)
title := fmt.Sprintf("%s %s (%s)", translatedView, tr.Panel, translatedContextName)
return header{priority: 1, title: title}
})
}
func formatSections(tr *i18n.TranslationSet, bindingSections []*bindingSection) string {
@ -262,3 +198,14 @@ func formatSections(tr *i18n.TranslationSet, bindingSections []*bindingSection)
return content
}
func formatTitle(title string) string {
return fmt.Sprintf("\n## %s\n\n", title)
}
func formatBinding(binding *types.Binding) string {
if binding.Alternative != "" {
return fmt.Sprintf(" <kbd>%s</kbd>: %s (%s)\n", gui.GetKeyDisplay(binding.Key), binding.Description, binding.Alternative)
}
return fmt.Sprintf(" <kbd>%s</kbd>: %s\n", gui.GetKeyDisplay(binding.Key), binding.Description)
}

View File

@ -0,0 +1,281 @@
package cheatsheet
import (
"testing"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/stretchr/testify/assert"
)
func TestGetBindingSections(t *testing.T) {
tr := i18n.EnglishTranslationSet()
tests := []struct {
testName string
bindings []*types.Binding
expected []*bindingSection
}{
{
testName: "no bindings",
bindings: []*types.Binding{},
expected: []*bindingSection{},
},
{
testName: "one binding",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
},
},
expected: []*bindingSection{
{
title: "Files Panel",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
},
},
},
},
},
{
testName: "one binding with context",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
Contexts: []string{"submodules"},
},
},
expected: []*bindingSection{
{
title: "Files Panel (Submodules)",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
Contexts: []string{"submodules"},
},
},
},
},
},
{
testName: "global binding",
bindings: []*types.Binding{
{
ViewName: "",
Description: "quit",
},
},
expected: []*bindingSection{
{
title: "Global Keybindings",
bindings: []*types.Binding{
{
ViewName: "",
Description: "quit",
},
},
},
},
},
{
testName: "grouped bindings",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
Contexts: []string{"files"},
},
{
ViewName: "files",
Description: "unstage file",
Contexts: []string{"files"},
},
{
ViewName: "files",
Description: "drop submodule",
Contexts: []string{"submodules"},
},
{
ViewName: "commits",
Description: "revert commit",
},
},
expected: []*bindingSection{
{
title: "Commits Panel",
bindings: []*types.Binding{
{
ViewName: "commits",
Description: "revert commit",
},
},
},
{
title: "Files Panel (Files)",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
Contexts: []string{"files"},
},
{
ViewName: "files",
Description: "unstage file",
Contexts: []string{"files"},
},
},
},
{
title: "Files Panel (Submodules)",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "drop submodule",
Contexts: []string{"submodules"},
},
},
},
},
},
{
testName: "with navigation bindings",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
},
{
ViewName: "files",
Description: "unstage file",
},
{
ViewName: "files",
Description: "scroll",
Tag: "navigation",
},
{
ViewName: "commits",
Description: "revert commit",
},
},
expected: []*bindingSection{
{
title: "List Panel Navigation",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "scroll",
Tag: "navigation",
},
},
},
{
title: "Commits Panel",
bindings: []*types.Binding{
{
ViewName: "commits",
Description: "revert commit",
},
},
},
{
title: "Files Panel",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
},
{
ViewName: "files",
Description: "unstage file",
},
},
},
},
},
{
testName: "with duplicate navigation bindings",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
},
{
ViewName: "files",
Description: "unstage file",
},
{
ViewName: "files",
Description: "scroll",
Tag: "navigation",
},
{
ViewName: "commits",
Description: "revert commit",
},
{
ViewName: "commits",
Description: "scroll",
Tag: "navigation",
},
{
ViewName: "commits",
Description: "page up",
Tag: "navigation",
},
},
expected: []*bindingSection{
{
title: "List Panel Navigation",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "scroll",
Tag: "navigation",
},
{
ViewName: "commits",
Description: "page up",
Tag: "navigation",
},
},
},
{
title: "Commits Panel",
bindings: []*types.Binding{
{
ViewName: "commits",
Description: "revert commit",
},
},
},
{
title: "Files Panel",
bindings: []*types.Binding{
{
ViewName: "files",
Description: "stage file",
},
{
ViewName: "files",
Description: "unstage file",
},
},
},
},
},
}
for _, test := range tests {
t.Run(test.testName, func(t *testing.T) {
actual := getBindingSections(test.bindings, &tr)
assert.EqualValues(t, test.expected, actual)
})
}
}

View File

@ -76,3 +76,19 @@ func LimitStr(value string, limit int) string {
}
return value
}
// Similar to a regular GroupBy, except that each item can be grouped under multiple keys,
// so the callback returns a slice of keys instead of just one key.
func MuiltiGroupBy[T any, K comparable](slice []T, f func(T) []K) map[K][]T {
result := map[K][]T{}
for _, item := range slice {
for _, key := range f(item) {
if _, ok := result[key]; !ok {
result[key] = []T{item}
} else {
result[key] = append(result[key], item)
}
}
}
return result
}