1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Improve local shell CWD setting

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-11-19 15:43:06 -05:00
parent 7f852c0b70
commit 93d2caa6ca
4 changed files with 97 additions and 8 deletions

View File

@ -22,7 +22,7 @@
import path from "path"; import path from "path";
import os from "os"; import os from "os";
function resolveTilde(filePath: string) { export function resolveTilde(filePath: string) {
if (filePath[0] === "~" && (filePath[1] === "/" || filePath.length === 1)) { if (filePath[0] === "~" && (filePath[1] === "/" || filePath.length === 1)) {
return filePath.replace("~", os.homedir()); return filePath.replace("~", os.homedir());
} }

View File

@ -19,7 +19,6 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import fse from "fs-extra";
import type { Cluster } from "../cluster"; import type { Cluster } from "../cluster";
import { Kubectl } from "../kubectl"; import { Kubectl } from "../kubectl";
import type WebSocket from "ws"; import type WebSocket from "ws";
@ -34,6 +33,7 @@ import { appEventBus } from "../../common/event-bus";
import logger from "../logger"; import logger from "../logger";
import { TerminalChannels, TerminalMessage } from "../../renderer/api/terminal-api"; import { TerminalChannels, TerminalMessage } from "../../renderer/api/terminal-api";
import { deserialize, serialize } from "v8"; import { deserialize, serialize } from "v8";
import { stat } from "fs/promises";
export class ShellOpenError extends Error { export class ShellOpenError extends Error {
constructor(message: string, public cause: Error) { constructor(message: string, public cause: Error) {
@ -178,10 +178,22 @@ export abstract class ShellSession {
this.websocket.send(serialize(message)); this.websocket.send(serialize(message));
} }
protected async openShellProcess(shell: string, args: string[], env: Record<string, any>) { protected async getCwd(env: Record<string, string>): Promise<string> {
const cwd = (this.cwd && await fse.pathExists(this.cwd)) if (this.cwd) {
? this.cwd try {
: env.HOME; const stats = await stat(this.cwd);
if (stats.isDirectory()) {
return this.cwd;
}
} catch {}
}
return env.HOME;
}
protected async openShellProcess(shell: string, args: string[], env: Record<string, string>) {
const cwd = await this.getCwd(env);
const { shellProcess, resume } = this.ensureShellProcess(shell, args, env, cwd); const { shellProcess, resume } = this.ensureShellProcess(shell, args, env, cwd);
if (resume) { if (resume) {

View File

@ -25,6 +25,11 @@ import { observer, disposeOnUnmount } from "mobx-react";
import type { Cluster } from "../../../../main/cluster"; import type { Cluster } from "../../../../main/cluster";
import { Input } from "../../input"; import { Input } from "../../input";
import { SubTitle } from "../../layout/sub-title"; import { SubTitle } from "../../layout/sub-title";
import { stat } from "fs/promises";
import { Notifications } from "../../notifications";
import { resolveTilde } from "../../../utils";
import { Icon } from "../../icon";
import { PathPicker } from "../../path-picker";
interface Props { interface Props {
cluster: Cluster; cluster: Cluster;
@ -53,8 +58,45 @@ export class ClusterHomeDirSetting extends React.Component<Props> {
); );
} }
saveCWD = () => { saveCWD = async () => {
this.props.cluster.preferences.terminalCWD = this.directory; if (!this.directory) {
this.props.cluster.preferences.terminalCWD = undefined;
return;
}
try {
const dir = resolveTilde(this.directory);
const stats = await stat(dir);
if (stats.isDirectory()) {
this.props.cluster.preferences.terminalCWD = dir;
} else {
Notifications.error(
<>
<b>Shell Working Directory</b>
<p>Provided path is not a directory, your changes were not saved.</p>
</>,
);
}
} catch (error) {
if (error.code === "ENOENT") {
Notifications.error(
<>
<b>Shell Working Directory</b>
<p>Provided path does not exist, your changes were not saved.</p>
</>,
);
} else {
Notifications.error(
<>
<b>Shell Working Directory</b>
<p>Your changes were not saved due to the error bellow</p>
<p>{String(error)}</p>
</>,
);
}
}
}; };
onChangeTerminalCWD = (value: string) => { onChangeTerminalCWD = (value: string) => {
@ -73,6 +115,21 @@ export class ClusterHomeDirSetting extends React.Component<Props> {
this.defaultNamespace = value; this.defaultNamespace = value;
}; };
openFilePicker = () => {
PathPicker.pick({
label: "Choose Working Directory",
buttonLabel: "Pick",
properties: ["openDirectory", "showHiddenFiles"],
onPick: ([directory]) => {
this.props.cluster.preferences.terminalCWD = directory;
},
});
};
onClearCWD = () => {
this.props.cluster.preferences.terminalCWD = undefined;
};
render() { render() {
return ( return (
<> <>
@ -84,6 +141,24 @@ export class ClusterHomeDirSetting extends React.Component<Props> {
onChange={this.onChangeTerminalCWD} onChange={this.onChangeTerminalCWD}
onBlur={this.saveCWD} onBlur={this.saveCWD}
placeholder="$HOME" placeholder="$HOME"
iconRight={
<>
{
this.directory && (
<Icon
material="close"
title="Clear"
onClick={this.onClearCWD}
/>
)
}
<Icon
material="folder"
title="Pick from filesystem"
onClick={this.openFilePicker}
/>
</>
}
/> />
<small className="hint"> <small className="hint">
An explicit start path where the terminal will be launched,{" "} An explicit start path where the terminal will be launched,{" "}

View File

@ -51,6 +51,8 @@ export class PathPicker extends React.Component<PathPickerProps> {
...dialogOptions, ...dialogOptions,
}); });
console.log(filePaths);
if (canceled) { if (canceled) {
await onCancel?.(); await onCancel?.();
} else { } else {