Skip to content

Commit

Permalink
feat: add inputs to snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
wesbillman committed Jun 27, 2024
1 parent 2721f58 commit a52228b
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 38 deletions.
89 changes: 71 additions & 18 deletions extensions/vscode/src/commands/node-new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ export const nodeNewCommand = async (item: FtlTreeItem) => {
return
}

//TODO: Add all the types here...
// Also would be cool to have an httpingress type which would populate a valid //ftl:ingress ....
const nodeType = await vscode.window.showQuickPick(['verb', 'enum', 'pubsub', 'pubsub:subscription', 'fsm', 'database', 'config:string', 'config:struct', 'secret', 'cron'], {
const nodeType = await vscode.window.showQuickPick(['verb', 'ingress:http', 'enum', 'pubsub', 'pubsub:subscription', 'fsm', 'database', 'config:string', 'config:struct', 'secret', 'cron'], {
title: 'Which type of node would you like to add',
placeHolder: 'Choose a node type',
canPickMany: false,
Expand All @@ -34,7 +32,7 @@ export const nodeNewCommand = async (item: FtlTreeItem) => {
return
}

const snippet = snippetForNodeType(nodeType)
const snippet = await snippetForNodeType(nodeType, item)

if (snippet === '') {
vscode.window.showErrorMessage(`No snippet available for node type ${nodeType}`)
Expand All @@ -55,11 +53,14 @@ export const nodeNewCommand = async (item: FtlTreeItem) => {
editor.revealRange(lastLineRange, vscode.TextEditorRevealType.Default)
}

const snippetForNodeType = (nodeType: string): string => {
//TODO: fill out for all node types.
const snippetForNodeType = async (nodeType: string, item: FtlTreeItem): Promise<string | undefined> => {
switch (nodeType) {
case 'verb':
return verbSnippet
return verbSnippet()

case 'ingress:http':
return ingressSnippet(item)

case 'enum':
return enumSnippet

Expand All @@ -73,7 +74,7 @@ const snippetForNodeType = (nodeType: string): string => {
return fsmSnippet

case 'database':
return `var sampleDatabase = ftl.PostgresDatabase("sample_db")`
return databaseSnippet()

case 'config:string':
return `var sampleConfig = ftl.Config[string]("sample_config")`
Expand All @@ -86,26 +87,65 @@ const snippetForNodeType = (nodeType: string): string => {

case 'cron':
return cronSnippet

// Add more cases here for other node types
}

return ''
// vscode.window.showInformationMessage(`Adding a new ${nodeType} node to ${document.uri.toString()}`)
}

const verbSnippet = `type SampleRequest struct {
Name string
}
const verbSnippet = async () => {
const inputBoxOptions: vscode.InputBoxOptions = {
prompt: 'What would you like to name the verb?',
placeHolder: 'MyVerb',
}
const name = await vscode.window.showInputBox(inputBoxOptions)
if (name === undefined) {
return undefined
}

type SampleResponse struct {
Message string
return `type ${name}Request struct {}
type ${name}Response struct {
Message string
}
//ftl:verb
func Sample(ctx context.Context, req SampleRequest) (SampleResponse, error) {
return SampleResponse{Message: "Hello, world!"}, nil
func ${name}(ctx context.Context, req ${name}Request) (${name}Response, error) {
return ${name}Response{Message: "Hello, world!"}, nil
}`
}

const ingressSnippet = async (item: FtlTreeItem) => {
const inputBoxOptions: vscode.InputBoxOptions = {
prompt: 'What would you like to name the ingress?',
placeHolder: 'MyEndpoint',
}
const name = await vscode.window.showInputBox(inputBoxOptions)
if (name === undefined) {
return undefined
}

const method = await vscode.window.showQuickPick(['GET', 'POST', 'PUT', 'DELETE'], {
title: 'What method will you use for the ingress?',
placeHolder: 'Choose a method',
canPickMany: false,
ignoreFocusOut: true
})

if (method === undefined) {
return undefined
}

return `type ${name}Request struct {}
type ${name}Response struct {}
//ftl:ingress ${method} /${item.moduleName}/${name.toLowerCase()}
func ${name}(ctx context.Context, req builtin.HttpRequest[${name}Request]) (builtin.HttpResponse[${name}Response, ftl.Unit], error) {
return builtin.HttpResponse[${name}Response, ftl.Unit]{
Body: ftl.Some(${name}Response{}),
}, nil
}
`
}

const enumSnippet = `//ftl:enum
type SampleEnum string
Expand All @@ -129,6 +169,19 @@ func SampleSubscriber(ctx context.Context, event SamplePubSubEvent) error {
return nil
}`

const databaseSnippet = async () => {
const inputBoxOptions: vscode.InputBoxOptions = {
prompt: 'What would you like to name the database?',
placeHolder: 'my_db',
}
const name = await vscode.window.showInputBox(inputBoxOptions)
if (name === undefined) {
return undefined
}

return `var ${name.toLowerCase()}Database = ftl.PostgresDatabase("${name.toLowerCase()}")`
}

const fsmSnippet = `type SampleFSMMessage struct {
Instance string
Message string
Expand Down
2 changes: 1 addition & 1 deletion extensions/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as vscode from 'vscode'
import { FTLStatus } from './status'
import { MIN_FTL_VERSION, checkMinimumVersion, getFTLVersion, getProjectOrWorkspaceRoot, isFTLRunning, resolveFtlPath } from './config'
import { FTLClient } from './client'
import { FtlModulesDataProvider, ftlModulesActivate } from './ftl-modules'
import { ftlModulesActivate } from './ftl-modules'

const extensionId = 'ftl'
let client: FTLClient
Expand Down
4 changes: 2 additions & 2 deletions extensions/vscode/src/ftl-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class FtlModulesDataProvider implements vscode.TreeDataProvider<FtlTreeIt
readonly onDidChangeTreeData: vscode.Event<FtlTreeItem | undefined | void> = this._onDidChangeTreeData.event

private data: FtlTreeItem[] = [
new FtlTreeItem('modules', new vscode.ThemeIcon('rocket'), vscode.TreeItemCollapsibleState.Expanded, undefined, [], 'ftlModules')
new FtlTreeItem('modules', new vscode.ThemeIcon('rocket'), vscode.TreeItemCollapsibleState.Expanded, undefined, undefined, [], 'ftlModules')
]

refresh(): void {
Expand All @@ -53,7 +53,7 @@ export class FtlModulesDataProvider implements vscode.TreeDataProvider<FtlTreeIt

updateData(newData: FtlTreeItem[]): void {
this.data = [
new FtlTreeItem('modules', new vscode.ThemeIcon('rocket'), vscode.TreeItemCollapsibleState.Expanded, undefined, newData, 'ftlModules')
new FtlTreeItem('modules', new vscode.ThemeIcon('rocket'), vscode.TreeItemCollapsibleState.Expanded, undefined, undefined, newData, 'ftlModules')
]

this.refresh()
Expand Down
39 changes: 22 additions & 17 deletions extensions/vscode/src/tree-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ import * as vscode from 'vscode'

export class FtlTreeItem extends vscode.TreeItem {
public position: Position | undefined
public moduleName: string | undefined

constructor(
label: string,
icon: vscode.ThemeIcon,
collapsibleState: vscode.TreeItemCollapsibleState,
position: Position | undefined,
position?: Position | undefined,
moduleName?: string | undefined,
public readonly children?: FtlTreeItem[],
public readonly contextValue: string = 'ftlModulesView',
public readonly tappable: boolean = true) {
super(label, collapsibleState)
this.position = position
this.iconPath = icon
this.position = position
this.moduleName = moduleName
this.contextValue = contextValue
if (position && tappable) {
this.command = {
Expand All @@ -29,24 +32,26 @@ export class FtlTreeItem extends vscode.TreeItem {

export const eventToTreeItem = (event: PullSchemaResponse): FtlTreeItem => {
const isBuiltIn = event.moduleName === 'builtin'

return new FtlTreeItem(
event.moduleName,
new vscode.ThemeIcon('package'),
vscode.TreeItemCollapsibleState.Collapsed,
estimateModulePosition(event.schema),
schemaToTreeItems(isBuiltIn, event.schema),
event.moduleName,
schemaToTreeItems(isBuiltIn, event.moduleName, event.schema),
isBuiltIn ? 'ftlBuiltinModule' : 'ftlModule'
)
}

const schemaToTreeItems = (isBuiltIn: boolean, module?: Module | undefined,): FtlTreeItem[] => {
const schemaToTreeItems = (isBuiltIn: boolean, moduleName: string, module?: Module | undefined,): FtlTreeItem[] => {
const treeItems: FtlTreeItem[] = []
if (module === undefined) {
return treeItems
}

module.decls.forEach(decl => {
const item = declToTreeItem(decl, isBuiltIn)
const item = declToTreeItem(decl, moduleName, isBuiltIn)
if (item) {
treeItems.push(item)
}
Expand All @@ -55,34 +60,34 @@ const schemaToTreeItems = (isBuiltIn: boolean, module?: Module | undefined,): Ft
return treeItems
}

const declToTreeItem = (decl: Decl, isBuiltIn: boolean): FtlTreeItem | undefined => {
const declToTreeItem = (decl: Decl, moduleName: string, isBuiltIn: boolean): FtlTreeItem | undefined => {
const pos = decl.value.value?.pos
const name = decl.value.value?.name ?? ''
const collapsibleState = vscode.TreeItemCollapsibleState.None
switch (decl.value.case) {
case 'data':
if (isBuiltIn) {
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-struct'), collapsibleState, pos, [], 'ftlData', false)
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-struct'), collapsibleState, pos, moduleName, [], 'ftlData', false)
}
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-struct'), collapsibleState, pos, [], 'ftlData')
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-struct'), collapsibleState, pos, moduleName, [], 'ftlData')
case 'verb':
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-function'), collapsibleState, pos, [], 'ftlVerb')
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-function'), collapsibleState, pos, moduleName, [], 'ftlVerb')
case 'database':
return new FtlTreeItem(name, new vscode.ThemeIcon('database'), collapsibleState, pos, [], 'ftlDatabase')
return new FtlTreeItem(name, new vscode.ThemeIcon('database'), collapsibleState, pos, moduleName, [], 'ftlDatabase')
case 'enum':
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-enum'), collapsibleState, pos, [], 'ftlEnum')
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-enum'), collapsibleState, pos, moduleName, [], 'ftlEnum')
case 'typeAlias':
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-class'), collapsibleState, pos, [], 'ftlTypeAlias')
return new FtlTreeItem(name, new vscode.ThemeIcon('symbol-class'), collapsibleState, pos, moduleName, [], 'ftlTypeAlias')
case 'config':
return new FtlTreeItem(name, new vscode.ThemeIcon('gear'), collapsibleState, pos, [], 'ftlConfig')
return new FtlTreeItem(name, new vscode.ThemeIcon('gear'), collapsibleState, pos, moduleName, [], 'ftlConfig')
case 'secret':
return new FtlTreeItem(name, new vscode.ThemeIcon('key'), collapsibleState, pos, [], 'ftlSecret')
return new FtlTreeItem(name, new vscode.ThemeIcon('key'), collapsibleState, pos, moduleName, [], 'ftlSecret')
case 'fsm':
return new FtlTreeItem(name, new vscode.ThemeIcon('server-process'), collapsibleState, pos, [], 'ftlFsm')
return new FtlTreeItem(name, new vscode.ThemeIcon('server-process'), collapsibleState, pos, moduleName, [], 'ftlFsm')
case 'topic':
return new FtlTreeItem(name, new vscode.ThemeIcon('broadcast'), collapsibleState, pos, [], 'ftlTopic')
return new FtlTreeItem(name, new vscode.ThemeIcon('broadcast'), collapsibleState, pos, moduleName, [], 'ftlTopic')
case 'subscription':
return new FtlTreeItem(name, new vscode.ThemeIcon('broadcast'), collapsibleState, pos, [], 'ftlSubscription')
return new FtlTreeItem(name, new vscode.ThemeIcon('broadcast'), collapsibleState, pos, moduleName, [], 'ftlSubscription')
}

return undefined
Expand Down

0 comments on commit a52228b

Please sign in to comment.