From 0a505d3277f271dc73a3c7b2a5f5f6685149277a Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 10 Jul 2019 12:46:31 -0400 Subject: [PATCH] Adds per-comparision notation selection commands Changes working tree/branch comparision selection to be per-comparison --- CHANGELOG.md | 10 ++ README.md | 4 +- images/dark/icon-compare-threedot.svg | 4 + images/dark/icon-compare-twodot.svg | 4 + images/light/icon-compare-threedot.svg | 4 + images/light/icon-compare-twodot.svg | 4 + package.json | 204 ++++++++++++++++++++++----------- src/constants.ts | 10 +- src/views/compareView.ts | 8 +- src/views/nodes/compareBranchNode.ts | 86 +++++++++++--- src/views/nodes/compareResultsNode.ts | 39 +++++-- src/views/repositoriesView.ts | 16 +-- src/views/viewCommands.ts | 15 +++ 13 files changed, 300 insertions(+), 108 deletions(-) create mode 100644 images/dark/icon-compare-threedot.svg create mode 100644 images/dark/icon-compare-twodot.svg create mode 100644 images/light/icon-compare-threedot.svg create mode 100644 images/light/icon-compare-twodot.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 42f170e..a6d3c20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Added + +- Adds _Switch to Two-dot Comparison_ and _Switch to Three-dot Comparison_ commands to specify whether to use the symmetric difference (three-dot) notation or the range (two-dot) notation for the comparison — applies to all comparisons in the views + +### Changed + +- Changes the _Switch to Working Tree Comparison_ and _Switch to Branch Comparison_ commands to only affect the current comparison, rather than changing the `gitlens.views.repositories.showBranchComparison` setting + ## [9.8.3] - 2019-07-09 ### Added diff --git a/README.md b/README.md index 72b4e46..9c8f8f2 100644 --- a/README.md +++ b/README.md @@ -289,7 +289,7 @@ The repositories view provides the following features, - An inline toolbar provides quick access to the _Open File_, _Copy Commit ID to Clipboard_ (`alt-click` for _Copy Commit Message to Clipboard_), and _Open File on Remote_ (if available) commands - A context menu provides access to more common file revision commands - **\* Files Changed** — lists all of the files changed between the compared revisions - - An inline toolbar provides quick access to the _Switch to Working Tree Comparison_ or _Switch to Branch Comparison_, and _Refresh_ commands + - An inline toolbar provides quick access to the _Switch to Two-dot Comparison_ (when applicable), _Switch to Three-dot Comparison_ (when applicable), _Switch to Working Tree Comparison_ (when applicable), _Switch to Branch Comparison_ (when applicable), and _Refresh_ commands - **Branches** — lists the local branches in the repository @@ -467,7 +467,7 @@ A [customizable](#compare-view-settings- 'Jump to the Compare view settings') vi The compare view provides the following features, - Provides a semi-persistent results view for comparison operations - - An inline toolbar provides quick access to the _Swap Comparison_, _Pin Comparison_ (when applicable), _Unpin Comparison_ (when applicable), _Refresh_, and _Dismiss_ commands + - An inline toolbar provides quick access to the _Pin Comparison_ (when applicable), _Unpin Comparison_ (when applicable), _Switch to Two-dot Comparison_ (when applicable), _Switch to Three-dot Comparison_ (when applicable), _Swap Comparison_, _Refresh_, and _Dismiss_ (when applicable) commands - A context menu provides access to common comparison commands - **\* Commits** — lists the commits between the compared revisions - Expands to provide the message, author, date, and change indicator of each revision (commit) — fully [customizable](#view-settings- 'Jump to the View settings') diff --git a/images/dark/icon-compare-threedot.svg b/images/dark/icon-compare-threedot.svg new file mode 100644 index 0000000..01db5a1 --- /dev/null +++ b/images/dark/icon-compare-threedot.svg @@ -0,0 +1,4 @@ + + + + diff --git a/images/dark/icon-compare-twodot.svg b/images/dark/icon-compare-twodot.svg new file mode 100644 index 0000000..31db9e2 --- /dev/null +++ b/images/dark/icon-compare-twodot.svg @@ -0,0 +1,4 @@ + + + + diff --git a/images/light/icon-compare-threedot.svg b/images/light/icon-compare-threedot.svg new file mode 100644 index 0000000..5b0f47f --- /dev/null +++ b/images/light/icon-compare-threedot.svg @@ -0,0 +1,4 @@ + + + + diff --git a/images/light/icon-compare-twodot.svg b/images/light/icon-compare-twodot.svg new file mode 100644 index 0000000..e0ff914 --- /dev/null +++ b/images/light/icon-compare-twodot.svg @@ -0,0 +1,4 @@ + + + + diff --git a/package.json b/package.json index 2bd9fe3..6b80d33 100644 --- a/package.json +++ b/package.json @@ -1514,7 +1514,6 @@ }, { "type": "string", - "default": "working", "enum": [ "branch", "working" @@ -1525,6 +1524,7 @@ ] } ], + "default": "working", "markdownDescription": "Specifies whether to show a comparison of a user-selected reference (branch, tag. etc) to the current branch or the working tree in the _Repositories_ view", "scope": "window" }, @@ -2610,6 +2610,24 @@ } }, { + "command": "gitlens.views.setComparisonToTwoDot", + "title": "Switch to Two-dot Comparison", + "category": "GitLens", + "icon": { + "dark": "images/dark/icon-compare-twodot.svg", + "light": "images/light/icon-compare-twodot.svg" + } + }, + { + "command": "gitlens.views.setComparisonToThreeDot", + "title": "Switch to Three-dot Comparison", + "category": "GitLens", + "icon": { + "dark": "images/dark/icon-compare-threedot.svg", + "light": "images/light/icon-compare-threedot.svg" + } + }, + { "command": "gitlens.views.terminalCheckoutBranch", "title": "Checkout Branch (via Terminal)", "category": "GitLens" @@ -3457,6 +3475,14 @@ "when": "false" }, { + "command": "gitlens.views.setComparisonToTwoDot", + "when": "false" + }, + { + "command": "gitlens.views.setComparisonToThreeDot", + "when": "false" + }, + { "command": "gitlens.views.terminalCheckoutBranch", "when": "false" }, @@ -3525,6 +3551,14 @@ "when": "false" }, { + "command": "gitlens.views.repositories.setBranchComparisonToWorking", + "when": "false" + }, + { + "command": "gitlens.views.repositories.setBranchComparisonToBranch", + "when": "false" + }, + { "command": "gitlens.views.repositories.setFilesLayoutToAuto", "when": "false" }, @@ -3633,10 +3667,6 @@ "when": "false" }, { - "command": "gitlens.views.compare.swapComparison", - "when": "false" - }, - { "command": "gitlens.views.search.searchCommits", "when": "false" }, @@ -4188,68 +4218,68 @@ "view/item/context": [ { "command": "gitlens.openBranchesInRemote", - "when": "viewItem =~ /gitlens:branches\\b.*?\\+remotes\\b.*?/", + "when": "viewItem =~ /gitlens:branches\\b(?=.*?\\b\\+remotes\\b)/", "group": "inline@98" }, { "command": "gitlens.openBranchesInRemote", - "when": "viewItem =~ /gitlens:branches\\b.*?\\+remotes\\b.*?/", + "when": "viewItem =~ /gitlens:branches\\b(?=.*?\\b\\+remotes\\b)/", "group": "1_gitlens@1" }, { "command": "gitlens.views.star", - "when": "viewItem =~ /gitlens:branch\\b(?!.*?\\+starred\\b.*?)/", + "when": "viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+starred\\b)/", "group": "inline@1" }, { "command": "gitlens.views.unstar", - "when": "viewItem =~ /gitlens:branch\\b.*?\\+starred\\b.*?/", + "when": "viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+starred\\b)/", "group": "inline@2" }, { "command": "gitlens.views.checkout", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/", "group": "inline@10" }, { "command": "gitlens.views.compareWithRemote", - "when": "viewItem =~ /gitlens:branch\\b.*?\\+tracking\\b.*?/", + "when": "viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+tracking\\b)/", "group": "inline@96" }, { "command": "gitlens.views.compareWithHead", - "when": "viewItem =~ /gitlens:(branch\\b(?!.*?\\+current\\b.*?)|commit\\b|stash\\b|tag\\b)/", + "when": "viewItem =~ /gitlens:(branch\\b(?!.*?\\b\\+current\\b)|commit\\b|stash\\b|tag\\b)/", "group": "inline@97", "alt": "gitlens.views.compareWithWorking" }, { "command": "gitlens.views.compareWithWorking", - "when": "viewItem =~ /gitlens:branch\\b.*?\\+current\\b.*?/", + "when": "viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+current\\b)/", "group": "inline@97" }, { "command": "gitlens.openBranchInRemote", - "when": "viewItem =~ /gitlens:branch\\b.*?\\+(tracking|remote)\\b.*?/", + "when": "viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+(tracking|remote)\\b)/", "group": "inline@98" }, { "command": "gitlens.views.checkout", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/", "group": "1_gitlens@1" }, { "command": "gitlens.openBranchInRemote", - "when": "viewItem =~ /gitlens:branch\\b.*?\\+(tracking|remote)\\b.*?/", + "when": "viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+(tracking|remote)\\b)/", "group": "2_gitlens@1" }, { "command": "gitlens.views.compareWithRemote", - "when": "viewItem =~ /gitlens:branch\\b.*?\\+tracking\\b.*?/", + "when": "viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+tracking\\b)/", "group": "7_gitlens@1" }, { "command": "gitlens.views.compareWithHead", - "when": "viewItem =~ /gitlens:(branch\\b(?!.*?\\+current\\b.*?)|commit\\b|stash\\b|tag\\b)/", + "when": "viewItem =~ /gitlens:(branch\\b(?!.*?\\b\\+current\\b)|commit\\b|stash\\b|tag\\b)/", "group": "7_gitlens@2" }, { @@ -4259,7 +4289,7 @@ }, { "command": "gitlens.views.compareAncestryWithWorking", - "when": "viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/", + "when": "viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/", "group": "7_gitlens@4" }, { @@ -4289,27 +4319,27 @@ }, { "command": "gitlens.views.terminalCheckoutBranch", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)//", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)//", "group": "8_gitlens@1" }, { "command": "gitlens.views.terminalRebaseBranchToRemote", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b.*?\\+current\\b.*?\\+tracking\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+current\\b)(?=.*?\\b\\+tracking\\b)/", "group": "8_gitlens@1" }, { "command": "gitlens.views.terminalMergeBranch", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/", "group": "8_gitlens@2" }, { "command": "gitlens.views.terminalRebaseBranch", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/", "group": "8_gitlens@3" }, { "command": "gitlens.views.terminalSquashBranchIntoCommit", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/", "group": "8_gitlens@4" }, { @@ -4319,7 +4349,7 @@ }, { "command": "gitlens.views.terminalDeleteBranch", - "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/", "group": "8_gitlens@6" }, { @@ -4329,12 +4359,12 @@ }, { "command": "gitlens.views.star", - "when": "viewItem =~ /gitlens:branch\\b(?!.*?\\+starred\\b.*?)/", + "when": "viewItem =~ /gitlens:branch\\b(?!.*?\\b\\+starred\\b)/", "group": "8_gitlens_@1" }, { "command": "gitlens.views.unstar", - "when": "viewItem =~ /gitlens:branch\\b.*?\\+starred\\b.*?/", + "when": "viewItem =~ /gitlens:branch\\b(?=.*?\\b\\+starred\\b)/", "group": "8_gitlens_@1" }, { @@ -4405,7 +4435,7 @@ }, { "command": "gitlens.copyMessageToClipboard", - "when": "viewItem =~ /gitlens:(commit|stash|file\\b.*?\\+committed\\b.*?)\\b/", + "when": "viewItem =~ /gitlens:(commit|stash|file\\b(?=.*?\\b\\+committed\\b))\\b/", "group": "5_gitlens@2" }, { @@ -4425,12 +4455,12 @@ }, { "command": "gitlens.views.terminalPushCommit", - "when": "!gitlens:readonly && viewItem =~ /gitlens:commit\\b.*?\\+current\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:commit\\b(?=.*?\\b\\+current\\b)/", "group": "8_gitlens@2" }, { "command": "gitlens.views.terminalRevertCommit", - "when": "!gitlens:readonly && viewItem =~ /gitlens:commit\\b.*?\\+current\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:commit\\b(?=.*?\\b\\+current\\b)/", "group": "8_gitlens@3" }, { @@ -4455,39 +4485,39 @@ }, { "command": "gitlens.views.openFile", - "when": "viewItem =~ /gitlens:file\\b(?!.*?\\+history\\b.*?)/", + "when": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+history\\b)/", "group": "inline@1", "alt": "gitlens.views.openFileRevision" }, { "command": "gitlens.views.openFileRevision", - "when": "viewItem =~ /gitlens:file\\b.*?\\+history\\b.*?/", + "when": "viewItem =~ /gitlens:file\\b(?=.*?\\b\\+history\\b)/", "group": "inline@1", "alt": "gitlens.views.openFile" }, { "command": "gitlens.views.stageFile", - "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b.*?\\+unstaged\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b(?=.*?\\b\\+unstaged\\b)/", "group": "inline@1" }, { "command": "gitlens.views.unstageFile", - "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b.*?\\+staged\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b(?=.*?\\b\\+staged\\b)/", "group": "inline@1" }, { "command": "gitlens.views.stageFile", - "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b.*?\\+unstaged\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b(?=.*?\\b\\+unstaged\\b)/", "group": "1_gitlens@1" }, { "command": "gitlens.views.unstageFile", - "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b.*?\\+staged\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b(?=.*?\\b\\+staged\\b)/", "group": "1_gitlens@1" }, { "command": "gitlens.stashSaveFiles", - "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b.*?\\+(un)?staged\\b.*?/", + "when": "!gitlens:readonly && viewItem =~ /gitlens:file\\b(?=.*?\\b\\+(un)?staged\\b)/", "group": "1_gitlens@2" }, { @@ -4512,12 +4542,12 @@ }, { "command": "gitlens.views.openFileRevision", - "when": "viewItem =~ /gitlens:file\\b.*?\\+committed\\b.*?/", + "when": "viewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/", "group": "3_gitlens@2" }, { "command": "gitlens.openFileInRemote", - "when": "viewItem =~ /gitlens:(file\\b(?!.*?\\+(un)?staged\\b.*?)|history:(file|line))\\b/ && gitlens:hasRemotes", + "when": "viewItem =~ /gitlens:(file\\b(?!.*?\\b\\+(un)?staged\\b)|history:(file|line))\\b/ && gitlens:hasRemotes", "group": "inline@99", "alt": "gitlens.copyRemoteFileUrlToClipboard" }, @@ -4533,7 +4563,7 @@ }, { "command": "gitlens.views.openFileRevisionInRemote", - "when": "viewItem =~ /gitlens:file\\b.*?\\+committed\\b.*?/ && gitlens:hasRemotes", + "when": "viewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && gitlens:hasRemotes", "group": "4_gitlens@2" }, { @@ -4613,12 +4643,12 @@ }, { "command": "gitlens.views.setAsDefault", - "when": "viewItem =~ /gitlens:remote\\b(?!.*?\\+default\\b.*?)/", + "when": "viewItem =~ /gitlens:remote\\b(?!.*?\\b\\+default\\b)/", "group": "8_gitlens_@1" }, { "command": "gitlens.views.unsetAsDefault", - "when": "viewItem =~ /gitlens:remote\\b.*?\\+default\\b.*?/", + "when": "viewItem =~ /gitlens:remote\\b(?=.*?\\b\\+default\\b)/", "group": "8_gitlens_@1" }, { @@ -4633,12 +4663,12 @@ }, { "command": "gitlens.views.star", - "when": "viewItem =~ /gitlens:repository\\b(?!.*?\\+starred\\b.*?)/", + "when": "viewItem =~ /gitlens:repository\\b(?!.*?\\b\\+starred\\b)/", "group": "inline@1" }, { "command": "gitlens.views.unstar", - "when": "viewItem =~ /gitlens:repository\\b.*?\\+starred\\b.*?/", + "when": "viewItem =~ /gitlens:repository\\b(?=.*?\\b\\+starred\\b)/", "group": "inline@2" }, { @@ -4704,12 +4734,12 @@ }, { "command": "gitlens.views.star", - "when": "viewItem =~ /gitlens:repository\\b(?!.*?\\+starred\\b.*?)/", + "when": "viewItem =~ /gitlens:repository\\b(?!.*?\\b\\+starred\\b)/", "group": "8_gitlens@1" }, { "command": "gitlens.views.unstar", - "when": "viewItem =~ /gitlens:repository\\b.*?\\+starred\\b.*?/", + "when": "viewItem =~ /gitlens:repository\\b(?=.*?\\b\\+starred\\b)/", "group": "8_gitlens@1" }, { @@ -4745,48 +4775,78 @@ }, { "command": "gitlens.views.dismissNode", - "when": "viewItem =~ /gitlens:(compare:picker:ref|compare:results\\b(?!.*?\\+pinned\\b.*?)|search)\\b(?!:(commits|files))/", + "when": "viewItem =~ /gitlens:(compare:picker:ref|compare:results\\b(?!.*?\\b\\+pinned\\b)|search)\\b(?!:(commits|files))/", "group": "inline@99" }, { - "command": "gitlens.views.repositories.setBranchComparisonToWorking", - "when": "config.gitlens.views.repositories.showBranchComparison == branch && viewItem =~ /gitlens:compare:branch\\b/", + "command": "gitlens.views.setComparisonToTwoDot", + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+threedot\\b)/", "group": "inline@1" }, { - "command": "gitlens.views.repositories.setBranchComparisonToBranch", - "when": "config.gitlens.views.repositories.showBranchComparison == working && viewItem =~ /gitlens:compare:branch\\b/", + "command": "gitlens.views.setComparisonToThreeDot", + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+twodot\\b)/", "group": "inline@1" }, { "command": "gitlens.views.repositories.setBranchComparisonToWorking", - "when": "config.gitlens.views.repositories.showBranchComparison == branch && viewItem =~ /gitlens:compare:branch\\b/", - "group": "1_gitlens@1" + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+branch\\b)/", + "group": "inline@2" }, { "command": "gitlens.views.repositories.setBranchComparisonToBranch", - "when": "config.gitlens.views.repositories.showBranchComparison == working && viewItem =~ /gitlens:compare:branch\\b/", + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+working\\b)/", + "group": "inline@2" + }, + { + "command": "gitlens.views.setComparisonToTwoDot", + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+threedot\\b)/", + "group": "1_gitlens@1" + }, + { + "command": "gitlens.views.setComparisonToThreeDot", + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+twodot\\b)/", "group": "1_gitlens@1" }, { + "command": "gitlens.views.repositories.setBranchComparisonToWorking", + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+branch\\b)/", + "group": "1_gitlens@2" + }, + { + "command": "gitlens.views.repositories.setBranchComparisonToBranch", + "when": "viewItem =~ /gitlens:compare:branch\\b(?=.*?\\b\\+comparing\\b)(?=.*?\\b\\+working\\b)/", + "group": "1_gitlens@2" + }, + { "command": "gitlens.views.compare.pinComparison", - "when": "viewItem =~ /gitlens:compare:results\\b(?!.*?\\+pinned\\b.*?)/", + "when": "viewItem =~ /gitlens:compare:results\\b(?!.*?\\b\\+pinned\\b)/", "group": "inline@1" }, { "command": "gitlens.views.compare.unpinComparison", - "when": "viewItem =~ /gitlens:compare:results\\b.*?\\+pinned\\b.*?/", + "when": "viewItem =~ /gitlens:compare:results\\b(?=.*?\\b\\+pinned\\b)/", "group": "inline@1" }, { + "command": "gitlens.views.setComparisonToTwoDot", + "when": "viewItem =~ /gitlens:compare:results\\b(?=.*?\\b\\+threedot\\b)/", + "group": "inline@2" + }, + { + "command": "gitlens.views.setComparisonToThreeDot", + "when": "viewItem =~ /gitlens:compare:results\\b(?=.*?\\b\\+twodot\\b)/", + "group": "inline@2" + }, + { "command": "gitlens.views.compare.swapComparison", "when": "viewItem =~ /gitlens:compare:results\\b/", - "group": "inline@2" + "group": "inline@3" }, { "command": "gitlens.views.refreshNode", - "when": "viewItem =~ /gitlens:compare:(branch|results)\\b/", - "group": "inline@3" + "when": "viewItem =~ /gitlens:compare:(branch(?=.*?\\b\\+comparing\\b)|results)\\b/", + "group": "inline@4" }, { "command": "gitlens.views.openDirectoryDiff", @@ -4795,18 +4855,28 @@ }, { "command": "gitlens.views.compare.pinComparison", - "when": "viewItem =~ /gitlens:compare:results\\b(?!.*?\\+pinned\\b.*?)/", + "when": "viewItem =~ /gitlens:compare:results\\b(?!.*?\\b\\+pinned\\b)/", "group": "2_gitlens@1" }, { "command": "gitlens.views.compare.unpinComparison", - "when": "viewItem =~ /gitlens:compare:results\\b.*?\\+pinned\\b.*?/", + "when": "viewItem =~ /gitlens:compare:results\\b(?=.*?\\b\\+pinned\\b)/", "group": "2_gitlens@1" }, { + "command": "gitlens.views.setComparisonToTwoDot", + "when": "viewItem =~ /gitlens:compare:results\\b(?=.*?\\b\\+threedot\\b)/", + "group": "2_gitlens@2" + }, + { + "command": "gitlens.views.setComparisonToThreeDot", + "when": "viewItem =~ /gitlens:compare:results\\b(?=.*?\\b\\+twodot\\b)/", + "group": "2_gitlens@2" + }, + { "command": "gitlens.views.compare.swapComparison", "when": "viewItem =~ /gitlens:compare:results\\b/", - "group": "2_gitlens@2" + "group": "2_gitlens@3" }, { "command": "gitlens.views.search.searchCommits", @@ -4875,22 +4945,22 @@ }, { "command": "gitlens.views.stageDirectory", - "when": "viewItem =~ /gitlens:folder\\b.*?\\+working\\b.*?/", + "when": "viewItem =~ /gitlens:folder\\b(?=.*?\\b\\+working\\b)/", "group": "inline@1" }, { "command": "gitlens.views.unstageDirectory", - "when": "viewItem =~ /gitlens:folder\\b.*?\\+working\\b.*?/", + "when": "viewItem =~ /gitlens:folder\\b(?=.*?\\b\\+working\\b)/", "group": "inline@2" }, { "command": "gitlens.views.stageDirectory", - "when": "viewItem =~ /gitlens:folder\\b.*?\\+working\\b.*?/", + "when": "viewItem =~ /gitlens:folder\\b(?=.*?\\b\\+working\\b)/", "group": "1_gitlens@1" }, { "command": "gitlens.views.unstageDirectory", - "when": "viewItem =~ /gitlens:folder\\b.*?\\+working\\b.*?/", + "when": "viewItem =~ /gitlens:folder\\b(?=.*?\\b\\+working\\b)/", "group": "1_gitlens@2" }, { @@ -4900,7 +4970,7 @@ }, { "command": "gitlens.views.dismissNode", - "when": "viewItem =~ /gitlens:(compare:picker:ref|compare:results\\b(?!.*?\\+pinned\\b.*?)|search)\\b(?!:(commits|files))/", + "when": "viewItem =~ /gitlens:(compare:picker:ref|compare:results\\b(?!.*?\\b\\+pinned\\b)|search)\\b(?!:(commits|files))/", "group": "8_gitlens@2" }, { diff --git a/src/constants.ts b/src/constants.ts index ea881e4..9ddb637 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,5 +1,6 @@ 'use strict'; import { commands, TextDocument, TextEditor, window } from 'vscode'; +import { ViewShowBranchComparison } from './config'; export const applicationInsightsKey = 'a9c302f8-6483-4d01-b92c-c159c799c679'; export const extensionId = 'gitlens'; @@ -134,8 +135,14 @@ export const ImageMimetypes: { [key: string]: string } = { '.bmp': 'image/bmp' }; +export interface BranchComparison { + ref: string; + notation: '...' | '..' | undefined; + type: Exclude | undefined; +} + export interface BranchComparisons { - [id: string]: string; + [id: string]: string | BranchComparison; } export interface NamedRef { @@ -147,6 +154,7 @@ export interface PinnedComparison { path: string; ref1: NamedRef; ref2: NamedRef; + notation: '...' | '..' | undefined; } export interface PinnedComparisons { diff --git a/src/views/compareView.ts b/src/views/compareView.ts index 36753e8..6316e2c 100644 --- a/src/views/compareView.ts +++ b/src/views/compareView.ts @@ -126,7 +126,7 @@ export class CompareView extends ViewBase { const pinned = Container.context.workspaceState.get(WorkspaceState.PinnedComparisons); if (pinned == null) return []; - return Object.values(pinned).map(p => new CompareResultsNode(this, p.path, p.ref1, p.ref2, true)); + return Object.values(pinned).map(p => new CompareResultsNode(this, p.path, p.ref1, p.ref2, true, p.notation)); } async updatePinnedComparison(id: string, pin?: PinnedComparison) { @@ -136,11 +136,7 @@ export class CompareView extends ViewBase { } if (pin !== undefined) { - pinned![id] = { - path: pin.path, - ref1: pin.ref1, - ref2: pin.ref2 - }; + pinned![id] = { ...pin }; } else { // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/views/nodes/compareBranchNode.ts b/src/views/nodes/compareBranchNode.ts index 19bf4c5..e58cf49 100644 --- a/src/views/nodes/compareBranchNode.ts +++ b/src/views/nodes/compareBranchNode.ts @@ -1,25 +1,35 @@ 'use strict'; import { TreeItem, TreeItemCollapsibleState } from 'vscode'; -import { BranchComparisons, GlyphChars, WorkspaceState } from '../../constants'; +import { BranchComparison, BranchComparisons, GlyphChars, WorkspaceState } from '../../constants'; import { ResourceType, ViewNode } from './viewNode'; import { RepositoriesView } from '../repositoriesView'; import { GitBranch, GitService, GitUri } from '../../git/gitService'; import { CommandQuickPickItem, ReferencesQuickPick } from '../../quickpicks'; import { CommitsQueryResults, ResultsCommitsNode } from './resultsCommitsNode'; import { Container } from '../../container'; -import { Strings } from '../../system'; +import { log, Strings } from '../../system'; import { ResultsFilesNode } from './resultsFilesNode'; import { ViewShowBranchComparison } from '../../config'; export class CompareBranchNode extends ViewNode { private _children: ViewNode[] | undefined; - private _compareWith: string | undefined; + private _compareWith: BranchComparison | undefined; constructor(uri: GitUri, view: RepositoriesView, parent: ViewNode, public readonly branch: GitBranch) { super(uri, view, parent); const comparisons = Container.context.workspaceState.get(WorkspaceState.BranchComparisons); - this._compareWith = comparisons && comparisons[branch.id]; + const compareWith = comparisons && comparisons[branch.id]; + if (compareWith !== undefined && typeof compareWith === 'string') { + this._compareWith = { + ref: compareWith, + notation: Container.config.advanced.useSymmetricDifferenceNotation ? '...' : '..', + type: this.view.config.showBranchComparison || ViewShowBranchComparison.Working + }; + } + else { + this._compareWith = compareWith; + } } get id(): string { @@ -47,7 +57,7 @@ export class CompareBranchNode extends ViewNode { this.view, this, this.uri.repoPath!, - this._compareWith, + this._compareWith.ref, this.compareWithWorkingTree ? '' : this.branch.ref ) ]; @@ -68,7 +78,7 @@ export class CompareBranchNode extends ViewNode { else { label = `${this.branch.name}${this.compareWithWorkingTree ? ' (working)' : ''}`; description = `${GlyphChars.ArrowLeftRightLong}${GlyphChars.Space} ${GitService.shortenSha( - this._compareWith, + this._compareWith.ref, { working: 'Working Tree' } @@ -84,7 +94,9 @@ export class CompareBranchNode extends ViewNode { command: 'gitlens.views.executeNodeCallback', arguments: [() => this.compareWith()] }; - item.contextValue = ResourceType.CompareBranch; + item.contextValue = `${ResourceType.CompareBranch}${this._compareWith === undefined ? '' : '+comparing'}+${ + this.comparisonNotation === '..' ? 'twodot' : 'threedot' + }+${this.comparisonType}`; item.description = description; item.iconPath = { dark: Container.context.asAbsolutePath( @@ -102,30 +114,68 @@ export class CompareBranchNode extends ViewNode { return item; } - get compareWithWorkingTree() { - return this.view.config.showBranchComparison === ViewShowBranchComparison.Working; + @log() + async setComparisonNotation(comparisonNotation: '...' | '..') { + if (this._compareWith !== undefined) { + await this.updateCompareWith({ ...this._compareWith, notation: comparisonNotation }); + } + + this._children = undefined; + this.view.triggerNodeChange(this); + } + + @log() + async setComparisonType(comparisonType: Exclude) { + if (this._compareWith !== undefined) { + await this.updateCompareWith({ ...this._compareWith, type: comparisonType }); + } + + this._children = undefined; + this.view.triggerNodeChange(this); + } + + private get comparisonNotation() { + return ( + (this._compareWith && this._compareWith.notation) || + (Container.config.advanced.useSymmetricDifferenceNotation ? '...' : '..') + ); + } + + private get comparisonType() { + return ( + (this._compareWith && this._compareWith.type) || + this.view.config.showBranchComparison || + ViewShowBranchComparison.Working + ); + } + + private get compareWithWorkingTree() { + return this.comparisonType === ViewShowBranchComparison.Working; } - async compareWith() { + private async compareWith() { const pick = await new ReferencesQuickPick(this.branch.repoPath).show( `Compare ${this.branch.name}${this.compareWithWorkingTree ? ' (working)' : ''} with${GlyphChars.Ellipsis}`, { allowEnteringRefs: true, checked: this.branch.ref, checkmarks: true } ); if (pick === undefined || pick instanceof CommandQuickPickItem) return; - this._compareWith = pick.ref; - this.updateCompareWith(this._compareWith); + this.updateCompareWith({ + ref: pick.ref, + notation: this.comparisonNotation, + type: this.comparisonType + }); this._children = undefined; this.view.triggerNodeChange(this); } private async getCommitsQuery(maxCount: number | undefined): Promise { - const notation = Container.config.advanced.useSymmetricDifferenceNotation ? '...' : '..'; - const log = await Container.git.getLog(this.uri.repoPath!, { maxCount: maxCount, - ref: `${this._compareWith || 'HEAD'}${notation}${this.compareWithWorkingTree ? '' : this.branch.ref}` + ref: `${(this._compareWith && this._compareWith.ref) || 'HEAD'}${this.comparisonNotation}${ + this.compareWithWorkingTree ? '' : this.branch.ref + }` }); const count = log !== undefined ? log.count : 0; @@ -139,14 +189,16 @@ export class CompareBranchNode extends ViewNode { }; } - private async updateCompareWith(compareWith: string | undefined) { + private async updateCompareWith(compareWith: BranchComparison | undefined) { + this._compareWith = compareWith; + let comparisons = Container.context.workspaceState.get(WorkspaceState.BranchComparisons); if (comparisons === undefined) { comparisons = Object.create(null); } if (compareWith) { - comparisons![this.branch.id] = compareWith; + comparisons![this.branch.id] = { ...compareWith }; } else { // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/views/nodes/compareResultsNode.ts b/src/views/nodes/compareResultsNode.ts index ca10508..874ff5c 100644 --- a/src/views/nodes/compareResultsNode.ts +++ b/src/views/nodes/compareResultsNode.ts @@ -20,7 +20,8 @@ export class CompareResultsNode extends SubscribeableViewNode { public readonly repoPath: string, private _ref1: NamedRef, private _ref2: NamedRef, - private _pinned: boolean = false + private _pinned: boolean = false, + private _comparisonNotation?: '...' | '..' ) { super(GitUri.fromRepoPath(repoPath), view); this._instanceId = instanceId++; @@ -77,10 +78,13 @@ export class CompareResultsNode extends SubscribeableViewNode { } const item = new TreeItem(this.label, this._state || TreeItemCollapsibleState.Collapsed); - item.contextValue = ResourceType.CompareResults; + item.contextValue = `${ResourceType.CompareResults}+${ + this.comparisonNotation === '..' ? 'twodot' : 'threedot' + }`; if (this._pinned) { item.contextValue += '+pinned'; } + item.description = description; if (this._pinned) { item.iconPath = { @@ -103,7 +107,8 @@ export class CompareResultsNode extends SubscribeableViewNode { await this.view.updatePinnedComparison(this.getPinnableId(), { path: this.repoPath, ref1: this.ref1, - ref2: this.ref2 + ref2: this.ref2, + notation: this._comparisonNotation }); this._pinned = true; @@ -119,6 +124,23 @@ export class CompareResultsNode extends SubscribeableViewNode { } @log() + async setComparisonNotation(comparisonNotation: '...' | '..') { + this._comparisonNotation = comparisonNotation; + + if (this._pinned) { + await this.view.updatePinnedComparison(this.getPinnableId(), { + path: this.repoPath, + ref1: this.ref1, + ref2: this.ref2, + notation: this._comparisonNotation + }); + } + + this._children = undefined; + this.view.triggerNodeChange(this); + } + + @log() async swap() { // Save the current id so we can update it later const currentId = this.getPinnableId(); @@ -133,7 +155,8 @@ export class CompareResultsNode extends SubscribeableViewNode { await this.view.updatePinnedComparison(this.getPinnableId(), { path: this.repoPath, ref1: this.ref1, - ref2: this.ref2 + ref2: this.ref2, + notation: this._comparisonNotation }); } @@ -155,12 +178,14 @@ export class CompareResultsNode extends SubscribeableViewNode { return undefined; } - private async getCommitsQuery(maxCount: number | undefined): Promise { - const notation = Container.config.advanced.useSymmetricDifferenceNotation ? '...' : '..'; + private get comparisonNotation() { + return this._comparisonNotation || (Container.config.advanced.useSymmetricDifferenceNotation ? '...' : '..'); + } + private async getCommitsQuery(maxCount: number | undefined): Promise { const log = await Container.git.getLog(this.uri.repoPath!, { maxCount: maxCount, - ref: `${this._ref1.ref}${notation}${this._ref2.ref || 'HEAD'}` + ref: `${this._ref1.ref}${this.comparisonNotation}${this._ref2.ref || 'HEAD'}` }); const count = log !== undefined ? log.count : 0; diff --git a/src/views/repositoriesView.ts b/src/views/repositoriesView.ts index 51c4ccb..dd3f2c4 100644 --- a/src/views/repositoriesView.ts +++ b/src/views/repositoriesView.ts @@ -3,9 +3,10 @@ import { commands, ConfigurationChangeEvent, Event, EventEmitter } from 'vscode' import { configuration, RepositoriesViewConfig, ViewFilesLayout, ViewsConfig } from '../configuration'; import { CommandContext, setCommandContext, WorkspaceState } from '../constants'; import { Container } from '../container'; -import { RepositoriesNode } from './nodes'; +import { RepositoriesNode, ViewNode } from './nodes'; import { ViewBase } from './viewBase'; import { ViewShowBranchComparison } from '../config'; +import { CompareBranchNode } from './nodes/compareBranchNode'; export class RepositoriesView extends ViewBase { constructor() { @@ -58,12 +59,12 @@ export class RepositoriesView extends ViewBase { commands.registerCommand( this.getQualifiedCommand('setBranchComparisonToWorking'), - () => this.setBranchComparison(ViewShowBranchComparison.Working), + n => this.setBranchComparison(n, ViewShowBranchComparison.Working), this ); commands.registerCommand( this.getQualifiedCommand('setBranchComparisonToBranch'), - () => this.setBranchComparison(ViewShowBranchComparison.Branch), + n => this.setBranchComparison(n, ViewShowBranchComparison.Branch), this ); } @@ -122,11 +123,10 @@ export class RepositoriesView extends ViewBase { this._onDidChangeAutoRefresh.fire(); } - private setBranchComparison(comparison: ViewShowBranchComparison) { - return configuration.updateEffective( - configuration.name('views')('repositories')('showBranchComparison').value, - comparison - ); + private setBranchComparison(node: ViewNode, comparisonType: Exclude) { + if (!(node instanceof CompareBranchNode)) return undefined; + + return node.setComparisonType(comparisonType); } private setFilesLayout(layout: ViewFilesLayout) { diff --git a/src/views/viewCommands.ts b/src/views/viewCommands.ts index 5b64fe2..1c5ecd1 100644 --- a/src/views/viewCommands.ts +++ b/src/views/viewCommands.ts @@ -23,6 +23,7 @@ import { BranchTrackingStatusNode, CommitFileNode, CommitNode, + CompareResultsNode, ContributorNode, FileHistoryNode, FolderNode, @@ -42,6 +43,7 @@ import { } from './nodes'; import { Strings } from '../system/string'; import { PagerNode } from './nodes/common'; +import { CompareBranchNode } from './nodes/compareBranchNode'; interface CompareSelectedInfo { ref: string; @@ -129,6 +131,13 @@ export class ViewCommands implements Disposable { commands.registerCommand('gitlens.views.selectFileForCompare', this.selectFileForCompare, this); commands.registerCommand('gitlens.views.compareWithWorking', this.compareWithWorking, this); + commands.registerCommand('gitlens.views.setComparisonToTwoDot', n => this.setComparisonNotation(n, '..'), this); + commands.registerCommand( + 'gitlens.views.setComparisonToThreeDot', + n => this.setComparisonNotation(n, '...'), + this + ); + commands.registerCommand('gitlens.views.terminalCheckoutBranch', this.terminalCheckoutBranch, this); commands.registerCommand('gitlens.views.terminalCreateBranch', this.terminalCreateBranch, this); commands.registerCommand('gitlens.views.terminalDeleteBranch', this.terminalDeleteBranch, this); @@ -598,6 +607,12 @@ export class ViewCommands implements Disposable { return undefined; } + private setComparisonNotation(node: ViewNode, comparisonNotation: '...' | '..') { + if (!(node instanceof CompareResultsNode) && !(node instanceof CompareBranchNode)) return undefined; + + return node.setComparisonNotation(comparisonNotation); + } + terminalCheckoutBranch(node: BranchNode) { if (!(node instanceof BranchNode)) return;