Compare commits

...

64 Commits
v0.20 ... v0.21

Author SHA1 Message Date
Jesse Duffield
27cd12e2d9 accept umlaut keybindings 2020-08-12 20:07:56 +10:00
Jesse Duffield
bfaf1c4f70 use remote prefixed branch name when merging remote branch 2020-08-12 20:07:46 +10:00
Jesse Duffield
2d18d089ce allow entering a password when fast forwarding another branch 2020-08-12 18:47:16 +10:00
Jesse Duffield
9c7e40906d rename arg 2020-08-12 18:47:16 +10:00
Jesse Duffield
401f291c3b lowercase function name 2020-08-12 18:47:16 +10:00
Jesse Duffield
bea2ae5ff5 stop pulling in general 2020-08-12 18:47:16 +10:00
Jesse Duffield
f49e4946f2 minor refactor 2020-08-12 18:47:16 +10:00
Jesse Duffield
8ff74072f8 update config 2020-08-12 18:47:16 +10:00
Jesse Duffield
fcd5aea04e support multiple modes of git pull 2020-08-12 18:47:16 +10:00
Jesse Duffield
1c0da2967c update naming 2020-08-12 18:47:16 +10:00
Jesse Duffield
1b78a42b80 pass callback directly 2020-08-12 18:47:16 +10:00
Jesse Duffield
79e73d2eff minor cleanup
WIP
2020-08-12 18:47:16 +10:00
Jesse Duffield
23299f88e9 simplify patch modifier interface 2020-08-09 15:42:20 +10:00
mjarkk
ef744e45c1 Update dutch translations 2020-08-08 14:25:11 +10:00
Jesse Duffield
660cc2f3d1 follow cursor when staging and unstaging a file rename 2020-08-07 18:59:56 +10:00
Jesse Duffield
469ac116ef allow renames to be discarded 2020-08-07 18:01:26 +10:00
Jesse Duffield
a86103479b cleanup 2020-08-07 18:01:26 +10:00
Axel Navarro
d49e75bd3e Add tab keybinding in commit message 2020-07-26 16:28:01 +10:00
Jesse Duffield
f4718a9047 allow editing commit files 2020-07-21 18:24:39 +10:00
Jesse Duffield
7d5fe4b66c better logic for staging a renamed file 2020-07-19 14:11:32 +10:00
Jesse Duffield
845c80721f Decouple escaping from quitting
When a user is not entering text into a prompt, the 'q' key should immediately
quit the application. On the other hand, the 'esc' key should cancel/close/go-back
to the previous context.

If we're at the surface level (nothing to cancel/close) and the user hits the
escape key, the default behaviour is to close the app, however we now have a
`quitOnTopLevelReturn` config key to override this.

I actually think from the beginning we should have made this config option
default to false rather than true which is the default this PR gives it,
but I don't want to anger too many people familiar with the existing behaviour.
2020-07-18 20:00:48 +10:00
Gadzhi Kharkharov
0e65db10d8 add solus linux installation info 2020-07-18 19:48:05 +10:00
Jesse Duffield
a9cc321981 prompt to create new branch if branch not found 2020-07-17 09:20:50 +10:00
Jesse Duffield
6349214f00 prompt to commit all files if committing with no staged files 2020-07-17 09:01:40 +10:00
Randshot
96f821b841 fix TestGitCommandCommit test
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-15 09:41:16 +10:00
Randshot
964e3872c1 revert changes to 'os_default_platform.go' and 'os_windows.go'
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-15 09:41:16 +10:00
Randshot
5dfa26ea8b use strconv for quoting in 'GitCommand.Commit' and 'OSCommand.ShellCommandFromString'
use raw strings for the escaped quotes in 'os_default_platform.go' and 'os_windows.go'

Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-15 09:41:16 +10:00
Dawid Dziurla
dbf042b8ad goreleaser: fix deprecation and comment 2020-07-14 09:13:43 +02:00
Randshot
014e06eefd factor out duplicate code into 'ShellCommandFromString'
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-14 08:26:53 +10:00
Randshot
39a2122dc0 add quotes around the git commit command on non-windows systems
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-14 08:26:53 +10:00
Randshot
fe6d8d62c5 add overrideGpg switch to Config.md
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-12 11:50:12 +02:00
Randshot
570d27ffaa Merge branch 'master' into add-overrideGpg-switch
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-12 11:47:35 +02:00
Pranav Shikarpur
7b69aa1fda Added ENTRYPOINT to Dockerfile to jump directly into lazy git while running the docker container 2020-07-12 14:10:04 +10:00
Randshot
21e478dd59 fix 'Amend commit using gpg' test
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-12 14:06:53 +10:00
Randshot
d14fb36cb9 fix 'Commit using gpg' test
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-12 14:06:53 +10:00
Randshot
19a808642f fix platform specific quoting when using GPG
fixes #620

Signed-off-by: Randshot <randshot@norealm.xyz>
2020-07-12 14:06:53 +10:00
Jasper Mendiola
e921ba0910 Remove getLocalGitConfig 2020-07-10 18:55:00 +10:00
Jasper Mendiola
0f5a073d57 Rename appconfig to config 2020-07-10 18:55:00 +10:00
Jasper Mendiola
cb0bdd89c0 fix tests 2020-07-10 18:55:00 +10:00
Jasper Mendiola
e89bf5d06b add oneline-graph 2020-07-10 18:55:00 +10:00
David Chen
e82d2f37a1 Update example keybinding config for Colemak users 2020-06-03 22:14:21 +10:00
Randshot
65e955c622 add overrideGpg switch, which prevents lazygit from spawning a separate process when using GPG
Signed-off-by: Randshot <randshot@norealm.xyz>
2020-05-30 23:39:07 +02:00
Dima Kotik
e73f4c6b7e Better CWD check for a git repository. 2020-05-30 00:31:58 +10:00
Jesse Duffield
cf5cefb2d6 allow user to scroll themselves inside merge panel 2020-05-19 18:44:53 +10:00
Jesse Duffield
36ac764133 fix race condition when scrolling to merge conflict 2020-05-19 18:05:14 +10:00
Jesse Duffield
003e45d2f5 allow creating branches off of remote branches 2020-05-19 09:57:37 +10:00
Jesse Duffield
04e93317b8 fix https://github.com/jesseduffield/lazygit/issues/848 2020-05-19 09:57:37 +10:00
Jesse Duffield
f8dedb710b additional password prompt regex 2020-05-15 22:18:07 +10:00
Jesse Duffield
1c259f69f6 check if user has configured to push to current by default 2020-05-15 21:41:23 +10:00
Jesse Duffield
913f17ee3e prevent flicker from bolding background of selected line 2020-05-15 21:12:12 +10:00
Dawid Dziurla
6291c53966 workflows: update bumping action to v3 2020-05-13 13:36:59 +02:00
Jesse Duffield
267730bc00 standardise how we handle background colours 2020-05-13 21:24:25 +10:00
Jesse Duffield
d5db02a899 bump gocui to be on 'simple' branch.
The master branch of gocui contains stuff I added for lazynpm which changes how
the cursor is used. This will provide some benefits to lazygit as well but I
don't yet have the motivation to make the required changed in lazygit to support it.

So we're gonna be on the branch named 'simple' rather than master until I fix that up.
2020-05-13 21:24:25 +10:00
Gary Yendell
7ed8ee160d Add option to split patch into a new commit
Add GetHeadCommitMessage to read the subject of the HEAD commit
Create PullPatchIntoNewCommit based heavily on PullPatchIntoIndex to
  split the current patch from its commit and apply it in a separate
  commit immediately after.

WIP to Squash - Fill format string with format string

WIP
2020-05-09 11:59:37 +10:00
Josh Soref
3dd33b65a0 Minor fixes
* Windows
* Use backticks
* Italicize git config
2020-05-08 09:48:13 +10:00
Dawid Dziurla
b85048f616 workflows: update CI triggers
So it would run on pull requests from forks
2020-05-04 20:03:27 +02:00
Mike Palmer
0852f53455 Add path to config file on Windows 2020-04-27 19:15:06 +10:00
Glenn Vriesman
10fa119ab3 fix: fixed readme link
Signed-off-by: Glenn Vriesman <glenn.vriesman@gmail.com>
2020-04-27 19:14:43 +10:00
Tyler Davis
b5404c6159 fix issue #640 add catCmd and OS-specific values
Add a catCmd to the Platform struct and set the value to "cat" for
non-windows builds and "type" for windows builds.
2020-04-27 19:14:18 +10:00
Lars E
42d21c4bb6 Add FreeBSD installation instructions 2020-04-22 19:51:01 +10:00
Jesse Duffield
cc13ae252a totally screwed up the last commit 2020-04-22 11:21:20 +10:00
Jesse Duffield
b97f844a3e handle comments in todo files 2020-04-22 11:15:41 +10:00
Glenn Vriesman
1d6eb015c1 fix: fixed yaml typo
Signed-off-by: Glenn Vriesman <glenn.vriesman@gmail.com>
2020-04-22 08:52:08 +10:00
Jesse Duffield
07a8ae8c3e add handler for searching in menu 2020-04-21 19:28:31 +10:00
66 changed files with 1699 additions and 674 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1,5 +1,4 @@
# These are supported funding model platforms
github: [jesseduffield]
ko_fi: jesseduffield
custom: ['https://donorbox.org/lazygit']

View File

@@ -22,7 +22,7 @@ jobs:
env:
GITHUB_TOKEN: ${{secrets.GITHUB_API_TOKEN}}
- name: Bump Homebrew
uses: dawidd6/action-homebrew-bump-formula@v2
uses: dawidd6/action-homebrew-bump-formula@v3
with:
token: ${{secrets.GITHUB_API_TOKEN}}
formula: lazygit

View File

@@ -1,6 +1,10 @@
name: Continuous Integration
on: push
on:
push:
branches:
- '*'
pull_request: []
jobs:
ci:

View File

@@ -40,8 +40,8 @@ changelog:
- '^bump'
brews:
-
# Reporitory to push the tap to.
github:
# Repository to push the tap to.
tap:
owner: jesseduffield
name: homebrew-lazygit
@@ -61,5 +61,3 @@ brews:
# conflicts:
# - svn
# - bash
# test comment to see if goreleaser only releases on new commits

View File

@@ -1,6 +1,6 @@
# run with:
# docker build -t lazygit .
# docker run -it lazygit:latest /bin/sh -l
# docker run -it lazygit:latest /bin/sh
FROM golang:1.14-alpine3.11
WORKDIR /go/src/github.com/jesseduffield/lazygit/
@@ -13,3 +13,5 @@ WORKDIR /go/src/github.com/jesseduffield/lazygit/
COPY --from=0 /go/src/github.com/jesseduffield/lazygit /go/src/github.com/jesseduffield/lazygit
COPY --from=0 /go/src/github.com/jesseduffield/lazygit/lazygit /bin/
RUN echo "alias gg=lazygit" >> ~/.profile
ENTRYPOINT [ "lazygit" ]

View File

