feat: move snippets, keybinding actions and macros out of core into plugins

This commit is contained in:
LukeGus committed 2026-09-29 11:39:14 -05:00
1 parent d9bba10612
commit e0c30a4e6f
262 files changed
+9091 -10744

No files matched your search

@@ -1,55 +0,0 @@
export interface CommandHostVars {
ip?: string;
username?: string;
port?: number | string;
name?: string;
}
const INPUT_PATTERN =
/\$\{INPUT_(\d+)(?::([^}$]+))?\}|\$INPUT_(\d+)(?![a-zA-Z0-9_])/g;
function replaceVar(content: string, name: string, value?: string): string {
if (value === undefined) return content;
const pattern = new RegExp(`\\$\\{?${name}\\}?`, "g");
return content.replace(pattern, value);
}
/**
* $HOST/$USER/$PORT/$NAME/$INPUT_n substitution for an ad hoc fleet command,
* typed directly into the "run on fleet" box rather than loaded from a saved
* snippet. Mirrors the snippets plugin's own resolveSnippetCommand and the
* frontend's src/ui/lib/snippet-variables.ts - kept as a small standalone
* copy rather than a cross-plugin dependency for one pure function with no
* snippet data of its own to fetch.
*/
export function resolveCommandVariables(
content: string,
host: CommandHostVars | null,
inputValues: Record<string, string> = {},
): string {
let resolved = content;
resolved = replaceVar(resolved, "HOST", host?.ip);
resolved = replaceVar(resolved, "USER", host?.username);
resolved = replaceVar(
resolved,
"PORT",
host?.port !== undefined ? String(host.port) : undefined,
);
resolved = replaceVar(resolved, "NAME", host?.name);
resolved = resolved.replace(
INPUT_PATTERN,
(
fullMatch,
braceDigits: string | undefined,
_label,
plainDigits: string | undefined,
) => {
const key = `INPUT_${braceDigits ?? plainDigits}`;
return key in inputValues ? inputValues[key] : fullMatch;
},
);
return resolved;
}
+30 -1
View File
@@ -16,7 +16,6 @@ import {
ElevationError,
} from "@termix/plugin-sdk/host-commands";
import type { FleetRepository } from "./repository.js";
import { resolveCommandVariables } from "./command-variables.js";
const FLEET_TRANSFER_MAX_BYTES = 200 * 1024 * 1024;
const upload = multer({
@@ -74,6 +73,35 @@ function parseShareTargets(
return targets;
}
interface CommandVariables {
resolve: (
content: string,
host: {
ip?: string;
username?: string;
port?: number | string;
name?: string;
} | null,
inputValues?: Record<string, string>,
) => string;
}
/**
* $HOST, $USER, $PORT, $NAME and $INPUT_n in an ad hoc fleet command, through
* the snippets plugin, which owns the syntax. Without it the command runs as
* typed.
*/
export function resolveCommandVariables(
ctx: Pick<PluginContext, "registry">,
command: string,
host: Parameters<CommandVariables["resolve"]>[1],
inputValues: Record<string, string> = {},
): string {
const variables =
ctx.registry.consume<CommandVariables>("snippets.variables");
return variables ? variables.resolve(command, host, inputValues) : command;
}
function actor(ctx: PluginContext): string {
return ctx.currentActor() as string;
}
@@ -884,6 +912,7 @@ export function registerFleetRoutes(
}
const resolvedCommand = resolveCommandVariables(
ctx,
command,
{
ip: fullHost.ip,