mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 80e1e3ce55 | |||
| 85886afeb4 | |||
| 567e5b662c | |||
| 6b5d2833eb | |||
| b10910d229 | |||
| a7e6224862 | |||
| 5476b45f22 | |||
| efcd8ad03a | |||
| 03acda07b5 | |||
| 32342629c8 | |||
| d2ddf7bc58 | |||
| 01fb217785 | |||
| e5d3db7631 | |||
| c24e99e9ff | |||
| 65cab8a59a | |||
| c737c9df57 | |||
| 17cc4769af | |||
| b4d04c3a57 | |||
| 73e5515e17 | |||
| 6919dbfb5f | |||
| 5e4eb738b3 | |||
| 936e9fa7b4 | |||
| af6486e8bb | |||
| 1038a08789 | |||
| 7a377c4a2a | |||
| 8afa62fff2 | |||
| 97595a7718 | |||
| e4d353b5c1 | |||
| 2462c64793 | |||
| b451ee1ef9 | |||
| 2c64668382 | |||
| de21303fb1 | |||
| f6cdd53fd4 | |||
| 840b69d100 | |||
| 683c66f386 |
+1
-3
@@ -23,7 +23,6 @@
|
||||
"@table-nav/react": "^0.0.7",
|
||||
"@tanstack/match-sorter-utils": "^8.8.4",
|
||||
"@tanstack/react-table": "^8.10.3",
|
||||
"@withfig/autocomplete": "^2.652.3",
|
||||
"autobind-decorator": "^2.4.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"classnames": "^2.3.1",
|
||||
@@ -78,7 +77,6 @@
|
||||
"@types/throttle-debounce": "^5.0.1",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@types/webpack-env": "^1.18.3",
|
||||
"@withfig/autocomplete-types": "^1.30.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-plugin-jsx-control-statements": "^4.1.2",
|
||||
"copy-webpack-plugin": "^12.0.0",
|
||||
@@ -107,4 +105,4 @@
|
||||
"scripts": {
|
||||
"postinstall": "electron-builder install-app-deps"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<link rel="stylesheet" href="dist-dev/waveterm.css" />
|
||||
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/themequery.css" />
|
||||
<link rel="stylesheet" href="public/themes/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="measure"></div>
|
||||
|
||||
+28
-2
@@ -20,8 +20,9 @@ import { MainSideBar } from "./sidebar/main";
|
||||
import { RightSideBar } from "./sidebar/right";
|
||||
import { DisconnectedModal, ClientStopModal } from "@/modals";
|
||||
import { ModalsProvider } from "@/modals/provider";
|
||||
import { Button } from "@/elements";
|
||||
import { Button, TermStyleBlock } from "@/elements";
|
||||
import { ErrorBoundary } from "@/common/error/errorboundary";
|
||||
import { For } from "tsx-control-statements/components";
|
||||
import cn from "classnames";
|
||||
import "./app.less";
|
||||
|
||||
@@ -80,6 +81,21 @@ class App extends React.Component<{}, {}> {
|
||||
rightSidebarModel.saveState(width, false);
|
||||
}
|
||||
|
||||
getSelector(themeKey: string) {
|
||||
const sessions = GlobalModel.getSessionNames();
|
||||
const screens = GlobalModel.getScreenNames();
|
||||
|
||||
if (themeKey === "main") {
|
||||
return ":root";
|
||||
} else if (themeKey in screens) {
|
||||
return `.main-content [data-screenid="${themeKey}"]`;
|
||||
} else if (themeKey in sessions) {
|
||||
return `.main-content [data-sessionid="${themeKey}"]`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const remotesModel = GlobalModel.remotesModel;
|
||||
const disconnected = !GlobalModel.ws.open.get() || !GlobalModel.waveSrvRunning.get();
|
||||
@@ -124,9 +140,12 @@ class App extends React.Component<{}, {}> {
|
||||
const rightSidebarCollapsed = GlobalModel.rightSidebarModel.getCollapsed();
|
||||
const activeMainView = GlobalModel.activeMainView.get();
|
||||
const lightDarkClass = GlobalModel.isDarkTheme.get() ? "is-dark" : "is-light";
|
||||
const termTheme = GlobalModel.getTermTheme();
|
||||
const themeKey = null;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={"version-" + renderVersion}
|
||||
key={`version- + ${renderVersion}`}
|
||||
id="main"
|
||||
className={cn(
|
||||
"platform-" + platform,
|
||||
@@ -151,6 +170,13 @@ class App extends React.Component<{}, {}> {
|
||||
</div>
|
||||
</If>
|
||||
<div ref={this.mainContentRef} className="main-content">
|
||||
<For index="idx" each="themeKey" of={Object.keys(termTheme)}>
|
||||
<TermStyleBlock
|
||||
key={themeKey}
|
||||
themeName={termTheme[themeKey]}
|
||||
selector={this.getSelector(themeKey)}
|
||||
/>
|
||||
</For>
|
||||
<MainSideBar parentRef={this.mainContentRef} />
|
||||
<ErrorBoundary>
|
||||
<PluginsView />
|
||||
|
||||
@@ -7,13 +7,13 @@ import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { GlobalModel, GlobalCommandRunner, RemotesModel, getApi } from "@/models";
|
||||
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown, Button } from "@/common/elements";
|
||||
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/common/elements";
|
||||
import { commandRtnHandler, isBlank } from "@/util/util";
|
||||
import { getTermThemes } from "@/util/themeutil";
|
||||
import * as appconst from "@/app/appconst";
|
||||
|
||||
import "./clientsettings.less";
|
||||
import { MainView } from "@/common/elements/mainview";
|
||||
import { MainView } from "../common/elements/mainview";
|
||||
|
||||
class ClientSettingsKeybindings extends React.Component<{}, {}> {
|
||||
componentDidMount() {
|
||||
@@ -76,14 +76,13 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
|
||||
@boundMethod
|
||||
handleChangeTermTheme(theme: string): void {
|
||||
// For global terminal theme, the key is global, otherwise it's either
|
||||
// For main terminal theme, the key is main, otherwise it's either
|
||||
// sessionId or screenId.
|
||||
const currTheme = GlobalModel.getTermTheme()["global"];
|
||||
const currTheme = GlobalModel.getTermTheme()["main"];
|
||||
if (currTheme == theme) {
|
||||
return;
|
||||
}
|
||||
|
||||
const prtn = GlobalCommandRunner.setGlobalTermTheme(theme, false);
|
||||
const prtn = GlobalCommandRunner.setMainTermTheme(theme, false);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@@ -207,8 +206,8 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
const curFontSize = GlobalModel.getTermFontSize();
|
||||
const curFontFamily = GlobalModel.getTermFontFamily();
|
||||
const curTheme = GlobalModel.getThemeSource();
|
||||
const termThemes = getTermThemes(GlobalModel.termThemes, "Wave Default");
|
||||
const currTermTheme = GlobalModel.getTermTheme()["global"] ?? termThemes[0].label;
|
||||
const termThemes = getTermThemes(GlobalModel.termThemeOptions.get(), "Wave Default");
|
||||
const currTermTheme = GlobalModel.getTermTheme()["main"] ?? termThemes[0].label;
|
||||
|
||||
return (
|
||||
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
width: 100%;
|
||||
border: 2px solid var(--form-element-border-color);
|
||||
border-radius: 6px;
|
||||
line-height: 22px;
|
||||
line-height: 20px;
|
||||
background: var(--form-element-bg-color);
|
||||
|
||||
&.no-label {
|
||||
|
||||
@@ -18,4 +18,5 @@ export { Toggle } from "./toggle";
|
||||
export { Tooltip } from "./tooltip";
|
||||
export { TabIcon } from "./tabicon";
|
||||
export { DatePicker } from "./datepicker";
|
||||
export { TermStyleBlock } from "./termstyleblock";
|
||||
export { CopyButton } from "./copybutton";
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import { GlobalModel } from "@/models";
|
||||
|
||||
const VALID_CSS_VARIABLES = [
|
||||
"--term-black",
|
||||
"--term-red",
|
||||
"--term-green",
|
||||
"--term-yellow",
|
||||
"--term-blue",
|
||||
"--term-magenta",
|
||||
"--term-cyan",
|
||||
"--term-white",
|
||||
"--term-bright-black",
|
||||
"--term-bright-red",
|
||||
"--term-bright-green",
|
||||
"--term-bright-yellow",
|
||||
"--term-bright-blue",
|
||||
"--term-bright-magenta",
|
||||
"--term-bright-cyan",
|
||||
"--term-bright-white",
|
||||
"--term-gray",
|
||||
"--term-cmdtext",
|
||||
"--term-foreground",
|
||||
"--term-background",
|
||||
"--term-selection-background",
|
||||
"--term-cursor-accent",
|
||||
];
|
||||
|
||||
@mobxReact.observer
|
||||
class TermStyleBlock extends React.Component<{
|
||||
themeName: string;
|
||||
selector: string;
|
||||
}> {
|
||||
componentDidMount() {
|
||||
GlobalModel.bumpTermRenderVersion();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
GlobalModel.bumpTermRenderVersion();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.themeName !== this.props.themeName || prevProps.selector !== this.props.selector) {
|
||||
GlobalModel.bumpTermRenderVersion();
|
||||
}
|
||||
}
|
||||
|
||||
isValidCSSColor(color) {
|
||||
const element = document.createElement("div");
|
||||
element.style.color = color;
|
||||
return element.style.color !== "";
|
||||
}
|
||||
|
||||
camelCaseToKebabCase(str) {
|
||||
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
||||
}
|
||||
|
||||
getStyleRules() {
|
||||
const { selector, themeName } = this.props;
|
||||
const termThemeOptions = GlobalModel.getTermThemeOptions();
|
||||
if (!termThemeOptions) {
|
||||
return null;
|
||||
}
|
||||
const theme = termThemeOptions[themeName];
|
||||
if (!theme) {
|
||||
return null;
|
||||
}
|
||||
const styleProperties = Object.entries(theme)
|
||||
.filter(([key, value]) => {
|
||||
const cssVarName = `--term-${this.camelCaseToKebabCase(key)}`;
|
||||
return VALID_CSS_VARIABLES.includes(cssVarName) && this.isValidCSSColor(value);
|
||||
})
|
||||
.map(([key, value]) => `--term-${key}: ${value};`)
|
||||
.join(" ");
|
||||
|
||||
if (!styleProperties) {
|
||||
return null;
|
||||
}
|
||||
return `${selector} { ${styleProperties} }`;
|
||||
}
|
||||
|
||||
render() {
|
||||
const styleRules = this.getStyleRules();
|
||||
if (!styleRules) {
|
||||
return null;
|
||||
}
|
||||
return <style>{styleRules}</style>;
|
||||
}
|
||||
}
|
||||
|
||||
export { TermStyleBlock };
|
||||
@@ -160,6 +160,7 @@ class ScreenSettingsModal extends React.Component<{}, {}> {
|
||||
if (currTheme == theme) {
|
||||
return;
|
||||
}
|
||||
GlobalModel.setTermThemeScope(this.screenId, `.main-content [data-screenid="${this.screenId}"]`);
|
||||
const prtn = GlobalCommandRunner.setScreenTermTheme(this.screenId, theme, false);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
@@ -175,13 +176,8 @@ class ScreenSettingsModal extends React.Component<{}, {}> {
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
let color: string = null;
|
||||
let icon: string = null;
|
||||
let index: number = 0;
|
||||
const curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid);
|
||||
const termThemes = getTermThemes(GlobalModel.termThemes);
|
||||
const currTermTheme = GlobalModel.getTermTheme()[this.screenId] ?? termThemes[0].label;
|
||||
|
||||
return (
|
||||
<Modal className="screen-settings-modal">
|
||||
<Modal.Header onClose={this.closeModal} title={`Tab Settings (${screen.name.get()})`} />
|
||||
|
||||
@@ -99,7 +99,7 @@ class SessionSettingsModal extends React.Component<{}, {}> {
|
||||
if (this.session == null) {
|
||||
return null;
|
||||
}
|
||||
const termThemes = getTermThemes(GlobalModel.termThemes);
|
||||
const termThemes = getTermThemes(GlobalModel.termThemeOptions.get());
|
||||
const currTermTheme = GlobalModel.getTermTheme()[this.sessionId] ?? termThemes[0].label;
|
||||
|
||||
return (
|
||||
|
||||
@@ -649,11 +649,6 @@ class LineContainer extends React.Component<{ historyId: string; width: number }
|
||||
this.line = hvm.getLineById(this.historyItem.lineid);
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
GlobalModel.bumpTermRenderVersion();
|
||||
GlobalModel.termThemeSrcEl.set(null);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleHeightChange(lineNum: number, newHeight: number, oldHeight: number): void {
|
||||
return;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { SuggestionBlob } from "@/autocomplete/runtime/model";
|
||||
import { GlobalModel } from "@/models";
|
||||
import cn from "classnames";
|
||||
import { useMemo } from "react";
|
||||
|
||||
export const AutocompleteSuggestions = async (props: { curLine: string }) => {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
const suggestions = await useMemo(async () => await inputModel.getSuggestions(), [props.curLine]);
|
||||
|
||||
if (!suggestions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const items = suggestions.suggestions.map((s) => `${s.icon} ${s.name}`);
|
||||
|
||||
return (
|
||||
<div className="autocomplete-suggestions">
|
||||
{items.map((item, idx) => (
|
||||
<div key={idx} className={cn("autocomplete-item")}>
|
||||
{item}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@ import { debounce } from "throttle-debounce";
|
||||
import dayjs from "dayjs";
|
||||
import { GlobalCommandRunner, ForwardLineContainer, GlobalModel, ScreenLines, Screen, Session } from "@/models";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { Button } from "@/elements";
|
||||
import { Button, TermStyleBlock } from "@/elements";
|
||||
import { Line } from "@/app/line/linecomps";
|
||||
import { LinesView } from "@/app/line/linesview";
|
||||
import * as util from "@/util/util";
|
||||
@@ -184,10 +184,18 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, {
|
||||
winWidth = screenWidth - realWidth + "px";
|
||||
sidebarWidth = realWidth - MagicLayout.ScreenSidebarWidthPadding + "px";
|
||||
}
|
||||
const termRenderVersion = GlobalModel.termRenderVersion.get();
|
||||
|
||||
return (
|
||||
<div className="screen-view" data-screenid={screen.screenId} ref={this.screenViewRef}>
|
||||
<div className="screen-view" id={screen.screenId} data-screenid={screen.screenId} ref={this.screenViewRef}>
|
||||
{/* <TermStyleBlock
|
||||
scope="screen"
|
||||
termTheme={termTheme}
|
||||
themeSrcEl={this.screenViewRef.current}
|
||||
themeKey={screen.screenId}
|
||||
/> */}
|
||||
<ScreenWindowView
|
||||
key={screen.screenId + ":" + fontSize + ":" + dprStr}
|
||||
key={screen.screenId + ":" + fontSize + ":" + dprStr + ":" + termRenderVersion}
|
||||
session={session}
|
||||
screen={screen}
|
||||
width={winWidth}
|
||||
|
||||
@@ -187,4 +187,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.terminal-theme-dropdown {
|
||||
width: 412px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ScreenTabs } from "./screen/tabs";
|
||||
import { ErrorBoundary } from "@/common/error/errorboundary";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import type { Screen } from "@/models";
|
||||
import { Button } from "@/elements";
|
||||
import { Button, TermStyleBlock } from "@/elements";
|
||||
import { commandRtnHandler } from "@/util/util";
|
||||
import { getTermThemes } from "@/util/themeutil";
|
||||
import { Dropdown } from "@/elements/dropdown";
|
||||
@@ -140,6 +140,7 @@ class TabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
|
||||
@boundMethod
|
||||
handleChangeTermTheme(theme: string): void {
|
||||
console.log("theme", theme);
|
||||
const { screenId } = this.props.screen;
|
||||
const currTheme = GlobalModel.getTermTheme()[screenId];
|
||||
if (currTheme == theme) {
|
||||
@@ -152,7 +153,7 @@ class TabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
render() {
|
||||
const { screen } = this.props;
|
||||
const rptr = screen.curRemote.get();
|
||||
const termThemes = getTermThemes(GlobalModel.termThemes);
|
||||
const termThemes = getTermThemes(GlobalModel.termThemeOptions.get());
|
||||
const currTermTheme = GlobalModel.getTermTheme()[screen.screenId] ?? termThemes[0].label;
|
||||
return (
|
||||
<div className="newtab-container">
|
||||
@@ -175,6 +176,7 @@ class TabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
<If condition={termThemes.length > 0}>
|
||||
<div className="newtab-section">
|
||||
<Dropdown
|
||||
label="Terminal Theme"
|
||||
className="terminal-theme-dropdown"
|
||||
options={termThemes}
|
||||
defaultValue={currTermTheme}
|
||||
@@ -208,59 +210,6 @@ class TabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
@mobxReact.observer
|
||||
class WorkspaceView extends React.Component<{}, {}> {
|
||||
sessionRef = React.createRef<HTMLDivElement>();
|
||||
theme: string;
|
||||
themeReactionDisposer: mobx.IReactionDisposer;
|
||||
|
||||
componentDidMount() {
|
||||
this.setupThemeReaction();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.setupThemeReaction();
|
||||
}
|
||||
|
||||
setupThemeReaction() {
|
||||
if (this.themeReactionDisposer) {
|
||||
this.themeReactionDisposer();
|
||||
}
|
||||
|
||||
// This handles session and screen-level terminal theming.
|
||||
// Ideally, screen-level theming should be handled in the inner-level component, but
|
||||
// the frequent mounting and unmounting of the screen view make it really difficult to work.
|
||||
this.themeReactionDisposer = mobx.reaction(
|
||||
() => {
|
||||
return {
|
||||
termTheme: GlobalModel.getTermTheme(),
|
||||
session: GlobalModel.getActiveSession(),
|
||||
screen: GlobalModel.getActiveScreen(),
|
||||
};
|
||||
},
|
||||
({ termTheme, session, screen }) => {
|
||||
let currTheme = termTheme[session.sessionId];
|
||||
if (termTheme[screen.screenId]) {
|
||||
currTheme = termTheme[screen.screenId];
|
||||
}
|
||||
if (session && currTheme !== this.theme && this.sessionRef.current) {
|
||||
const reset = currTheme == null;
|
||||
const theme = currTheme ?? this.theme;
|
||||
const themeSrcEl = reset ? null : this.sessionRef.current;
|
||||
const rtn = GlobalModel.updateTermTheme(this.sessionRef.current, theme, reset);
|
||||
rtn.then(() => {
|
||||
GlobalModel.termThemeSrcEl.set(themeSrcEl);
|
||||
}).then(() => {
|
||||
GlobalModel.bumpTermRenderVersion();
|
||||
});
|
||||
this.theme = currTheme;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.themeReactionDisposer) {
|
||||
this.themeReactionDisposer();
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
toggleTabSettings() {
|
||||
@@ -277,15 +226,14 @@ class WorkspaceView extends React.Component<{}, {}> {
|
||||
sessionId = session.sessionId;
|
||||
activeScreen = session.getActiveScreen();
|
||||
}
|
||||
|
||||
const isHidden = GlobalModel.activeMainView.get() != "session";
|
||||
const mainSidebarModel = GlobalModel.mainSidebarModel;
|
||||
const termRenderVersion = GlobalModel.termRenderVersion.get();
|
||||
const showTabSettings = GlobalModel.tabSettingsOpen.get();
|
||||
return (
|
||||
<div
|
||||
ref={this.sessionRef}
|
||||
className={cn("mainview", "session-view", { "is-hidden": isHidden })}
|
||||
id={sessionId}
|
||||
data-sessionid={sessionId}
|
||||
style={{
|
||||
width: `${window.innerWidth - mainSidebarModel.getWidth()}px`,
|
||||
@@ -307,11 +255,7 @@ class WorkspaceView extends React.Component<{}, {}> {
|
||||
</div>
|
||||
</If>
|
||||
<ErrorBoundary key="eb">
|
||||
<ScreenView
|
||||
key={`screenview-${sessionId}-${termRenderVersion}`}
|
||||
session={session}
|
||||
screen={activeScreen}
|
||||
/>
|
||||
<ScreenView key={`screenview-${sessionId}`} session={session} screen={activeScreen} />
|
||||
<If condition={activeScreen != null}>
|
||||
<CmdInput key={"cmdinput-" + sessionId} />
|
||||
</If>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Autocomplete parser
|
||||
|
||||
This is the autocomplete parser for Wave. Much of the runtime for this parser is forked from the [@microsoft/inshellisense project](https://github.com/microsoft/inshellisense). We've modified the exec code to proxy commands to the active `waveshell` instance. All suggestions, as with inshellisense, come from the [@withfig/autocomplete project](https://github.com/withfig/autocomplete). We will be supplementing these with some of our own autocomplete for our own `/slashcommands` and `metacommands`.
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from "./runtime/runtime";
|
||||
export * from "./utils/shell";
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import log from "../utils/log";
|
||||
import { runTemplates } from "./template";
|
||||
import { buildExecuteShellCommand } from "./utils";
|
||||
|
||||
const getGeneratorContext = (cwd: string): Fig.GeneratorContext => {
|
||||
return {
|
||||
environmentVariables: Object.fromEntries(
|
||||
Object.entries(process.env).filter((entry): entry is [string, string] => entry[1] != null)
|
||||
),
|
||||
currentWorkingDirectory: cwd,
|
||||
currentProcess: "", // TODO: define current process
|
||||
sshPrefix: "", // deprecated, should be empty
|
||||
isDangerous: false,
|
||||
searchTerm: "", // TODO: define search term
|
||||
};
|
||||
};
|
||||
|
||||
// TODO: add support for caching, trigger, & getQueryTerm
|
||||
export const runGenerator = async (
|
||||
generator: Fig.Generator,
|
||||
tokens: string[],
|
||||
cwd: string
|
||||
): Promise<Fig.Suggestion[]> => {
|
||||
// TODO: support trigger
|
||||
const { script, postProcess, scriptTimeout, splitOn, custom, template, filterTemplateSuggestions } = generator;
|
||||
|
||||
const executeShellCommand = buildExecuteShellCommand(scriptTimeout ?? 5000);
|
||||
const suggestions = [];
|
||||
try {
|
||||
if (script) {
|
||||
const shellInput = typeof script === "function" ? script(tokens) : script;
|
||||
const scriptOutput = Array.isArray(shellInput)
|
||||
? await executeShellCommand({ command: shellInput.at(0) ?? "", args: shellInput.slice(1), cwd })
|
||||
: await executeShellCommand({ ...shellInput, cwd });
|
||||
|
||||
const scriptStdout = scriptOutput.stdout.trim();
|
||||
if (postProcess) {
|
||||
suggestions.push(...postProcess(scriptStdout, tokens));
|
||||
} else if (splitOn) {
|
||||
suggestions.push(...scriptStdout.split(splitOn).map((s) => ({ name: s })));
|
||||
}
|
||||
}
|
||||
|
||||
if (custom) {
|
||||
suggestions.push(...(await custom(tokens, executeShellCommand, getGeneratorContext(cwd))));
|
||||
}
|
||||
|
||||
if (template != null) {
|
||||
const templateSuggestions = await runTemplates(template, cwd);
|
||||
if (filterTemplateSuggestions) {
|
||||
suggestions.push(...filterTemplateSuggestions(templateSuggestions));
|
||||
} else {
|
||||
suggestions.push(...templateSuggestions);
|
||||
}
|
||||
}
|
||||
return suggestions;
|
||||
} catch (e) {
|
||||
const err = typeof e === "string" ? e : e instanceof Error ? e.message : e;
|
||||
log.debug({ msg: "generator failed", err, script, splitOn, template });
|
||||
}
|
||||
return suggestions;
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
export type Suggestion = {
|
||||
name: string;
|
||||
allNames: string[];
|
||||
description?: string;
|
||||
icon: string;
|
||||
priority: number;
|
||||
insertValue?: string;
|
||||
};
|
||||
|
||||
export type SuggestionBlob = {
|
||||
suggestions: Suggestion[];
|
||||
argumentDescription?: string;
|
||||
charactersToDrop?: number;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user