Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit c4cac4d

Browse files
committed
Support syncing the file open in topmost browser
When browser is in the context of a file, open a file with the same name after repository is opened.
1 parent a82390f commit c4cac4d

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

src/GitHub.App/Services/GitHubContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ public class GitHubContext
88
public string Branch { get; set; }
99
public int? PullRequest { get; set; }
1010
public int? Issue { get; set; }
11+
public string Path { get; set; }
1112
}
1213
}

src/GitHub.App/Services/GitHubContextService.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ public class GitHubContextService
2626

2727
const string issue = "(?<issue>[0-9]+)";
2828

29+
static readonly string path = $"^{repo}/(?<path>[^ ]+)";
30+
2931
static readonly Regex windowTitleRepositoryRegex = new Regex($"^{owner}/{repo}: ", RegexOptions.Compiled);
3032
static readonly Regex windowTitleBranchRegex = new Regex($"^{owner}/{repo} at {branch} ", RegexOptions.Compiled);
3133
static readonly Regex windowTitlePullRequestRegex = new Regex($" · Pull Request #{pull} · {owner}/{repo} - ", RegexOptions.Compiled);
3234
static readonly Regex windowTitleIssueRegex = new Regex($" · Issue #{issue} · {owner}/{repo} - ", RegexOptions.Compiled);
33-
static readonly Regex windowTitlePathRegex = new Regex($" at {branch} · {owner}/{repo} - ", RegexOptions.Compiled);
35+
static readonly Regex windowTitlePathRegex = new Regex($"{path} at {branch} · {owner}/{repo} - ", RegexOptions.Compiled);
3436
static readonly Regex windowTitleBranchesRegex = new Regex($"Branches · {owner}/{repo} - ", RegexOptions.Compiled);
3537

3638
public GitHubContext FindContextFromUrl(UriString url)
@@ -68,7 +70,7 @@ public IEnumerable<string> FindWindowTitlesForClass(string className = "Chrome_W
6870

6971
public GitHubContext FindContextFromWindowTitle(string windowTitle)
7072
{
71-
var (success, owner, repo, branch, pullRequest, issue) = MatchWindowTitle(windowTitle);
73+
var (success, owner, repo, branch, pullRequest, issue, path) = MatchWindowTitle(windowTitle);
7274
if (!success)
7375
{
7476
return null;
@@ -80,51 +82,52 @@ public GitHubContext FindContextFromWindowTitle(string windowTitle)
8082
RepositoryName = repo,
8183
Branch = branch,
8284
PullRequest = pullRequest,
83-
Issue = issue
85+
Issue = issue,
86+
Path = path
8487
};
8588
}
8689

87-
static (bool success, string owner, string repo, string branch, int? pullRequest, int? issue) MatchWindowTitle(string windowTitle)
90+
static (bool success, string owner, string repo, string branch, int? pullRequest, int? issue, string path) MatchWindowTitle(string windowTitle)
8891
{
8992
var match = windowTitlePathRegex.Match(windowTitle);
9093
if (match.Success)
9194
{
92-
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, match.Groups["branch"].Value, null, null);
95+
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, match.Groups["branch"].Value, null, null, match.Groups["path"].Value);
9396
}
9497

9598
match = windowTitleRepositoryRegex.Match(windowTitle);
9699
if (match.Success)
97100
{
98-
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, null, null);
101+
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, null, null, null);
99102
}
100103

101104
match = windowTitleBranchRegex.Match(windowTitle);
102105
if (match.Success)
103106
{
104-
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, match.Groups["branch"].Value, null, null);
107+
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, match.Groups["branch"].Value, null, null, null);
105108
}
106109

107110
match = windowTitleBranchesRegex.Match(windowTitle);
108111
if (match.Success)
109112
{
110-
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, null, null);
113+
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, null, null, null);
111114
}
112115

