Skip to main content

Entrypoint Generator

Overview

Entrypoint generator is used for procedural generation of entrypoints.

Functionality

  • Dynamically add, remove, update one or more entrypoints at any point in plugin lifetime
  • Generated entrypoints can have accessories
  • Generated entrypoints can have multiple actions, each of which can be a command or a view

For performance reasons, the entrypoints are generated once and stored for later use instead of being generated each time when main window is opened. This means that after initial generator run the only way to add, delete or remove generated entrypoint is based on some external event e.g. file change

Plugin Manifest

To use entrypoint generator, entrypoint with type "entrypoint-generator" is required

Example

[[entrypoint]]
id = 'main'
name = 'Main'
path = 'src/main.tsx'
type = 'entrypoint-generator'
description = 'Description of a entrypoint generator'

Note on usage of async

JavaScript is a single-threaded language, at any time only one chunk of code is being executed.

This has implications on Gauntlet plugins.

Let's say in the same plugin you have 2 entrypoints: view and entrypoint generator, let's also say that your generator entrypoint needs to scan some directories. If you are using synchronous versions of functions to access file system, user will not be able to open any views because JS runtime is being busy with scanning directories. For this reason prefer using async versions of APIs where possible, or if your code is computationally intensive, offload the computation to a worker

Examples

Simple

import { GeneratorContext } from "@project-gauntlet/api/helpers";
import { ReactElement } from "react";
import { List } from "@project-gauntlet/api/components";

function ListView(): ReactElement {
return (
<List>
<List.Item id="example-item" title="Example Item"/>
</List>
)
}

export default function EntrypointGenerator({ add }: GeneratorContext): void {
add('generated', {
name: 'Generated Command',
actions: [
{
label: "Run the Gauntlet",
run: () => {
console.log('Running the Gauntlet...')
}
}
]
})

add('generated', {
name: 'Generated View',
actions: [
{
label: "Open generated view",
view: () => <ListView/>
}
]
})
}

Update based on file system events

This example shows how the name of the generated item can be dependent on the content of the file and will be updated when content of the file is updated

import { GeneratorContext } from "@project-gauntlet/api/helpers";

export default async function EntrypointGenerator({ add, remove }: GeneratorContext): Promise<void | (() => void)> {
const id = "generated";
const path = "/tmp/gauntlet-example";

await Deno.create(path)
add(id, generatedItem("default"))

const watcher = Deno.watchFs(path);

(async () => {
for await (const _event of watcher) {
try {
const value = await Deno.readTextFile(path);
add(id, generatedItem(value))
} catch (err) {
remove(id)
}
}
})();

return () => {
watcher.close()
}
}

function generatedItem(value: string) {
return {
name: `Generated Command - ${value}`,
actions: [
{
label: "Run the Gauntlet",
run: () => {
console.log('Running the Gauntlet...')
}
}
]
};
}

Accessories

import { GeneratorContext } from "@project-gauntlet/api/helpers";
import { Icons } from "@project-gauntlet/api/components";

export default function EntrypointGenerator({ add }: GeneratorContext): void {
add('generated', {
name: 'Generated Command',
actions: [
{
label: "Run the Gauntlet",
run: () => {
console.log('Running the Gauntlet...')
}
}
],
accessories: [{ icon: Icons.Battery, text: "100 %" }]
})
}

Icons

import { GeneratorContext } from "@project-gauntlet/api/helpers";

export default async function EntrypointGenerator({ add }: GeneratorContext): Promise<void> {

const response = await fetch("https://img.icons8.com/?size=32&id=21276&format=png");
const arrayBuffer = await response.bytes();

add('generated', {
name: 'Generated Command',
actions: [
{
label: "Run the Gauntlet",
run: () => {
console.log('Running the Gauntlet...')
}
}
],
icon: arrayBuffer
});
}

Preferences

Try changing the preference values in Settings UI, the change will be automatically reflected in the entrypoint list

import { GeneratorContext } from "@project-gauntlet/api/helpers";

type PluginGeneratorContext = GeneratorContext<{ testBool: boolean }, { testStr: string }>;

export default function EntrypointGenerator({ add, pluginPreferences, entrypointPreferences }: PluginGeneratorContext): void {
add('generated', {
name: 'Generated Command - ' + entrypointPreferences.testStr,
actions: [
{
label: "Run the Gauntlet",
run: () => {
console.log('Running the Gauntlet... ' + pluginPreferences.testBool)
}
}
],
});
}

Action shortcuts

It is possible to assign specific shortcut to Entrypoint Action that works when the Entrypoint is focused

See Plugin Manifest for more information on meaning of manifest property values

import { GeneratorContext } from "@project-gauntlet/api/helpers";

type PluginGeneratorContext = GeneratorContext<{ testBool: boolean }, { testStr: string }>;

export default function EntrypointGenerator({ add }: PluginGeneratorContext): void {
add('generated', {
name: 'Generated Command',
actions: [
{
label: "Primary Action", // Executed when Enter is pressed
run: () => {
console.log('Running the Gauntlet... - Primary Action')
}
},
{
label: "Secondary Action", // Executed when Shift+Enter is pressed
run: () => {
console.log('Running the Gauntlet... - Secondary Action')
}
},
{
ref: "anotherAction", // Executed when pressing shortcut specified in Plugin Manifest
label: "Another Action",
run: () => {
console.log('Running the Gauntlet... - Another Action')
}
}
],
});
}