@@ -21,6 +21,8 @@ If you're a mere mortal like me and you're tired of hearing how powerful git is
- [Scoop (Windows)](#scoop-windows)
- [Arch Linux](#arch-linux)
- [Fedora and CentOS 7](#fedora-and-centos-7)
- [Solus Linux](#solus-linux)
- [FreeBSD](#freebsd)
- [Conda](#conda)
- [Go](#go)
- [Usage](#usage)
@@ -124,6 +126,19 @@ sudo dnf copr enable atim/lazygit -y
sudo dnf install lazygit
```
### Solus Linux
```sh
sudo eopkg install lazygit
```
### FreeBSD
```sh
pkg install lazygit
```
### Conda
Released versions are available for different platforms, see <https://anaconda.org/conda-forge/lazygit>

View File

@@ -4,6 +4,7 @@ Default path for the config file:
* Linux: `~/.config/jesseduffield/lazygit/config.yml`
* MacOS: `~/Library/Application Support/jesseduffield/lazygit/config.yml`
* Windows: `%APPDATA%\jesseduffield\lazygit\config.yml`
## Default
@@ -23,6 +24,8 @@ Default path for the config file:
optionsTextColor:
- blue
selectedLineBgColor:
- default
selectedRangeBgColor:
- blue
commitLength:
show: true
@@ -38,13 +41,19 @@ Default path for the config file:
manualCommit: false
# extra args passed to `git merge`, e.g. --no-ff
args: ""
pull:
mode: 'merge' # one of 'merge' | 'rebase' | 'ff-only'
skipHookPrefix: WIP
autoFetch: true
branchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --"
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
update:
method: prompt # can be: prompt | background | never
days: 14 # how often an update is checked for
reporting: 'undetermined' # one of: 'on' | 'off' | 'undetermined'
confirmOnQuit: false
# determines whether hitting 'esc' will quit the application when there is nothing to cancel/close
quitOnTopLevelReturn: true
keybinding:
universal:
quit: 'q'
@@ -92,7 +101,7 @@ Default path for the config file:
prevScreenMode: '_'
undo: 'z'
redo: '<c-z>'
filteringMenu: <c-s>
filteringMenu: '<c-s>'
diffingMenu: '<c-e>'
copyToClipboard: '<c-o>'
status:
@@ -215,7 +224,20 @@ If you have issues with a light terminal theme where you can't read / see the te
inactiveBorderColor:
- black
selectedLineBgColor:
- blue
- default
```
## Struggling to see selected line
If you struggle to see the selected line I recomment using the reverse attribute on selected lines like so:
```yaml
gui:
theme:
selectedLineBgColor:
- reverse
selectedRangeBgColor:
- reverse
```
## Example Coloring
@@ -244,14 +266,18 @@ For all possible keybinding options, check [Custom_Keybindings.md](https://githu
scrollDownMain-alt1: 'E'
scrollUpMain-alt2: '<c-u>'
scrollDownMain-alt2: '<c-e>'
undo: 'l'
redo: '<c-r>'
diffingMenu: 'M'
filteringMenu: '<c-f>'
files:
ignoreFile: 'I'
commits:
moveDownCommit: '<c-e>'
moveUpCommit: '<c-u>'
toggleDiffCommit: 'l'
branches:
viewGitFlowOptions: 'I'
setUpstream: 'U'
```
## Custom pull request URLs

View File

@@ -1,8 +1,8 @@
# Custom Pagers
Lazygit supports custom pagers, [configured](/docs/Config.md) in the config.yml file (which can be opened by pressing 'o' in the Status panel).
Lazygit supports custom pagers, [configured](/docs/Config.md) in the config.yml file (which can be opened by pressing `o` in the Status panel).
Support does not extend to windows users, because we're making use of a package which doesn't have windows support.
Support does not extend to Windows users, because we're making use of a package which doesn't have Windows support.
## Default:
@@ -13,7 +13,7 @@ git:
useConfig: false
```
the `colorArg` key is for whether you want the `--color=always` arg in your `git diff` command. Some pagers want it set to always, others want it set to 'never'.
the `colorArg` key is for whether you want the `--color=always` arg in your `git diff` command. Some pagers want it set to `always`, others want it set to `never`.
## Delta:
@@ -61,4 +61,4 @@ git:
useConfig: true
```
If you set `useConfig: true`, lazygit will use whatever pager is specified in $GIT_PAGER, $PAGER, or your git config. If the pager ends with something like ' | less' we will strip that part out, because less doesn't play nice with our rendering approach. If the custom pager uses less under the hood, that will also break rendering (hence the `--paging=never` flag for the `delta` pager).
If you set `useConfig: true`, lazygit will use whatever pager is specified in `$GIT_PAGER`, `$PAGER`, or your *git config*. If the pager ends with something like ` | less` we will strip that part out, because less doesn't play nice with our rendering approach. If the custom pager uses less under the hood, that will also break rendering (hence the `--paging=never` flag for the `delta` pager).

View File

@@ -16,6 +16,8 @@
<kbd>+</kbd>: next screen mode (normal/half/fullscreen)
<kbd>_</kbd>: prev screen mode
<kbd>:</kbd>: execute custom command
<kbd>|</kbd>: view scoping options
<kbd>ctrl+e</kbd>: open diff menu
</pre>
## Branches Panel
@@ -40,6 +42,7 @@
<kbd>f</kbd>: fast-forward this branch from its upstream
<kbd>g</kbd>: view reset options
<kbd>R</kbd>: rename branch
<kbd>ctrl+o</kbd>: copy branch name to clipboard
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
@@ -53,6 +56,7 @@
<kbd>esc</kbd>: return to remotes list
<kbd>g</kbd>: view reset options
<kbd>space</kbd>: checkout
<kbd>n</kbd>: new branch
<kbd>M</kbd>: merge into currently checked out branch
<kbd>d</kbd>: delete branch
<kbd>r</kbd>: rebase checked-out branch onto this branch
@@ -100,6 +104,7 @@
<kbd>c</kbd>: checkout file
<kbd>d</kbd>: discard this commit's changes to this file
<kbd>o</kbd>: open file
<kbd>e</kbd>: edit file
<kbd>space</kbd>: toggle file included in patch
<kbd>enter</kbd>: enter file to add selected lines to the patch
<kbd>,</kbd>: previous page
@@ -134,11 +139,11 @@
<kbd>p</kbd>: pick commit (when mid-rebase)
<kbd>t</kbd>: revert commit
<kbd>c</kbd>: copy commit (cherry-pick)
<kbd>ctrl+o</kbd>: copy commit SHA to clipboard
<kbd>C</kbd>: copy commit range (cherry-pick)
<kbd>v</kbd>: paste commits (cherry-pick)
<kbd>enter</kbd>: view commit's files
<kbd>space</kbd>: checkout commit
<kbd>i</kbd>: select commit to diff with another commit
<kbd>T</kbd>: tag commit
<kbd>ctrl+r</kbd>: reset cherry-picked (copied) commits selection
<kbd>,</kbd>: previous page
@@ -246,7 +251,6 @@
<pre>
<kbd>esc</kbd>: close menu
<kbd>q</kbd>: close menu
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top

View File

@@ -1,31 +1,33 @@
# Lazygit Keybindings
# Lazygit Sneltoetsen
## Global
<pre>
<kbd>pgup</kbd>: scroll up main panel (fn+up)
<kbd>pgdown</kbd>: scroll down main panel (fn+down)
<kbd>pgup</kbd>: scroll omhoog naar hooft paneel (fn+up)
<kbd>pgdown</kbd>: scroll beneden naar hooft paneel (fn+down)
<kbd>m</kbd>: bekijk merge/rebase opties
<kbd>ctrl+p</kbd>: view custom patch options
<kbd>ctrl+p</kbd>: bekijk aangepaste patch opties
<kbd>P</kbd>: push
<kbd>p</kbd>: pull
<kbd>R</kbd>: verversen
<kbd>x</kbd>: open menu
<kbd>z</kbd>: undo (via reflog) (experimental)
<kbd>ctrl+z</kbd>: redo (via reflog) (experimental)
<kbd>+</kbd>: next screen mode (normal/half/fullscreen)
<kbd>_</kbd>: prev screen mode
<kbd>z</kbd>: ongedaan maken (via reflog) (experimenteel)
<kbd>ctrl+z</kbd>: redo (via reflog) (experimenteel)
<kbd>+</kbd>: volgende schermmode (normaal/half/groot )
<kbd>_</kbd>: vorige schermmode
<kbd>:</kbd>: voor aangepast commando uit
<kbd>|</kbd>: view scoping options
<kbd>ctrl+e</kbd>: open diff menu
</pre>
## Branches Panel
## Branches Paneel
<pre>
<kbd>]</kbd>: next tab
<kbd>[</kbd>: previous tab
<kbd>]</kbd>: volgende tab
<kbd>[</kbd>: vorige tab
</pre>
## Branches Panel (Branches Tab)
## Branches Paneel (Branches Tab)
<pre>
<kbd>space</kbd>: uitchecken
@@ -35,93 +37,96 @@
<kbd>n</kbd>: nieuwe branch
<kbd>d</kbd>: verwijder branch
<kbd>r</kbd>: rebase branch
<kbd>M</kbd>: merge in met huidige checked out branch
<kbd>i</kbd>: show git-flow options
<kbd>f</kbd>: fast-forward this branch from its upstream
<kbd>M</kbd>: merge in met huidige uitgecheckte branch
<kbd>i</kbd>: laat git-flow opties zien
<kbd>f</kbd>: fast-forward deze branch van zijn upstream
<kbd>g</kbd>: bekijk reset opties
<kbd>R</kbd>: rename branch
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>R</kbd>: hernoem branch
<kbd>ctrl+o</kbd>: copieer branch name clipboard
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Branches Panel (Remote Branches (in Remotes tab))
## Branches Paneel (Remote Branches (in Remotes tab))
<pre>
<kbd>esc</kbd>: return to remotes list
<kbd>esc</kbd>: ga terug naar remotes lijst
<kbd>g</kbd>: bekijk reset opties
<kbd>space</kbd>: uitchecken
<kbd>M</kbd>: merge in met huidige checked out branch
<kbd>n</kbd>: nieuwe branch
<kbd>M</kbd>: merge in met huidige uitgecheckte branch
<kbd>d</kbd>: verwijder branch
<kbd>r</kbd>: rebase branch
<kbd>u</kbd>: set as upstream of checked-out branch
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Branches Panel (Remotes Tab)
## Branches Paneel (Remotes Tab)
<pre>
<kbd>f</kbd>: fetch remote
<kbd>n</kbd>: add new remote
<kbd>d</kbd>: remove remote
<kbd>e</kbd>: edit remote
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>f</kbd>: remote ophalen
<kbd>n</kbd>: nieuwe remote toevoegen
<kbd>d</kbd>: verwijder remote
<kbd>e</kbd>: wijzig remote
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Branches Panel (Tags Tab)
## Branches Paneel (Tags Tab)
<pre>
<kbd>space</kbd>: uitchecken
<kbd>d</kbd>: delete tag
<kbd>d</kbd>: verwijdert tag
<kbd>P</kbd>: push tag
<kbd>n</kbd>: create tag
<kbd>n</kbd>: nieuwe tag
<kbd>g</kbd>: bekijk reset opties
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Commit bestanden Panel
## Commit bestanden Paneel
<pre>
<kbd>esc</kbd>: ga terug
<kbd>c</kbd>: bestand uitchecken
<kbd>d</kbd>: uitsluit deze commit zijn veranderingen aan dit bestand
<kbd>d</kbd>: uitsluit deze commit zijn wijzigingen aan dit bestand
<kbd>o</kbd>: open bestand
<kbd>space</kbd>: toggle file included in patch
<kbd>enter</kbd>: enter file to add selected lines to the patch
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>e</kbd>: verander bestand
<kbd>space</kbd>: wissel bestand opgenomen in patch
<kbd>enter</kbd>: open bestand om specifieke lijnen toe te voegen aan patch
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Commits Panel
## Commits Paneel
<pre>
<kbd>]</kbd>: next tab
<kbd>[</kbd>: previous tab
<kbd>]</kbd>: volgende tab
<kbd>[</kbd>: vorige tab
</pre>
## Commits Panel (Commits Tab)
## Commits Paneel (Commits Tab)
<pre>
<kbd>s</kbd>: squash beneden
<kbd>r</kbd>: hernoem commit
<kbd>R</kbd>: rename commit with editor
<kbd>R</kbd>: hernoem commit met editor
<kbd>g</kbd>: reset naar deze commit
<kbd>f</kbd>: Fixup commit
<kbd>F</kbd>: creëer fixup commit voor deze commit
@@ -130,64 +135,64 @@
<kbd>ctrl+j</kbd>: verplaats commit 1 omlaag
<kbd>ctrl+k</kbd>: verplaats commit 1 omhoog
<kbd>e</kbd>: verander commit
<kbd>A</kbd>: wijzig commit met staged veranderingen
<kbd>p</kbd>: pick commit (when mid-rebase)
<kbd>A</kbd>: wijzig commit met staged wijzigingen
<kbd>p</kbd>: pick commit (wanneer midden in rebase)
<kbd>t</kbd>: commit omgedaan maken
<kbd>c</kbd>: kopiëer commit (cherry-pick)
<kbd>ctrl+o</kbd>: kopiëer commit SHA naar clipboard
<kbd>C</kbd>: kopiëer commit reeks (cherry-pick)
<kbd>v</kbd>: plak commits (cherry-pick)
<kbd>enter</kbd>: bekijk gecommite bestanden
<kbd>space</kbd>: checkout commit
<kbd>i</kbd>: select commit to diff with another commit
<kbd>T</kbd>: tag commit
<kbd>ctrl+r</kbd>: reset cherry-picked (copied) commits selection
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>ctrl+r</kbd>: reset cherry-picked (gecopieerde) commits selectie
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Commits Panel (Reflog Tab)
## Commits Paneel (Reflog Tab)
<pre>
<kbd>space</kbd>: checkout commit
<kbd>g</kbd>: bekijk reset opties
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Bestanden Panel
## Bestanden Paneel
<pre>
<kbd>c</kbd>: Commit veranderingen
<kbd>w</kbd>: commit veranderingen zonder pre-commit hook
<kbd>c</kbd>: commit wijzigingen
<kbd>w</kbd>: commit wijzigingen zonder pre-commit hook
<kbd>A</kbd>: wijzig laatste commit
<kbd>C</kbd>: commit veranderingen met de git editor
<kbd>space</kbd>: toggle staged
<kbd>d</kbd>: bekijk 'veranderingen ongedaan maken' opties
<kbd>C</kbd>: commit wijzigingen met de git editor
<kbd>space</kbd>: wissel staged
<kbd>d</kbd>: bekijk 'wijzigingen ongedaan maken' opties
<kbd>e</kbd>: verander bestand
<kbd>o</kbd>: open bestand
<kbd>i</kbd>: voeg toe aan .gitignore
<kbd>r</kbd>: refresh bestanden
<kbd>r</kbd>: bestanden vernieuwen
<kbd>s</kbd>: stash-bestanden
<kbd>S</kbd>: view stash options
<kbd>a</kbd>: toggle staged alle
<kbd>S</kbd>: bekijk stash opties
<kbd>a</kbd>: wissel staged alle
<kbd>D</kbd>: bekijk reset opties
<kbd>enter</kbd>: stage individuele hunks/lijnen
<kbd>f</kbd>: fetch
<kbd>g</kbd>: view upstream reset options
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>g</kbd>: bekijk upstream reset optie
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Hoofd Panel (Merging)
## Hoofd Paneel (Merging)
<pre>
<kbd>esc</kbd>: ga terug naar het bestanden paneel
@@ -200,78 +205,77 @@
<kbd>z</kbd>: ongedaan maken
</pre>
## Hoofd Panel (Normaal)
## Hoofd Paneel (Normaal)
<pre>
<kbd> ̄</kbd>: scroll omlaag (fn+up)
<kbd>¦</kbd>: scroll omhoog (fn+down)
</pre>
## Hoofd Panel (Patch Building)
## Hoofd Paneel (Patch Building)
<pre>
<kbd>esc</kbd>: exit line-by-line mode
<kbd>esc</kbd>: sluit lijn-bij-lijn mode
<kbd>▲</kbd>: selecteer de vorige lijn
<kbd>▼</kbd>: selecteer de volgende lijn
<kbd>◄</kbd>: selecteer de vorige hunk
<kbd>►</kbd>: selecteer de volgende hunk
<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
<kbd>space</kbd>: voeg toe/verwijdert lijn(en) in patch
<kbd>v</kbd>: wissel drag selectie
<kbd>V</kbd>: wissel drag selectie
<kbd>a</kbd>: wissel selectie hunk
</pre>
## Hoofd Panel (Stage Lines/Hunks)
## Hoofd Paneel (Stage Lines/Hunks)
<pre>
<kbd>esc</kbd>: ga terug naar het bestanden paneel
<kbd>space</kbd>: toggle line staged / unstaged
<kbd>d</kbd>: delete change (git reset)
<kbd>tab</kbd>: switch to other panel
<kbd>space</kbd>: wissel lijn staged / unstaged
<kbd>d</kbd>: verwijdert wijziging (git reset)
<kbd>tab</kbd>: ga naar ander paneel
<kbd>▲</kbd>: selecteer de vorige lijn
<kbd>▼</kbd>: selecteer de volgende lijn
<kbd>◄</kbd>: selecteer de vorige hunk
<kbd>►</kbd>: selecteer de volgende hunk
<kbd>e</kbd>: verander bestand
<kbd>o</kbd>: open bestand
<kbd>v</kbd>: toggle drag select
<kbd>V</kbd>: toggle drag select
<kbd>a</kbd>: toggle select hunk
<kbd>c</kbd>: Commit veranderingen
<kbd>w</kbd>: commit veranderingen zonder pre-commit hook
<kbd>C</kbd>: commit veranderingen met de git editor
<kbd>v</kbd>: wissel drag selectie
<kbd>V</kbd>: wissel drag selectie
<kbd>a</kbd>: wissel selectie hunk
<kbd>c</kbd>: commit wijzigingen
<kbd>w</kbd>: commit wijzigingen zonder pre-commit hook
<kbd>C</kbd>: commit wijzigingen met de git editor
</pre>
## Menu Panel
## Menu Paneel
<pre>
<kbd>esc</kbd>: close menu
<kbd>q</kbd>: close menu
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd>esc</kbd>: sluit menu
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
</pre>
## Stash Panel
## Stash Paneel
<pre>
<kbd>space</kbd>: toepassen
<kbd>g</kbd>: pop
<kbd>d</kbd>: drop
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
<kbd>/</kbd>: start search
<kbd>></kbd>: scroll to bottom
<kbd>,</kbd>: vorige pagina
<kbd>.</kbd>: volgende pagina
<kbd><</kbd>: scroll naar bovenkant
<kbd>/</kbd>: start met zoekken
<kbd>></kbd>: scroll naar bodem
</pre>
## Status Panel
## Status Paneel
<pre>
<kbd>e</kbd>: verander config file
<kbd>o</kbd>: open config file
<kbd>o</kbd>: open config bestand
<kbd>u</kbd>: check voor updates
<kbd>enter</kbd>: wissel naar een recente repo
</pre>

View File

@@ -16,6 +16,8 @@
<kbd>+</kbd>: next screen mode (normal/half/fullscreen)
<kbd>_</kbd>: prev screen mode
<kbd>:</kbd>: execute custom command
<kbd>|</kbd>: view scoping options
<kbd>ctrl+e</kbd>: open diff menu
</pre>
## Gałęzie Panel
@@ -40,6 +42,7 @@
<kbd>f</kbd>: fast-forward this branch from its upstream
<kbd>g</kbd>: view reset options
<kbd>R</kbd>: rename branch
<kbd>ctrl+o</kbd>: copy branch name to clipboard
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top
@@ -53,6 +56,7 @@
<kbd>esc</kbd>: return to remotes list
<kbd>g</kbd>: view reset options
<kbd>space</kbd>: przełącz
<kbd>n</kbd>: nowa gałąź
<kbd>M</kbd>: scal do obecnej gałęzi
<kbd>d</kbd>: usuń gałąź
<kbd>r</kbd>: rebase branch
@@ -100,6 +104,7 @@
<kbd>c</kbd>: checkout file
<kbd>d</kbd>: discard this commit's changes to this file
<kbd>o</kbd>: otwórz plik
<kbd>e</kbd>: edytuj plik
<kbd>space</kbd>: toggle file included in patch
<kbd>enter</kbd>: enter file to add selected lines to the patch
<kbd>,</kbd>: previous page
@@ -134,11 +139,11 @@
<kbd>p</kbd>: pick commit (when mid-rebase)
<kbd>t</kbd>: revert commit
<kbd>c</kbd>: copy commit (cherry-pick)
<kbd>ctrl+o</kbd>: copy commit SHA to clipboard
<kbd>C</kbd>: copy commit range (cherry-pick)
<kbd>v</kbd>: paste commits (cherry-pick)
<kbd>enter</kbd>: view commit's files
<kbd>space</kbd>: checkout commit
<kbd>i</kbd>: select commit to diff with another commit
<kbd>T</kbd>: tag commit
<kbd>ctrl+r</kbd>: reset cherry-picked (copied) commits selection
<kbd>,</kbd>: previous page
@@ -246,7 +251,6 @@
<pre>
<kbd>esc</kbd>: close menu
<kbd>q</kbd>: close menu
<kbd>,</kbd>: previous page
<kbd>.</kbd>: next page
<kbd><</kbd>: scroll to top

8
go.mod
View File

@@ -7,19 +7,19 @@ require (
github.com/creack/pty v1.1.10-0.20191209115840-8ab47f72e854
github.com/fatih/color v1.7.0
github.com/fsnotify/fsnotify v1.4.7
github.com/go-errors/errors v1.0.1
github.com/go-errors/errors v1.0.2
github.com/go-git/go-git/v5 v5.0.0
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-cmp v0.3.1 // indirect
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/gocui v0.3.1-0.20200309001002-7765949e1c8a
github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9 // indirect
github.com/jesseduffield/gocui v0.3.1-0.20200513110002-8cde0b9be542
github.com/jesseduffield/termbox-go v0.0.0-20200405031649-4dc645f7e8ba // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.11 // indirect
github.com/mattn/go-runewidth v0.0.8
github.com/mattn/go-runewidth v0.0.9
github.com/mgutz/str v1.2.0
github.com/nicksnyder/go-i18n/v2 v2.0.3
github.com/onsi/ginkgo v1.10.3 // indirect

8
go.sum
View File

@@ -44,6 +44,8 @@ github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
@@ -88,8 +90,12 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jesseduffield/gocui v0.3.1-0.20200309001002-7765949e1c8a h1:JSORQue6V4bMppr22dtUuYX+w79cgupo66PcGZ9ijlU=
github.com/jesseduffield/gocui v0.3.1-0.20200309001002-7765949e1c8a/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw=
github.com/jesseduffield/gocui v0.3.1-0.20200513110002-8cde0b9be542 h1:ezzJM/NZh5vgdHWupW4K6lWsnmVADzLqFa2E3zB2bzA=
github.com/jesseduffield/gocui v0.3.1-0.20200513110002-8cde0b9be542/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw=
github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9 h1:iBBk1lhFwjwJw//J2m1yyz9S368GeXQTpMVACTyQMh0=
github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9/go.mod h1:anMibpZtqNxjDbxrcDEAwSdaJ37vyUeM1f/M4uekib4=
github.com/jesseduffield/termbox-go v0.0.0-20200405031649-4dc645f7e8ba h1:hWBdYchM9nZ2+GldroQQ627ISOC83iRDdpfwY+uyJeI=
github.com/jesseduffield/termbox-go v0.0.0-20200405031649-4dc645f7e8ba/go.mod h1:anMibpZtqNxjDbxrcDEAwSdaJ37vyUeM1f/M4uekib4=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@@ -121,6 +127,8 @@ github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGe
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/str v1.2.0 h1:4IzWSdIz9qPQWLfKZ0rJcV0jcUDpxvP4JVZ4GXQyvSw=
github.com/mgutz/str v1.2.0/go.mod h1:w1v0ofgLaJdoD0HpQ3fycxKD1WtxpjSo151pK/31q6w=

View File

@@ -131,9 +131,16 @@ func NewApp(config config.AppConfigurer, filterPath string) (*App, error) {
func (app *App) setupRepo() error {
// if we are not in a git repo, we ask if we want to `git init`
if err := app.OSCommand.RunCommand("git status"); err != nil {
if !strings.Contains(err.Error(), "Not a git repository") {
cwd, err := os.Getwd()
if err != nil {
return err
}
info, _ := os.Stat(filepath.Join(cwd, ".git"))
if info != nil && info.IsDir() {
return err // Current directory appears to be a git repository.
}
// Offer to initialize a new repository in current directory.
fmt.Print(app.Tr.SLocalize("CreateRepo"))
response, _ := bufio.NewReader(os.Stdin).ReadString('\n')
if strings.Trim(response, " \n") != "y" {

View File

@@ -52,7 +52,7 @@ func (b *BranchListBuilder) obtainBranches() []*Branch {
split := strings.Split(line, SEPARATION_CHAR)
name := split[1]
name := strings.TrimPrefix(split[1], "heads/")
branch := &Branch{
Name: name,
Pullables: "?",

View File

@@ -215,6 +215,9 @@ func (c *CommitListBuilder) getInteractiveRebasingCommits() ([]*Commit, error) {
if line == "" || line == "noop" {
return commits, nil
}
if strings.HasPrefix(line, "#") {
continue
}
splitLine := strings.Split(line, " ")
commits = append([]*Commit{{
Sha: splitLine[1],
@@ -224,7 +227,7 @@ func (c *CommitListBuilder) getInteractiveRebasingCommits() ([]*Commit, error) {
}}, commits...)
}
return nil, nil
return commits, nil
}
// assuming the file starts like this:

View File

@@ -19,6 +19,11 @@ func NewDummyOSCommand() *OSCommand {
// NewDummyAppConfig creates a new dummy AppConfig for testing
func NewDummyAppConfig() *config.AppConfig {
userConfig := viper.New()
userConfig.SetConfigType("yaml")
if err := config.LoadDefaults(userConfig, config.GetDefaultConfig()); err != nil {
panic(err)
}
appConfig := &config.AppConfig{
Name: "lazygit",
Version: "unversioned",
@@ -26,7 +31,7 @@ func NewDummyAppConfig() *config.AppConfig {
BuildDate: "",
Debug: false,
BuildSource: "",
UserConfig: viper.New(),
UserConfig: userConfig,
}
_ = yaml.Unmarshal([]byte{}, appConfig.AppState)
return appConfig

View File

@@ -1,5 +1,11 @@
package commands
import (
"strings"
"github.com/jesseduffield/lazygit/pkg/utils"
)
// File : A file from git status
// duplicating this for now
type File struct {
@@ -14,3 +20,19 @@ type File struct {
Type string // one of 'file', 'directory', and 'other'
ShortStatus string // e.g. 'AD', ' A', 'M ', '??'
}
const RENAME_SEPARATOR = " -> "
func (f *File) IsRename() bool {
return strings.Contains(f.Name, RENAME_SEPARATOR)
}
// Names returns an array containing just the filename, or in the case of a rename, the after filename and the before filename
func (f *File) Names() []string {
return strings.Split(f.Name, RENAME_SEPARATOR)
}
// returns true if the file names are the same or if a a file rename includes the filename of the other
func (f *File) Matches(f2 *File) bool {
return utils.StringArraysOverlap(f.Names(), f2.Names())
}

View File

@@ -85,6 +85,9 @@ type GitCommand struct {
DotGitDir string
onSuccessfulContinue func() error
PatchManager *PatchManager
// Push to current determines whether the user has configured to push to the remote branch of the same name as the current or not
PushToCurrent bool
}
// NewGitCommand it runs git commands
@@ -92,6 +95,15 @@ func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer,
var worktree *gogit.Worktree
var repo *gogit.Repository
// see what our default push behaviour is
output, err := osCommand.RunCommandWithOutput("git config --get push.default")
pushToCurrent := false
if err != nil {
log.Errorf("error reading git config: %v", err)
} else {
pushToCurrent = strings.TrimSpace(output) == "current"
}
fs := []func() error{
func() error {
return verifyInGitRepo(osCommand.RunCommand)
@@ -128,6 +140,7 @@ func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer,
getLocalGitConfig: gitconfig.Local,
removeFile: os.RemoveAll,
DotGitDir: dotGitDir,
PushToCurrent: pushToCurrent,
}
gitCommand.PatchManager = NewPatchManager(log, gitCommand.ApplyPatch)
@@ -218,8 +231,12 @@ func (c *GitCommand) ShowStashEntryCmdStr(index int) string {
}
// GetStatusFiles git status files
func (c *GitCommand) GetStatusFiles() []*File {
statusOutput, _ := c.GitStatus()
type GetStatusFileOptions struct {
NoRenames bool
}
func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*File {
statusOutput, _ := c.GitStatus(GitStatusOptions{NoRenames: opts.NoRenames})
statusStrings := utils.SplitLines(statusOutput)
files := []*File{}
@@ -262,7 +279,7 @@ func (c *GitCommand) StashSave(message string) error {
}
// MergeStatusFiles merge status files
func (c *GitCommand) MergeStatusFiles(oldFiles, newFiles []*File) []*File {
func (c *GitCommand) MergeStatusFiles(oldFiles, newFiles []*File, selectedFile *File) []*File {
if len(oldFiles) == 0 {
return newFiles
}
@@ -273,10 +290,15 @@ func (c *GitCommand) MergeStatusFiles(oldFiles, newFiles []*File) []*File {
result := []*File{}
for _, oldFile := range oldFiles {
for newIndex, newFile := range newFiles {
if oldFile.Name == newFile.Name {
if includesInt(appendedIndexes, newIndex) {
continue
}
// if we just staged B and in doing so created 'A -> B' and we are currently have oldFile: A and newFile: 'A -> B', we want to wait until we come across B so the our cursor isn't jumping anywhere
waitForMatchingFile := selectedFile != nil && newFile.IsRename() && !selectedFile.IsRename() && newFile.Matches(selectedFile) && !oldFile.Matches(selectedFile)
if oldFile.Matches(newFile) && !waitForMatchingFile {
result = append(result, newFile)
appendedIndexes = append(appendedIndexes, newIndex)
break
}
}
}
@@ -347,11 +369,26 @@ func (c *GitCommand) RebaseBranch(branchName string) error {
return c.OSCommand.RunPreparedCommand(cmd)
}
type FetchOptions struct {
PromptUserForCredential func(string) string
RemoteName string
BranchName string
}
// Fetch fetch git repo
func (c *GitCommand) Fetch(unamePassQuestion func(string) string, canAskForCredentials bool) error {
return c.OSCommand.DetectUnamePass("git fetch", func(question string) string {
if canAskForCredentials {
return unamePassQuestion(question)
func (c *GitCommand) Fetch(opts FetchOptions) error {
command := "git fetch"
if opts.RemoteName != "" {
command = fmt.Sprintf("%s %s", command, opts.RemoteName)
}
if opts.BranchName != "" {
command = fmt.Sprintf("%s %s", command, opts.BranchName)
}
return c.OSCommand.DetectUnamePass(command, func(question string) string {
if opts.PromptUserForCredential != nil {
return opts.PromptUserForCredential(question)
}
return "\n"
})
@@ -408,10 +445,20 @@ func (c *GitCommand) ListStash() (string, error) {
return c.OSCommand.RunCommandWithOutput("git stash list")
}
type MergeOpts struct {
FastForwardOnly bool
}
// Merge merge
func (c *GitCommand) Merge(branchName string) error {
func (c *GitCommand) Merge(branchName string, opts MergeOpts) error {
mergeArgs := c.Config.GetUserConfig().GetString("git.merging.args")
return c.OSCommand.RunCommand("git merge --no-edit %s %s", mergeArgs, branchName)
command := fmt.Sprintf("git merge --no-edit %s %s", mergeArgs, branchName)
if opts.FastForwardOnly {
command = fmt.Sprintf("%s --ff-only", command)
}
return c.OSCommand.RunCommand(command)
}
// AbortMerge abort merge
@@ -422,6 +469,11 @@ func (c *GitCommand) AbortMerge() error {
// usingGpg tells us whether the user has gpg enabled so that we can know
// whether we need to run a subprocess to allow them to enter their password
func (c *GitCommand) usingGpg() bool {
overrideGpg := c.Config.GetUserConfig().GetBool("git.overrideGpg")
if overrideGpg {
return false
}
gpgsign, _ := c.getLocalGitConfig("commit.gpgsign")
if gpgsign == "" {
gpgsign, _ = c.getGlobalGitConfig("commit.gpgsign")
@@ -433,36 +485,33 @@ func (c *GitCommand) usingGpg() bool {
// Commit commits to git
func (c *GitCommand) Commit(message string, flags string) (*exec.Cmd, error) {
command := fmt.Sprintf("git commit %s -m %s", flags, c.OSCommand.Quote(message))
command := fmt.Sprintf("git commit %s -m %s", flags, strconv.Quote(message))
if c.usingGpg() {
return c.OSCommand.PrepareSubProcess(c.OSCommand.Platform.shell, c.OSCommand.Platform.shellArg, command), nil
return c.OSCommand.ShellCommandFromString(command), nil
}
return nil, c.OSCommand.RunCommand(command)
}
// Get the subject of the HEAD commit
func (c *GitCommand) GetHeadCommitMessage() (string, error) {
cmdStr := "git log -1 --pretty=%s"
message, err := c.OSCommand.RunCommandWithOutput(cmdStr)
return strings.TrimSpace(message), err
}
// AmendHead amends HEAD with whatever is staged in your working tree
func (c *GitCommand) AmendHead() (*exec.Cmd, error) {
command := "git commit --amend --no-edit --allow-empty"
if c.usingGpg() {
return c.OSCommand.PrepareSubProcess(c.OSCommand.Platform.shell, c.OSCommand.Platform.shellArg, command), nil
return c.OSCommand.ShellCommandFromString(command), nil
}
return nil, c.OSCommand.RunCommand(command)
}
// Pull pulls from repo
func (c *GitCommand) Pull(args string, ask func(string) string) error {
return c.OSCommand.DetectUnamePass("git pull --no-edit "+args, ask)
}
// PullWithoutPasswordCheck assumes that the pull will not prompt the user for a password
func (c *GitCommand) PullWithoutPasswordCheck(args string) error {
return c.OSCommand.RunCommand("git pull --no-edit " + args)
}
// Push pushes to a branch
func (c *GitCommand) Push(branchName string, force bool, upstream string, args string, ask func(string) string) error {
func (c *GitCommand) Push(branchName string, force bool, upstream string, args string, promptUserForCredential func(string) string) error {
forceFlag := ""
if force {
forceFlag = "--force-with-lease"
@@ -474,17 +523,19 @@ func (c *GitCommand) Push(branchName string, force bool, upstream string, args s
}
cmd := fmt.Sprintf("git push --follow-tags %s %s %s", forceFlag, setUpstreamArg, args)
return c.OSCommand.DetectUnamePass(cmd, ask)
return c.OSCommand.DetectUnamePass(cmd, promptUserForCredential)
}
// CatFile obtains the content of a file
func (c *GitCommand) CatFile(fileName string) (string, error) {
return c.OSCommand.RunCommandWithOutput("cat %s", c.OSCommand.Quote(fileName))
return c.OSCommand.RunCommandWithOutput("%s %s", c.OSCommand.Platform.catCmd, c.OSCommand.Quote(fileName))
}
// StageFile stages a file
func (c *GitCommand) StageFile(fileName string) error {
return c.OSCommand.RunCommand("git add %s", c.OSCommand.Quote(fileName))
// renamed files look like "file1 -> file2"
fileNames := strings.Split(fileName, " -> ")
return c.OSCommand.RunCommand("git add %s", c.OSCommand.Quote(fileNames[len(fileNames)-1]))
}
// StageAll stages all files
@@ -515,8 +566,16 @@ func (c *GitCommand) UnStageFile(fileName string, tracked bool) error {
}
// GitStatus returns the plaintext short status of the repo
func (c *GitCommand) GitStatus() (string, error) {
return c.OSCommand.RunCommandWithOutput("git status --untracked-files=all --porcelain")
type GitStatusOptions struct {
NoRenames bool
}
func (c *GitCommand) GitStatus(opts GitStatusOptions) (string, error) {
noRenamesFlag := ""
if opts.NoRenames {
noRenamesFlag = "--no-renames"
}
return c.OSCommand.RunCommandWithOutput("git status --untracked-files=all --porcelain %s", noRenamesFlag)
}
// IsInMergeState states whether we are still mid-merge
@@ -542,8 +601,61 @@ func (c *GitCommand) RebaseMode() (string, error) {
}
}
func (c *GitCommand) BeforeAndAfterFileForRename(file *File) (*File, *File, error) {
if !file.IsRename() {
return nil, nil, errors.New("Expected renamed file")
}
// we've got a file that represents a rename from one file to another. Unfortunately
// our File abstraction fails to consider this case, so here we will refetch
// all files, passing the --no-renames flag and then recursively call the function
// again for the before file and after file. At some point we should fix the abstraction itself
split := strings.Split(file.Name, " -> ")
filesWithoutRenames := c.GetStatusFiles(GetStatusFileOptions{NoRenames: true})
var beforeFile *File
var afterFile *File
for _, f := range filesWithoutRenames {
if f.Name == split[0] {
beforeFile = f
}
if f.Name == split[1] {
afterFile = f
}
}
if beforeFile == nil || afterFile == nil {
return nil, nil, errors.New("Could not find deleted file or new file for file rename")
}
if beforeFile.IsRename() || afterFile.IsRename() {
// probably won't happen but we want to ensure we don't get an infinite loop
return nil, nil, errors.New("Nested rename found")
}
return beforeFile, afterFile, nil
}
// DiscardAllFileChanges directly
func (c *GitCommand) DiscardAllFileChanges(file *File) error {
if file.IsRename() {
beforeFile, afterFile, err := c.BeforeAndAfterFileForRename(file)
if err != nil {
return err
}
if err := c.DiscardAllFileChanges(beforeFile); err != nil {
return err
}
if err := c.DiscardAllFileChanges(afterFile); err != nil {
return err
}
return nil
}
// if the file isn't tracked, we assume you want to delete it
quotedFileName := c.OSCommand.Quote(file.Name)
if file.HasStagedChanges || file.HasMergeConflicts {
@@ -615,7 +727,11 @@ func (c *GitCommand) ShowCmdStr(sha string, filterPath string) string {
}
func (c *GitCommand) GetBranchGraphCmdStr(branchName string) string {
return fmt.Sprintf("git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium %s --", branchName)
branchLogCmdTemplate := c.Config.GetUserConfig().GetString("git.branchLogCmd")
templateValues := map[string]string{
"branchName": branchName,
}
return utils.ResolvePlaceholderString(branchLogCmdTemplate, templateValues)
}
// GetRemoteURL returns current repo remote url
@@ -675,8 +791,9 @@ func (c *GitCommand) ApplyPatch(patch string, flags ...string) error {
return c.OSCommand.RunCommand("git apply %s %s", flagStr, c.OSCommand.Quote(filepath))
}
func (c *GitCommand) FastForward(branchName string, remoteName string, remoteBranchName string) error {
return c.OSCommand.RunCommand("git fetch %s %s:%s", remoteName, remoteBranchName, branchName)
func (c *GitCommand) FastForward(branchName string, remoteName string, remoteBranchName string, promptUserForCredential func(string) string) error {
command := fmt.Sprintf("git fetch %s %s:%s", remoteName, remoteBranchName, branchName)
return c.OSCommand.DetectUnamePass(command, promptUserForCredential)
}
func (c *GitCommand) RunSkipEditorCommand(command string) error {
@@ -1064,7 +1181,7 @@ func (c *GitCommand) StashSaveStagedChanges(message string) error {
// if you had staged an untracked file, that will now appear as 'AD' in git status
// meaning it's deleted in your working tree but added in your index. Given that it's
// now safely stashed, we need to remove it.
files := c.GetStatusFiles()
files := c.GetStatusFiles(GetStatusFileOptions{})
for _, file := range files {
if file.ShortStatus == "AD" {
if err := c.UnStageFile(file.Name, false); err != nil {

View File

@@ -6,6 +6,7 @@ import (
"os"
"os/exec"
"regexp"
"runtime"
"testing"
"time"
@@ -419,7 +420,7 @@ func TestGitCommandGetStatusFiles(t *testing.T) {
gitCmd := NewDummyGitCommand()
gitCmd.OSCommand.command = s.command
s.test(gitCmd.GetStatusFiles())
s.test(gitCmd.GetStatusFiles(GetStatusFileOptions{}))
})
}
}
@@ -540,7 +541,7 @@ func TestGitCommandMergeStatusFiles(t *testing.T) {
t.Run(s.testName, func(t *testing.T) {
gitCmd := NewDummyGitCommand()
s.test(gitCmd.MergeStatusFiles(s.oldFiles, s.newFiles))
s.test(gitCmd.MergeStatusFiles(s.oldFiles, s.newFiles, nil))
})
}
}
@@ -702,7 +703,7 @@ func TestGitCommandMerge(t *testing.T) {
return exec.Command("echo")
}
assert.NoError(t, gitCmd.Merge("test"))
assert.NoError(t, gitCmd.Merge("test", MergeOpts{}))
}
// TestGitCommandUsingGpg is a function.
@@ -814,7 +815,7 @@ func TestGitCommandCommit(t *testing.T) {
"Commit using gpg",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "bash", cmd)
assert.EqualValues(t, []string{"-c", `git commit -m 'test'`}, args)
assert.EqualValues(t, []string{"-c", "git commit -m \"test\""}, args)
return exec.Command("echo")
},
@@ -1022,11 +1023,18 @@ func TestGitCommandPush(t *testing.T) {
}
}
// TestGitCommandCatFile is a function.
// TestGitCommandCatFile tests emitting a file using commands, where commands vary by OS.
func TestGitCommandCatFile(t *testing.T) {
var osCmd string
switch os := runtime.GOOS; os {
case "windows":
osCmd = "type"
default:
osCmd = "cat"
}
gitCmd := NewDummyGitCommand()
gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "cat", cmd)
assert.EqualValues(t, osCmd, cmd)
assert.EqualValues(t, []string{"test.txt"}, args)
return exec.Command("echo", "-n", "test")
@@ -1379,10 +1387,8 @@ func TestGitCommandGetBranchGraph(t *testing.T) {
gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"log", "--graph", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "test", "--"}, args)
return exec.Command("echo")
}
_, err := gitCmd.GetBranchGraph("test")
assert.NoError(t, err)
}
@@ -1402,7 +1408,7 @@ func TestGitCommandDiff(t *testing.T) {
"Default case",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"diff", "--color=", "--", "test.txt"}, args)
assert.EqualValues(t, []string{"diff", "--color=always", "--", "test.txt"}, args)
return exec.Command("echo")
},
@@ -1418,7 +1424,7 @@ func TestGitCommandDiff(t *testing.T) {
"cached",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"diff", "--color=", "--cached", "--", "test.txt"}, args)
assert.EqualValues(t, []string{"diff", "--color=always", "--cached", "--", "test.txt"}, args)
return exec.Command("echo")
},
@@ -1450,7 +1456,7 @@ func TestGitCommandDiff(t *testing.T) {
"File not tracked and file has no staged changes",
func(cmd string, args ...string) *exec.Cmd {
assert.EqualValues(t, "git", cmd)
assert.EqualValues(t, []string{"diff", "--color=", "--no-index", "/dev/null", "test.txt"}, args)
assert.EqualValues(t, []string{"diff", "--color=always", "--no-index", "/dev/null", "test.txt"}, args)
return exec.Command("echo")
},

View File

@@ -8,6 +8,7 @@ import (
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
@@ -23,6 +24,7 @@ import (
// Platform stores the os state
type Platform struct {
os string
catCmd string
shell string
shellArg string
escapedQuote string
@@ -117,28 +119,43 @@ func (c *OSCommand) ExecutableFromString(commandStr string) *exec.Cmd {
return cmd
}
// ShellCommandFromString takes a string like `git commit` and returns an executable shell command for it
func (c *OSCommand) ShellCommandFromString(commandStr string) *exec.Cmd {
quotedCommand := ""
// Windows does not seem to like quotes around the command
if c.Platform.os == "windows" {
quotedCommand = commandStr
} else {
quotedCommand = strconv.Quote(commandStr)
}
shellCommand := fmt.Sprintf("%s %s %s", c.Platform.shell, c.Platform.shellArg, quotedCommand)
return c.ExecutableFromString(shellCommand)
}
// RunCommandWithOutputLive runs RunCommandWithOutputLiveWrapper
func (c *OSCommand) RunCommandWithOutputLive(command string, output func(string) string) error {
return RunCommandWithOutputLiveWrapper(c, command, output)
}
// DetectUnamePass detect a username / password question in a command
// ask is a function that gets executen when this function detect you need to fillin a password
// The ask argument will be "username" or "password" and expects the user's password or username back
func (c *OSCommand) DetectUnamePass(command string, ask func(string) string) error {
// promptUserForCredential is a function that gets executed when this function detect you need to fillin a password
// The promptUserForCredential argument will be "username" or "password" and expects the user's password or username back
func (c *OSCommand) DetectUnamePass(command string, promptUserForCredential func(string) string) error {
ttyText := ""
errMessage := c.RunCommandWithOutputLive(command, func(word string) string {
ttyText = ttyText + " " + word
prompts := map[string]string{
"password": `Password\s*for\s*'.+':`,
"username": `Username\s*for\s*'.+':`,
`.+'s password:`: "password",
`Password\s*for\s*'.+':`: "password",
`Username\s*for\s*'.+':`: "username",
}
for askFor, pattern := range prompts {
for pattern, askFor := range prompts {
if match, _ := regexp.MatchString(pattern, ttyText); match {
ttyText = ""
return ask(askFor)
return promptUserForCredential(askFor)
}
}

View File

@@ -9,6 +9,7 @@ import (
func getPlatform() *Platform {
return &Platform{
os: runtime.GOOS,
catCmd: "cat",
shell: "bash",
shellArg: "-c",
escapedQuote: "'",

View File

@@ -3,6 +3,7 @@ package commands
func getPlatform() *Platform {
return &Platform{
os: "windows",
catCmd: "type",
shell: "cmd",
shellArg: "/c",
escapedQuote: `\"`,

View File

@@ -23,7 +23,7 @@ type PatchManager struct {
ApplyPatch applyPatchFunc
}
// NewPatchManager returns a new PatchModifier
// NewPatchManager returns a new PatchManager
func NewPatchManager(log *logrus.Entry, applyPatch applyPatchFunc) *PatchManager {
return &PatchManager{
Log: log,
@@ -31,7 +31,7 @@ func NewPatchManager(log *logrus.Entry, applyPatch applyPatchFunc) *PatchManager
}
}
// NewPatchManager returns a new PatchModifier
// NewPatchManager returns a new PatchManager
func (p *PatchManager) Start(commitSha string, diffMap map[string]string) {
p.CommitSha = commitSha
p.fileInfoMap = map[string]*fileInfo{}
@@ -101,8 +101,7 @@ func (p *PatchManager) RenderPlainPatchForFile(filename string, reverse bool, ke
return info.diff
case PART:
// generate a new diff with just the selected lines
m := NewPatchModifier(p.Log, filename, info.diff)
return m.ModifiedPatchForLines(info.includedLineIndices, reverse, keepOriginalHeader)
return ModifiedPatchForLines(p.Log, filename, info.diff, info.includedLineIndices, reverse, keepOriginalHeader)
default:
return ""
}

View File

@@ -258,3 +258,8 @@ func ModifiedPatchForRange(log *logrus.Entry, filename string, diffText string,
p := NewPatchModifier(log, filename, diffText)
return p.ModifiedPatchForRange(firstLineIdx, lastLineIdx, reverse, keepOriginalHeader)
}
func ModifiedPatchForLines(log *logrus.Entry, filename string, diffText string, includedLineIndices []int, reverse bool, keepOriginalHeader bool) string {
p := NewPatchModifier(log, filename, diffText)
return p.ModifiedPatchForLines(includedLineIndices, reverse, keepOriginalHeader)
}

View File

@@ -120,7 +120,7 @@ func coloredString(colorAttr color.Attribute, str string, selected bool, include
var cl *color.Color
attributes := []color.Attribute{colorAttr}
if selected {
attributes = append(attributes, theme.SelectedLineBgColor)
attributes = append(attributes, theme.SelectedRangeBgColor)
}
cl = color.New(attributes...)
var clIncluded *color.Color

View File

@@ -1,6 +1,9 @@
package commands
import "github.com/go-errors/errors"
import (
"fmt"
"github.com/go-errors/errors"
)
// DeletePatchesFromCommit applies a patch in reverse for a commit
func (c *GitCommand) DeletePatchesFromCommit(commits []*Commit, commitIndex int, p *PatchManager) error {
@@ -183,3 +186,43 @@ func (c *GitCommand) PullPatchIntoIndex(commits []*Commit, commitIdx int, p *Pat
return c.GenericMerge("rebase", "continue")
}
func (c *GitCommand) PullPatchIntoNewCommit(commits []*Commit, commitIdx int, p *PatchManager) error {
if err := c.BeginInteractiveRebaseForCommit(commits, commitIdx); err != nil {
return err
}
if err := p.ApplyPatches(true); err != nil {
if err := c.GenericMerge("rebase", "abort"); err != nil {
return err
}
return err
}
// amend the commit
if _, err := c.AmendHead(); err != nil {
return err
}
// add patches to index
if err := p.ApplyPatches(false); err != nil {
if err := c.GenericMerge("rebase", "abort"); err != nil {
return err
}
return err
}
head_message, _ := c.GetHeadCommitMessage()
new_message := fmt.Sprintf("Split from \"%s\"", head_message)
_, err := c.Commit(new_message, "")
if err != nil {
return err
}
if c.onSuccessfulContinue != nil {
return errors.New("You are midway through another rebase operation. Please abort to start again")
}
c.PatchManager.Reset()
return c.GenericMerge("rebase", "continue")
}

View File

@@ -256,6 +256,8 @@ func GetDefaultConfig() []byte {
optionsTextColor:
- blue
selectedLineBgColor:
- default
selectedRangeBgColor:
- blue
commitLength:
show: true
@@ -266,14 +268,19 @@ git:
merging:
manualCommit: false
args: ""
pull:
mode: 'merge' # one of 'merge' | 'rebase' | 'ff-only'
skipHookPrefix: 'WIP'
autoFetch: true
branchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --"
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
update:
method: prompt # can be: prompt | background | never
days: 14 # how often a update is checked for
reporting: 'undetermined' # one of: 'on' | 'off' | 'undetermined'
splashUpdatesIndex: 0
confirmOnQuit: false
quitOnTopLevelReturn: true
keybinding:
universal:
quit: 'q'

View File

@@ -6,5 +6,5 @@ func GetPlatformDefaultConfig() []byte {
`os:
openCommand: 'cmd /c "start "" {{filename}}"'
openLinkCommand: 'cmd /c "start "" {{link}}"'
copyToClipboardCommand: 'cmd \c "echo -n {{str}} > /dev/clipboard"`)
copyToClipboardCommand: 'cmd \c "echo -n {{str}} > /dev/clipboard"'`)
}

View File

@@ -129,8 +129,9 @@ func (gui *Gui) handleGitFetch(g *gocui.Gui, v *gocui.View) error {
return err
}
go func() {
unamePassOpend, err := gui.fetch(g, v, true)
gui.HandleCredentialsPopup(g, unamePassOpend, err)
err := gui.fetch(true)
gui.handleCredentialsPopup(err)
_ = gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}()
return nil
}
@@ -150,6 +151,7 @@ func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error {
type handleCheckoutRefOptions struct {
WaitingStatus string
EnvVars []string
onRefNotFound func(ref string) error
}
func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions) error {
@@ -171,6 +173,10 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions)
if err := gui.GitCommand.Checkout(ref, cmdOptions); err != nil {
// note, this will only work for english-language git commands. If we force git to use english, and the error isn't this one, then the user will receive an english command they may not understand. I'm not sure what the best solution to this is. Running the command once in english and a second time in the native language is one option
if options.onRefNotFound != nil && strings.Contains(err.Error(), "did not match any file(s) known to git") {
return options.onRefNotFound(ref)
}
if strings.Contains(err.Error(), "Please commit your changes or stash them before you switch branch") {
// offer to autostash changes
return gui.createConfirmationPanel(gui.g, gui.getBranchesView(), true, gui.Tr.SLocalize("AutoStashTitle"), gui.Tr.SLocalize("AutoStashPrompt"), func(g *gocui.Gui, v *gocui.View) error {
@@ -205,7 +211,13 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions)
func (gui *Gui) handleCheckoutByName(g *gocui.Gui, v *gocui.View) error {
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("BranchName")+":", "", func(g *gocui.Gui, v *gocui.View) error {
return gui.handleCheckoutRef(gui.trimmedContent(v), handleCheckoutRefOptions{})
return gui.handleCheckoutRef(gui.trimmedContent(v), handleCheckoutRefOptions{
onRefNotFound: func(ref string) error {
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("BranchNotFoundTitle"), fmt.Sprintf("%s %s%s", gui.Tr.SLocalize("BranchNotFoundPrompt"), ref, "?"), func(_g *gocui.Gui, _v *gocui.View) error {
return gui.createNewBranchWithName(ref)
}, nil)
},
})
})
}
@@ -229,14 +241,23 @@ func (gui *Gui) handleNewBranch(g *gocui.Gui, v *gocui.View) error {
},
)
return gui.createPromptPanel(g, v, message, "", func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.NewBranch(gui.trimmedContent(v), branch.Name); err != nil {
return gui.surfaceError(err)
}
gui.State.Panels.Branches.SelectedLine = 0
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
return gui.createNewBranchWithName(gui.trimmedContent(v))
})
}
func (gui *Gui) createNewBranchWithName(newBranchName string) error {
branch := gui.getSelectedBranch()
if branch == nil {
return nil
}
if err := gui.GitCommand.NewBranch(newBranchName, branch.Name); err != nil {
return gui.surfaceError(err)
}
gui.State.Panels.Branches.SelectedLine = 0
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}
func (gui *Gui) handleDeleteBranch(g *gocui.Gui, v *gocui.View) error {
return gui.deleteBranch(g, v, false)
}
@@ -301,7 +322,7 @@ func (gui *Gui) mergeBranchIntoCheckedOutBranch(branchName string) error {
return gui.createConfirmationPanel(gui.g, gui.getBranchesView(), true, gui.Tr.SLocalize("MergingTitle"), prompt,
func(g *gocui.Gui, v *gocui.View) error {
err := gui.GitCommand.Merge(branchName)
err := gui.GitCommand.Merge(branchName, commands.MergeOpts{})
return gui.handleGenericMergeCommandResult(err)
}, nil)
}
@@ -378,20 +399,12 @@ func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error {
_ = gui.createLoaderPanel(gui.g, v, message)
if gui.State.Panels.Branches.SelectedLine == 0 {
if err := gui.GitCommand.PullWithoutPasswordCheck("--ff-only"); err != nil {
_ = gui.surfaceError(err)
return
}
_ = gui.refreshSidePanels(refreshOptions{mode: ASYNC})
_ = gui.pullWithMode("ff-only", PullFilesOptions{})
} else {
if err := gui.GitCommand.FastForward(branch.Name, remoteName, remoteBranchName); err != nil {
_ = gui.surfaceError(err)
return
}
err := gui.GitCommand.FastForward(branch.Name, remoteName, remoteBranchName, gui.promptUserForCredential)
gui.handleCredentialsPopup(err)
_ = gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []int{BRANCHES}})
}
_ = gui.closeConfirmationPrompt(gui.g, true)
}()
return nil
}

View File

@@ -121,9 +121,22 @@ func (gui *Gui) refreshCommitFilesView() error {
func (gui *Gui) handleOpenOldCommitFile(g *gocui.Gui, v *gocui.View) error {
file := gui.getSelectedCommitFile()
if file == nil {
return nil
}
return gui.openFile(file.Name)
}
func (gui *Gui) handleEditCommitFile(g *gocui.Gui, v *gocui.View) error {
file := gui.getSelectedCommitFile()
if file == nil {
return nil
}
return gui.editFile(file.Name)
}
func (gui *Gui) handleToggleFileForPatch(g *gocui.Gui, v *gocui.View) error {
if ok, err := gui.validateNormalWorkingTreeState(); !ok {
return err

View File

@@ -62,10 +62,11 @@ func (gui *Gui) handleCommitFocused(g *gocui.Gui, v *gocui.View) error {
}
message := gui.Tr.TemplateLocalize(
"CloseConfirm",
"CommitMessageConfirm",
Teml{
"keyBindClose": "esc",
"keyBindConfirm": "enter",
"keyBindNewLine": "tab",
},
)
gui.renderString(g, "options", message)

View File

@@ -8,10 +8,10 @@ import (
type credentials chan string
// waitForPassUname wait for a username or password input from the credentials popup
func (gui *Gui) waitForPassUname(g *gocui.Gui, currentView *gocui.View, passOrUname string) string {
// promptUserForCredential wait for a username or password input from the credentials popup
func (gui *Gui) promptUserForCredential(passOrUname string) string {
gui.credentials = make(chan string)
g.Update(func(g *gocui.Gui) error {
gui.g.Update(func(g *gocui.Gui) error {
credentialsView, _ := g.View("credentials")
if passOrUname == "username" {
credentialsView.Title = gui.Tr.SLocalize("CredentialsUsername")
@@ -20,7 +20,7 @@ func (gui *Gui) waitForPassUname(g *gocui.Gui, currentView *gocui.View, passOrUn
credentialsView.Title = gui.Tr.SLocalize("CredentialsPassword")
credentialsView.Mask = '*'
}
err := gui.switchFocus(g, currentView, credentialsView)
err := gui.switchFocus(g, gui.g.CurrentView(), credentialsView)
if err != nil {
return err
}
@@ -76,11 +76,9 @@ func (gui *Gui) handleCredentialsViewFocused(g *gocui.Gui, v *gocui.View) error
return nil
}
// HandleCredentialsPopup handles the views after executing a command that might ask for credentials
func (gui *Gui) HandleCredentialsPopup(g *gocui.Gui, popupOpened bool, cmdErr error) {
if popupOpened {
_, _ = gui.g.SetViewOnBottom("credentials")
}
// handleCredentialsPopup handles the views after executing a command that might ask for credentials
func (gui *Gui) handleCredentialsPopup(cmdErr error) {
_, _ = gui.g.SetViewOnBottom("credentials")
if cmdErr != nil {
errMessage := cmdErr.Error()
if strings.Contains(errMessage, "Invalid username or password") {
@@ -89,7 +87,6 @@ func (gui *Gui) HandleCredentialsPopup(g *gocui.Gui, popupOpened bool, cmdErr er
// we are not logging this error because it may contain a password
_ = gui.createSpecificErrorPanel(errMessage, gui.getFilesView(), false)
} else {
_ = gui.closeConfirmationPrompt(g, true)
_ = gui.refreshSidePanels(refreshOptions{mode: ASYNC})
_ = gui.closeConfirmationPrompt(gui.g, true)
}
}

View File

@@ -284,9 +284,12 @@ func (gui *Gui) handleWIPCommitPress(g *gocui.Gui, filesView *gocui.View) error
}
func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.stagedFiles()) == 0 && gui.GitCommand.WorkingTreeState() == "normal" {
return gui.createErrorPanel(gui.Tr.SLocalize("NoStagedFilesToCommit"))
if len(gui.stagedFiles()) == 0 {
return gui.promptToStageAllAndRetry(func() error {
return gui.handleCommitPress(gui.g, filesView)
})
}
commitMessageView := gui.getCommitMessageView()
prefixPattern := gui.Config.GetUserConfig().GetString("git.commitPrefixes." + utils.GetCurrentRepoName() + ".pattern")
prefixReplace := gui.Config.GetUserConfig().GetString("git.commitPrefixes." + utils.GetCurrentRepoName() + ".replace")
@@ -317,10 +320,28 @@ func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
return nil
}
func (gui *Gui) promptToStageAllAndRetry(retry func() error) error {
return gui.createConfirmationPanel(
gui.g, gui.getFilesView(), true, gui.Tr.SLocalize("NoFilesStagedTitle"), gui.Tr.SLocalize("NoFilesStagedPrompt"),
func(*gocui.Gui, *gocui.View) error {
if err := gui.GitCommand.StageAll(); err != nil {
return gui.surfaceError(err)
}
if err := gui.refreshFiles(); err != nil {
return gui.surfaceError(err)
}
return retry()
}, nil)
}
func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.stagedFiles()) == 0 && gui.GitCommand.WorkingTreeState() == "normal" {
return gui.createErrorPanel(gui.Tr.SLocalize("NoStagedFilesToCommit"))
if len(gui.stagedFiles()) == 0 {
return gui.promptToStageAllAndRetry(func() error {
return gui.handleAmendCommitPress(gui.g, filesView)
})
}
if len(gui.State.Commits) == 0 {
return gui.createErrorPanel(gui.Tr.SLocalize("NoCommitToAmend"))
}
@@ -344,9 +365,12 @@ func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) erro
// handleCommitEditorPress - handle when the user wants to commit changes via
// their editor rather than via the popup panel
func (gui *Gui) handleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.stagedFiles()) == 0 && gui.GitCommand.WorkingTreeState() == "normal" {
return gui.createErrorPanel(gui.Tr.SLocalize("NoStagedFilesToCommit"))
if len(gui.stagedFiles()) == 0 {
return gui.promptToStageAllAndRetry(func() error {
return gui.handleCommitEditorPress(gui.g, filesView)
})
}
gui.PrepareSubProcess(g, "git", "commit")
return nil
}
@@ -386,37 +410,31 @@ func (gui *Gui) handleRefreshFiles(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) refreshStateFiles() error {
// keep track of where the cursor is currently and the current file names
// when we refresh, go looking for a matching name
// move the cursor to there.
selectedFile, _ := gui.getSelectedFile()
// get files to stage
files := gui.GitCommand.GetStatusFiles()
gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.Files, files)
files := gui.GitCommand.GetStatusFiles(commands.GetStatusFileOptions{})
gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.Files, files, selectedFile)
if err := gui.fileWatcher.addFilesToFileWatcher(files); err != nil {
return err
}
// let's try to find our file again and move the cursor to that
for idx, f := range gui.State.Files {
if selectedFile != nil && f.Matches(selectedFile) {
gui.State.Panels.Files.SelectedLine = idx
break
}
}
gui.refreshSelectedLine(&gui.State.Panels.Files.SelectedLine, len(gui.State.Files))
return nil
}
func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) {
item, err := gui.getSelectedFile()
if err != nil {
if err != gui.Errors.ErrNoFiles {
return "", err
}
return "", gui.newStringTask("main", gui.Tr.SLocalize("NoFilesDisplay"))
}
if item.Type != "file" {
return "", gui.newStringTask("main", gui.Tr.SLocalize("NotAFile"))
}
cat, err := gui.GitCommand.CatFile(item.Name)
if err != nil {
gui.Log.Error(err)
return "", gui.newStringTask("main", err.Error())
}
return cat, nil
}
func (gui *Gui) handlePullFiles(g *gocui.Gui, v *gocui.View) error {
// if we have no upstream branch we need to set that first
currentBranch := gui.currentBranch()
@@ -428,7 +446,7 @@ func (gui *Gui) handlePullFiles(g *gocui.Gui, v *gocui.View) error {
}
for branchName, branch := range conf.Branches {
if branchName == currentBranch.Name {
return gui.pullFiles(v, fmt.Sprintf("%s %s", branch.Remote, branchName))
return gui.pullFiles(PullFilesOptions{RemoteName: branch.Remote, BranchName: branch.Name})
}
}
@@ -441,42 +459,67 @@ func (gui *Gui) handlePullFiles(g *gocui.Gui, v *gocui.View) error {
}
return gui.createErrorPanel(errorMessage)
}
return gui.pullFiles(v, "")
return gui.pullFiles(PullFilesOptions{})
})
}
return gui.pullFiles(v, "")
return gui.pullFiles(PullFilesOptions{})
}
func (gui *Gui) pullFiles(v *gocui.View, args string) error {
if err := gui.createLoaderPanel(gui.g, v, gui.Tr.SLocalize("PullWait")); err != nil {
type PullFilesOptions struct {
RemoteName string
BranchName string
}
func (gui *Gui) pullFiles(opts PullFilesOptions) error {
if err := gui.createLoaderPanel(gui.g, gui.g.CurrentView(), gui.Tr.SLocalize("PullWait")); err != nil {
return err
}
go func() {
unamePassOpend := false
err := gui.GitCommand.Pull(args, func(passOrUname string) string {
unamePassOpend = true
return gui.waitForPassUname(gui.g, v, passOrUname)
})
gui.HandleCredentialsPopup(gui.g, unamePassOpend, err)
}()
mode := gui.Config.GetUserConfig().GetString("git.pull.mode")
go gui.pullWithMode(mode, opts)
return nil
}
func (gui *Gui) pullWithMode(mode string, opts PullFilesOptions) error {
err := gui.GitCommand.Fetch(
commands.FetchOptions{
PromptUserForCredential: gui.promptUserForCredential,
RemoteName: opts.RemoteName,
BranchName: opts.BranchName,
},
)
gui.handleCredentialsPopup(err)
if err != nil {
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}
switch mode {
case "rebase":
err := gui.GitCommand.RebaseBranch("FETCH_HEAD")
return gui.handleGenericMergeCommandResult(err)
case "merge":
err := gui.GitCommand.Merge("FETCH_HEAD", commands.MergeOpts{})
return gui.handleGenericMergeCommandResult(err)
case "ff-only":
err := gui.GitCommand.Merge("FETCH_HEAD", commands.MergeOpts{FastForwardOnly: true})
return gui.handleGenericMergeCommandResult(err)
default:
return gui.createErrorPanel(fmt.Sprintf("git pull mode '%s' unrecognised", mode))
}
}
func (gui *Gui) pushWithForceFlag(g *gocui.Gui, v *gocui.View, force bool, upstream string, args string) error {
if err := gui.createLoaderPanel(gui.g, v, gui.Tr.SLocalize("PushWait")); err != nil {
return err
}
go func() {
unamePassOpend := false
branchName := gui.getCheckedOutBranch().Name
err := gui.GitCommand.Push(branchName, force, upstream, args, func(passOrUname string) string {
unamePassOpend = true
return gui.waitForPassUname(g, v, passOrUname)
})
gui.HandleCredentialsPopup(g, unamePassOpend, err)
err := gui.GitCommand.Push(branchName, force, upstream, args, gui.promptUserForCredential)
gui.handleCredentialsPopup(err)
_ = gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}()
return nil
}
@@ -497,9 +540,13 @@ func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error {
}
}
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("EnterUpstream"), "origin "+currentBranch.Name, func(g *gocui.Gui, v *gocui.View) error {
return gui.pushWithForceFlag(g, v, false, gui.trimmedContent(v), "")
})
if gui.GitCommand.PushToCurrent {
return gui.pushWithForceFlag(g, v, false, "", "--set-upstream")
} else {
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("EnterUpstream"), "origin "+currentBranch.Name, func(g *gocui.Gui, v *gocui.View) error {
return gui.pushWithForceFlag(g, v, false, gui.trimmedContent(v), "")
})
}
} else if currentBranch.Pullables == "0" {
return gui.pushWithForceFlag(g, v, false, "", "")
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
@@ -65,10 +66,18 @@ func (gui *Gui) scrollDownView(viewName string) error {
}
func (gui *Gui) scrollUpMain(g *gocui.Gui, v *gocui.View) error {
if gui.canScrollMergePanel() {
gui.State.Panels.Merging.UserScrolling = true
}
return gui.scrollUpView("main")
}
func (gui *Gui) scrollDownMain(g *gocui.Gui, v *gocui.View) error {
if gui.canScrollMergePanel() {
gui.State.Panels.Merging.UserScrolling = true
}
return gui.scrollDownView("main")
}
@@ -158,23 +167,24 @@ func (gui *Gui) handleInfoClick(g *gocui.Gui, v *gocui.View) error {
return nil
}
func (gui *Gui) fetch(g *gocui.Gui, v *gocui.View, canAskForCredentials bool) (unamePassOpend bool, err error) {
unamePassOpend = false
err = gui.GitCommand.Fetch(func(passOrUname string) string {
unamePassOpend = true
return gui.waitForPassUname(gui.g, v, passOrUname)
}, canAskForCredentials)
func (gui *Gui) fetch(canPromptForCredentials bool) (err error) {
fetchOpts := commands.FetchOptions{}
if canPromptForCredentials {
fetchOpts.PromptUserForCredential = gui.promptUserForCredential
}
if canAskForCredentials && err != nil && strings.Contains(err.Error(), "exit status 128") {
err = gui.GitCommand.Fetch(fetchOpts)
if canPromptForCredentials && err != nil && strings.Contains(err.Error(), "exit status 128") {
colorFunction := color.New(color.FgRed).SprintFunc()
coloredMessage := colorFunction(strings.TrimSpace(gui.Tr.SLocalize("PassUnameWrong")))
close := func(g *gocui.Gui, v *gocui.View) error {
return nil
}
_ = gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("Error"), coloredMessage, close, close)
_ = gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("Error"), coloredMessage, close, close)
}
gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, COMMITS, REMOTES, TAGS}, mode: ASYNC})
return unamePassOpend, err
return err
}

View File

@@ -112,6 +112,10 @@ type mergingPanelState struct {
ConflictTop bool
Conflicts []commands.Conflict
EditHistory *stack.Stack
// UserScrolling tells us if the user has started scrolling through the file themselves
// in which case we won't auto-scroll to a conflict.
UserScrolling bool
}
type filePanelState struct {
@@ -497,12 +501,12 @@ func (gui *Gui) startBackgroundFetch() {
if !isNew {
time.After(60 * time.Second)
}
_, err := gui.fetch(gui.g, gui.g.CurrentView(), false)
err := gui.fetch(false)
if err != nil && strings.Contains(err.Error(), "exit status 128") && isNew {
_ = gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("NoAutomaticGitFetchTitle"), gui.Tr.SLocalize("NoAutomaticGitFetchBody"), nil, nil)
} else {
gui.goEvery(time.Second*60, gui.stopChan, func() error {
_, err := gui.fetch(gui.g, gui.g.CurrentView(), false)
err := gui.fetch(false)
return err
})
}

View File

@@ -4,6 +4,8 @@ import (
"log"
"strings"
"unicode/utf8"
"github.com/jesseduffield/gocui"
)
@@ -178,14 +180,15 @@ func GetKeyDisplay(key interface{}) string {
func (gui *Gui) getKey(name string) interface{} {
key := gui.Config.GetUserConfig().GetString("keybinding." + name)
if len(key) > 1 {
runeCount := utf8.RuneCountInString(key)
if runeCount > 1 {
binding := keymap[strings.ToLower(key)]
if binding == nil {
log.Fatalf("Unrecognized key %s for keybinding %s", strings.ToLower(key), name)
} else {
return binding
}
} else if len(key) == 1 {
} else if runeCount == 1 {
return []rune(key)[0]
}
log.Fatal("Key empty for keybinding: " + strings.ToLower(name))
@@ -217,7 +220,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "",
Key: gui.getKey("universal.return"),
Modifier: gocui.ModNone,
Handler: gui.handleQuit,
Handler: gui.handleTopLevelReturn,
},
{
ViewName: "",
@@ -848,12 +851,6 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleMenuClose,
Description: gui.Tr.SLocalize("closeMenu"),
},
{
ViewName: "menu",
Key: gui.getKey("universal.quit"),
Handler: gui.handleMenuClose,
Description: gui.Tr.SLocalize("closeMenu"),
},
{
ViewName: "information",
Key: gocui.MouseLeft,
@@ -884,6 +881,12 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleOpenOldCommitFile,
Description: gui.Tr.SLocalize("openFile"),
},
{
ViewName: "commitFiles",
Key: gui.getKey("universal.edit"),
Handler: gui.handleEditCommitFile,
Description: gui.Tr.SLocalize("editFile"),
},
{
ViewName: "commitFiles",
Key: gui.getKey("universal.select"),
@@ -1287,6 +1290,14 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleCheckoutRemoteBranch,
Description: gui.Tr.SLocalize("checkout"),
},
{
ViewName: "branches",
Contexts: []string{"remote-branches"},
Key: gui.getKey("universal.new"),
Handler: gui.handleNewBranchOffRemote,
Description: gui.Tr.SLocalize("newBranch"),
},
{
ViewName: "branches",
Contexts: []string{"remote-branches"},

View File

@@ -311,14 +311,15 @@ func (gui *Gui) layout(g *gocui.Gui) error {
branchesView.ContainsList = true
}
if v, err := g.SetViewBeneath("commitFiles", "branches", vHeights["commits"]); err != nil {
commitFilesView, err := g.SetViewBeneath("commitFiles", "branches", vHeights["commits"])
if err != nil {
if err.Error() != "unknown view" {
return err
}
v.Title = gui.Tr.SLocalize("CommitFiles")
v.FgColor = textColor
v.SetOnSelectItem(gui.onSelectItemWrapper(gui.onCommitFilesPanelSearchSelect))
v.ContainsList = true
commitFilesView.Title = gui.Tr.SLocalize("CommitFiles")
commitFilesView.FgColor = textColor
commitFilesView.SetOnSelectItem(gui.onSelectItemWrapper(gui.onCommitFilesPanelSearchSelect))
commitFilesView.ContainsList = true
}
commitsView, err := g.SetViewBeneath("commits", "branches", vHeights["commits"])
@@ -397,7 +398,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
searchPrefixView.BgColor = gocui.ColorDefault
searchPrefixView.FgColor = gocui.ColorGreen
searchPrefixView.Frame = false
gui.setViewContent(gui.g, searchPrefixView, searchPrefix)
gui.setViewContent(searchPrefixView, searchPrefix)
}
if searchView, err := g.SetView("search", appStatusOptionsBoundary-1+searchViewOffset+len(searchPrefix), height-2+searchViewOffset, optionsVersionBoundary+searchViewOffset, height+searchViewOffset, 0); err != nil {
@@ -439,7 +440,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
}
}
if gui.State.OldInformation != information {
gui.setViewContent(g, informationView, information)
gui.setViewContent(informationView, information)
gui.State.OldInformation = information
}
@@ -472,6 +473,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
{view: commitsView, context: "branch-commits", selectedLine: gui.State.Panels.Commits.SelectedLine, lineCount: len(gui.State.Commits)},
{view: commitsView, context: "reflog-commits", selectedLine: gui.State.Panels.ReflogCommits.SelectedLine, lineCount: len(gui.State.FilteredReflogCommits)},
{view: stashView, context: "", selectedLine: gui.State.Panels.Stash.SelectedLine, lineCount: len(gui.State.StashEntries)},
{view: commitFilesView, context: "", selectedLine: gui.State.Panels.CommitFiles.SelectedLine, lineCount: len(gui.State.CommitFiles)},
}
// menu view might not exist so we check to be safe
@@ -485,6 +487,8 @@ func (gui *Gui) layout(g *gocui.Gui) error {
}
// check if the selected line is now out of view and if so refocus it
listView.view.FocusPoint(0, listView.selectedLine)
listView.view.SelBgColor = theme.GocuiSelectedLineBgColor
}
mainViewWidth, mainViewHeight := gui.getMainView().Size()

View File

@@ -88,7 +88,7 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
}
gui.g.Update(func(*gocui.Gui) error {
gui.setViewContent(gui.g, gui.getSecondaryView(), secondaryPatchParser.Render(-1, -1, nil))
gui.setViewContent(gui.getSecondaryView(), secondaryPatchParser.Render(-1, -1, nil))
return nil
})
@@ -242,7 +242,7 @@ func (gui *Gui) refreshMainView() error {
mainView.Wrap = false
gui.g.Update(func(*gocui.Gui) error {
gui.setViewContent(gui.g, gui.getMainView(), colorDiff)
gui.setViewContent(gui.getMainView(), colorDiff)
return nil
})

View File

@@ -25,7 +25,7 @@ func (gui *Gui) handleMenuSelect(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) renderMenuOptions() error {
optionsMap := map[string]string{
fmt.Sprintf("%s/%s", gui.getKeyDisplay("universal.return"), gui.getKeyDisplay("universal.quit")): gui.Tr.SLocalize("close"),
gui.getKeyDisplay("universal.return"): gui.Tr.SLocalize("close"),
fmt.Sprintf("%s %s", gui.getKeyDisplay("universal.prevItem"), gui.getKeyDisplay("universal.nextItem")): gui.Tr.SLocalize("navigate"),
gui.getKeyDisplay("universal.select"): gui.Tr.SLocalize("execute"),
}
@@ -79,6 +79,11 @@ func (gui *Gui) createMenu(title string, items []*menuItem, createMenuOptions cr
menuView.FgColor = theme.GocuiDefaultTextColor
menuView.ContainsList = true
menuView.Clear()
menuView.SetOnSelectItem(gui.onSelectItemWrapper(func(selectedLine int) error {
gui.State.Panels.Menu.SelectedLine = selectedLine
menuView.FocusPoint(0, selectedLine)
return nil
}))
fmt.Fprint(menuView, list)
gui.State.Panels.Menu.SelectedLine = 0

View File

@@ -59,6 +59,7 @@ func (gui *Gui) coloredConflictFile(content string, conflicts []commands.Conflic
colour := color.New(colourAttr)
if hasFocus && conflictIndex < len(conflicts) && conflicts[conflictIndex] == conflict && gui.shouldHighlightLine(i, conflict, conflictTop) {
colour.Add(color.Bold)
colour.Add(theme.SelectedRangeBgColor)
}
if i == conflict.End && len(remainingConflicts) > 0 {
conflict, remainingConflicts = gui.shiftConflict(remainingConflicts)
@@ -68,17 +69,24 @@ func (gui *Gui) coloredConflictFile(content string, conflicts []commands.Conflic
return outputBuffer.String(), nil
}
func (gui *Gui) takeOverScrolling() {
gui.State.Panels.Merging.UserScrolling = false
}
func (gui *Gui) handleSelectTop(g *gocui.Gui, v *gocui.View) error {
gui.takeOverScrolling()
gui.State.Panels.Merging.ConflictTop = true
return gui.refreshMergePanel()
}
func (gui *Gui) handleSelectBottom(g *gocui.Gui, v *gocui.View) error {
gui.takeOverScrolling()
gui.State.Panels.Merging.ConflictTop = false
return gui.refreshMergePanel()
}
func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error {
gui.takeOverScrolling()
if gui.State.Panels.Merging.ConflictIndex >= len(gui.State.Panels.Merging.Conflicts)-1 {
return nil
}
@@ -87,6 +95,7 @@ func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error {
gui.takeOverScrolling()
if gui.State.Panels.Merging.ConflictIndex <= 0 {
return nil
}
@@ -159,6 +168,8 @@ func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error {
gui.takeOverScrolling()
conflict := gui.State.Panels.Merging.Conflicts[gui.State.Panels.Merging.ConflictIndex]
if err := gui.pushFileSnapshot(g); err != nil {
return err
@@ -183,6 +194,8 @@ func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error {
gui.takeOverScrolling()
conflict := gui.State.Panels.Merging.Conflicts[gui.State.Panels.Merging.ConflictIndex]
if err := gui.pushFileSnapshot(g); err != nil {
return err
@@ -221,20 +234,44 @@ func (gui *Gui) refreshMergePanel() error {
return err
}
mainView := gui.getMainView()
mainView.Wrap = false
if err := gui.newStringTask("main", content); err != nil {
if err := gui.scrollToConflict(gui.g); err != nil {
return err
}
if err := gui.scrollToConflict(gui.g); err != nil {
mainView := gui.getMainView()
mainView.Wrap = false
if err := gui.newStringTaskWithoutScroll("main", content); err != nil {
return err
}
return nil
}
func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) {
item, err := gui.getSelectedFile()
if err != nil {
if err != gui.Errors.ErrNoFiles {
return "", err
}
return "", gui.newStringTask("main", gui.Tr.SLocalize("NoFilesDisplay"))
}
if item.Type != "file" {
return "", gui.newStringTask("main", gui.Tr.SLocalize("NotAFile"))
}
cat, err := gui.GitCommand.CatFile(item.Name)
if err != nil {
gui.Log.Error(err)
return "", gui.newStringTask("main", err.Error())
}
return cat, nil
}
func (gui *Gui) scrollToConflict(g *gocui.Gui) error {
if gui.State.Panels.Merging.UserScrolling {
return nil
}
panelState := gui.State.Panels.Merging
if len(panelState.Conflicts) == 0 {
return nil
@@ -262,6 +299,8 @@ func (gui *Gui) renderMergeOptions() error {
}
func (gui *Gui) handleEscapeMerge(g *gocui.Gui, v *gocui.View) error {
gui.takeOverScrolling()
gui.State.Panels.Merging.EditHistory = stack.New()
if err := gui.refreshSidePanels(refreshOptions{scope: []int{FILES}}); err != nil {
return err
@@ -295,7 +334,23 @@ func (gui *Gui) handleCompleteMerge() error {
// promptToContinue asks the user if they want to continue the rebase/merge that's in progress
func (gui *Gui) promptToContinue() error {
gui.takeOverScrolling()
return gui.createConfirmationPanel(gui.g, gui.getFilesView(), true, "continue", gui.Tr.SLocalize("ConflictsResolved"), func(g *gocui.Gui, v *gocui.View) error {
return gui.genericMergeCommand("continue")
}, nil)
}
func (gui *Gui) canScrollMergePanel() bool {
currentViewName := gui.currentViewName()
if currentViewName != "main" {
return false
}
file, err := gui.getSelectedFile()
if err != nil {
return false
}
return file.HasInlineMergeConflicts
}

View File

@@ -94,7 +94,7 @@ func (gui *Gui) refreshSecondaryPatchPanel() error {
secondaryView.Wrap = false
gui.g.Update(func(*gocui.Gui) error {
gui.setViewContent(gui.g, gui.getSecondaryView(), gui.GitCommand.PatchManager.RenderAggregatedPatchColored(false))
gui.setViewContent(gui.getSecondaryView(), gui.GitCommand.PatchManager.RenderAggregatedPatchColored(false))
return nil
})
} else {

View File

@@ -20,6 +20,10 @@ func (gui *Gui) handleCreatePatchOptionsMenu(g *gocui.Gui, v *gocui.View) error
displayString: "pull patch out into index",
onPress: gui.handlePullPatchIntoWorkingTree,
},
{
displayString: "pull patch into new commit",
onPress: gui.handlePullPatchIntoNewCommit,
},
{
displayString: "apply patch",
onPress: func() error { return gui.handleApplyPatch(false) },
@@ -137,6 +141,22 @@ func (gui *Gui) handlePullPatchIntoWorkingTree() error {
}
}
func (gui *Gui) handlePullPatchIntoNewCommit() error {
if ok, err := gui.validateNormalWorkingTreeState(); !ok {
return err
}
if err := gui.returnFocusFromLineByLinePanelIfNecessary(); err != nil {
return err
}
return gui.WithWaitingStatus(gui.Tr.SLocalize("RebasingStatus"), func() error {
commitIndex := gui.getPatchCommitIndex()
err := gui.GitCommand.PullPatchIntoNewCommit(gui.State.Commits, commitIndex, gui.GitCommand.PatchManager)
return gui.handleGenericMergeCommandResult(err)
})
}
func (gui *Gui) handleApplyPatch(reverse bool) error {
if err := gui.returnFocusFromLineByLinePanelIfNecessary(); err != nil {
return err

View File

@@ -28,9 +28,6 @@ func getFileDisplayStrings(f *commands.File, diffed bool) []string {
return []string{red.Sprint(f.DisplayString)}
}
output := green.Sprint(f.DisplayString[0:1])
output += red.Sprint(f.DisplayString[1:3])
var restColor *color.Color
if diffed {
restColor = diffColor
@@ -39,6 +36,22 @@ func getFileDisplayStrings(f *commands.File, diffed bool) []string {
} else {
restColor = green
}
output += restColor.Sprint(f.Name)
// this is just making things look nice when the background attribute is 'reverse'
firstChar := f.DisplayString[0:1]
firstCharCl := green
if firstChar == " " {
firstCharCl = restColor
}
secondChar := f.DisplayString[1:2]
secondCharCl := red
if secondChar == " " {
secondCharCl = restColor
}
output := firstCharCl.Sprint(firstChar)
output += secondCharCl.Sprint(secondChar)
output += restColor.Sprintf(" %s", f.Name)
return []string{output}
}

View File

@@ -34,6 +34,14 @@ func (gui *Gui) handleQuit(g *gocui.Gui, v *gocui.View) error {
return gui.quit(v)
}
func (gui *Gui) handleTopLevelReturn(g *gocui.Gui, v *gocui.View) error {
if gui.Config.GetUserConfig().GetBool("quitOnTopLevelReturn") {
return gui.handleQuit(g, v)
}
return nil
}
func (gui *Gui) quit(v *gocui.View) error {
if gui.State.Updating {
return gui.createUpdateQuitConfirmation(gui.g, v)

View File

@@ -84,7 +84,7 @@ func (gui *Gui) handleCheckoutRemoteBranch(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleMergeRemoteBranch(g *gocui.Gui, v *gocui.View) error {
selectedBranchName := gui.getSelectedRemoteBranch().Name
selectedBranchName := gui.getSelectedRemoteBranch().FullName()
return gui.mergeBranchIntoCheckedOutBranch(selectedBranchName)
}
@@ -139,3 +139,26 @@ func (gui *Gui) handleCreateResetToRemoteBranchMenu(g *gocui.Gui, v *gocui.View)
return gui.createResetMenu(fmt.Sprintf("%s/%s", selectedBranch.RemoteName, selectedBranch.Name))
}
func (gui *Gui) handleNewBranchOffRemote(g *gocui.Gui, v *gocui.View) error {
branch := gui.getSelectedRemoteBranch()
if branch == nil {
return nil
}
message := gui.Tr.TemplateLocalize(
"NewBranchNameBranchOff",
Teml{
"branchName": branch.FullName(),
},
)
return gui.createPromptPanel(g, v, message, branch.FullName(), func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.NewBranch(gui.trimmedContent(v), branch.FullName()); err != nil {
return gui.surfaceError(err)
}
gui.State.Panels.Branches.SelectedLine = 0
if err := gui.switchBranchesPanelContext("local-branches"); err != nil {
return err
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
})
}

View File

@@ -42,7 +42,7 @@ func (gui *Gui) refreshStatus() {
status += fmt.Sprintf("%s → %s ", repoName, name)
gui.g.Update(func(*gocui.Gui) error {
gui.setViewContent(gui.g, gui.getStatusView(), status)
gui.setViewContent(gui.getStatusView(), status)
return nil
})
}

View File

@@ -70,6 +70,26 @@ func (gui *Gui) newStringTask(viewName string, str string) error {
return nil
}
func (gui *Gui) newStringTaskWithoutScroll(viewName string, str string) error {
view, err := gui.g.View(viewName)
if err != nil {
return nil // swallowing for now
}
manager := gui.getManager(view)
f := func(stop chan struct{}) error {
gui.setViewContent(view, str)
return nil
}
if err := manager.NewTask(f); err != nil {
return err
}
return nil
}
func (gui *Gui) getManager(view *gocui.View) *tasks.ViewBufferManager {
manager, ok := gui.viewBufferManagerMap[view.Name()]
if !ok {

View File

@@ -340,7 +340,7 @@ func (gui *Gui) cleanString(s string) string {
return utils.NormalizeLinefeeds(output)
}
func (gui *Gui) setViewContent(g *gocui.Gui, v *gocui.View, s string) {
func (gui *Gui) setViewContent(v *gocui.View, s string) {
v.Clear()
fmt.Fprint(v, gui.cleanString(s))
}
@@ -358,7 +358,7 @@ func (gui *Gui) renderString(g *gocui.Gui, viewName, s string) {
if err := v.SetCursor(0, 0); err != nil {
return err
}
gui.setViewContent(gui.g, v, s)
gui.setViewContent(v, s)
return nil
})
}
@@ -513,7 +513,8 @@ func (gui *Gui) renderGlobalOptions() error {
return gui.renderOptionsMap(map[string]string{
fmt.Sprintf("%s/%s", gui.getKeyDisplay("universal.scrollUpMain"), gui.getKeyDisplay("universal.scrollDownMain")): gui.Tr.SLocalize("scroll"),
fmt.Sprintf("%s %s %s %s", gui.getKeyDisplay("universal.prevBlock"), gui.getKeyDisplay("universal.nextBlock"), gui.getKeyDisplay("universal.prevItem"), gui.getKeyDisplay("universal.nextItem")): gui.Tr.SLocalize("navigate"),
fmt.Sprintf("%s/%s", gui.getKeyDisplay("universal.return"), gui.getKeyDisplay("universal.quit")): gui.Tr.SLocalize("close"),
gui.getKeyDisplay("universal.return"): gui.Tr.SLocalize("cancel"),
gui.getKeyDisplay("universal.quit"): gui.Tr.SLocalize("quit"),
gui.getKeyDisplay("universal.optionMenu"): gui.Tr.SLocalize("menu"),
"1-5": gui.Tr.SLocalize("jump"),
})

View File

@@ -28,24 +28,33 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "CommitsTitle",
Other: "Commits",
}, &i18n.Message{
ID: "CommitsDiffTitle",
Other: "Commits (specific diff mode)",
}, &i18n.Message{
ID: "CommitsDiff",
Other: "select commit to diff with another commit",
}, &i18n.Message{
ID: "StashTitle",
Other: "Stash",
}, &i18n.Message{
ID: "UnstagedChanges",
Other: `Unstaged Changes`,
Other: `Unstaged wijzigingen`,
}, &i18n.Message{
ID: "StagedChanges",
Other: `Staged Changes`,
Other: `Staged Wijzigingen`,
}, &i18n.Message{
ID: "PatchBuildingMainTitle",
Other: `Voeg lijnen/hunks toe aan Patch`,
}, &i18n.Message{
ID: "MergingMainTitle",
Other: "Resolve merge conflicts",
Other: "Los merge conflicten op",
}, &i18n.Message{
ID: "MainTitle",
Other: "Hooft",
}, &i18n.Message{
ID: "StagingTitle",
Other: "Staging",
}, &i18n.Message{
ID: "MergingTitle",
Other: "Merging",
}, &i18n.Message{
ID: "NormalTitle",
Other: "Normaal",
}, &i18n.Message{
ID: "CommitMessage",
Other: "Commit bericht",
@@ -78,7 +87,7 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "Status",
}, &i18n.Message{
ID: "GlobalTitle",
Other: "Global",
Other: "Globaal",
}, &i18n.Message{
ID: "navigate",
Other: "navigeer",
@@ -124,6 +133,9 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "resolveMergeConflicts",
Other: "los merge conflicten op",
}, &i18n.Message{
ID: "MergeConflictsTitle",
Other: "Merge Conflicten",
}, &i18n.Message{
ID: "checkout",
Other: "uitchecken",
@@ -136,9 +148,6 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "CannotGitAdd",
Other: "Kan commando niet uitvoeren git add --path untracked files",
}, &i18n.Message{
ID: "NoStagedFilesToCommit",
Other: "Er zijn geen staged bestanden om te commiten",
}, &i18n.Message{
ID: "NoFilesDisplay",
Other: "Geen bestanden om te laten zien",
@@ -157,6 +166,9 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "FileNoMergeCons",
Other: "Dit bestand heeft geen merge conflicten",
}, &i18n.Message{
ID: "softReset",
Other: "zacht reset",
}, &i18n.Message{
ID: "SureTo",
Other: "Weet je het zeker dat je {{.fileName}} wilt {{.deleteVerb}} (je veranderingen zullen worden verwijderd)",
@@ -190,6 +202,9 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "rebaseBranch",
Other: "rebase branch",
}, &i18n.Message{
ID: "CantRebaseOntoSelf",
Other: "Je kan niet een branch rebasen op zichzelf",
}, &i18n.Message{
ID: "CantMergeBranchIntoItself",
Other: "Je kan niet een branch in zichzelf mergen",
@@ -217,15 +232,21 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "NoTrackingThisBranch",
Other: "deze branch wordt niet gevolgd",
}, &i18n.Message{
ID: "CommitMessageConfirm",
Other: "{{.keyBindClose}}: Sluiten, {{.keyBindNewLine}}: Nieuwe lijn, {{.keyBindConfirm}}: Bevestig",
}, &i18n.Message{
ID: "CommitWithoutMessageErr",
Other: "Je kan geen commit maken zonder commit bericht",
}, &i18n.Message{
ID: "CloseConfirm",
Other: "{{.keyBindClose}}: Sluiten, {{.keyBindConfirm}}: Bevestigen",
Other: "{{.keyBindClose}}: Sluiten, {{.keyBindConfirm}}: Bevestig",
}, &i18n.Message{
ID: "close",
Other: "sluiten",
}, &i18n.Message{
ID: "quit",
Other: "quit",
}, &i18n.Message{
ID: "SureResetThisCommit",
Other: "Weet je het zeker dat je wil resetten naar deze commit?",
@@ -262,18 +283,48 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "SureFixupThisCommit",
Other: "Weet je zeker dat je fixup wil uitvoeren op deze commit? De commit hieronder zol worden squashed in deze",
}, &i18n.Message{
ID: "SureSquashThisCommit",
Other: "Weet je zeker dat je deze commit wil samenvoegen met de commit hieronder?",
}, &i18n.Message{
ID: "Squash",
Other: "Squash",
}, &i18n.Message{
ID: "pickCommit",
Other: "kies commit (wanneer midden in rebase)",
}, &i18n.Message{
ID: "revertCommit",
Other: "commit ongedaan maken",
}, &i18n.Message{
ID: "OnlyRenameTopCommit",
Other: "Je kan alleen de bovenste commit hernoemen",
}, &i18n.Message{
ID: "renameCommit",
Other: "hernoem commit",
}, &i18n.Message{
ID: "deleteCommit",
Other: "verwijder commit",
}, &i18n.Message{
ID: "moveDownCommit",
Other: "verplaats commit 1 naar beneden",
}, &i18n.Message{
ID: "moveUpCommit",
Other: "verplaats commit 1 naar boven",
}, &i18n.Message{
ID: "editCommit",
Other: "wijzig commit",
}, &i18n.Message{
ID: "amendToCommit",
Other: "wijzig commit met staged veranderingen",
}, &i18n.Message{
ID: "renameCommitEditor",
Other: "rename commit with editor",
Other: "hernoem commit met editor",
}, &i18n.Message{
ID: "PotentialErrInGetselectedCommit",
Other: "Er is mogelijk een error in getSelected Commit (geen match tussen ui en state)",
}, &i18n.Message{
ID: "NoCommitsThisBranch",
Other: "Geen commits in deze branch",
}, &i18n.Message{
ID: "Error",
Other: "Foutmelding",
@@ -298,12 +349,18 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "undo",
Other: "ongedaan maken",
}, &i18n.Message{
ID: "undoReflog",
Other: "ongedaan maken (via reflog) (experimenteel)",
}, &i18n.Message{
ID: "redoReflog",
Other: "redo (via reflog) (experimenteel)",
}, &i18n.Message{
ID: "pop",
Other: "pop",
}, &i18n.Message{
ID: "drop",
Other: "drop",
Other: "laten vallen",
}, &i18n.Message{
ID: "apply",
Other: "toepassen",
@@ -312,10 +369,22 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "Geen stash items",
}, &i18n.Message{
ID: "StashDrop",
Other: "Stash drop",
Other: "Stash laten vallen",
}, &i18n.Message{
ID: "SureDropStashEntry",
Other: "Weet je het zeker dat je deze stash entry wil laten vallen?",
}, &i18n.Message{
ID: "StashPop",
Other: "Stash pop",
}, &i18n.Message{
ID: "SurePopStashEntry",
Other: "Weet je zeker dat je deze stash entry wil poppen?",
}, &i18n.Message{
ID: "StashApply",
Other: "Stash toepassen",
}, &i18n.Message{
ID: "SureApplyStashEntry",
Other: "Weet je zeker dat je deze stash entry wil toepassen?",
}, &i18n.Message{
ID: "NoStashTo",
Other: "Geen stash voor {{.method}}",
@@ -334,15 +403,18 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "newFocusedViewIs",
Other: "nieuw gefocussed weergave is {{.newFocusedView}}",
}, &i18n.Message{
ID: "NoChangedFiles",
Other: "Geen veranderde bestanden",
}, &i18n.Message{
ID: "MergeAborted",
Other: "Merge afgebroken",
}, &i18n.Message{
ID: "OpenConfig",
Other: "open config file",
Other: "open config bestand",
}, &i18n.Message{
ID: "EditConfig",
Other: "verander config file",
Other: "verander config bestand",
}, &i18n.Message{
ID: "ForcePush",
Other: "Forceer push",
@@ -370,6 +442,19 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "AnonymousReportingPrompt",
Other: "Zou je anonieme data rapportage willen aanzetten om lazygit beter te kunnen maken? (enter/esc)",
}, &i18n.Message{
ID: "ShamelessSelfPromotionTitle",
Other: "Schaamteloose zelf promotie",
}, &i18n.Message{
ID: "ShamelessSelfPromotionMessage",
Other: `Bedankt voor het gebruik maken van lazygit! 3 dingen die je moet weten:
1) lazygit heeft nu basis muis support!
2) Als je meer van lazygit zijn features wilt leren bekijk dan deze video:
https://youtu.be/CPLdltN7wgE
3) Github matched nu elke donations euro voor euro voor de komende 12 maanden, dus als je graag zou willen doneren klik the doneer knop rechts onderin`,
}, &i18n.Message{
ID: "GitconfigParseErr",
Other: `Gogit kon je gitconfig bestand niet goed parsen door de aanwezigheid van losstaande '\' tekens. Het weghalen van deze tekens zou het probleem moeten oplossen. `,
@@ -419,14 +504,29 @@ func addDutch(i18nObject *i18n.Bundle) error {
ID: "FileStagingRequirements",
Other: `Kan alleen individuele lijnen stagen van getrackte bestanden met onstaged veranderingen`,
}, &i18n.Message{
ID: "StagingTitle",
Other: `Stage Lines/Hunks`,
ID: "SelectHunk",
Other: `selecteer hunk`,
}, &i18n.Message{
ID: "StageHunk",
Other: `stage hunk`,
ID: "StageSelection",
Other: `toggle lijnen staged / unstaged`,
}, &i18n.Message{
ID: "StageLine",
Other: `stage lijn`,
ID: "ResetSelection",
Other: `verwijdert change (git reset)`,
}, &i18n.Message{
ID: "ToggleDragSelect",
Other: `toggle drag selecteer`,
}, &i18n.Message{
ID: "ToggleSelectHunk",
Other: `toggle selecteer hunk`,
}, &i18n.Message{
ID: "ToggleSelectionForPatch",
Other: `voeg toe/verwijder lijn(en) in patch`,
}, &i18n.Message{
ID: "TogglePanel",
Other: `ga naar een ander paneel`,
}, &i18n.Message{
ID: "CantStageStaged",
Other: `Je kan niet al gestaged verandering stagen!`,
}, &i18n.Message{
ID: "ReturnToFilesPanel",
Other: `ga terug naar het bestanden paneel`,
@@ -437,65 +537,11 @@ func addDutch(i18nObject *i18n.Bundle) error {
ID: "CantFindHunk",
Other: `Kan geen hunk vinden`,
}, &i18n.Message{
ID: "RebasingTitle",
Other: "Rebasing",
ID: "FastForward",
Other: `fast-forward deze branch vanaf zijn upstream`,
}, &i18n.Message{
ID: "MergingTitle",
Other: "Merging",
}, &i18n.Message{
ID: "ConfirmRebase",
Other: "Weet je zeker dat je {{.checkedOutBranch}} op {{.selectedBranch}} wil rebasen?",
}, &i18n.Message{
ID: "ConfirmMerge",
Other: "Weet je zeker dat je {{.selectedBranch}} in {{.checkedOutBranch}} wil mergen?",
}, &i18n.Message{
ID: "FwdNoUpstream",
Other: "Kan niet de branch vooruitspoelen zonder upstream",
}, &i18n.Message{
ID: "ErrorOccurred",
Other: "Er is iets fout gegaan! Zou je hier een issue aan willen maken: https://github.com/jesseduffield/lazygit/issues",
}, &i18n.Message{
ID: "FwdCommitsToPush",
Other: "Je kan niet vooruitspoelen als de branch geen nieuwe commits heeft",
}, &i18n.Message{
ID: "MainTitle",
Other: "Hoofd",
}, &i18n.Message{
ID: "NormalTitle",
Other: "Normaal",
}, &i18n.Message{
ID: "softReset",
Other: "zacht reset",
}, &i18n.Message{
ID: "CantRebaseOntoSelf",
Other: "Je kan niet een branch rebasen op zichzelf",
}, &i18n.Message{
ID: "SureSquashThisCommit",
Other: "Weet je zeker dat je deze commit wil samenvoegen met de commit hieronder?",
}, &i18n.Message{
ID: "Squash",
Other: "Squash",
}, &i18n.Message{
ID: "pickCommit",
Other: "pick commit (when mid-rebase)",
}, &i18n.Message{
ID: "revertCommit",
Other: "commit omgedaan maken",
}, &i18n.Message{
ID: "deleteCommit",
Other: "verwijder commit",
}, &i18n.Message{
ID: "moveDownCommit",
Other: "verplaats commit 1 omlaag",
}, &i18n.Message{
ID: "moveUpCommit",
Other: "verplaats commit 1 omhoog",
}, &i18n.Message{
ID: "editCommit",
Other: "verander commit",
}, &i18n.Message{
ID: "amendToCommit",
Other: "wijzig commit met staged veranderingen",
ID: "Fetching",
Other: "fetching en fast-forwarding {{.from}} -> {{.to}} ...",
}, &i18n.Message{
ID: "FoundConflicts",
Other: "Conflicten!, Om af te breken druk 'esc', anders druk op 'enter'",
@@ -507,10 +553,10 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "ongedaan maken",
}, &i18n.Message{
ID: "PickHunk",
Other: "pick hunk",
Other: "kies hunk",
}, &i18n.Message{
ID: "PickBothHunks",
Other: "pick beide hunks",
Other: "kies bijde hunks",
}, &i18n.Message{
ID: "ViewMergeRebaseOptions",
Other: "bekijk merge/rebase opties",
@@ -519,16 +565,85 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "Je bent momenteel niet aan het rebasen of mergen",
}, &i18n.Message{
ID: "RecentRepos",
Other: "recent repositories",
Other: "recente repositories",
}, &i18n.Message{
ID: "MergeOptionsTitle",
Other: "Merge Opties",
}, &i18n.Message{
ID: "RebaseOptionsTitle",
Other: "Rebase Opties",
}, &i18n.Message{
ID: "CommitMessageTitle",
Other: "Commit Bericht",
}, &i18n.Message{
ID: "Local-BranchesTitle",
Other: "Branches Tab",
}, &i18n.Message{
ID: "SearchTitle",
Other: "Zoek",
}, &i18n.Message{
ID: "TagsTitle",
Other: "Tags Tab",
}, &i18n.Message{
ID: "Branch-CommitsTitle",
Other: "Commits Tab",
}, &i18n.Message{
ID: "MenuTitle",
Other: "Menu",
}, &i18n.Message{
ID: "RemotesTitle",
Other: "Remotes Tab",
}, &i18n.Message{
ID: "CredentialsTitle",
Other: "Credentials",
}, &i18n.Message{
ID: "Remote-BranchesTitle",
Other: "Remote Branches (in Remotes tab)",
}, &i18n.Message{
ID: "Patch-BuildingTitle",
Other: "Patch Bouwen",
}, &i18n.Message{
ID: "InformationTitle",
Other: "Informatie",
}, &i18n.Message{
ID: "SecondaryTitle",
Other: "Secondary",
}, &i18n.Message{
ID: "Reflog-CommitsTitle",
Other: "Reflog Tab",
}, &i18n.Message{
ID: "Title",
Other: "Title",
}, &i18n.Message{
ID: "GlobalTitle",
Other: "Globaale Sneltoetsen",
}, &i18n.Message{
ID: "MerginTitle",
Other: "Mergen",
}, &i18n.Message{
ID: "ConflictsResolved",
Other: "alle merge conflicten zijn opgelost. Wilt je verder gaan?",
}, &i18n.Message{
ID: "RebasingTitle",
Other: "Rebasen",
}, &i18n.Message{
ID: "MergingTitle",
Other: "Merggen",
}, &i18n.Message{
ID: "ConfirmRebase",
Other: "Weet je zeker dat je {{.checkedOutBranch}} op {{.selectedBranch}} wil rebasen?",
}, &i18n.Message{
ID: "ConfirmMerge",
Other: "Weet je zeker dat je {{.selectedBranch}} in {{.checkedOutBranch}} wil mergen?",
}, &i18n.Message{
ID: "FwdNoUpstream",
Other: "Kan niet de branch vooruitspoelen zonder upstream",
}, &i18n.Message{
ID: "FwdCommitsToPush",
Other: "Je kan niet vooruitspoelen als de branch geen nieuwe commits heeft",
}, &i18n.Message{
ID: "ErrorOccurred",
Other: "Er is iets fout gegaan! Zou je hier een issue aan willen maken: https://github.com/jesseduffield/lazygit/issues",
}, &i18n.Message{
ID: "NoRoom",
Other: "Niet genoeg ruimte",
@@ -592,6 +707,12 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "ScrollUp",
Other: "scroll omhoog",
}, &i18n.Message{
ID: "scrollUpMainPanel",
Other: "scroll naar beneden vanaf hooft paneel",
}, &i18n.Message{
ID: "scrollDownMainPanel",
Other: "scroll naar beneden vabaf hooft paneel",
}, &i18n.Message{
ID: "AmendCommitTitle",
Other: "Commit wijzigen",
@@ -606,7 +727,7 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "Weet je zeker dat je deze commit wil verwijderen?",
}, &i18n.Message{
ID: "SquashingStatus",
Other: "squashing",
Other: "squashen",
}, &i18n.Message{
ID: "FixingStatus",
Other: "fixing up",
@@ -618,13 +739,22 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "verplaatsen",
}, &i18n.Message{
ID: "RebasingStatus",
Other: "rebasing",
Other: "rebasen",
}, &i18n.Message{
ID: "AmendingStatus",
Other: "wijzigen",
}, &i18n.Message{
ID: "CherryPickingStatus",
Other: "cherry-picking",
Other: "cherry-picken",
}, &i18n.Message{
ID: "UndoingStatus",
Other: "ongedaan maken",
}, &i18n.Message{
ID: "RedoingStatus",
Other: "redoing",
}, &i18n.Message{
ID: "CheckingOutStatus",
Other: "uitchecken",
}, &i18n.Message{
ID: "CommitFiles",
Other: "Commit bestanden",
@@ -684,7 +814,7 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "verwijder werkende tree",
}, &i18n.Message{
ID: "discardAnyUnstagedChanges",
Other: "discard unstaged changes",
Other: "discard unstaged wijzigingen",
}, &i18n.Message{
ID: "discardUntrackedFiles",
Other: "negeer niet-gevonden bestanden",
@@ -694,6 +824,12 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "hardReset",
Other: "harde reset",
}, &i18n.Message{
ID: "hardResetUpstream",
Other: "harde naar upstream branch",
}, &i18n.Message{
ID: "viewResetOptions",
Other: `bekijk reset opties`,
}, &i18n.Message{
ID: "createFixupCommit",
Other: `creëer fixup commit voor deze commit`,
@@ -726,46 +862,304 @@ func addDutch(i18nObject *i18n.Bundle) error {
Other: "Je hebt nog niet een commit bericht voorvoegsel ingesteld voor het overslaan van hooks. Set `git.skipHookPrefix = 'WIP'` in je config",
}, &i18n.Message{
ID: "resetTo",
Other: `reset to`,
Other: `reset naar`,
}, &i18n.Message{
ID: "pressEnterToReturn",
Other: "Press enter to return to lazygit",
Other: "Press om terug te gaan naar lazygit",
}, &i18n.Message{
ID: "viewStashOptions",
Other: "view stash options",
Other: "bekijk stash opties",
}, &i18n.Message{
ID: "stashAllChanges",
Other: "stash-bestanden",
}, &i18n.Message{
ID: "stashStagedChanges",
Other: "stash staged changes",
Other: "stash staged wijzigingen",
}, &i18n.Message{
ID: "stashOptions",
Other: "Stash options",
Other: "Stash opties",
}, &i18n.Message{
ID: "notARepository",
Other: "Error: must be run inside a git repository",
Other: "Fout: must be run inside a git repository",
}, &i18n.Message{
ID: "jump",
Other: "jump to panel",
Other: "ga naar paneel",
}, &i18n.Message{
ID: "DiscardPatch",
Other: "Patch weg gooien",
}, &i18n.Message{
ID: "DiscardPatchConfirm",
Other: "Je kan alleen maar een patch bouwen van 1 commit. actueel patch weg gooien?",
}, &i18n.Message{
ID: "CantPatchWhileRebasingError",
Other: "Je kan geen patch bouwen of patch commando uitvoeren wanneer je in een merging of rebasing state zit",
}, &i18n.Message{
ID: "toggleAddToPatch",
Other: "toggle bestand inbegrepen in patch",
}, &i18n.Message{
ID: "ViewPatchOptions",
Other: "bekijk aangepaste patch opties",
}, &i18n.Message{
ID: "PatchOptionsTitle",
Other: "Patch Opties",
}, &i18n.Message{
ID: "NoPatchError",
Other: "Nog geen patch gecreëerd. Om een patch te bouwen gebruik 'space' op een commit bestand of 'enter' om een spesiefieke lijnen toe te voegen",
}, &i18n.Message{
ID: "enterFile",
Other: "enter bestand to add selecteered lines to the patch",
}, &i18n.Message{
ID: "ExitLineByLineMode",
Other: `exit line-by-line mode`,
Other: `sluit lijn-bij-lijn mode`,
}, &i18n.Message{
ID: "EnterUpstream",
Other: `Enter upstream as '<remote> <branchname>'`,
Other: `Enter upstream als '<remote> <branchnaam>'`,
}, &i18n.Message{
ID: "EnterUpstreamWithSlash",
Other: `Enter upstream als '<remote>/<branchnaam>'`,
}, &i18n.Message{
ID: "notTrackingRemote",
Other: "(nog geen remote aan het volgen)",
}, &i18n.Message{
ID: "ReturnToRemotesList",
Other: `return to remotes list`,
Other: `Ga terug naar remotes lijst`,
}, &i18n.Message{
ID: "addNewRemote",
Other: `voeg een nieuwe remote toe`,
}, &i18n.Message{
ID: "newRemoteName",
Other: `Nieuwe remote name:`,
}, &i18n.Message{
ID: "newRemoteUrl",
Other: `Nieuwe remote url:`,
}, &i18n.Message{
ID: "editRemoteName",
Other: `Enter updated remote naam voor {{ .remoteName }}:`,
}, &i18n.Message{
ID: "editRemoteUrl",
Other: `Enter updated remote url voor {{ .remoteName }}:`,
}, &i18n.Message{
ID: "removeRemote",
Other: `verwijder remote`,
}, &i18n.Message{
ID: "removeRemotePrompt",
Other: "Weet je zeker dat je deze remote wilt verwijderen",
}, &i18n.Message{
ID: "DeleteRemoteBranch",
Other: "Verwijder Remote Branch",
}, &i18n.Message{
ID: "DeleteRemoteBranchMessage",
Other: "Weet je zeker dat je deze remote branch wilt verwijderen",
}, &i18n.Message{
ID: "setUpstream",
Other: "stel in als upstream van uitgecheckte branch",
}, &i18n.Message{
ID: "SetUpstreamTitle",
Other: "Stel in als upstream branch",
}, &i18n.Message{
ID: "SetUpstreamMessage",
Other: "Weet je zeker dat je de upstream branch van '{{.checkedOut}}' naar '{{.selected}}' wilt zetten",
}, &i18n.Message{
ID: "editRemote",
Other: "wijzig remote",
}, &i18n.Message{
ID: "tagCommit",
Other: "tag commit",
}, &i18n.Message{
ID: "TagNameTitle",
Other: "Tag naam:",
}, &i18n.Message{
ID: "deleteTag",
Other: "verwijder tag",
}, &i18n.Message{
ID: "DeleteTagTitle",
Other: "Verwijder tag",
}, &i18n.Message{
ID: "DeleteTagPrompt",
Other: "Weet je zeker dat je '{{.tagName}}' wil verwijderen?",
}, &i18n.Message{
ID: "PushTagTitle",
Other: "remote om tag '{{.tagName}}' te pushen naar:",
}, &i18n.Message{
ID: "pushTag",
Other: "push tag",
}, &i18n.Message{
ID: "createTag",
Other: "creëer tag",
}, &i18n.Message{
ID: "CreateTagTitle",
Other: "Tag naam:",
}, &i18n.Message{
ID: "fetchRemote",
Other: "fetch remote",
}, &i18n.Message{
ID: "FetchingRemoteStatus",
Other: "remote fetchen",
}, &i18n.Message{
ID: "checkoutCommit",
Other: "checkout commit",
}, &i18n.Message{
ID: "SureCheckoutThisCommit",
Other: "Weet je zeker dat je deze commit wil uitchecken?",
}, &i18n.Message{
ID: "gitFlowOptions",
Other: "laat git-flow opties zien",
}, &i18n.Message{
ID: "NotAGitFlowBranch",
Other: "Dit lijkt geen git flow branch te zijn",
}, &i18n.Message{
ID: "NewBranchNamePrompt",
Other: "nieuwe {{.branchType}} naam:",
}, &i18n.Message{
ID: "IgnoreTracked",
Other: "Ignore tracked file",
Other: "Negeer tracked bestand",
}, &i18n.Message{
ID: "IgnoreTrackedPrompt",
Other: "Are you sure you want to ignore a tracked file?",
Other: "weet je zeker dat je een getracked bestand wil negeeren?",
}, &i18n.Message{
ID: "viewResetToUpstreamOptions",
Other: "bekijk upstream reset opties",
}, &i18n.Message{
ID: "nextScreenMode",
Other: "volgende schermmode (normaal/half/groot )",
}, &i18n.Message{
ID: "prevScreenMode",
Other: "vorige schermmode",
}, &i18n.Message{
ID: "startSearch",
Other: "start met zoekken",
}, &i18n.Message{
ID: "Panel",
Other: "Paneel",
}, &i18n.Message{
ID: "Keybindings",
Other: "Sneltoetsen",
}, &i18n.Message{
ID: "renameBranch",
Other: "hernoem branch",
}, &i18n.Message{
ID: "NewBranchNamePrompt",
Other: "Noem een nieuwe branch naam",
}, &i18n.Message{
ID: "RenameBranchWarning",
Other: "Deze branch volgt een remote. Deze actie zal alleen de locale branch name wijzigen niet de naam van de remote branch. Verder gaan?",
}, &i18n.Message{
ID: "openMenu",
Other: "open menu",
}, &i18n.Message{
ID: "closeMenu",
Other: "sluit menu",
}, &i18n.Message{
ID: "resetCherryPick",
Other: "reset cherry-picked (gecopieerde) commits selectie",
}, &i18n.Message{
ID: "nextTab",
Other: "volgende tab",
}, &i18n.Message{
ID: "prevTab",
Other: "vorige tab",
}, &i18n.Message{
ID: "cantUndoWhileRebasing",
Other: "Kan niet ongedaan maken terwijl je aan het rebasen bent",
}, &i18n.Message{
ID: "cantRedoWhileRebasing",
Other: "Kan niet opnieuw doen (redo) terwijl je aan het rebasen bent",
}, &i18n.Message{
ID: "MustStashWarning",
Other: "Een patch in de index stoppen verijst stashen en onstashen van je wijzigingen. Als iets verkeert gaat kan je je bestanden terug vinden in de stash. Verder gaan?",
}, &i18n.Message{
ID: "MustStashTitle",
Other: "Moet stashen",
}, &i18n.Message{
ID: "ConfirmationTitle",
Other: "Bevestigings Paneel",
}, &i18n.Message{
ID: "prevPage",
Other: "vorige pagina",
}, &i18n.Message{
ID: "nextPage",
Other: "volgende pagina",
}, &i18n.Message{
ID: "gotoTop",
Other: "scroll naar boven",
}, &i18n.Message{
ID: "gotoBottom",
Other: "scroll naar beneden",
}, &i18n.Message{
ID: "filteringBy",
Other: "filteren bij",
}, &i18n.Message{
ID: "(reset)",
Other: "(reset)",
}, &i18n.Message{
ID: "openScopingMenu",
Other: "bekijk scoping opties",
}, &i18n.Message{
ID: "filterBy",
Other: "filter bij",
}, &i18n.Message{
ID: "exitFilterMode",
Other: "stop met filteren bij pad",
}, &i18n.Message{
ID: "filterPathOption",
Other: "vulin pad om op te filteren",
}, &i18n.Message{
ID: "enterFileName",
Other: "vulin path:",
}, &i18n.Message{
ID: "FilteringMenuTitle",
Other: "Filteren",
}, &i18n.Message{
ID: "MustExitFilterModeTitle",
Other: "Command niet beschikbaar",
}, &i18n.Message{
ID: "MustExitFilterModePrompt",
Other: "Command niet beschikbaar in filter mode. Sluit filter mode?",
}, &i18n.Message{
ID: "diff",
Other: "diff",
}, &i18n.Message{
ID: "enterRefToDiff",
Other: "vulin ref to diff",
}, &i18n.Message{
ID: "enteRefName",
Other: "vulin ref:",
}, &i18n.Message{
ID: "exitDiffMode",
Other: "sluit diff mode",
}, &i18n.Message{
ID: "DiffingMenuTitle",
Other: "Diffen",
}, &i18n.Message{
ID: "swapDiff",
Other: "keer diff richting om",
}, &i18n.Message{
ID: "openDiffingMenu",
Other: "open diff menu",
}, &i18n.Message{
ID: "showingGitDiff",
Other: "laat output zien voor:",
}, &i18n.Message{
ID: "copyCommitShaToClipboard",
Other: "copieer commit SHA naar clipboard",
}, &i18n.Message{
ID: "copyBranchNameToClipboard",
Other: "copieer branch name naar clipboard",
}, &i18n.Message{
ID: "commitPrefixPatternError",
Other: "Error in commitPrefix pattern",
Other: "Fout in commitPrefix patroon",
}, &i18n.Message{
ID: "NoFilesStagedTitle",
Other: "geen bestanden gestaged",
}, &i18n.Message{
ID: "NoFilesStagedPrompt",
Other: "Je hebt geen bestanden gestaged. Commit alle bestanden?",
}, &i18n.Message{
ID: "BranchNotFoundTitle",
Other: "Branch niet gevonden",
}, &i18n.Message{
ID: "BranchNotFoundPrompt",
Other: "Branch niet gevonden. Creëer een nieuwe branch genaamd",
},
)
}

View File

@@ -156,9 +156,6 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "CannotGitAdd",
Other: "Cannot git add --patch untracked files",
}, &i18n.Message{
ID: "NoStagedFilesToCommit",
Other: "There are no staged files to commit",
}, &i18n.Message{
ID: "NoFilesDisplay",
Other: "No file to display",
@@ -243,6 +240,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "NoTrackingThisBranch",
Other: "There is no tracking for this branch",
}, &i18n.Message{
ID: "CommitMessageConfirm",
Other: "{{.keyBindClose}}: close, {{.keyBindNewLine}}: new line, {{.keyBindConfirm}}: confirm",
}, &i18n.Message{
ID: "CommitWithoutMessageErr",
Other: "You cannot commit without a commit message",
@@ -252,6 +252,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "close",
Other: "close",
}, &i18n.Message{
ID: "quit",
Other: "quit",
}, &i18n.Message{
ID: "SureResetThisCommit",
Other: "Are you sure you want to reset to this commit?",
@@ -526,12 +529,10 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "ToggleSelectionForPatch",
Other: `add/remove line(s) to patch`,
},
&i18n.Message{
}, &i18n.Message{
ID: "TogglePanel",
Other: `switch to other panel`,
},
&i18n.Message{
}, &i18n.Message{
ID: "CantStageStaged",
Other: `You can't stage an already staged change!`,
}, &i18n.Message{
@@ -926,7 +927,7 @@ func addEnglish(i18nObject *i18n.Bundle) error {
Other: "(not tracking any remote)",
}, &i18n.Message{
ID: "ReturnToRemotesList",
Other: `return to remotes list`,
Other: `Return to remotes list`,
}, &i18n.Message{
ID: "addNewRemote",
Other: `add new remote`,
@@ -1152,6 +1153,18 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "commitPrefixPatternError",
Other: "Error in commitPrefix pattern",
}, &i18n.Message{
ID: "NoFilesStagedTitle",
Other: "No files staged",
}, &i18n.Message{
ID: "NoFilesStagedPrompt",
Other: "You have not staged any files. Commit all files?",
}, &i18n.Message{
ID: "BranchNotFoundTitle",
Other: "Branch not found",
}, &i18n.Message{
ID: "BranchNotFoundPrompt",
Other: "Branch not found. Create a new branch named",
},
)
}

View File

@@ -128,9 +128,6 @@ func addPolish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "CannotGitAdd",
Other: "Nie można git add --patch nieśledzonych plików",
}, &i18n.Message{
ID: "NoStagedFilesToCommit",
Other: "Brak zatwierdzonych plików do commita",
}, &i18n.Message{
ID: "NoFilesDisplay",
Other: "Brak pliku do wyświetlenia",
@@ -209,6 +206,9 @@ func addPolish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "NoTrackingThisBranch",
Other: "Brak śledzenia dla tej gałęzi",
}, &i18n.Message{
ID: "CommitMessageConfirm",
Other: "{{.keyBindClose}}: zamknij, {{.keyBindNewLine}}: new line, {{.keyBindConfirm}}: potwierdź",
}, &i18n.Message{
ID: "CommitWithoutMessageErr",
Other: "Nie możesz commitować bez podania wiadomości",
@@ -749,6 +749,18 @@ func addPolish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "commitPrefixPatternError",
Other: "Error in commitPrefix pattern",
}, &i18n.Message{
ID: "NoFilesStagedTitle",
Other: "No files staged",
}, &i18n.Message{
ID: "NoFilesStagedPrompt",
Other: "You have not staged any files. Commit all files?",
}, &i18n.Message{
ID: "BranchNotFoundTitle",
Other: "Branch not found",
}, &i18n.Message{
ID: "BranchNotFoundPrompt",
Other: "Branch not found. Create a new branch named",
},
)
}

View File

@@ -24,6 +24,12 @@ var (
// SelectedLineBgColor is the background color for the selected line
SelectedLineBgColor color.Attribute
// SelectedRangeBgColor is the background color of the selected range of lines
SelectedRangeBgColor color.Attribute
// GocuiSelectedLineBgColor is the background color for the selected line in gocui
GocuiSelectedLineBgColor gocui.Attribute
OptionsFgColor color.Attribute
OptionsColor gocui.Attribute
@@ -36,6 +42,8 @@ func UpdateTheme(userConfig *viper.Viper) {
ActiveBorderColor = GetGocuiColor(userConfig.GetStringSlice("gui.theme.activeBorderColor"))
InactiveBorderColor = GetGocuiColor(userConfig.GetStringSlice("gui.theme.inactiveBorderColor"))
SelectedLineBgColor = GetBgColor(userConfig.GetStringSlice("gui.theme.selectedLineBgColor"))
SelectedRangeBgColor = GetBgColor(userConfig.GetStringSlice("gui.theme.selectedRangeBgColor"))
GocuiSelectedLineBgColor = GetGocuiColor(userConfig.GetStringSlice("gui.theme.selectedLineBgColor"))
OptionsColor = GetGocuiColor(userConfig.GetStringSlice("gui.theme.optionsTextColor"))
OptionsFgColor = GetFgColor(userConfig.GetStringSlice("gui.theme.optionsTextColor"))

View File

@@ -322,3 +322,15 @@ func FindStringSubmatch(str string, regexpStr string) (bool, []string) {
match := re.FindStringSubmatch(str)
return len(match) > 0, match
}
func StringArraysOverlap(strArrA []string, strArrB []string) bool {
for _, first := range strArrA {
for _, second := range strArrB {
if first == second {
return true
}
}
}
return false
}

View File

@@ -31,7 +31,7 @@ func main() {
for _, lang := range langs {
os.Setenv("LC_ALL", lang)
mApp, _ := app.NewApp(mConfig)
mApp, _ := app.NewApp(mConfig, "")
file, err := os.Create(getProjectRoot() + "/docs/keybindings/Keybindings_" + lang + ".md")
if err != nil {
panic(err)

View File

@@ -91,6 +91,10 @@ func New(e interface{}) *Error {
// fmt.Errorf("%v"). The skip parameter indicates how far up the stack
// to start the stacktrace. 0 is from the current call, 1 from its caller, etc.
func Wrap(e interface{}, skip int) *Error {
if e == nil {
return nil
}
var err error
switch e := e.(type) {
@@ -117,6 +121,9 @@ func Wrap(e interface{}, skip int) *Error {
// up the stack to start the stacktrace. 0 is from the current call,
// 1 from its caller, etc.
func WrapPrefix(e interface{}, prefix string, skip int) *Error {
if e == nil {
return nil
}
err := Wrap(e, 1+skip)

3
vendor/github.com/go-errors/errors/go.mod generated vendored Normal file
View File

@@ -0,0 +1,3 @@
module github.com/go-errors/errors
go 1.14

View File

@@ -1,9 +1,10 @@
package errors
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"runtime"
"strings"
)
@@ -62,18 +63,29 @@ func (frame *StackFrame) String() string {
// SourceLine gets the line of code (from File and Line) of the original source if possible.
func (frame *StackFrame) SourceLine() (string, error) {
data, err := ioutil.ReadFile(frame.File)
if frame.LineNumber <= 0 {
return "???", nil
}
file, err := os.Open(frame.File)
if err != nil {
return "", New(err)
}
defer file.Close()
lines := bytes.Split(data, []byte{'\n'})
if frame.LineNumber <= 0 || frame.LineNumber >= len(lines) {
return "???", nil
scanner := bufio.NewScanner(file)
currentLine := 1
for scanner.Scan() {
if currentLine == frame.LineNumber {
return string(bytes.Trim(scanner.Bytes(), " \t")), nil
}
currentLine++
}
// -1 because line-numbers are 1 based, but our array is 0 based
return string(bytes.Trim(lines[frame.LineNumber-1], " \t")), nil
if err := scanner.Err(); err != nil {
return "", New(err)
}
return "???", nil
}
func packageAndName(fn *runtime.Func) (string, string) {

View File

@@ -703,7 +703,9 @@ func (g *Gui) drawTitle(v *View, fgColor, bgColor Attribute) error {
if v != g.currentView {
currentFgColor -= AttrBold
}
currentBgColor = v.SelBgColor
if v.HighlightSelectedTabWithoutFocus || v == g.CurrentView() {
currentBgColor = v.SelBgColor
}
}
if err := g.SetRune(x, v.y0, ch, currentFgColor, currentBgColor); err != nil {
return err

View File

@@ -83,6 +83,8 @@ type View struct {
Tabs []string
TabIndex int
// HighlightTabWithoutFocus allows you to show which tab is selected without the view being focused
HighlightSelectedTabWithoutFocus bool
// If Frame is true, Subtitle allows to configure a subtitle for the view.
Subtitle string
@@ -324,6 +326,7 @@ func (v *View) setRune(x, y int, ch rune, fgColor, bgColor Attribute) error {
ch = v.Mask
} else if v.Highlight && ry == rcy {
fgColor = fgColor | AttrBold
bgColor = bgColor | v.SelBgColor
}
termbox.SetCell(v.x0+x+1, v.y0+y+1, ch,

View File

@@ -335,6 +335,7 @@ func PollEvent() Event {
event.N = len(inbuf)
}
copy(inbuf, inbuf[event.N:])
event.Bytes = append(event.Bytes, inbuf[:event.N]...)
inbuf = inbuf[:len(inbuf)-event.N]
}
if status == event_extracted {
@@ -366,6 +367,7 @@ func PollEvent() Event {
event.N = len(inbuf)
}
copy(inbuf, inbuf[event.N:])
event.Bytes = append(event.Bytes, inbuf[:event.N]...)
inbuf = inbuf[:len(inbuf)-event.N]
}
if status == event_extracted {
@@ -383,6 +385,7 @@ func PollEvent() Event {
event.N = len(inbuf)
}
copy(inbuf, inbuf[event.N:])
event.Bytes = append(event.Bytes, inbuf[:event.N]...)
inbuf = inbuf[:len(inbuf)-event.N]
}
if status == event_extracted {

View File

@@ -26,6 +26,7 @@ type Event struct {
MouseX int // x coord of mouse
MouseY int // y coord of mouse
N int // number of bytes written when getting a raw event
Bytes []byte // byte array that triggered the event
}
// A cell, single conceptual entity on the screen. The screen is basically a 2d

View File

@@ -2,14 +2,16 @@
package termbox
import "unicode/utf8"
import "bytes"
import "syscall"
import "unsafe"
import "strings"
import "strconv"
import "os"
import "io"
import (
"bytes"
"io"
"os"
"strconv"
"strings"
"syscall"
"unicode/utf8"
"unsafe"
)
// private API

View File

@@ -62,7 +62,10 @@ func isEastAsian(locale string) bool {
// IsEastAsian return true if the current locale is CJK
func IsEastAsian() bool {
locale := os.Getenv("LC_CTYPE")
locale := os.Getenv("LC_ALL")
if locale == "" {
locale = os.Getenv("LC_CTYPE")
}
if locale == "" {
locale = os.Getenv("LANG")
}

View File

@@ -5,18 +5,19 @@ package runewidth
var combining = table{
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3},
{0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0D00, 0x0D01},
{0x135D, 0x135F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1ABE},
{0x135D, 0x135F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1AC0},
{0x1B6B, 0x1B73}, {0x1DC0, 0x1DF9}, {0x1DFB, 0x1DFF},
{0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF},
{0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D},
{0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1},
{0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x10376, 0x1037A},
{0x10F46, 0x10F50}, {0x11300, 0x11301}, {0x1133B, 0x1133C},
{0x11366, 0x1136C}, {0x11370, 0x11374}, {0x16AF0, 0x16AF4},
{0x1D165, 0x1D169}, {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182},
{0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244},
{0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021},
{0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E8D0, 0x1E8D6},
{0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x11300, 0x11301},
{0x1133B, 0x1133C}, {0x11366, 0x1136C}, {0x11370, 0x11374},
{0x16AF0, 0x16AF4}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172},
{0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
{0x1D242, 0x1D244}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018},
{0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, {0x1E026, 0x1E02A},
{0x1E8D0, 0x1E8D6},
}
var doublewidth = table{
@@ -34,29 +35,30 @@ var doublewidth = table{
{0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99},
{0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB},
{0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF},
{0x3105, 0x312F}, {0x3131, 0x318E}, {0x3190, 0x31BA},
{0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247},
{0x3250, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6},
{0xA960, 0xA97C}, {0xAC00, 0xD7A3}, {0xF900, 0xFAFF},
{0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE66},
{0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6},
{0x16FE0, 0x16FE3}, {0x17000, 0x187F7}, {0x18800, 0x18AF2},
{0x1B000, 0x1B11E}, {0x1B150, 0x1B152}, {0x1B164, 0x1B167},
{0x1B170, 0x1B2FB}, {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF},
{0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, {0x1F200, 0x1F202},
{0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, {0x1F250, 0x1F251},
{0x1F260, 0x1F265}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335},
{0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA},
{0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4},
{0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC},
{0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567},
{0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4},
{0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC},
{0x1F6D0, 0x1F6D2}, {0x1F6D5, 0x1F6D5}, {0x1F6EB, 0x1F6EC},
{0x1F6F4, 0x1F6FA}, {0x1F7E0, 0x1F7EB}, {0x1F90D, 0x1F971},
{0x1F973, 0x1F976}, {0x1F97A, 0x1F9A2}, {0x1F9A5, 0x1F9AA},
{0x1F9AE, 0x1F9CA}, {0x1F9CD, 0x1F9FF}, {0x1FA70, 0x1FA73},
{0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA82}, {0x1FA90, 0x1FA95},
{0x3105, 0x312F}, {0x3131, 0x318E}, {0x3190, 0x31E3},
{0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x4DBF},
{0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C},
{0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19},
{0xFE30, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B},
{0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4},
{0x16FF0, 0x16FF1}, {0x17000, 0x187F7}, {0x18800, 0x18CD5},
{0x18D00, 0x18D08}, {0x1B000, 0x1B11E}, {0x1B150, 0x1B152},
{0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, {0x1F004, 0x1F004},
{0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A},
{0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248},
{0x1F250, 0x1F251}, {0x1F260, 0x1F265}, {0x1F300, 0x1F320},
{0x1F32D, 0x1F335}, {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393},
{0x1F3A0, 0x1F3CA}, {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0},
{0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440},
{0x1F442, 0x1F4FC}, {0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E},
{0x1F550, 0x1F567}, {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596},
{0x1F5A4, 0x1F5A4}, {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5},
{0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D2}, {0x1F6D5, 0x1F6D7},
{0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB},
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F978},
{0x1F97A, 0x1F9CB}, {0x1F9CD, 0x1F9FF}, {0x1FA70, 0x1FA74},
{0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA86}, {0x1FA90, 0x1FAA8},
{0x1FAB0, 0x1FAB6}, {0x1FAC0, 0x1FAC2}, {0x1FAD0, 0x1FAD6},
{0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
}
@@ -153,7 +155,7 @@ var neutral = table{
{0x0600, 0x061C}, {0x061E, 0x070D}, {0x070F, 0x074A},
{0x074D, 0x07B1}, {0x07C0, 0x07FA}, {0x07FD, 0x082D},
{0x0830, 0x083E}, {0x0840, 0x085B}, {0x085E, 0x085E},
{0x0860, 0x086A}, {0x08A0, 0x08B4}, {0x08B6, 0x08BD},
{0x0860, 0x086A}, {0x08A0, 0x08B4}, {0x08B6, 0x08C7},
{0x08D3, 0x0983}, {0x0985, 0x098C}, {0x098F, 0x0990},
{0x0993, 0x09A8}, {0x09AA, 0x09B0}, {0x09B2, 0x09B2},
{0x09B6, 0x09B9}, {0x09BC, 0x09C4}, {0x09C7, 0x09C8},
@@ -172,7 +174,7 @@ var neutral = table{
{0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, {0x0B13, 0x0B28},
{0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, {0x0B35, 0x0B39},
{0x0B3C, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D},
{0x0B56, 0x0B57}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63},
{0x0B55, 0x0B57}, {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63},
{0x0B66, 0x0B77}, {0x0B82, 0x0B83}, {0x0B85, 0x0B8A},
{0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, {0x0B99, 0x0B9A},
{0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4},
@@ -186,166 +188,169 @@ var neutral = table{
{0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9},
{0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD},
{0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE3},
{0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, {0x0D00, 0x0D03},
{0x0D05, 0x0D0C}, {0x0D0E, 0x0D10}, {0x0D12, 0x0D44},
{0x0D46, 0x0D48}, {0x0D4A, 0x0D4F}, {0x0D54, 0x0D63},
{0x0D66, 0x0D7F}, {0x0D82, 0x0D83}, {0x0D85, 0x0D96},
{0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD},
{0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4},
{0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DE6, 0x0DEF},
{0x0DF2, 0x0DF4}, {0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B},
{0x0E81, 0x0E82}, {0x0E84, 0x0E84}, {0x0E86, 0x0E8A},
{0x0E8C, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD},
{0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECD},
{0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, {0x0F00, 0x0F47},
{0x0F49, 0x0F6C}, {0x0F71, 0x0F97}, {0x0F99, 0x0FBC},
{0x0FBE, 0x0FCC}, {0x0FCE, 0x0FDA}, {0x1000, 0x10C5},
{0x10C7, 0x10C7}, {0x10CD, 0x10CD}, {0x10D0, 0x10FF},
{0x1160, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256},
{0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288},
{0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5},
{0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5},
{0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315},
{0x1318, 0x135A}, {0x135D, 0x137C}, {0x1380, 0x1399},
{0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x169C},
{0x16A0, 0x16F8}, {0x1700, 0x170C}, {0x170E, 0x1714},
{0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C},
{0x176E, 0x1770}, {0x1772, 0x1773}, {0x1780, 0x17DD},
{0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x180E},
{0x1810, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA},
{0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B},
{0x1930, 0x193B}, {0x1940, 0x1940}, {0x1944, 0x196D},
{0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9},
{0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E},
{0x1A60, 0x1A7C}, {0x1A7F, 0x1A89}, {0x1A90, 0x1A99},
{0x1AA0, 0x1AAD}, {0x1AB0, 0x1ABE}, {0x1B00, 0x1B4B},
{0x1B50, 0x1B7C}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37},
{0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA},
{0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA}, {0x1D00, 0x1DF9},
{0x1DFB, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45},
{0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59},
{0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D},
{0x1F80, 0x1FB4}, {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3},
{0x1FD6, 0x1FDB}, {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4},
{0x1FF6, 0x1FFE}, {0x2000, 0x200F}, {0x2011, 0x2012},
{0x2017, 0x2017}, {0x201A, 0x201B}, {0x201E, 0x201F},
{0x2023, 0x2023}, {0x2028, 0x202F}, {0x2031, 0x2031},
{0x2034, 0x2034}, {0x2036, 0x203A}, {0x203C, 0x203D},
{0x203F, 0x2064}, {0x2066, 0x2071}, {0x2075, 0x207E},
{0x2080, 0x2080}, {0x2085, 0x208E}, {0x2090, 0x209C},
{0x20A0, 0x20A8}, {0x20AA, 0x20AB}, {0x20AD, 0x20BF},
{0x20D0, 0x20F0}, {0x2100, 0x2102}, {0x2104, 0x2104},
{0x2106, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2115},
{0x2117, 0x2120}, {0x2123, 0x2125}, {0x2127, 0x212A},
{0x212C, 0x2152}, {0x2155, 0x215A}, {0x215F, 0x215F},
{0x216C, 0x216F}, {0x217A, 0x2188}, {0x218A, 0x218B},
{0x219A, 0x21B7}, {0x21BA, 0x21D1}, {0x21D3, 0x21D3},
{0x21D5, 0x21E6}, {0x21E8, 0x21FF}, {0x2201, 0x2201},
{0x2204, 0x2206}, {0x2209, 0x220A}, {0x220C, 0x220E},
{0x2210, 0x2210}, {0x2212, 0x2214}, {0x2216, 0x2219},
{0x221B, 0x221C}, {0x2221, 0x2222}, {0x2224, 0x2224},
{0x2226, 0x2226}, {0x222D, 0x222D}, {0x222F, 0x2233},
{0x2238, 0x223B}, {0x223E, 0x2247}, {0x2249, 0x224B},
{0x224D, 0x2251}, {0x2253, 0x225F}, {0x2262, 0x2263},
{0x2268, 0x2269}, {0x226C, 0x226D}, {0x2270, 0x2281},
{0x2284, 0x2285}, {0x2288, 0x2294}, {0x2296, 0x2298},
{0x229A, 0x22A4}, {0x22A6, 0x22BE}, {0x22C0, 0x2311},
{0x2313, 0x2319}, {0x231C, 0x2328}, {0x232B, 0x23E8},
{0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x2426},
{0x2440, 0x244A}, {0x24EA, 0x24EA}, {0x254C, 0x254F},
{0x2574, 0x257F}, {0x2590, 0x2591}, {0x2596, 0x259F},
{0x25A2, 0x25A2}, {0x25AA, 0x25B1}, {0x25B4, 0x25B5},
{0x25B8, 0x25BB}, {0x25BE, 0x25BF}, {0x25C2, 0x25C5},
{0x25C9, 0x25CA}, {0x25CC, 0x25CD}, {0x25D2, 0x25E1},
{0x25E6, 0x25EE}, {0x25F0, 0x25FC}, {0x25FF, 0x2604},
{0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613},
{0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F},
{0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F},
{0x2662, 0x2662}, {0x2666, 0x2666}, {0x266B, 0x266B},
{0x266E, 0x266E}, {0x2670, 0x267E}, {0x2680, 0x2692},
{0x2694, 0x269D}, {0x26A0, 0x26A0}, {0x26A2, 0x26A9},
{0x26AC, 0x26BC}, {0x26C0, 0x26C3}, {0x26E2, 0x26E2},
{0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709},
{0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B},
{0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756},
{0x2758, 0x2775}, {0x2780, 0x2794}, {0x2798, 0x27AF},
{0x27B1, 0x27BE}, {0x27C0, 0x27E5}, {0x27EE, 0x2984},
{0x2987, 0x2B1A}, {0x2B1D, 0x2B4F}, {0x2B51, 0x2B54},
{0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2C2E},
{0x2C30, 0x2C5E}, {0x2C60, 0x2CF3}, {0x2CF9, 0x2D25},
{0x2D27, 0x2D27}, {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67},
{0x2D6F, 0x2D70}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6},
{0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE},
{0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6},
{0x2DD8, 0x2DDE}, {0x2DE0, 0x2E4F}, {0x303F, 0x303F},
{0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7},
{0xA700, 0xA7BF}, {0xA7C2, 0xA7C6}, {0xA7F7, 0xA82B},
{0xA830, 0xA839}, {0xA840, 0xA877}, {0xA880, 0xA8C5},
{0xA8CE, 0xA8D9}, {0xA8E0, 0xA953}, {0xA95F, 0xA95F},
{0xA980, 0xA9CD}, {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE},
{0xAA00, 0xAA36}, {0xAA40, 0xAA4D}, {0xAA50, 0xAA59},
{0xAA5C, 0xAAC2}, {0xAADB, 0xAAF6}, {0xAB01, 0xAB06},
{0xAB09, 0xAB0E}, {0xAB11, 0xAB16}, {0xAB20, 0xAB26},
{0xAB28, 0xAB2E}, {0xAB30, 0xAB67}, {0xAB70, 0xABED},
{0xABF0, 0xABF9}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB},
{0xD800, 0xDFFF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17},
{0xFB1D, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E},
{0xFB40, 0xFB41}, {0xFB43, 0xFB44}, {0xFB46, 0xFBC1},
{0xFBD3, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7},
{0xFDF0, 0xFDFD}, {0xFE20, 0xFE2F}, {0xFE70, 0xFE74},
{0xFE76, 0xFEFC}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC},
{0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A},
{0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D},
{0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133},
{0x10137, 0x1018E}, {0x10190, 0x1019B}, {0x101A0, 0x101A0},
{0x101D0, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0},
{0x102E0, 0x102FB}, {0x10300, 0x10323}, {0x1032D, 0x1034A},
{0x10350, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x103C3},
{0x103C8, 0x103D5}, {0x10400, 0x1049D}, {0x104A0, 0x104A9},
{0x104B0, 0x104D3}, {0x104D8, 0x104FB}, {0x10500, 0x10527},
{0x10530, 0x10563}, {0x1056F, 0x1056F}, {0x10600, 0x10736},
{0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805},
{0x10808, 0x10808}, {0x1080A, 0x10835}, {0x10837, 0x10838},
{0x1083C, 0x1083C}, {0x1083F, 0x10855}, {0x10857, 0x1089E},
{0x108A7, 0x108AF}, {0x108E0, 0x108F2}, {0x108F4, 0x108F5},
{0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x1093F, 0x1093F},
{0x10980, 0x109B7}, {0x109BC, 0x109CF}, {0x109D2, 0x10A03},
{0x10A05, 0x10A06}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17},
{0x10A19, 0x10A35}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48},
{0x10A50, 0x10A58}, {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6},
{0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55},
{0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C},
{0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2},
{0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27}, {0x10D30, 0x10D39},
{0x10E60, 0x10E7E}, {0x10F00, 0x10F27}, {0x10F30, 0x10F59},
{0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, {0x0D00, 0x0D0C},
{0x0D0E, 0x0D10}, {0x0D12, 0x0D44}, {0x0D46, 0x0D48},
{0x0D4A, 0x0D4F}, {0x0D54, 0x0D63}, {0x0D66, 0x0D7F},
{0x0D81, 0x0D83}, {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1},
{0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6},
{0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6},
{0x0DD8, 0x0DDF}, {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4},
{0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82},
{0x0E84, 0x0E84}, {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3},
{0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4},
{0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9},
{0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C},
{0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC},
{0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7},
{0x10CD, 0x10CD}, {0x10D0, 0x10FF}, {0x1160, 0x1248},
{0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258},
{0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D},
{0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE},
{0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6},
{0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A},
{0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5},
{0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8},
{0x1700, 0x170C}, {0x170E, 0x1714}, {0x1720, 0x1736},
{0x1740, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770},
{0x1772, 0x1773}, {0x1780, 0x17DD}, {0x17E0, 0x17E9},
{0x17F0, 0x17F9}, {0x1800, 0x180E}, {0x1810, 0x1819},
{0x1820, 0x1878}, {0x1880, 0x18AA}, {0x18B0, 0x18F5},
{0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B},
{0x1940, 0x1940}, {0x1944, 0x196D}, {0x1970, 0x1974},
{0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x19D0, 0x19DA},
{0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C},
{0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD},
{0x1AB0, 0x1AC0}, {0x1B00, 0x1B4B}, {0x1B50, 0x1B7C},
{0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49},
{0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7},
{0x1CD0, 0x1CFA}, {0x1D00, 0x1DF9}, {0x1DFB, 0x1F15},
{0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D},
{0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B},
{0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4},
{0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB},
{0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE},
{0x2000, 0x200F}, {0x2011, 0x2012}, {0x2017, 0x2017},
{0x201A, 0x201B}, {0x201E, 0x201F}, {0x2023, 0x2023},
{0x2028, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034},
{0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064},
{0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080},
{0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8},
{0x20AA, 0x20AB}, {0x20AD, 0x20BF}, {0x20D0, 0x20F0},
{0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108},
{0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120},
{0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152},
{0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F},
{0x217A, 0x2188}, {0x218A, 0x218B}, {0x219A, 0x21B7},
{0x21BA, 0x21D1}, {0x21D3, 0x21D3}, {0x21D5, 0x21E6},
{0x21E8, 0x21FF}, {0x2201, 0x2201}, {0x2204, 0x2206},
{0x2209, 0x220A}, {0x220C, 0x220E}, {0x2210, 0x2210},
{0x2212, 0x2214}, {0x2216, 0x2219}, {0x221B, 0x221C},
{0x2221, 0x2222}, {0x2224, 0x2224}, {0x2226, 0x2226},
{0x222D, 0x222D}, {0x222F, 0x2233}, {0x2238, 0x223B},
{0x223E, 0x2247}, {0x2249, 0x224B}, {0x224D, 0x2251},
{0x2253, 0x225F}, {0x2262, 0x2263}, {0x2268, 0x2269},
{0x226C, 0x226D}, {0x2270, 0x2281}, {0x2284, 0x2285},
{0x2288, 0x2294}, {0x2296, 0x2298}, {0x229A, 0x22A4},
{0x22A6, 0x22BE}, {0x22C0, 0x2311}, {0x2313, 0x2319},
{0x231C, 0x2328}, {0x232B, 0x23E8}, {0x23ED, 0x23EF},
{0x23F1, 0x23F2}, {0x23F4, 0x2426}, {0x2440, 0x244A},
{0x24EA, 0x24EA}, {0x254C, 0x254F}, {0x2574, 0x257F},
{0x2590, 0x2591}, {0x2596, 0x259F}, {0x25A2, 0x25A2},
{0x25AA, 0x25B1}, {0x25B4, 0x25B5}, {0x25B8, 0x25BB},
{0x25BE, 0x25BF}, {0x25C2, 0x25C5}, {0x25C9, 0x25CA},
{0x25CC, 0x25CD}, {0x25D2, 0x25E1}, {0x25E6, 0x25EE},
{0x25F0, 0x25FC}, {0x25FF, 0x2604}, {0x2607, 0x2608},
{0x260A, 0x260D}, {0x2610, 0x2613}, {0x2616, 0x261B},
{0x261D, 0x261D}, {0x261F, 0x263F}, {0x2641, 0x2641},
{0x2643, 0x2647}, {0x2654, 0x265F}, {0x2662, 0x2662},
{0x2666, 0x2666}, {0x266B, 0x266B}, {0x266E, 0x266E},
{0x2670, 0x267E}, {0x2680, 0x2692}, {0x2694, 0x269D},
{0x26A0, 0x26A0}, {0x26A2, 0x26A9}, {0x26AC, 0x26BC},
{0x26C0, 0x26C3}, {0x26E2, 0x26E2}, {0x26E4, 0x26E7},
{0x2700, 0x2704}, {0x2706, 0x2709}, {0x270C, 0x2727},
{0x2729, 0x273C}, {0x273E, 0x274B}, {0x274D, 0x274D},
{0x274F, 0x2752}, {0x2756, 0x2756}, {0x2758, 0x2775},
{0x2780, 0x2794}, {0x2798, 0x27AF}, {0x27B1, 0x27BE},
{0x27C0, 0x27E5}, {0x27EE, 0x2984}, {0x2987, 0x2B1A},
{0x2B1D, 0x2B4F}, {0x2B51, 0x2B54}, {0x2B5A, 0x2B73},
{0x2B76, 0x2B95}, {0x2B97, 0x2C2E}, {0x2C30, 0x2C5E},
{0x2C60, 0x2CF3}, {0x2CF9, 0x2D25}, {0x2D27, 0x2D27},
{0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D70},
{0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE},
{0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6},
{0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE},
{0x2DE0, 0x2E52}, {0x303F, 0x303F}, {0x4DC0, 0x4DFF},
{0xA4D0, 0xA62B}, {0xA640, 0xA6F7}, {0xA700, 0xA7BF},
{0xA7C2, 0xA7CA}, {0xA7F5, 0xA82C}, {0xA830, 0xA839},
{0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9},
{0xA8E0, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD},
{0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36},
{0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2},
{0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E},
{0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E},
{0xAB30, 0xAB6B}, {0xAB70, 0xABED}, {0xABF0, 0xABF9},
{0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF},
{0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36},
{0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41},
{0xFB43, 0xFB44}, {0xFB46, 0xFBC1}, {0xFBD3, 0xFD3F},
{0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFD},
{0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC},
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B},
{0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D},
{0x1003F, 0x1004D}, {0x10050, 0x1005D}, {0x10080, 0x100FA},
{0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018E},
{0x10190, 0x1019C}, {0x101A0, 0x101A0}, {0x101D0, 0x101FD},
{0x10280, 0x1029C}, {0x102A0, 0x102D0}, {0x102E0, 0x102FB},
{0x10300, 0x10323}, {0x1032D, 0x1034A}, {0x10350, 0x1037A},
{0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5},
{0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3},
{0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563},
{0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755},
{0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808},
{0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C},
{0x1083F, 0x10855}, {0x10857, 0x1089E}, {0x108A7, 0x108AF},
{0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x1091B},
{0x1091F, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x109B7},
{0x109BC, 0x109CF}, {0x109D2, 0x10A03}, {0x10A05, 0x10A06},
{0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A35},
{0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, {0x10A50, 0x10A58},
{0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, {0x10AEB, 0x10AF6},
{0x10B00, 0x10B35}, {0x10B39, 0x10B55}, {0x10B58, 0x10B72},
{0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF},
{0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2},
{0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, {0x10E60, 0x10E7E},
{0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, {0x10EB0, 0x10EB1},
{0x10F00, 0x10F27}, {0x10F30, 0x10F59}, {0x10FB0, 0x10FCB},
{0x10FE0, 0x10FF6}, {0x11000, 0x1104D}, {0x11052, 0x1106F},
{0x1107F, 0x110C1}, {0x110CD, 0x110CD}, {0x110D0, 0x110E8},
{0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11146},
{0x11150, 0x11176}, {0x11180, 0x111CD}, {0x111D0, 0x111DF},
{0x111E1, 0x111F4}, {0x11200, 0x11211}, {0x11213, 0x1123E},
{0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D},
{0x1128F, 0x1129D}, {0x1129F, 0x112A9}, {0x112B0, 0x112EA},
{0x112F0, 0x112F9}, {0x11300, 0x11303}, {0x11305, 0x1130C},
{0x1130F, 0x11310}, {0x11313, 0x11328}, {0x1132A, 0x11330},
{0x11332, 0x11333}, {0x11335, 0x11339}, {0x1133B, 0x11344},
{0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350},
{0x11357, 0x11357}, {0x1135D, 0x11363}, {0x11366, 0x1136C},
{0x11370, 0x11374}, {0x11400, 0x11459}, {0x1145B, 0x1145B},
{0x1145D, 0x1145F}, {0x11480, 0x114C7}, {0x114D0, 0x114D9},
{0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644},
{0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B8},
{0x116C0, 0x116C9}, {0x11700, 0x1171A}, {0x1171D, 0x1172B},
{0x11730, 0x1173F}, {0x11800, 0x1183B}, {0x118A0, 0x118F2},
{0x118FF, 0x118FF}, {0x119A0, 0x119A7}, {0x119AA, 0x119D7},
{0x119DA, 0x119E4}, {0x11A00, 0x11A47}, {0x11A50, 0x11AA2},
{0x11AC0, 0x11AF8}, {0x11C00, 0x11C08}, {0x11C0A, 0x11C36},
{0x11C38, 0x11C45}, {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F},
{0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06},
{0x11D08, 0x11D09}, {0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A},
{0x11D3C, 0x11D3D}, {0x11D3F, 0x11D47}, {0x11D50, 0x11D59},
{0x11D60, 0x11D65}, {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E},
{0x11D90, 0x11D91}, {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9},
{0x11EE0, 0x11EF8}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399},
{0x110F0, 0x110F9}, {0x11100, 0x11134}, {0x11136, 0x11147},
{0x11150, 0x11176}, {0x11180, 0x111DF}, {0x111E1, 0x111F4},
{0x11200, 0x11211}, {0x11213, 0x1123E}, {0x11280, 0x11286},
{0x11288, 0x11288}, {0x1128A, 0x1128D}, {0x1128F, 0x1129D},
{0x1129F, 0x112A9}, {0x112B0, 0x112EA}, {0x112F0, 0x112F9},
{0x11300, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310},
{0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333},
{0x11335, 0x11339}, {0x1133B, 0x11344}, {0x11347, 0x11348},
{0x1134B, 0x1134D}, {0x11350, 0x11350}, {0x11357, 0x11357},
{0x1135D, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374},
{0x11400, 0x1145B}, {0x1145D, 0x11461}, {0x11480, 0x114C7},
{0x114D0, 0x114D9}, {0x11580, 0x115B5}, {0x115B8, 0x115DD},
{0x11600, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C},
{0x11680, 0x116B8}, {0x116C0, 0x116C9}, {0x11700, 0x1171A},
{0x1171D, 0x1172B}, {0x11730, 0x1173F}, {0x11800, 0x1183B},
{0x118A0, 0x118F2}, {0x118FF, 0x11906}, {0x11909, 0x11909},
{0x1190C, 0x11913}, {0x11915, 0x11916}, {0x11918, 0x11935},
{0x11937, 0x11938}, {0x1193B, 0x11946}, {0x11950, 0x11959},
{0x119A0, 0x119A7}, {0x119AA, 0x119D7}, {0x119DA, 0x119E4},
{0x11A00, 0x11A47}, {0x11A50, 0x11AA2}, {0x11AC0, 0x11AF8},
{0x11C00, 0x11C08}, {0x11C0A, 0x11C36}, {0x11C38, 0x11C45},
{0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7},
{0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D08, 0x11D09},
{0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A}, {0x11D3C, 0x11D3D},
{0x11D3F, 0x11D47}, {0x11D50, 0x11D59}, {0x11D60, 0x11D65},
{0x11D67, 0x11D68}, {0x11D6A, 0x11D8E}, {0x11D90, 0x11D91},
{0x11D93, 0x11D98}, {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8},
{0x11FB0, 0x11FB0}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399},
{0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543},
{0x13000, 0x1342E}, {0x13430, 0x13438}, {0x14400, 0x14646},
{0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69},
@@ -384,20 +389,22 @@ var neutral = table{
{0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1EEF0, 0x1EEF1},
{0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, {0x1F030, 0x1F093},
{0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CE},
{0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10C}, {0x1F12E, 0x1F12F},
{0x1F16A, 0x1F16C}, {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F32C},
{0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, {0x1F394, 0x1F39F},
{0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF}, {0x1F3F1, 0x1F3F3},
{0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441},
{0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A}, {0x1F54F, 0x1F54F},
{0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, {0x1F597, 0x1F5A3},
{0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, {0x1F6C6, 0x1F6CB},
{0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4}, {0x1F6E0, 0x1F6EA},
{0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D8},
{0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859},
{0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0x1F900, 0x1F90B},
{0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D}, {0xE0001, 0xE0001},
{0xE0020, 0xE007F},
{0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10F}, {0x1F12E, 0x1F12F},
{0x1F16A, 0x1F16F}, {0x1F1AD, 0x1F1AD}, {0x1F1E6, 0x1F1FF},
{0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D},
{0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF},
{0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F},
{0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A},
{0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594},
{0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F},
{0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4},
{0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773},
{0x1F780, 0x1F7D8}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847},
{0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD},
{0x1F8B0, 0x1F8B1}, {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B},
{0x1F946, 0x1F946}, {0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D},
{0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA}, {0x1FBF0, 0x1FBF9},
{0xE0001, 0xE0001}, {0xE0020, 0xE007F},
}
var emoji = table{
@@ -425,5 +432,6 @@ var emoji = table{
{0x1F546, 0x1F64F}, {0x1F680, 0x1F6FF}, {0x1F774, 0x1F77F},
{0x1F7D5, 0x1F7FF}, {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F},
{0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F8FF},
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1FFFD},
{0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1FAFF},
{0x1FC00, 0x1FFFD},
}

8
vendor/modules.txt vendored
View File

@@ -19,7 +19,7 @@ github.com/fatih/color
# github.com/fsnotify/fsnotify v1.4.7
## explicit
github.com/fsnotify/fsnotify
# github.com/go-errors/errors v1.0.1
# github.com/go-errors/errors v1.0.2
## explicit
github.com/go-errors/errors
# github.com/go-git/gcfg v1.5.0
@@ -99,10 +99,10 @@ github.com/hashicorp/hcl/json/token
github.com/integrii/flaggy
# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
github.com/jbenet/go-context/io
# github.com/jesseduffield/gocui v0.3.1-0.20200309001002-7765949e1c8a
# github.com/jesseduffield/gocui v0.3.1-0.20200513110002-8cde0b9be542
## explicit
github.com/jesseduffield/gocui
# github.com/jesseduffield/termbox-go v0.0.0-20200130214842-1d31d1faa3c9
# github.com/jesseduffield/termbox-go v0.0.0-20200405031649-4dc645f7e8ba
## explicit
github.com/jesseduffield/termbox-go
# github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
@@ -121,7 +121,7 @@ github.com/mattn/go-colorable
# github.com/mattn/go-isatty v0.0.11
## explicit
github.com/mattn/go-isatty
# github.com/mattn/go-runewidth v0.0.8
# github.com/mattn/go-runewidth v0.0.9
## explicit
github.com/mattn/go-runewidth
# github.com/mgutz/str v1.2.0