Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Nimaoth committed Nov 24, 2024
1 parent 72f74a3 commit e9e64bf
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 12 deletions.
14 changes: 14 additions & 0 deletions config/comp_test.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ proc initPlugin() =
let s = getSelection()
echo r2.slice(s.first.column, s.last.column).debug()
echo r2.slice(s.first.column, s.last.column).text()

bindKeys(ws"editor.text", ws"", ws"<C-a>", ws"uiaeuiae", ws"1", ws"MOVE THE CURSOR", (ws"comp_test.nim", 0.int32, 0.int32))

proc handleCommand(name: WitString; arg: WitString): WitString =
echo "handleCommand ", name, ", ", arg

case $name:
of "uiaeuiae":
runCommand(ws"next-view", ws"")

else:
discard

return ws""
150 changes: 150 additions & 0 deletions config/plugin_api_guest.nim
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,156 @@ proc getCurrentEditorRope*(): Rope {.nodestroy.} =
let res = textGetCurrentEditorRopeImported()
result.handle = res + 1

proc coreBindKeysImported(a0: int32; a1: int32; a2: int32; a3: int32; a4: int32;
a5: int32; a6: int32; a7: int32; a8: int32; a9: int32;
a10: int32; a11: int32; a12: int32; a13: int32;
a14: int32; a15: int32): void {.
wasmimport("bind-keys", "nev:plugins/core").}
proc bindKeys*(context: WitString; subContext: WitString; keys: WitString;
action: WitString; arg: WitString; description: WitString;
source: (WitString, int32, int32)): void {.nodestroy.} =
var
arg0: int32
arg1: int32
arg2: int32
arg3: int32
arg4: int32
arg5: int32
arg6: int32
arg7: int32
arg8: int32
arg9: int32
arg10: int32
arg11: int32
arg12: int32
arg13: int32
arg14: int32
arg15: int32
if context.len > 0:
arg0 = cast[int32](context[0].addr)
else:
arg0 = 0
arg1 = context.len
if subContext.len > 0:
arg2 = cast[int32](subContext[0].addr)
else:
arg2 = 0
arg3 = subContext.len
if keys.len > 0:
arg4 = cast[int32](keys[0].addr)
else:
arg4 = 0
arg5 = keys.len
if action.len > 0:
arg6 = cast[int32](action[0].addr)
else:
arg6 = 0
arg7 = action.len
if arg.len > 0:
arg8 = cast[int32](arg[0].addr)
else:
arg8 = 0
arg9 = arg.len
if description.len > 0:
arg10 = cast[int32](description[0].addr)
else:
arg10 = 0
arg11 = description.len
if source[0].len > 0:
arg12 = cast[int32](source[0][0].addr)
else:
arg12 = 0
arg13 = source[0].len
arg14 = cast[int32](source[1])
arg15 = cast[int32](source[2])
coreBindKeysImported(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
arg9, arg10, arg11, arg12, arg13, arg14, arg15)

proc coreDefineCommandImported(a0: int32; a1: int32; a2: int32; a3: int32;
a4: int32; a5: int32; a6: int32; a7: int32;
a8: int32; a9: int32; a10: int32): void {.
wasmimport("define-command", "nev:plugins/core").}
proc defineCommand*(name: WitString; active: bool; docs: WitString;
params: WitList[(WitString, WitString)];
returnType: WitString; context: WitString): void {.nodestroy.} =
var
arg0: int32
arg1: int32
arg2: int32
arg3: int32
arg4: int32
arg5: int32
arg6: int32
arg7: int32
arg8: int32
arg9: int32
arg10: int32
if name.len > 0:
arg0 = cast[int32](name[0].addr)
else:
arg0 = 0
arg1 = name.len
arg2 = cast[int32](active)
if docs.len > 0:
arg3 = cast[int32](docs[0].addr)
else:
arg3 = 0
arg4 = docs.len
if params.len > 0:
arg5 = cast[int32](params[0].addr)
else:
arg5 = 0
arg6 = params.len
if returnType.len > 0:
arg7 = cast[int32](returnType[0].addr)
else:
arg7 = 0
arg8 = returnType.len
if context.len > 0:
arg9 = cast[int32](context[0].addr)
else:
arg9 = 0
arg10 = context.len
coreDefineCommandImported(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
arg8, arg9, arg10)

proc coreRunCommandImported(a0: int32; a1: int32; a2: int32; a3: int32): void {.
wasmimport("run-command", "nev:plugins/core").}
proc runCommand*(name: WitString; args: WitString): void {.nodestroy.} =
var
arg0: int32
arg1: int32
arg2: int32
arg3: int32
if name.len > 0:
arg0 = cast[int32](name[0].addr)
else:
arg0 = 0
arg1 = name.len
if args.len > 0:
arg2 = cast[int32](args[0].addr)
else:
arg2 = 0
arg3 = args.len
coreRunCommandImported(arg0, arg1, arg2, arg3)

proc initPlugin(): void
proc initPluginExported(): void {.wasmexport("init-plugin").} =
initPlugin()

