Skip to content

Commit 6c674e3

Browse files
authoredJun 3, 2024··
open from url (#64)
1 parent ae2595c commit 6c674e3

File tree

6 files changed

+118
-3
lines changed

6 files changed

+118
-3
lines changed
 

‎CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## 3.2.0 - 2024-06-02
11+
12+
### Added
13+
14+
- added "Open from URL" command to open a workspace file from a GitHub repository URL. (#64)
15+
1016
## 3.1.0 - 2024-06-02
1117

1218
### Added

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ With `vsce` installed from NPM (`yarn global add vsce`), clone [this repo](https
4141
| `Githubinator: Repository` ||| open repo | N/A |
4242
| `Githubinator: History` ||| open history | N/A |
4343
| `Githubinator: Open Pull Request` ||| open pull request | N/A |
44+
| `Githubinator: Open from URL` | N/A | N/A | open file | N/A |
4445
| `Githubinator: Compare` ||| compare branch | N/A |
4546

4647
The "main" branch is configured via `githubinator.mainBranches` (see "Extension Settings" below).

‎package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "githubinator",
33
"displayName": "Githubinator",
44
"description": "Quickly open files on Github and other providers. View blame information, copy permalinks and more. See the \"commands\" section of the README for more details.",
5-
"version": "3.1.0",
5+
"version": "3.2.0",
66
"publisher": "chdsbd",
77
"license": "SEE LICENSE IN LICENSE",
88
"icon": "images/logo256.png",
@@ -58,6 +58,11 @@
5858
"title": "Copy",
5959
"category": "Githubinator"
6060
},
61+
{
62+
"command": "extension.githubinatorOpenFromUrl",
63+
"title": "Open from URL",
64+
"category": "Githubinator"
65+
},
6166
{
6267
"command": "extension.githubinatorCopyMaster",
6368
"title": "Copy Main",

‎src/extension.ts

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as vscode from "vscode"
22
import * as git from "./git"
33
import { providers, IUrlInfo, createSha, createBranch } from "./providers"
44
import { getRelativeFilePath } from "./utils"
5+
import { openFileFromGitHubUrl } from "./openfromUrl"
56

67
const COMMANDS: [string, IGithubinator][] = [
78
[
@@ -84,6 +85,11 @@ export function activate(context: vscode.ExtensionContext) {
8485
)
8586
context.subscriptions.push(disposable)
8687
})
88+
vscode.commands.registerCommand(
89+
"extension.githubinatorOpenFromUrl",
90+
openFileFromGitHubUrl,
91+
)
92+
8793
console.log("githubinator.active.complete")
8894
}
8995

‎src/openfromUrl.ts

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import * as vscode from "vscode"
2+
3+
function strToLocation(
4+
x: string | null,
5+
): { line: number; character: number } | null {
6+
if (!x) {
7+
return null
8+
}
9+
const line = Number(x.split("C")[0].split("L")[1]) - 1 || null
10+
const character = Number(x.split("C")[1]) - 1 || 0
11+
12+
if (line == null) {
13+
return null
14+
}
15+
16+
return { line, character }
17+
}
18+
19+
function fragmentToSelection(fragment: string): vscode.Selection | null {
20+
const [start, end] = fragment.split("-")
21+
if (!start) {
22+
return null
23+
}
24+
// start: L1C1 or L1
25+
const startLocation = strToLocation(start)
26+
if (!startLocation) {
27+
return null
28+
}
29+
const endLocation = strToLocation(end)
30+
if (!endLocation) {
31+
return new vscode.Selection(
32+
startLocation.line,
33+
startLocation.character,
34+
startLocation.line,
35+
startLocation.character,
36+
)
37+
}
38+
39+
return new vscode.Selection(
40+
startLocation.line,
41+
startLocation.character,
42+
endLocation.line,
43+
endLocation.character,
44+
)
45+
}
46+
47+
/**
48+
* We only support GitHub for now.
49+
*/
50+
export async function openFileFromGitHubUrl() {
51+
const input = await vscode.window.showInputBox({
52+
title: "Paste URL to open",
53+
placeHolder:
54+
"https://github.com/owner/repo/blob/branch/file.js#L1C1-L10C10",
55+
})
56+
if (!input) {
57+
return
58+
}
59+
const url = vscode.Uri.parse(input)
60+
61+
// we only support simple blob/branch/ paths.
62+
// if a branch name has a / in it, this won't work.
63+
//
64+
// /org/repo/blob/branch/my/file.js -> /my/file.js
65+
const path =
66+
"/" +
67+
url.path
68+
.split("/")
69+
.slice(5)
70+
.join("/")
71+
if (!path) {
72+
return
73+
}
74+
const selection = fragmentToSelection(url.fragment)
75+
const results = await Promise.allSettled(
76+
vscode.workspace.workspaceFolders?.map(async folder => {
77+
const doc = await vscode.workspace.openTextDocument(
78+
folder.uri.fsPath + path,
79+
)
80+
81+
const editor = await vscode.window.showTextDocument(doc)
82+
if (selection) {
83+
editor.selections = [selection]
84+
}
85+
}) ?? [],
86+
)
87+
88+
for (const result of results) {
89+
// we were able to open the file in at least one workspace.
90+
if (result.status === "fulfilled") {
91+
return
92+
}
93+
}
94+
// don't wait for error message so we can trigger command.
95+
vscode.window.showErrorMessage("Could not open file from URL.")
96+
await vscode.commands.executeCommand("extension.githubinatorOpenFromUrl")
97+
}

‎tsconfig.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"compilerOptions": {
33
"module": "commonjs",
4-
"target": "es6",
4+
"target": "es2020",
55
"outDir": "out",
6-
"lib": ["es6"],
6+
"lib": ["es2020"],
77
"sourceMap": true,
88
"rootDir": "src",
99
"esModuleInterop": true,

0 commit comments

Comments
 (0)
Please sign in to comment.