Skip to content

Commit

Permalink
clipboard working in browser
Browse files Browse the repository at this point in the history
  • Loading branch information
Nimaoth committed Jan 4, 2024
1 parent 90d8e87 commit 0ed005e
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 57 deletions.
3 changes: 0 additions & 3 deletions scripting/absytree_internal.nim
Original file line number Diff line number Diff line change
Expand Up @@ -651,8 +651,5 @@ proc editor_scriptSetOptionString_void_string_string_impl*(path: string;
discard
proc editor_scriptSetCallback_void_string_int_impl*(path: string; id: int) =
discard
proc editor_setRegisterText_void_App_string_string_impl*(text: string;
register: string = "") =
discard
proc lsp_lspLogVerbose_void_bool_impl*(val: bool) =
discard
2 changes: 0 additions & 2 deletions scripting/absytree_internal_wasm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,4 @@ proc editor_scriptSetOptionBool_void_string_bool_impl(path: string; value: bool)
proc editor_scriptSetOptionString_void_string_string_impl(path: string;
value: string) {.importc.}
proc editor_scriptSetCallback_void_string_int_impl(path: string; id: int) {.importc.}
proc editor_setRegisterText_void_App_string_string_impl(text: string;
register: string = "") {.importc.}
proc lsp_lspLogVerbose_void_bool_impl(val: bool) {.importc.}
2 changes: 0 additions & 2 deletions scripting/editor_api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,3 @@ proc scriptSetOptionString*(path: string; value: string) =
editor_scriptSetOptionString_void_string_string_impl(path, value)
proc scriptSetCallback*(path: string; id: int) =
editor_scriptSetCallback_void_string_int_impl(path, id)
proc setRegisterText*(text: string; register: string = "") =
editor_setRegisterText_void_App_string_string_impl(text, register)
19 changes: 0 additions & 19 deletions scripting/editor_api_wasm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1213,22 +1213,3 @@ proc scriptSetCallback*(path: string; id: int) =
let res {.used.} = editor_scriptSetCallback_void_string_int_wasm(
argsJsonString.cstring)


proc editor_setRegisterText_void_App_string_string_wasm(arg: cstring): cstring {.
importc.}
proc setRegisterText*(text: string; register: string = "") =
var argsJson = newJArray()
argsJson.add block:
when string is JsonNode:
text
else:
text.toJson()
argsJson.add block:
when string is JsonNode:
register
else:
register.toJson()
let argsJsonString = $argsJson
let res {.used.} = editor_setRegisterText_void_App_string_string_wasm(
argsJsonString.cstring)

25 changes: 13 additions & 12 deletions src/app.nim
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ implTrait ConfigProvider, App:

proc handleLog(self: App, level: Level, args: openArray[string])
proc getEventHandlerConfig*(self: App, context: string): EventHandlerConfig
proc setRegisterText*(self: App, text: string, register: string = "")
proc getRegisterText*(self: App, text: var string, register: string = "")
proc setRegisterText*(self: App, text: string, register: string = ""): Future[void] {.async.}
proc getRegisterText*(self: App, register: string = ""): Future[string] {.async.}
proc openWorkspaceFile*(self: App, path: string, folder: WorkspaceFolder): Option[DocumentEditor]
proc openFile*(self: App, path: string, app: bool = false): Option[DocumentEditor]
proc handleUnknownDocumentEditorAction*(self: App, editor: DocumentEditor, action: string, args: JsonNode): EventResponse
Expand All @@ -198,9 +198,8 @@ implTrait AppInterface, App:

getEventHandlerConfig(EventHandlerConfig, App, string)

setRegisterText(void, App, string, string)
proc getRegisterText*(self: App, register: string): string =
self.getRegisterText(result, register)
setRegisterText(Future[void], App, string, string)
getRegisterText(Future[string], App, string)

proc configProvider*(self: App): ConfigProvider = self.asConfigProvider

Expand Down Expand Up @@ -1892,21 +1891,23 @@ proc scriptSetCallback*(path: string, id: int) {.expose("editor").} =
return
gEditor.callbacks[path] = id

proc setRegisterText*(self: App, text: string, register: string = "") {.expose("editor").} =
proc setRegisterText*(self: App, text: string, register: string = ""): Future[void] {.async.} =
self.registers[register] = Register(kind: Text, text: text)
if register.len == 0:
setSystemClipboardText(text)

proc getRegisterText*(self: App, text: var string, register: string = "") =
proc getRegisterText*(self: App, register: string = ""): Future[string] {.async.} =
# For some reason returning string causes a crash, the returned pointer is just different at the call site for some reason.
# var string parameter seems to fix it
text = ""
if register.len == 0 and getSystemClipboardText().getSome(t):
text = t
return
if register.len == 0:
let text = getSystemClipboardText().await
if text.isSome:
return text.get

if self.registers.contains(register):
text = self.registers[register].getText()
return self.registers[register].getText()

return ""

genDispatcher("editor")
addGlobalDispatchTable "editor", genDispatchTable("editor")
Expand Down
6 changes: 3 additions & 3 deletions src/app_interface.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import std/[json, options]
import misc/[traits]
import misc/[traits, custom_async]
import platform/platform
import workspaces/workspace
import text/language/language_server_base
Expand All @@ -10,8 +10,8 @@ traitRef AppInterface:
method platform*(self: AppInterface): Platform
method configProvider*(self: AppInterface): ConfigProvider
method getEventHandlerConfig*(self: AppInterface, context: string): EventHandlerConfig
method setRegisterText*(self: AppInterface, text: string, register: string)
method getRegisterText*(self: AppInterface, register: string): string
method setRegisterText*(self: AppInterface, text: string, register: string): Future[void]
method getRegisterText*(self: AppInterface, register: string): Future[string]
method openWorkspaceFile*(self: AppInterface, path: string, workspace: WorkspaceFolder): Option[DocumentEditor]
method openFile*(self: AppInterface, path: string): Option[DocumentEditor]
method handleUnknownDocumentEditorAction*(self: AppInterface, editor: DocumentEditor, action: string, args: JsonNode): EventResponse
Expand Down
28 changes: 20 additions & 8 deletions src/ast/model_document.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3121,7 +3121,7 @@ proc runSelectedFunctionAsync*(self: ModelDocumentEditor): Future[void] {.async.
proc runSelectedFunction*(self: ModelDocumentEditor) {.expose("editor.model").} =
asyncCheck runSelectedFunctionAsync(self)

proc copyNode*(self: ModelDocumentEditor) {.expose("editor.model").} =
proc copyNodeAsync*(self: ModelDocumentEditor): Future[void] {.async.} =
let selection = self.selection.normalized
let (parentTargetCell, firstPath, lastPath) = selection.getParentInfo
let parentBaseCell = parentTargetCell.nodeRootCell # the root cell for the given node
Expand Down Expand Up @@ -3154,22 +3154,29 @@ proc copyNode*(self: ModelDocumentEditor) {.expose("editor.model").} =
json = parentTargetCell.node.toJson

if json.isNotNil:
self.app.setRegisterText($json, "")
self.app.setRegisterText($json, "").await

proc copyNode*(self: ModelDocumentEditor) {.expose("editor.model").} =
asyncCheck self.copyNodeAsync()

proc getNodeFromRegister(self: ModelDocumentEditor, register: string): seq[AstNode] =
let text = self.app.getRegisterText(register)
proc getNodeFromRegister(self: ModelDocumentEditor, register: string): Future[seq[AstNode]] {.async.} =
let text = self.app.getRegisterText(register).await
let json = text.parseJson
var res = newSeq[AstNode]()

if json.kind == JObject:
if json.jsonToAstNode(self.document.model).getSome(node):
result.add node
res.add node
elif json.kind == JArray:
for j in json:
if j.jsonToAstNode(self.document.model).getSome(node):
result.add node
res.add node
else:
log lvlError, fmt"Can't parse node from register"

proc pasteNode*(self: ModelDocumentEditor) {.expose("editor.model").} =
return res

proc pasteNodeAsync*(self: ModelDocumentEditor): Future[void] {.async.} =
if self.document.project.isNil:
log lvlError, fmt"No project set for model document '{self.document.filename}'"
return
Expand All @@ -3182,7 +3189,7 @@ proc pasteNode*(self: ModelDocumentEditor) {.expose("editor.model").} =
defer:
self.document.finishTransaction()

let nodes = self.getNodeFromRegister("")
let nodes = self.getNodeFromRegister("").await
if nodes.len == 0:
log lvlError, fmt"Can't parse node from register"
return
Expand Down Expand Up @@ -3226,6 +3233,11 @@ proc pasteNode*(self: ModelDocumentEditor) {.expose("editor.model").} =
self.rebuildCells()
self.cursor = self.getFirstEditableCellOfNode(newNode).get

self.markDirty()

proc pasteNode*(self: ModelDocumentEditor) {.expose("editor.model").} =
asyncCheck self.pasteNodeAsync()

type ModelLanguageSelectorItem* = ref object of SelectorItem
language*: Language
name*: string
Expand Down
26 changes: 22 additions & 4 deletions src/clipboard.nim
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
import std/[options]
import misc/[util, custom_async, custom_logger]

logCategory "clipboard"

when defined(js):
import std/[jsffi, dom]

type Clipboard = ref object of JsObject

proc hasClipboard(): bool {.importjs: "!!navigator.clipboard@".}
proc getClipboard(): Clipboard {.importjs: "navigator.clipboard@".}
proc readText(clipboard: Clipboard): Future[cstring] {.importjs: "#.readText()".}
proc writeText(clipboard: Clipboard, str: cstring): Future[void] {.importjs: "#.writeText(@)".}

proc setSystemClipboardText*(str: string) =
discard
if not hasClipboard():
log lvlError, "Clipboard not available"
return
asyncCheck getClipboard().writeText(str.cstring)

proc getSystemClipboardText*(): Option[string] =
return string.none
proc getSystemClipboardText*(): Future[Option[string]] {.async.} =
if not hasClipboard():
log lvlError, "Clipboard not available"
return string.none
return some $getClipboard().readText().await

else:
import nimclipboard/libclipboard
Expand All @@ -16,6 +34,6 @@ else:
clipboard.clipboardClear(LCB_CLIPBOARD)
discard clipboard.clipboardSetText(str.cstring)

proc getSystemClipboardText*(): Option[string] =
proc getSystemClipboardText*(): Future[Option[string]] {.async.} =
return some $clipboard.clipboardText()

14 changes: 10 additions & 4 deletions src/text/text_editor.nim
Original file line number Diff line number Diff line change
Expand Up @@ -634,17 +634,20 @@ proc redo*(self: TextDocumentEditor) {.expose("editor.text").} =
self.selections = selections
self.scrollToCursor(Last)

proc copy*(self: TextDocumentEditor) {.expose("editor.text").} =
proc copyAsync*(self: TextDocumentEditor): Future[void] {.async.} =
var text = ""
for i, selection in self.selections:
if i > 0:
text.add "\n"
text.add self.document.contentString(selection)

self.app.setRegisterText(text, "")
self.app.setRegisterText(text, "").await

proc paste*(self: TextDocumentEditor) {.expose("editor.text").} =
let text = self.app.getRegisterText("")
proc copy*(self: TextDocumentEditor) {.expose("editor.text").} =
asyncCheck self.copyAsync()

proc pasteAsync*(self: TextDocumentEditor): Future[void] {.async.} =
let text = self.app.getRegisterText("").await

let numLines = text.count('\n') + 1

Expand All @@ -664,6 +667,9 @@ proc paste*(self: TextDocumentEditor) {.expose("editor.text").} =
self.selections = newSelections
self.scrollToCursor(Last)

proc paste*(self: TextDocumentEditor) {.expose("editor.text").} =
asyncCheck self.pasteAsync()

proc scrollText(self: TextDocumentEditor, amount: float32) {.expose("editor.text").} =
if self.disableScrolling:
return
Expand Down

0 comments on commit 0ed005e

Please sign in to comment.