Skip to content

Commit

Permalink
Implement command generators, a way for plugins to provide entrypoints
Browse files Browse the repository at this point in the history
  • Loading branch information
Exidex committed Mar 23, 2024
1 parent fce4ea5 commit e6ff621
Show file tree
Hide file tree
Showing 19 changed files with 558 additions and 179 deletions.
7 changes: 7 additions & 0 deletions dev_plugin/gauntlet.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ path = 'src/command-a.ts'
type = 'command'
description = ''

[[entrypoint]]
id = 'command-generator'
name = 'Command generator'
path = 'src/command-generator.ts'
type = 'command-generator'
description = ''

[[supported_system]]
os = 'linux'

Expand Down
38 changes: 38 additions & 0 deletions dev_plugin/src/command-generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
interface GeneratedCommand { // TODO Add this type to api
id: string
name: string
fn: () => void
}

export default function CommandGenerator(): GeneratedCommand[] {
return [
{
id: 'generated-test-1',
name: 'Generated Item 1',
fn: () => {
console.log('generated-test-1')
}
},
{
id: 'generated-test-2',
name: 'Generated Item 2',
fn: () => {
console.log('generated-test-2')
}
},
{
id: 'generated-test-3',
name: 'Generated Item 3',
fn: () => {
console.log('generated-test-3')
}
},
{
id: 'generated-test-4',
name: 'Generated Item 4',
fn: () => {
console.log('generated-test-4')
}
}
]
}
49 changes: 49 additions & 0 deletions js/core/src/command-generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// @ts-expect-error does typescript support such symbol declarations?
const denoCore: DenoCore = Deno[Deno.internal].core;
const InternalApi = denoCore.ops;

interface GeneratedCommand { // TODO Add this type to api
id: string
name: string
fn: () => void
}

let storedGeneratedCommands: (GeneratedCommand & { lookupId: string })[] = []

export async function runCommandGenerators(): Promise<void> {
storedGeneratedCommands = []

const entrypointIds = await InternalApi.get_command_generator_entrypoint_ids();
for (const entrypointId of entrypointIds) {
try {
const generator: () => GeneratedCommand[] = (await import(`gauntlet:entrypoint?${entrypointId}`)).default;

const generatedCommands = generator()
.map(value => ({
lookupId: entrypointId + ":" + value.id,
...value
}));

storedGeneratedCommands.push(...generatedCommands)
} catch (e) {
console.error("Error occurred when calling command generator for entrypoint: " + entrypointId, e)
}
}
}

export function generatedCommandSearchIndex(): AdditionalSearchItem[] {
return storedGeneratedCommands.map(value => ({
entrypoint_id: value.lookupId,
entrypoint_name: value.name,
}))
}

export function runGeneratedCommand(entrypointId: string) {
const generatedCommand = storedGeneratedCommands.find(value => value.lookupId === entrypointId);

if (generatedCommand) {
generatedCommand.fn()
} else {
throw new Error("Generated command with entrypoint id '" + entrypointId + "' not found")
}
}
19 changes: 19 additions & 0 deletions js/core/src/init.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { FC } from "react";
import { generatedCommandSearchIndex, runCommandGenerators, runGeneratedCommand } from "./command-generator";
import { loadSearchIndex } from "./search-index";

// @ts-expect-error does typescript support such symbol declarations?
const denoCore: DenoCore = Deno[Deno.internal].core;
Expand Down Expand Up @@ -98,6 +100,14 @@ async function runLoop() {
}
break;
}
case "RunGeneratedCommand": {
try {
runGeneratedCommand(pluginEvent.entrypointId)
} catch (e) {
console.error("Error occurred when running a generated command", pluginEvent.entrypointId, e)
}
break;
}
case "OpenInlineView": {
const endpoint_id = InternalApi.op_inline_view_endpoint_id();

Expand All @@ -124,11 +134,20 @@ async function runLoop() {
return;
}
}
break;
}
case "ReloadSearchIndex": {
await loadSearchIndex();
break;
}
}
}
}

await runCommandGenerators();

await loadSearchIndex();

(async () => {
await runLoop()
})();
9 changes: 9 additions & 0 deletions js/core/src/search-index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { generatedCommandSearchIndex } from "./command-generator";

// @ts-expect-error does typescript support such symbol declarations?
const denoCore: DenoCore = Deno[Deno.internal].core;
const InternalApi = denoCore.ops;

export async function loadSearchIndex() {
await InternalApi.load_search_index(generatedCommandSearchIndex());
}
21 changes: 20 additions & 1 deletion js/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface DenoCore {
ops: InternalApi
}

type PluginEvent = ViewEvent | RunCommand | OpenView | PluginCommand | OpenInlineView
type PluginEvent = ViewEvent | RunCommand | RunGeneratedCommand | OpenView | PluginCommand | OpenInlineView | ReloadSearchIndex
type RenderLocation = "InlineView" | "View"

