From 16d855a3a00c01ed5e3365d5da532117d6064c80 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Sun, 4 Feb 2018 19:00:26 -0500 Subject: [PATCH] Updates the tree layout for branches - Removes mix-tree support - Avoids nesting on the current branch - Caches basename - Replaces folder icons with theme icons - Folder icons will now follow the file icon theme used - Fixes minor nitpicks --- CHANGELOG.md | 10 ++++++--- README.md | 39 +++++++++++++++++---------------- images/dark/folder.svg | 4 +++- images/light/folder.svg | 4 +++- package.json | 7 +++--- src/git/models/branch.ts | 29 +++++++++++++++++++----- src/ui/config.ts | 18 +++++++-------- src/ui/settings/index.html | 16 ++++++++++---- src/ui/shared/app-base.ts | 5 ++++- src/ui/welcome/index.html | 1 + src/views/branchFolderNode.ts | 51 +++++++++---------------------------------- src/views/branchNode.ts | 18 +++++++-------- src/views/branchesNode.ts | 25 +++++++++++++-------- src/views/folderNode.ts | 1 + src/views/gitExplorer.ts | 9 +++++++- src/views/remoteNode.ts | 14 +++++------- src/views/resultsExplorer.ts | 9 +++++++- 17 files changed, 141 insertions(+), 119 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd4dd0f..a1e6f5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ 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 a tree layout option to branches in the *GitLens* explorer — closes [#258](https://github.com/eamodio/vscode-gitlens/issues/258) thanks to [PR #260](https://github.com/eamodio/vscode-gitlens/pull/260) by Yukai Huang ([@Yukaii](https://github.com/Yukaii))! + +### Fixed +- Fixes [#35](https://github.com/eamodio/vscode-gitlens/issues/35) - Copy Commit Sha to Clipboard not working (linux) + ## [8.0.0-beta3] - 2018-02-03 ### Added - Adds an all-new GitLens welcome page via the *Welcome* (`gitlens.showWelcomePage`) command — provides a welcome / onboarding experience @@ -71,9 +78,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - Removes `gitlens.annotations.line.hover.changes` setting, use `gitlens.hovers.annotations.changes` instead - Removes `gitlens.annotations.line.hover.details` setting, use `gitlens.hovers.annotations.details` instead -### Fixed -- Fixes [#35](https://github.com/eamodio/vscode-gitlens/issues/35) - Copy Commit Sha to Clipboard not working (linux) - ## [7.5.10] - 2018-02-01 ### Added - Adds support for custom remotes with split project/repo url structure — closes [#267](https://github.com/eamodio/vscode-gitlens/issues/267) diff --git a/README.md b/README.md index d826916..8ac7d90 100644 --- a/README.md +++ b/README.md @@ -325,7 +325,7 @@ An on-demand, [customizable](#gitlens-results-view-settings "Jump to the GitLens - Use `#` to search for a commit with id of `` — See [Git docs](https://git-scm.com/docs/git-log "Open Git docs") - Use `~` to search for commits with differences whose patch text contains added/removed lines that match `` — See [Git docs](https://git-scm.com/docs/git-log#git-log--Gltregexgt "Open Git docs") - Use `=` to search for commits with differences that change the number of occurrences of the specified string (i.e. addition/deletion) in a file — See [Git docs](https://git-scm.com/docs/git-log#git-log--Sltstringgt "Open Git docs") - - Provides a *Show in Results* option to show the search results in the **GitLens Results** view + - Provides a *Show in Results* option to show the search results in the *GitLens Results* view --- ### Navigate and Explore @@ -490,15 +490,15 @@ See also [Explorer Settings](#explorer-settings "Jump to the Explorer settings") |Name | Description |-----|------------ -|`gitlens.gitExplorer.autoRefresh`|Specifies whether or not to automatically refresh the **GitLens** view when the repository or the file system changes -|`gitlens.gitExplorer.branches.layout`| Specifies how the **Branches** view will display branches
`list` - display all branches
`tree` - organize branch as folder if branch name contains slashes "/"
`mix-tree` - display branch folders along with normal branch alphabetically -|`gitlens.gitExplorer.enabled`|Specifies whether or not to show the **GitLens** view" -|`gitlens.gitExplorer.files.compact`|Specifies whether or not to compact (flatten) unnecessary file nesting in the **GitLens** view
Only applies when displaying files as a `tree` or `auto` -|`gitlens.gitExplorer.files.layout`|Specifies how the **GitLens** view will display files
`auto` - automatically switches between displaying files as a `tree` or `list` based on the `gitlens.gitExplorer.files.threshold` setting and the number of files at each nesting level
`list` - displays files as a list
`tree` - displays files as a tree -|`gitlens.gitExplorer.files.threshold`|Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the **GitLens** view
Only applies when displaying files as `auto` -|`gitlens.gitExplorer.includeWorkingTree`|Specifies whether or not to include working tree files inside the `Repository Status` node of the **GitLens** view -|`gitlens.gitExplorer.showTrackingBranch`|Specifies whether or not to show the tracking branch when displaying local branches in the **GitLens** view" -|`gitlens.gitExplorer.view`|Specifies the starting view (mode) of the **GitLens** view
`auto` - shows the last selected view, defaults to `repository`
`history` - shows the commit history of the active file
`repository` - shows a repository explorer" +|`gitlens.gitExplorer.autoRefresh`|Specifies whether or not to automatically refresh the *GitLens* explorer when the repository or the file system changes +|`gitlens.gitExplorer.branches.layout`|Specifies how the *GitLens* explorer will display branches
`list` - displays branches as a list
`tree` - displays branches as a tree when branch names contain slashes `/` +|`gitlens.gitExplorer.enabled`|Specifies whether or not to show the *GitLens* explorer" +|`gitlens.gitExplorer.files.compact`|Specifies whether or not to compact (flatten) unnecessary file nesting in the *GitLens* explorer
Only applies when displaying files as a `tree` or `auto` +|`gitlens.gitExplorer.files.layout`|Specifies how the *GitLens* explorer will display files
`auto` - automatically switches between displaying files as a `tree` or `list` based on the `gitlens.gitExplorer.files.threshold` setting and the number of files at each nesting level
`list` - displays files as a list
`tree` - displays files as a tree +|`gitlens.gitExplorer.files.threshold`|Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the *GitLens* explorer
Only applies when displaying files as `auto` +|`gitlens.gitExplorer.includeWorkingTree`|Specifies whether or not to include working tree files inside the `Repository Status` node of the *GitLens* explorer +|`gitlens.gitExplorer.showTrackingBranch`|Specifies whether or not to show the tracking branch when displaying local branches in the *GitLens* explorer" +|`gitlens.gitExplorer.view`|Specifies the starting view (mode) of the *GitLens* explorer
`auto` - shows the last selected view, defaults to `repository`
`history` - shows the commit history of the active file
`repository` - shows a repository explorer" ### GitLens Results View Settings @@ -506,20 +506,20 @@ See also [Explorer Settings](#explorer-settings "Jump to the Explorer settings") |Name | Description |-----|------------ -|`gitlens.resultsExplorer.files.compact`|Specifies whether or not to compact (flatten) unnecessary file nesting in the **GitLens Results** view
Only applies when displaying files as a `tree` or `auto` -|`gitlens.resultsExplorer.files.layout`|Specifies how the **GitLens Results** view will display files
`auto` - automatically switches between displaying files as a `tree` or `list` based on the `gitlens.resultsExplorer.files.threshold` setting and the number of files at each nesting level
`list` - displays files as a list
`tree` - displays files as a tree -|`gitlens.resultsExplorer.files.threshold`|Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the **GitLens Results** view
Only applies when displaying files as `auto` +|`gitlens.resultsExplorer.files.compact`|Specifies whether or not to compact (flatten) unnecessary file nesting in the *GitLens Results* view
Only applies when displaying files as a `tree` or `auto` +|`gitlens.resultsExplorer.files.layout`|Specifies how the *GitLens Results* view will display files
`auto` - automatically switches between displaying files as a `tree` or `list` based on the `gitlens.resultsExplorer.files.threshold` setting and the number of files at each nesting level
`list` - displays files as a list
`tree` - displays files as a tree +|`gitlens.resultsExplorer.files.threshold`|Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the *GitLens Results* view
Only applies when displaying files as `auto` ### Explorer Settings |Name | Description |-----|------------ -|`gitlens.explorers.avatars`|Specifies whether or not to show avatar images instead of commit (or status) icons in the **GitLens** and **GitLens Results** views -|`gitlens.explorers.commitFileFormat`|Specifies the format of a committed file in the **GitLens** and **GitLens Results** views
Available tokens
${directory} - directory name
${file} - file name
${filePath} - formatted file name and path
${path} - full file path -|`gitlens.explorers.commitFormat`|Specifies the format of committed changes in the **GitLens** and **GitLens Results** views
Available tokens
${id} - commit id
${author} - commit author
${message} - commit message
${ago} - relative commit date (e.g. 1 day ago)
${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)
${authorAgo} - commit author, relative commit date
See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting -|`gitlens.explorers.stashFileFormat`|Specifies the format of a stashed file in the **GitLens** and **GitLens Results** views
Available tokens
${directory} - directory name
${file} - file name
${filePath} - formatted file name and path
${path} - full file path -|`gitlens.explorers.stashFormat`|Specifies the format of stashed changes in the **GitLens** and **GitLens Results** views
Available tokens
${id} - commit id
${author} - commit author
${message} - commit message
${ago} - relative commit date (e.g. 1 day ago)
${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)
${authorAgo} - commit author, relative commit date
See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting -|`gitlens.explorers.statusFileFormat`|Specifies the format of the status of a working or committed file in the **GitLens** and **GitLens Results** views
Available tokens
${directory} - directory name
${file} - file name
${filePath} - formatted file name and path
${path} - full file path
${working} - optional indicator if the file is uncommitted +|`gitlens.explorers.avatars`|Specifies whether or not to show avatar images instead of commit (or status) icons in the *GitLens* and *GitLens Results* views +|`gitlens.explorers.commitFileFormat`|Specifies the format of a committed file in the *GitLens* and *GitLens Results* views
Available tokens
${directory} - directory name
${file} - file name
${filePath} - formatted file name and path
${path} - full file path +|`gitlens.explorers.commitFormat`|Specifies the format of committed changes in the *GitLens* and *GitLens Results* views
Available tokens
${id} - commit id
${author} - commit author
${message} - commit message
${ago} - relative commit date (e.g. 1 day ago)
${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)
${authorAgo} - commit author, relative commit date
See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting +|`gitlens.explorers.stashFileFormat`|Specifies the format of a stashed file in the *GitLens* and *GitLens Results* views
Available tokens
${directory} - directory name
${file} - file name
${filePath} - formatted file name and path
${path} - full file path +|`gitlens.explorers.stashFormat`|Specifies the format of stashed changes in the *GitLens* and *GitLens Results* views
Available tokens
${id} - commit id
${author} - commit author
${message} - commit message
${ago} - relative commit date (e.g. 1 day ago)
${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)
${authorAgo} - commit author, relative commit date
See https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting +|`gitlens.explorers.statusFileFormat`|Specifies the format of the status of a working or committed file in the *GitLens* and *GitLens Results* views
Available tokens
${directory} - directory name
${file} - file name
${filePath} - formatted file name and path
${path} - full file path
${working} - optional indicator if the file is uncommitted ### Code Lens Settings @@ -647,6 +647,7 @@ Add [`"gitlens.insiders": true`](#general-settings "Jump to GitLens settings") t A big thanks to the people that have contributed to this project: - Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=AmandaCameron)) +- Yukai Huang ([@Yukaii](https://github.com/Yukaii)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=Yukaii)) - Helmut Januschka ([@hjanuschka](https://github.com/hjanuschka)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=hjanuschka)) - Chris Kaczor ([@ckaczor](https://github.com/ckaczor)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=ckaczor)) - Peng Lyu ([@rebornix](https://github.com/rebornix)) — [contributions](https://github.com/eamodio/vscode-gitlens/commits?author=rebornix)) diff --git a/images/dark/folder.svg b/images/dark/folder.svg index f503533..09100fd 100644 --- a/images/dark/folder.svg +++ b/images/dark/folder.svg @@ -1,2 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/images/light/folder.svg b/images/light/folder.svg index 04bd155..ccd1c74 100644 --- a/images/light/folder.svg +++ b/images/light/folder.svg @@ -1,2 +1,4 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/package.json b/package.json index a959dda..d0d544b 100644 --- a/package.json +++ b/package.json @@ -399,13 +399,12 @@ }, "gitlens.gitExplorer.branches.layout": { "type": "string", - "default": "list", + "default": "tree", "enum": [ "list", - "tree", - "mix-tree" + "tree" ], - "description": "Specifies how the `Branches` view will display branches\n `list` - display all branches \n`tree` - organize branch as folder if branch name contains slashes \"\/\"\n `mix-tree` - display branch folders along with normal branch alphabetically", + "description": "Specifies how the `GitLens` explorer will display branches\n `list` - displays branches as a list \n`tree` - displays branches as a tree when branch names contain slashes `/`", "scope": "window" }, "gitlens.gitExplorer.enabled": { diff --git a/src/git/models/branch.ts b/src/git/models/branch.ts index 50f6754..52c1d4f 100644 --- a/src/git/models/branch.ts +++ b/src/git/models/branch.ts @@ -10,7 +10,6 @@ export class GitBranch { ahead: number; behind: number; }; - basename: string; constructor( public readonly repoPath: string, @@ -30,7 +29,6 @@ export class GitBranch { this.current = current; this.name = branch; - this.basename = this.name.split('/').pop() || this.name; this.tracking = tracking === '' || tracking == null ? undefined : tracking; this.state = { ahead: ahead, @@ -38,6 +36,19 @@ export class GitBranch { }; } + private _basename: string | undefined; + getBasename(): string { + if (this._basename === undefined) { + const name = this.getName(); + const index = name.lastIndexOf('/'); + this._basename = index !== -1 + ? name.substring(index + 1) + : name; + } + + return this._basename; + } + private _name: string | undefined; getName(): string { if (this._name === undefined) { @@ -49,10 +60,6 @@ export class GitBranch { return this._name; } - getBasename(): string { - return this.basename; - } - getRemote(): string | undefined { if (this.remote) return GitBranch.getRemote(this.name); if (this.tracking !== undefined) return GitBranch.getRemote(this.tracking); @@ -60,7 +67,17 @@ export class GitBranch { return undefined; } + isValid(): boolean { + return GitBranch.isValid(this.name); + } + static getRemote(branch: string): string { return branch.substring(0, branch.indexOf('/')); } + + static isValid(name: string): boolean { + // If there is whitespace in the name assume this is not a valid branch name + // Deals with detached HEAD states + return name.match(/\s/) === null; + } } \ No newline at end of file diff --git a/src/ui/config.ts b/src/ui/config.ts index e500529..e744983 100644 --- a/src/ui/config.ts +++ b/src/ui/config.ts @@ -34,16 +34,15 @@ export enum DateStyle { Relative = 'relative' } -export enum ExplorerFilesLayout { - Auto = 'auto', +export enum ExplorerBranchesLayout { List = 'list', Tree = 'tree' } -export enum ExplorerBranchesLayout { +export enum ExplorerFilesLayout { + Auto = 'auto', List = 'list', - Tree = 'tree', - MixTree = 'mix-tree' + Tree = 'tree' } export enum FileAnnotationType { @@ -181,10 +180,6 @@ export interface ICodeLensConfig { export interface IExplorersConfig { avatars: boolean; - branches: { - layout: ExplorerBranchesLayout; - }; - files: { layout: ExplorerFilesLayout; compact: boolean; @@ -208,6 +203,11 @@ export interface IExplorersFilesConfig { export interface IGitExplorerConfig { autoRefresh: boolean; + + branches: { + layout: ExplorerBranchesLayout; + }; + enabled: boolean; files: IExplorersFilesConfig; includeWorkingTree: boolean; diff --git a/src/ui/settings/index.html b/src/ui/settings/index.html index 94fd008..d55cf52 100644 --- a/src/ui/settings/index.html +++ b/src/ui/settings/index.html @@ -63,6 +63,14 @@
+ + +
+ +
-

Compacts (flattens) unnecessary file nesting when using a tree layout

+

Compacts (flattens) unnecessary nesting when using a tree layouts

@@ -124,11 +132,11 @@
-
+
-

Compacts (flattens) unnecessary file nesting when using a tree layout

+

Compacts (flattens) unnecessary nesting when using a tree layouts

diff --git a/src/ui/shared/app-base.ts b/src/ui/shared/app-base.ts index bb55718..243239d 100644 --- a/src/ui/shared/app-base.ts +++ b/src/ui/shared/app-base.ts @@ -32,7 +32,10 @@ export abstract class App { for (const el of document.querySelectorAll('select')) { const value = getSettingValue(el.name); - el.querySelector(`option[value='${value}']`)!.selected = true; + const input = el.querySelector(`option[value='${value}']`); + if (input != null) { + input.selected = true; + } } const state = flatten(config); diff --git a/src/ui/welcome/index.html b/src/ui/welcome/index.html index caf2aad..c4825d0 100644 --- a/src/ui/welcome/index.html +++ b/src/ui/welcome/index.html @@ -36,6 +36,7 @@
  • NEWBrand new Welcome experience — you're looking at it
  • NEWBrand new WYSIWYG GitLens Settings editor — GitLens is easier than ever to customize to suit your needs
  • +
  • NEWAdds a tree layout option to branches in the GitLens explorer — thanks to Yukai Huang (@Yukaii)!
  • IMPROVEDReworked settings — clearer, simpler settings
diff --git a/src/views/branchFolderNode.ts b/src/views/branchFolderNode.ts index 198bed0..b3f4852 100644 --- a/src/views/branchFolderNode.ts +++ b/src/views/branchFolderNode.ts @@ -1,10 +1,9 @@ 'use strict'; import { Arrays, Objects } from '../system'; import { TreeItem, TreeItemCollapsibleState } from 'vscode'; -import { Container } from '../container'; -import { Explorer, ExplorerNode, ResourceType } from './explorerNode'; import { BranchNode } from './branchNode'; -import { ExplorerBranchesLayout } from '../configuration'; +// import { Container } from '../container'; +import { Explorer, ExplorerNode, ResourceType } from './explorerNode'; import { GitUri } from '../gitService'; export class BranchFolderNode extends ExplorerNode { @@ -15,9 +14,9 @@ export class BranchFolderNode extends ExplorerNode { public readonly relativePath: string | undefined, public readonly root: Arrays.IHierarchicalItem, private readonly explorer: Explorer - ) { - super(GitUri.fromRepoPath(repoPath)); - } + ) { + super(GitUri.fromRepoPath(repoPath)); + } async getChildren(): Promise { if (this.root.descendants === undefined || this.root.children === undefined) return []; @@ -32,47 +31,17 @@ export class BranchFolderNode extends ExplorerNode { children.push(folder.value); } - if (this.explorer.config.branches.layout === ExplorerBranchesLayout.Tree) { - // sort strategy: current branch / current branch folder - normal branches - other folder branches (alphabetical order) - children.sort((a, b) => { - return (a.current ? -1 : 1) - (b.current ? -1 : 1) || - ((a instanceof BranchNode) ? -1 : 1) - ((b instanceof BranchNode) ? -1 : 1) || - ((a instanceof BranchNode && a.branch.current) ? -1 : 1) - ((b instanceof BranchNode && b.branch.current) ? -1 : 1) || - a.label!.localeCompare(b.label!); - }); - } - return children; - } + } - async getTreeItem(): Promise { - const item = new TreeItem(this.label, this.current ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed); + async getTreeItem(): Promise { + const item = new TreeItem(this.label, TreeItemCollapsibleState.Collapsed); item.contextValue = ResourceType.Folder; - item.iconPath = { - dark: Container.context.asAbsolutePath('images/dark/folder.svg'), - light: Container.context.asAbsolutePath('images/light/folder.svg') - }; + (item as any).resourceUri = this.explorer.folderResourceUri; return item; - } + } get label(): string { return this.branchFolderName; } - - get current(): boolean { - return this.findCurrent(this.root); - } - - // collect whether branch folder containes the current branch recursively - findCurrent(tree: Arrays.IHierarchicalItem): boolean { - if (tree.value !== undefined) { // BranchNode - return tree.value.branch.current; - } else if (tree.children !== undefined) { // BranchFolderNode - return Object.keys(tree.children).reduce((bool, key) => { - return bool || this.findCurrent(tree.children![key]); - }, false); - } else { - return false; - } - } } diff --git a/src/views/branchNode.ts b/src/views/branchNode.ts index bbdf31a..30c0cde 100644 --- a/src/views/branchNode.ts +++ b/src/views/branchNode.ts @@ -2,12 +2,12 @@ import { Iterables } from '../system'; import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { CommitNode } from './commitNode'; +import { ExplorerBranchesLayout } from '../configuration'; import { GlyphChars } from '../constants'; import { Container } from '../container'; import { ExplorerNode, ExplorerRefNode, MessageNode, ResourceType, ShowAllNode } from './explorerNode'; import { GitExplorer } from './gitExplorer'; import { GitBranch, GitUri } from '../gitService'; -import { ExplorerBranchesLayout } from '../configuration'; export class BranchNode extends ExplorerRefNode { @@ -21,21 +21,19 @@ export class BranchNode extends ExplorerRefNode { super(uri); } - get ref(): string { - return this.branch.name; + get current(): boolean { + return this.branch.current; } get label(): string { const branchName = this.branch.getName(); - if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) { - return branchName; - } else { - return !!branchName.match(/\s/) ? branchName : this.branch.getBasename(); - } + if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) return branchName; + + return GitBranch.isValid(branchName) && !this.current ? this.branch.getBasename() : branchName; } - get current(): boolean { - return this.branch.current; + get ref(): string { + return this.branch.name; } async getChildren(): Promise { diff --git a/src/views/branchesNode.ts b/src/views/branchesNode.ts index 98639a3..2a24d7b 100644 --- a/src/views/branchesNode.ts +++ b/src/views/branchesNode.ts @@ -1,13 +1,13 @@ 'use strict'; import { Arrays, Iterables } from '../system'; import { TreeItem, TreeItemCollapsibleState } from 'vscode'; +import { BranchFolderNode } from './branchFolderNode'; import { BranchNode } from './branchNode'; +import { ExplorerBranchesLayout } from '../configuration'; import { Container } from '../container'; import { ExplorerNode, ResourceType } from './explorerNode'; import { GitExplorer } from './gitExplorer'; import { GitUri, Repository } from '../gitService'; -import { BranchFolderNode } from './branchFolderNode'; -import { ExplorerBranchesLayout } from '../configuration'; export class BranchesNode extends ExplorerNode { @@ -26,20 +26,27 @@ export class BranchesNode extends ExplorerNode { branches.sort((a, b) => (a.current ? -1 : 1) - (b.current ? -1 : 1) || a.name.localeCompare(b.name)); - let children = []; // filter local branches const branchNodes = [...Iterables.filterMap(branches, b => b.remote ? undefined : new BranchNode(b, this.uri, this.explorer))]; + if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) return branchNodes; - if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) { - return branchNodes; - } + // Take out the current branch, since that should always be first and un-nested + const current = (branchNodes.length > 0 && branchNodes[0].current) + ? branchNodes.splice(0, 1)[0] + : undefined; const hierarchy = Arrays.makeHierarchical(branchNodes, - n => !!n.branch.name.match(/\s/) ? [n.branch.name] : n.branch.name.split('/'), - (...paths: string[]) => paths.join('/'), this.explorer.config.files.compact); + n => n.branch.isValid() ? n.branch.getName().split('/') : [n.branch.name], + (...paths: string[]) => paths.join('/'), + this.explorer.config.files.compact); const root = new BranchFolderNode(this.repo.path, '', undefined, hierarchy, this.explorer); - children = await root.getChildren() as (BranchFolderNode | BranchNode)[]; + const children = await root.getChildren() as (BranchFolderNode | BranchNode)[]; + + // If we found a current branch, insert it at the start + if (current !== undefined) { + children.splice(0, 0, current); + } return children; } diff --git a/src/views/folderNode.ts b/src/views/folderNode.ts index 1ad276b..fb8b42b 100644 --- a/src/views/folderNode.ts +++ b/src/views/folderNode.ts @@ -63,6 +63,7 @@ export class FolderNode extends ExplorerNode { // TODO: Change this to expanded once https://github.com/Microsoft/vscode/issues/30918 is fixed const item = new TreeItem(this.label, TreeItemCollapsibleState.Collapsed); item.contextValue = ResourceType.Folder; + (item as any).resourceUri = this.explorer.folderResourceUri; return item; } diff --git a/src/views/gitExplorer.ts b/src/views/gitExplorer.ts index 354e018..beab9f1 100644 --- a/src/views/gitExplorer.ts +++ b/src/views/gitExplorer.ts @@ -1,6 +1,6 @@ 'use strict'; import { Functions } from '../system'; -import { commands, ConfigurationChangeEvent, ConfigurationTarget, Disposable, Event, EventEmitter, TextDocumentShowOptions, TextEditor, TreeDataProvider, TreeItem, Uri, window } from 'vscode'; +import { commands, ConfigurationChangeEvent, ConfigurationTarget, Disposable, Event, EventEmitter, TextDocumentShowOptions, TextEditor, TreeDataProvider, TreeItem, Uri, window, workspace } from 'vscode'; import { UriComparer } from '../comparers'; import { configuration, ExplorerFilesLayout, GitExplorerView, IExplorersConfig, IGitExplorerConfig } from '../configuration'; import { CommandContext, GlyphChars, setCommandContext, WorkspaceState } from '../constants'; @@ -138,6 +138,13 @@ export class GitExplorer extends Disposable implements TreeDataProvider | undefined; async getChildren(node?: ExplorerNode): Promise { diff --git a/src/views/remoteNode.ts b/src/views/remoteNode.ts index 4c19ce1..13529ed 100644 --- a/src/views/remoteNode.ts +++ b/src/views/remoteNode.ts @@ -1,13 +1,13 @@ 'use strict'; import { Arrays, Iterables } from '../system'; import { TreeItem, TreeItemCollapsibleState } from 'vscode'; +import { BranchFolderNode } from './branchFolderNode'; import { BranchNode } from './branchNode'; +import { ExplorerBranchesLayout } from '../configuration'; import { GlyphChars } from '../constants'; import { ExplorerNode, ResourceType } from './explorerNode'; import { GitExplorer } from './gitExplorer'; import { GitRemote, GitRemoteType, GitUri, Repository } from '../gitService'; -import { BranchFolderNode } from './branchFolderNode'; -import { ExplorerBranchesLayout } from '../configuration'; export class RemoteNode extends ExplorerNode { @@ -26,23 +26,19 @@ export class RemoteNode extends ExplorerNode { branches.sort((a, b) => a.name.localeCompare(b.name)); - let children = []; // filter remote branches const branchNodes = [...Iterables.filterMap(branches, b => !b.remote || !b.name.startsWith(this.remote.name) ? undefined : new BranchNode(b, this.uri, this.explorer))]; - - if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) { - return branchNodes; - } + if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) return branchNodes; const hierarchy = Arrays.makeHierarchical( branchNodes, - n => !!n.branch.name.match(/\s/) ? [n.branch.name] : n.branch.name.split('/').slice(1), // remove remote name + n => n.branch.isValid() ? n.branch.getName().split('/') : [n.branch.name], (...paths: string[]) => paths.join('/'), this.explorer.config.files.compact ); const root = new BranchFolderNode(this.repo.path, '', undefined, hierarchy, this.explorer); - children = await root.getChildren() as (BranchFolderNode | BranchNode)[]; + const children = await root.getChildren() as (BranchFolderNode | BranchNode)[]; return children; } diff --git a/src/views/resultsExplorer.ts b/src/views/resultsExplorer.ts index fd31924..45160e4 100644 --- a/src/views/resultsExplorer.ts +++ b/src/views/resultsExplorer.ts @@ -1,6 +1,6 @@ 'use strict'; import { Functions, Strings } from '../system'; -import { commands, ConfigurationChangeEvent, ConfigurationTarget, Disposable, Event, EventEmitter, TreeDataProvider, TreeItem, window } from 'vscode'; +import { commands, ConfigurationChangeEvent, ConfigurationTarget, Disposable, Event, EventEmitter, TreeDataProvider, TreeItem, Uri, window, workspace } from 'vscode'; import { configuration, ExplorerFilesLayout, IExplorersConfig, IResultsExplorerConfig } from '../configuration'; import { CommandContext, GlyphChars, setCommandContext, WorkspaceState } from '../constants'; import { Container } from '../container'; @@ -70,6 +70,13 @@ export class ResultsExplorer extends Disposable implements TreeDataProvider(WorkspaceState.ResultsExplorerKeepResults, false); }