113116
match = windowTitlePullRequestRegex.Match(windowTitle);
114117
if (match.Success)
115118
{
116119
int.TryParse(match.Groups["pull"].Value, out int pullRequest);
117-
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, pullRequest, null);
120+
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, pullRequest, null, null);
118121
}
119122

120123
match = windowTitleIssueRegex.Match(windowTitle);
121124
if (match.Success)
122125
{
123126
int.TryParse(match.Groups["issue"].Value, out int issue);
124-
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, null, issue);
127+
return (match.Success, match.Groups["owner"].Value, match.Groups["repo"].Value, null, null, issue, null);
125128
}
126129

127-
return (match.Success, null, null, null, null, null);
130+
return (match.Success, null, null, null, null, null, null);
128131
}
129132

130133
static class User32

src/GitHub.VisualStudio/Commands/OpenFromUrlCommand.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.IO;
3+
using System.Linq;
34
using System.Windows;
45
using System.Threading.Tasks;
56
using System.ComponentModel.Composition;
@@ -64,10 +65,11 @@ public override async Task Execute(string url)
6465
gitHubUrl = null;
6566
}
6667

68+
GitHubContext context = null;
6769
if (gitHubUrl == null)
6870
{
6971
// HACK: Reconstruct a GitHub URL from the topmost browser window
70-
var context = gitHubContextService.Value.FindContextFromBrowser();
72+
context = gitHubContextService.Value.FindContextFromBrowser();
7173
if (context != null)
7274
{
7375
gitHubUrl = $"https://github.com/{context.Owner}/{context.RepositoryName}";
@@ -101,7 +103,7 @@ public override async Task Execute(string url)
101103
}
102104

103105
await TryOpenPullRequest(gitHubUrl);
104-
TryOpenFile(gitHubUrl, repositoryDir);
106+
TryOpenFile(gitHubUrl, context, repositoryDir);
105107
}
106108

107109
static bool ContainsDirectory(string repositoryDir, string solutionDir)
@@ -135,9 +137,9 @@ static string FindSolutionDirectory(Solution solution)
135137
return null;
136138
}
137139

138-
bool TryOpenFile(UriString gitHubUrl, string repositoryDir)
140+
bool TryOpenFile(UriString gitHubUrl, GitHubContext context, string repositoryDir)
139141
{
140-
var path = FindSubPath(gitHubUrl, "/blob/master/");
142+
var path = FindSubPath(gitHubUrl, "/blob/master/") ?? context?.Path;
141143
if (path == null)
142144
{
143145
return false;
@@ -146,6 +148,13 @@ bool TryOpenFile(UriString gitHubUrl, string repositoryDir)
146148
var windowsPath = path.Replace('/', '\\');
147149
var fullPath = Path.Combine(repositoryDir, windowsPath);
148150
if (!File.Exists(fullPath))
151+
{
152+
// Search by filename only
153+
var fileName = Path.GetFileName(path);
154+
fullPath = Directory.EnumerateFiles(repositoryDir, fileName, SearchOption.AllDirectories).FirstOrDefault();
155+
}
156+
157+
if (fullPath == null)
149158
{
150159
return false;
151160
}

test/GitHub.App.UnitTests/Services/GitHubContextServiceTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,16 @@ public void Issue(string windowTitle, int expectIssue)
163163

164164
Assert.That(context.Issue, Is.EqualTo(expectIssue));
165165
}
166+
167+
[TestCase("VisualStudio/mark_github.xaml at master · github/VisualStudio - Google Chrome", "mark_github.xaml")]
168+
[TestCase("VisualStudio/src/GitHub.VisualStudio/Resources/icons at master · github/VisualStudio - Google Chrome", "src/GitHub.VisualStudio/Resources/icons")]
169+
public void Path(string windowTitle, string expectPath)
170+
{
171+
var target = new GitHubContextService();
172+
173+
var context = target.FindContextFromWindowTitle(windowTitle);
174+
175+
Assert.That(context?.Path, Is.EqualTo(expectPath));
176+
}
166177
}
167178
}

0 commit comments

Comments
 (0)