Skip to content

Commit 7d91ec9

Browse files
authored
use which to search nu location, add icon too. (#153)
* use `which` to search `nu` location, add icon too. * also use `env:CARGO_HOME` and fallback to `~/.cargo/` * change behavior in case `nu` cannot be found. if the profile provider returns undefined, users will get a confusing error message: ``` No terminal profile options provided for id "nushell_default" ``` if we instead just return a program name "nu", the error message became: ``` path to shell executable "nu" does not exist ``` which should give the user more clue what went wrong. * add detailed error message on failure. the error message also guide the user to install `nushell` from website and reload vscode. * fix CI failure caused by empty function lint
1 parent 8b78b95 commit 7d91ec9

File tree

2 files changed

+56
-57
lines changed

2 files changed

+56
-57
lines changed

client/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"vscode": "^1.75.0"
1414
},
1515
"dependencies": {
16-
"vscode-languageclient": "^8.1.0"
16+
"vscode-languageclient": "^8.1.0",
17+
"which": "^4.0.0"
1718
},
1819
"devDependencies": {
1920
"@types/vscode": "^1.75.1",

client/src/extension.ts

Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,31 @@ export function activate(context: vscode.ExtensionContext) {
2424
provideTerminalProfile(
2525
token: vscode.CancellationToken
2626
): vscode.ProviderResult<vscode.TerminalProfile> {
27+
const which = require("which");
2728
const path = require("path");
28-
const fs = require("fs");
29-
const glob = require("glob");
30-
const os = require("os");
3129

30+
const PATH_FROM_ENV = process.env["PATH"];
3231
const pathsToCheck = [
32+
PATH_FROM_ENV,
3333
// cargo install location
34-
"~/.cargo/bin/nu",
35-
"~/.cargo/bin/nu.exe",
34+
(process.env["CARGO_HOME"] || "~/.cargo") + "/bin",
3635

3736
// winget on Windows install location
38-
"c:\\program files\\nu\\bin\\nu.exe",
37+
"c:\\program files\\nu\\bin",
3938
// just add a few other drives for fun
40-
"d:\\program files\\nu\\bin\\nu.exe",
41-
"e:\\program files\\nu\\bin\\nu.exe",
42-
"f:\\program files\\nu\\bin\\nu.exe",
39+
"d:\\program files\\nu\\bin",
40+
"e:\\program files\\nu\\bin",
41+
"f:\\program files\\nu\\bin",
4342

4443
// SCOOP:TODO
4544
// all user installed programs and scoop itself install to
4645
// c:\users\<user>\scoop\ unless SCOOP env var is set
4746
// globally installed programs go in
4847
// c:\programdata\scoop unless SCOOP_GLOBAL env var is set
4948
// scoop install location
50-
"~/scoop/apps/nu/*/nu.exe",
51-
"~/scoop/shims/nu.exe",
49+
// SCOOP should already set up the correct `PATH` env var
50+
//"~/scoop/apps/nu/*/nu.exe",
51+
//"~/scoop/shims/nu.exe",
5252

5353
// chocolatey install location - same as winget
5454
// 'c:\\program files\\nu\\bin\\nu.exe',
@@ -60,59 +60,57 @@ export function activate(context: vscode.ExtensionContext) {
6060

6161
// brew install location mac
6262
// intel
63-
"/usr/local/bin/nu",
63+
"/usr/local/bin",
6464
// arm
65-
"/opt/homebrew/bin/nu",
65+
"/opt/homebrew/bin",
6666

6767
// native package manager install location
68-
"/usr/bin/nu",
68+
// standard location should be in `PATH` env var
69+
//"/usr/bin/nu",
6970
];
7071

71-
let found_nushell_path = "";
72-
const home = os.homedir();
73-
74-
for (const cur_val of pathsToCheck) {
75-
// console.log("Inspecting location: " + cur_val);
76-
let constructed_file = "";
77-
if (cur_val.startsWith("~/scoop")) {
78-
// console.log("Found scoop: " + cur_val);
79-
const p = path.join(home, cur_val.slice(1));
80-
// console.log("Expanded ~: " + p);
81-
const file = glob.sync(p, "debug").toString();
82-
// console.log("Glob for files: " + file);
83-
84-
if (file) {
85-
// console.log("Found some file: " + file);
86-
// if there are slashes, reverse them to back slashes
87-
constructed_file = file.replace(/\//g, "\\");
72+
const found_nushell_path = which.sync("nu", {
73+
nothrow: true,
74+
path: pathsToCheck.join(path.delimiter),
75+
});
76+
77+
if (found_nushell_path == null) {
78+
console.log(
79+
"Nushell not found in env:PATH or any of the heuristic locations."
80+
);
81+
// use an async arrow funciton to use `await` inside
82+
return (async () => {
83+
if (
84+
(await vscode.window.showErrorMessage(
85+
"We cannot find a nushell executable in your path or pre-defined locations",
86+
"install from website"
87+
)) &&
88+
(await vscode.env.openExternal(
89+
vscode.Uri.parse("https://www.nushell.sh/")
90+
)) &&
91+
(await vscode.window.showInformationMessage(
92+
"after you install nushell, you might need to reload vscode",
93+
"reload now"
94+
))
95+
) {
96+
vscode.commands.executeCommand("workbench.action.reloadWindow");
8897
}
89-
} else if (cur_val.startsWith("~")) {
90-
constructed_file = path.join(home, cur_val.slice(1));
91-
// console.log("Found ~, constructing path: " + constructed_file);
92-
} else {
93-
constructed_file = cur_val;
94-
}
95-
96-
if (fs.existsSync(constructed_file)) {
97-
// console.log("File exists, returning: " + constructed_file);
98-
found_nushell_path = constructed_file;
99-
break;
100-
} else {
101-
// console.log("File not found: " + constructed_file);
102-
}
98+
// user has already seen error messages, but they didn't click through
99+
// return a promise that never resolve to supress the confusing error
100+
return await new Promise(() => undefined);
101+
})();
103102
}
104103

105-
if (found_nushell_path.length > 0) {
106-
return {
107-
options: {
108-
name: "Nushell",
109-
shellPath: found_nushell_path,
110-
},
111-
};
112-
} else {
113-
console.log("Nushell not found, returning undefined");
114-
return undefined;
115-
}
104+
return {
105+
options: {
106+
name: "Nushell",
107+
shellPath: found_nushell_path,
108+
iconPath: vscode.Uri.joinPath(
109+
context.extensionUri,
110+
"assets/nu.svg"
111+
),
112+
},
113+
};
116114
},
117115
})
118116
);

0 commit comments

Comments
 (0)