proc handleCommand(name: WitString; arg: WitString): WitString
var handleCommandRetArea: array[16, uint8]
proc handleCommandExported(a0: int32; a1: int32; a2: int32; a3: int32): int32 {.
wasmexport("handle-command").} =
var
name: WitString
arg: WitString
name = ws(cast[ptr char](a0), a1)
arg = ws(cast[ptr char](a2), a3)
let res = handleCommand(name, arg)
if res.len > 0:
cast[ptr int32](handleCommandRetArea[0].addr)[] = cast[int32](res[0].addr)
else:
cast[ptr int32](handleCommandRetArea[0].addr)[] = 0
cast[ptr int32](handleCommandRetArea[4].addr)[] = res.len
cast[int32](handleCommandRetArea[0].addr)
7 changes: 7 additions & 0 deletions scripting/plugin_api.wit
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ interface text-editor {
get-selection: func() -> selection;
}

interface core {
bind-keys: func(context: string, sub-context: string, keys: string, action: string, arg: string, description: string, source: tuple<string, s32, s32>);
define-command: func(name: string, active: bool, docs: string, params: list<tuple<string, string>>, return-type: string, context: string);
run-command: func(name: string, args: string);
}
interface text {
use types.{cursor};

Expand All @@ -37,6 +42,8 @@ world plugin {

import text-editor;
import text;
import core;

export init-plugin: func();
export handle-command: func(name: string, arg: string) -> string;
}
19 changes: 19 additions & 0 deletions scripting/plugins_api_wasm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ import scripting_api, misc/myjsonutils
## This file is auto generated, don't modify.


proc plugins_bindKeys_void_PluginService_string_string_string_string_string_string_tuple_filename_string_line_int_column_int_wasm(
arg: cstring): cstring {.importc.}
proc bindKeys*(context: string; subContext: string; keys: string;
action: string; arg: string = ""; description: string = "";
source: tuple[filename: string, line: int, column: int] = ("", 0, 0)) {.
gcsafe, raises: [].} =
var argsJson = newJArray()
argsJson.add context.toJson()
argsJson.add subContext.toJson()
argsJson.add keys.toJson()
argsJson.add action.toJson()
argsJson.add arg.toJson()
argsJson.add description.toJson()
argsJson.add source.toJson()
let argsJsonString = $argsJson
let res {.used.} = plugins_bindKeys_void_PluginService_string_string_string_string_string_string_tuple_filename_string_line_int_column_int_wasm(
argsJsonString.cstring)


proc plugins_callScriptAction_JsonNode_PluginService_string_JsonNode_wasm(
arg: cstring): cstring {.importc.}
proc callScriptAction*(context: string; args: JsonNode): JsonNode {.gcsafe,
Expand Down
13 changes: 9 additions & 4 deletions src/app.nim
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ proc setLocationList*(self: App, list: seq[FinderItem], previewer: Option[Previe
proc closeUnusedDocuments*(self: App)
proc addCommandScript*(self: App, context: string, subContext: string, keys: string, action: string, arg: string = "", description: string = "", source: tuple[filename: string, line: int, column: int] = ("", 0, 0))
proc currentEventHandlers*(self: App): seq[EventHandler]
proc scriptRunAction*(action: string, arg: string)

implTrait AppInterface, App:
getActiveEditor(Option[DocumentEditor], App)
Expand Down Expand Up @@ -247,10 +248,14 @@ proc initScripting(self: App, options: AppOptions) {.async.} =
except CatchableError:
log lvlError, &"Failed to load wasm configs: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}"

self.runConfigCommands("wasm-plugin-post-load-commands")
self.runConfigCommands("plugin-post-load-commands")

if not options.disableWasmPlugins:
try:
log(lvlInfo, fmt"load wasm components")
self.wasmCompScriptContext = new ScriptContextWasmComp
# self.plugins.scriptContexts.add self.wasmCompScriptContext
self.plugins.scriptContexts.add self.wasmCompScriptContext
self.wasmCompScriptContext.services = self.services
self.wasmCompScriptContext.moduleVfs = VFS()
self.wasmCompScriptContext.vfs = self.vfs
Expand All @@ -267,9 +272,6 @@ proc initScripting(self: App, options: AppOptions) {.async.} =
except CatchableError:
log lvlError, &"Failed to load wasm components: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}"

self.runConfigCommands("wasm-plugin-post-load-commands")
self.runConfigCommands("plugin-post-load-commands")

log lvlInfo, &"Finished loading plugins"

proc setupDefaultKeybindings(self: App) =
Expand Down Expand Up @@ -640,6 +642,9 @@ proc newApp*(backend: api.Backend, platform: Platform, services: Services, optio
self.timer = startTimer()
self.frameTimer = startTimer()

{.gcsafe.}:
scriptRunActionImpl = scriptRunAction

self.layout = services.getService(LayoutService).get
self.config = services.getService(ConfigService).get
self.editors = services.getService(DocumentEditorService).get
Expand Down
33 changes: 33 additions & 0 deletions src/scripting/plugin_api_host.nim
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ proc textSlice(host: WasmContext; store: ptr ComponentContextT;
proc textSlicePoints(host: WasmContext; store: ptr ComponentContextT;
self: var RopeResource; a: Cursor; b: Cursor): RopeResource
proc textGetCurrentEditorRope(host: WasmContext; store: ptr ComponentContextT): RopeResource
proc coreBindKeys(host: WasmContext; store: ptr ComponentContextT;
context: string; subContext: string; keys: string;
action: string; arg: string; description: string;
source: (string, int32, int32)): void
proc coreDefineCommand(host: WasmContext; store: ptr ComponentContextT;
name: string; active: bool; docs: string;
params: seq[(string, string)]; returnType: string;
context: string): void
proc coreRunCommand(host: WasmContext; store: ptr ComponentContextT;
name: string; args: string): void
proc defineComponent*(linker: ptr ComponentLinkerT; host: WasmContext): WasmtimeResult[
void] =
?linker.defineResource("nev:plugins/text", "rope", RopeResource)
Expand Down Expand Up @@ -75,3 +85,26 @@ proc defineComponent*(linker: ptr ComponentLinkerT; host: WasmContext): Wasmtime
linker.defineFunc("nev:plugins/text", "[static]rope.get-current-editor-rope"):
let res = textGetCurrentEditorRope(host, store)
results[0] = ?store.resourceNew(res)
linker.defineFunc("nev:plugins/core", "bind-keys"):
let context = parameters[0].to(string)
let subContext = parameters[1].to(string)
let keys = parameters[2].to(string)
let action = parameters[3].to(string)
let arg = parameters[4].to(string)
let description = parameters[5].to(string)
let source = parameters[6].to((string, int32, int32))
coreBindKeys(host, store, context, subContext, keys, action, arg,
description, source)
linker.defineFunc("nev:plugins/core", "define-command"):
let name = parameters[0].to(string)
let active = parameters[1].to(bool)
let docs = parameters[2].to(string)
let params = parameters[3].to(seq[(string, string)])
let returnType = parameters[4].to(string)
let context = parameters[5].to(string)
coreDefineCommand(host, store, name, active, docs, params, returnType,
context)
linker.defineFunc("nev:plugins/core", "run-command"):
let name = parameters[0].to(string)
let args = parameters[1].to(string)
coreRunCommand(host, store, name, args)
25 changes: 23 additions & 2 deletions src/scripting/scripting_base.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import std/[macros, macrocache, json, strutils, tables, options, sequtils]
import misc/[custom_logger, custom_async, util, myjsonutils]
import expose, document_editor, compilation_config, service, vfs, dispatch_tables
import expose, document_editor, compilation_config, service, vfs, dispatch_tables, events

{.push gcsafe.}
{.push raises: [].}
Expand All @@ -20,6 +20,7 @@ type
currentScriptContext*: Option[ScriptContext] = ScriptContext.none

scriptActions*: Table[string, ScriptAction]
events: EventHandlerService

method init*(self: ScriptContext, path: string, vfs: VFS): Future[void] {.base.} = discard
method deinit*(self: ScriptContext) {.base.} = discard
Expand All @@ -34,9 +35,10 @@ method getCurrentContext*(self: ScriptContext): string {.base.} = ""

func serviceName*(_: typedesc[PluginService]): string = "PluginService"

addBuiltinService(PluginService)
addBuiltinService(PluginService, EventHandlerService)

method init*(self: PluginService): Future[Result[void, ref CatchableError]] {.async: (raises: []).} =
self.events = self.services.getService(EventHandlerService).get
return ok()

{.pop.} # raises
Expand Down Expand Up @@ -160,6 +162,25 @@ proc getPluginService(): Option[PluginService] =
static:
addInjector(PluginService, getPluginService)

proc bindKeys*(self: PluginService, context: string, subContext: string, keys: string, action: string, arg: string = "", description: string = "", source: tuple[filename: string, line: int, column: int] = ("", 0, 0)) {.expose("plugins").} =
let command = if arg.len == 0: action else: action & " " & arg
log(lvlInfo, fmt"Adding command to '{context}': ('{subContext}', '{keys}', '{command}')")

let (context, subContext) = if (let i = context.find('#'); i != -1):
(context[0..<i], context[i+1..^1] & subContext)
else:
(context, subContext)

if description.len > 0:
self.events.commandDescriptions[context & subContext & keys] = description

var source = source
if self.currentScriptContext.getSome(scriptContext):
source.filename = scriptContext.getCurrentContext() & source.filename

self.events.getEventHandlerConfig(context).addCommand(subContext, keys, command, source)
self.events.invalidateCommandToKeysMap()

proc callScriptAction*(self: PluginService, context: string, args: JsonNode): JsonNode {.expose("plugins").} =
if not self.scriptActions.contains(context):
log lvlError, fmt"Unknown script action '{context}'"
Expand Down
Loading

0 comments on commit e9e64bf

Please sign in to comment.