Compare commits

..

44 Commits

Author SHA1 Message Date
Evan Simkowitz e5a168f34c making textareainput functional component 2024-04-08 15:48:05 -07:00
Evan Simkowitz cc547e526b save 2024-04-08 14:20:10 -07:00
Evan Simkowitz 1b1e6edaee Merge branch 'main' into evan/inshellisense 2024-04-08 13:47:17 -07:00
Evan Simkowitz f4aeb92d32 Merge branch 'main' into evan/inshellisense 2024-04-08 13:16:01 -07:00
Evan Simkowitz b780d5b244 Merge branch 'main' into evan/inshellisense 2024-04-08 11:19:25 -07:00
Evan Simkowitz d81a6ed480 Merge branch 'main' into evan/inshellisense 2024-04-05 10:49:22 -07:00
Evan Simkowitz d8393ae50b Merge branch 'main' into evan/inshellisense 2024-04-02 18:48:59 -07:00
Evan Simkowitz 79deb01ea4 save work 2024-04-02 18:48:38 -07:00
Evan Simkowitz 12f9a50686 beginning to add autocomplete to textareainput 2024-04-02 18:35:12 -07:00
Evan Simkowitz 239933be3e Got autocomplete working! 2024-04-02 18:14:49 -07:00
Evan Simkowitz 4692cf698b hook up runtime 2024-04-02 17:13:54 -07:00
Evan Simkowitz 907e87c217 expand cwd 2024-04-02 17:05:14 -07:00
Evan Simkowitz f97bb699a1 plumb timeout to waveshell 2024-04-02 16:57:34 -07:00
Evan Simkowitz 077545ed93 bad merrge 2024-04-02 15:50:46 -07:00
Evan Simkowitz 60d0f0e976 Merge branch 'main' into evan/inshellisense 2024-04-02 15:49:32 -07:00
Evan Simkowitz cd4671e5bb store pointer to syncs 2024-04-02 14:58:39 -07:00
Evan Simkowitz d8a714dd4a ensure only one downstream writer can read from the buffer 2024-04-02 14:28:15 -07:00
Evan Simkowitz e0fa1b2560 document UsePty 2024-04-02 14:19:46 -07:00
Evan Simkowitz 2dffcc9237 add UsePty to EphemeralRunOpts 2024-04-02 14:17:12 -07:00
Evan Simkowitz 70090b8684 add package comment 2024-04-02 14:08:10 -07:00
Evan Simkowitz 3f8952caf4 more naming changes 2024-04-02 14:06:51 -07:00
Evan Simkowitz 15a2486e94 delete unused package 2024-04-02 14:01:57 -07:00
Evan Simkowitz 38aa7016b8 comment 2024-04-02 14:01:03 -07:00
Evan Simkowitz cff353ca94 formatting 2024-04-02 13:59:59 -07:00
Evan Simkowitz 5b440ace65 Making EphemeralWriteCloser into a more generic BufferedPipe 2024-04-02 13:58:56 -07:00
Evan Simkowitz 87de0dbc44 revert waveshell changes 2024-04-01 22:17:44 -07:00
Evan Simkowitz 74839b8e1b env vars are now working 2024-04-01 22:12:58 -07:00
Evan Simkowitz 8a24953a88 fix stdout/stderr 2024-04-01 20:55:23 -07:00
Evan Simkowitz a95854514a Add separate paths for stdout and stderr writers 2024-04-01 20:51:26 -07:00
Evan Simkowitz 229fcf8cd4 got cwd override working 2024-04-01 18:27:18 -07:00
Evan Simkowitz 83542ddab8 clean up code 2024-04-01 17:42:03 -07:00
Evan Simkowitz b520242f04 fixing spaghetti 2024-04-01 17:12:51 -07:00
Evan Simkowitz bc73ed1b6c save debug statements 2024-04-01 16:04:42 -07:00
Evan Simkowitz c4647945a4 fix bad merge 2024-04-01 14:22:23 -07:00
Evan Simkowitz 3db40b1c63 Merge branch 'main' into evan/inshellisense 2024-04-01 14:22:17 -07:00
Evan Simkowitz f6d7c37915 save debugging 2024-03-29 16:54:29 -07:00
Evan Simkowitz a41e866b1f Command pipes thru, triggers infinite loop 2024-03-28 18:44:37 -07:00
Evan Simkowitz a772715ae4 Add EphemeralWriteCloser 2024-03-28 18:02:27 -07:00
Evan Simkowitz d32e2aae05 Merge branch 'main' into evan/inshellisense 2024-03-28 16:24:27 -07:00
Evan Simkowitz 3f9d52a7e4 save work 2024-03-26 16:04:37 -07:00
Evan Simkowitz a239a8d70e Merge branch 'main' into evan/inshellisense 2024-03-26 13:00:21 -07:00
Evan Simkowitz a1bddd971f save work 2024-03-25 17:43:02 -07:00
Evan Simkowitz 722318f57d save work, starting to add backend types 2024-03-25 10:54:27 -07:00
Evan Simkowitz 3b633328a1 initial 2024-03-22 16:01:08 -07:00
56 changed files with 1863 additions and 956 deletions
+3 -1
View File
@@ -23,6 +23,7 @@
"@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",
@@ -77,6 +78,7 @@
"@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",
@@ -105,4 +107,4 @@
"scripts": {
"postinstall": "electron-builder install-app-deps"
}
}
}
-1
View File
@@ -13,7 +13,6 @@
<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>
+2 -28
View File
@@ -20,9 +20,8 @@ import { MainSideBar } from "./sidebar/main";
import { RightSideBar } from "./sidebar/right";
import { DisconnectedModal, ClientStopModal } from "@/modals";
import { ModalsProvider } from "@/modals/provider";
import { Button, TermStyleBlock } from "@/elements";
import { Button } from "@/elements";
import { ErrorBoundary } from "@/common/error/errorboundary";
import { For } from "tsx-control-statements/components";
import cn from "classnames";
import "./app.less";
@@ -81,21 +80,6 @@ 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();
@@ -140,12 +124,9 @@ 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,
@@ -170,13 +151,6 @@ 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 />
+8 -7
View File
@@ -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 } from "@/common/elements";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown, Button } 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,13 +76,14 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
@boundMethod
handleChangeTermTheme(theme: string): void {
// For main terminal theme, the key is main, otherwise it's either
// For global terminal theme, the key is global, otherwise it's either
// sessionId or screenId.
const currTheme = GlobalModel.getTermTheme()["main"];
const currTheme = GlobalModel.getTermTheme()["global"];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setMainTermTheme(theme, false);
const prtn = GlobalCommandRunner.setGlobalTermTheme(theme, false);
commandRtnHandler(prtn, this.errorMessage);
}
@@ -206,8 +207,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.termThemeOptions.get(), "Wave Default");
const currTermTheme = GlobalModel.getTermTheme()["main"] ?? termThemes[0].label;
const termThemes = getTermThemes(GlobalModel.termThemes, "Wave Default");
const currTermTheme = GlobalModel.getTermTheme()["global"] ?? termThemes[0].label;
return (
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
+1 -1
View File
@@ -5,7 +5,7 @@
width: 100%;
border: 2px solid var(--form-element-border-color);
border-radius: 6px;
line-height: 20px;
line-height: 22px;
background: var(--form-element-bg-color);
&.no-label {
-1
View File
@@ -18,5 +18,4 @@ export { Toggle } from "./toggle";
export { Tooltip } from "./tooltip";
export { TabIcon } from "./tabicon";
export { DatePicker } from "./datepicker";
export { TermStyleBlock } from "./termstyleblock";
export { CopyButton } from "./copybutton";
@@ -1,95 +0,0 @@
// 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 };
+5 -1
View File
@@ -160,7 +160,6 @@ 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);
}
@@ -176,8 +175,13 @@ 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()})`} />
+1 -1
View File
@@ -99,7 +99,7 @@ class SessionSettingsModal extends React.Component<{}, {}> {
if (this.session == null) {
return null;
}
const termThemes = getTermThemes(GlobalModel.termThemeOptions.get());
const termThemes = getTermThemes(GlobalModel.termThemes);
const currTermTheme = GlobalModel.getTermTheme()[this.sessionId] ?? termThemes[0].label;
return (
+5
View File
@@ -649,6 +649,11 @@ 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;
@@ -0,0 +1,28 @@
// 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
+3 -11
View File
@@ -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, TermStyleBlock } from "@/elements";
import { Button } from "@/elements";
import { Line } from "@/app/line/linecomps";
import { LinesView } from "@/app/line/linesview";
import * as util from "@/util/util";
@@ -184,18 +184,10 @@ 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" id={screen.screenId} data-screenid={screen.screenId} ref={this.screenViewRef}>
{/* <TermStyleBlock
scope="screen"
termTheme={termTheme}
themeSrcEl={this.screenViewRef.current}
themeKey={screen.screenId}
/> */}
<div className="screen-view" data-screenid={screen.screenId} ref={this.screenViewRef}>
<ScreenWindowView
key={screen.screenId + ":" + fontSize + ":" + dprStr + ":" + termRenderVersion}
key={screen.screenId + ":" + fontSize + ":" + dprStr}
session={session}
screen={screen}
width={winWidth}
-4
View File
@@ -187,8 +187,4 @@
}
}
}
.terminal-theme-dropdown {
width: 412px;
}
}
+62 -6
View File
@@ -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, TermStyleBlock } from "@/elements";
import { Button } from "@/elements";
import { commandRtnHandler } from "@/util/util";
import { getTermThemes } from "@/util/themeutil";
import { Dropdown } from "@/elements/dropdown";
@@ -140,7 +140,6 @@ 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) {
@@ -153,7 +152,7 @@ class TabSettings extends React.Component<{ screen: Screen }, {}> {
render() {
const { screen } = this.props;
const rptr = screen.curRemote.get();
const termThemes = getTermThemes(GlobalModel.termThemeOptions.get());
const termThemes = getTermThemes(GlobalModel.termThemes);
const currTermTheme = GlobalModel.getTermTheme()[screen.screenId] ?? termThemes[0].label;
return (
<div className="newtab-container">
@@ -176,7 +175,6 @@ 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}
@@ -210,6 +208,59 @@ 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() {
@@ -226,14 +277,15 @@ 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`,
@@ -255,7 +307,11 @@ class WorkspaceView extends React.Component<{}, {}> {
</div>
</If>
<ErrorBoundary key="eb">
<ScreenView key={`screenview-${sessionId}`} session={session} screen={activeScreen} />
<ScreenView
key={`screenview-${sessionId}-${termRenderVersion}`}
session={session}
screen={activeScreen}
/>
<If condition={activeScreen != null}>
<CmdInput key={"cmdinput-" + sessionId} />
</If>
+3
View File
@@ -0,0 +1,3 @@
# 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`.
+2
View File
@@ -0,0 +1,2 @@
export * from "./runtime/runtime";
export * from "./utils/shell";
+65
View File
@@ -0,0 +1,65 @@
// 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;
};
+17
View File
@@ -0,0 +1,17 @@
// 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