type ViewEvent = {
Expand All @@ -27,6 +27,11 @@ type RunCommand = {
entrypointId: string
}

type RunGeneratedCommand = {
type: "RunGeneratedCommand"
entrypointId: string
}

type PluginCommand = {
type: "PluginCommand"
commandType: "stop"
Expand All @@ -37,6 +42,10 @@ type OpenInlineView = {
text: string
}

type ReloadSearchIndex = {
type: "ReloadSearchIndex"
}

type PropertyValue = PropertyValueString | PropertyValueNumber | PropertyValueBool | PropertyValueUndefined
type PropertyValueString = { type: "String", value: string }
type PropertyValueNumber = { type: "Number", value: number }
Expand All @@ -53,6 +62,11 @@ type UiWidget = {
type Props = { [key: string]: any };
type PropsWithChildren = { children?: UiWidget[] } & Props;

type AdditionalSearchItem = {
entrypoint_name: string,
entrypoint_id: string,
}

interface InternalApi {
op_log_trace(target: string, message: string): void;
op_log_debug(target: string, message: string): void;
Expand All @@ -67,9 +81,14 @@ interface InternalApi {
op_inline_view_endpoint_id(): string | null;
clear_inline_view(): void;

plugin_id(): string;

get_command_generator_entrypoint_ids(): Promise<string[]>
get_plugin_preferences(): Record<string, any>;
get_entrypoint_preferences(entrypointId: string): Record<string, any>;

load_search_index(searchItems: AdditionalSearchItem[]): Promise<void>;

op_react_replace_view(render_location: RenderLocation, top_level_view: boolean, container: UiWidget): void;
}

Expand Down
1 change: 1 addition & 0 deletions rust/client/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct NativeUiSearchResult {
pub enum SearchResultEntrypointType {
Command,
View,
GeneratedCommand,
}

#[derive(Debug)]
Expand Down
49 changes: 40 additions & 9 deletions rust/client/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use tonic::transport::Server;

use client_context::ClientContext;
use common::model::{EntrypointId, PluginId, PropertyValue, RenderLocation};
use common::rpc::{BackendClient, RpcEntrypointType, RpcEventRenderView, RpcEventRunCommand, RpcEventViewEvent, RpcRequestRunCommandRequest, RpcRequestViewRenderRequest, RpcSearchRequest, RpcSendViewEventRequest, RpcUiPropertyValue, RpcUiWidgetId};
use common::rpc::{BackendClient, RpcEntrypointTypeSearchResult, RpcEventRenderView, RpcEventRunCommand, RpcEventRunGeneratedCommand, RpcEventViewEvent, RpcRequestRunCommandRequest, RpcRequestRunGeneratedCommandRequest, RpcRequestViewRenderRequest, RpcSearchRequest, RpcSendViewEventRequest, RpcUiPropertyValue, RpcUiWidgetId};
use common::rpc::rpc_backend_client::RpcBackendClient;
use common::rpc::rpc_frontend_server::RpcFrontendServer;
use common::rpc::rpc_ui_property_value::Value;
Expand Down Expand Up @@ -68,6 +68,10 @@ pub enum AppMsg {
plugin_id: PluginId,
entrypoint_id: EntrypointId,
},
RunGeneratedCommandEvent {
plugin_id: PluginId,
entrypoint_id: EntrypointId,
},
PromptChanged(String),
SetSearchResults(Vec<NativeUiSearchResult>),
SetTopLevelView(bool),
Expand Down Expand Up @@ -180,6 +184,12 @@ impl Application for AppModel {
self.run_command(plugin_id, entrypoint_id),
])
}
AppMsg::RunGeneratedCommandEvent { plugin_id, entrypoint_id } => {
Command::batch([
self.hide_window(),
self.run_generated_command(plugin_id, entrypoint_id),
])
}
AppMsg::PromptChanged(new_prompt) => {
self.prompt.replace(new_prompt.clone());

Expand All @@ -196,26 +206,24 @@ impl Application for AppModel {
.into_inner()
.results
.into_iter()
.flat_map(|search_result| {
.map(|search_result| {
let entrypoint_type = search_result.entrypoint_type
.try_into()
.unwrap();

let entrypoint_type = match entrypoint_type {
RpcEntrypointType::Command => SearchResultEntrypointType::Command,
RpcEntrypointType::View => SearchResultEntrypointType::View,
RpcEntrypointType::InlineView => {
return None;
}
RpcEntrypointTypeSearchResult::SrCommand => SearchResultEntrypointType::Command,
RpcEntrypointTypeSearchResult::SrView => SearchResultEntrypointType::View,
RpcEntrypointTypeSearchResult::SrGeneratedCommand => SearchResultEntrypointType::GeneratedCommand,
};

Some(NativeUiSearchResult {
NativeUiSearchResult {
plugin_id: PluginId::from_string(search_result.plugin_id),
plugin_name: search_result.plugin_name,
entrypoint_id: EntrypointId::from_string(search_result.entrypoint_id),
entrypoint_name: search_result.entrypoint_name,
entrypoint_type,
})
}
})
.collect();

Expand Down Expand Up @@ -331,6 +339,10 @@ impl Application for AppModel {
plugin_id: event.plugin_id,
entrypoint_id: event.entrypoint_id,
},
|event| AppMsg::RunGeneratedCommandEvent {
plugin_id: event.plugin_id,
entrypoint_id: event.entrypoint_id,
},
);

let list: Element<_> = scrollable(search_list)
Expand Down Expand Up @@ -517,6 +529,25 @@ impl AppModel {
.unwrap();
}, |_| AppMsg::Noop)
}

fn run_generated_command(&self, plugin_id: PluginId, entrypoint_id: EntrypointId) -> Command<AppMsg> {
let mut backend_client = self.backend_client.clone();

Command::perform(async move {
let event = RpcEventRunGeneratedCommand {
entrypoint_id: entrypoint_id.to_string(),
};

let request = RpcRequestRunGeneratedCommandRequest {
plugin_id: plugin_id.to_string(),
event: Some(event),
};

backend_client.request_run_generated_command(Request::new(request))
.await
.unwrap();
}, |_| AppMsg::Noop)
}
}

fn register_shortcut() -> GlobalHotKeyManager {
Expand Down
Loading

0 comments on commit e6ff621

Please sign in to comment.