Skip to content

Commit

Permalink
added symbol finder popup
Browse files Browse the repository at this point in the history
  • Loading branch information
Nimaoth committed Dec 5, 2023
1 parent 53f451e commit 7d8a364
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 12 deletions.
Binary file modified config/absytree_config_wasm.wasm
Binary file not shown.
3 changes: 3 additions & 0 deletions config/keybindings_normal.nim
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ proc loadNormalKeybindings*() {.scriptActionWasmNims("load-normal-keybindings").
addModelCommand "", "<C-m>", "select-next"
addModelCommand "", "<C-t>", "select-next"

addModelCommand "", "<C-g>g", "find-declaration", false
addModelCommand "", "<C-g>G", "find-declaration", true

addModelCommand "", "<*C-g>c", "goto-next-node-of-class", "ConstDecl"
addModelCommand "", "<*C-g>C", "goto-prev-node-of-class", "ConstDecl"
addModelCommand "", "<*C-g>l", "goto-next-node-of-class", "LetDecl"
Expand Down
2 changes: 2 additions & 0 deletions config/keybindings_vim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ proc loadVimKeybindings*() {.scriptActionWasmNims("load-vim-keybindings").} =
addCommand("editor.model", "w", "move-cursor-right-cell")
addCommand("editor.model", "u", "undo")
addCommand("editor.model", "U", "redo")
addModelCommand "", "}", "goto-next-node-of-class", "EmptyLine"
addModelCommand "", "{", "goto-prev-node-of-class", "EmptyLine"

addModelCommandBlock "", "<C-e>":
editor.setMode("")
Expand Down
3 changes: 3 additions & 0 deletions scripting/absytree_internal.nim
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ proc editor_model_saveProject_void_ModelDocumentEditor_impl*(
proc editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_impl*(
self: ModelDocumentEditor) =
discard
proc editor_model_findDeclaration_void_ModelDocumentEditor_bool_impl*(
self: ModelDocumentEditor; global: bool) =
discard
proc editor_getBackend_Backend_App_impl*(): Backend =
discard
proc editor_toggleShowDrawnNodes_void_App_impl*() =
Expand Down
2 changes: 2 additions & 0 deletions scripting/absytree_internal_wasm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ proc editor_model_saveProject_void_ModelDocumentEditor_impl(
self: ModelDocumentEditor) {.importc.}
proc editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_impl(
self: ModelDocumentEditor) {.importc.}
proc editor_model_findDeclaration_void_ModelDocumentEditor_bool_impl(
self: ModelDocumentEditor; global: bool) {.importc.}
proc editor_getBackend_Backend_App_impl(): Backend {.importc.}
proc editor_toggleShowDrawnNodes_void_App_impl() {.importc.}
proc editor_saveAppState_void_App_impl() {.importc.}
Expand Down
2 changes: 2 additions & 0 deletions scripting/editor_model_api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,5 @@ proc saveProject*(self: ModelDocumentEditor) =
editor_model_saveProject_void_ModelDocumentEditor_impl(self)
proc loadBaseLanguageModel*(self: ModelDocumentEditor) =
editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_impl(self)
proc findDeclaration*(self: ModelDocumentEditor; global: bool) =
editor_model_findDeclaration_void_ModelDocumentEditor_bool_impl(self, global)
19 changes: 19 additions & 0 deletions scripting/editor_model_api_wasm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -909,3 +909,22 @@ proc loadBaseLanguageModel*(self: ModelDocumentEditor) =
let res {.used.} = editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_wasm(
argsJsonString.cstring)


proc editor_model_findDeclaration_void_ModelDocumentEditor_bool_wasm(
arg: cstring): cstring {.importc.}
proc findDeclaration*(self: ModelDocumentEditor; global: bool) =
var argsJson = newJArray()
argsJson.add block:
when ModelDocumentEditor is JsonNode:
self
else:
self.toJson()
argsJson.add block:
when bool is JsonNode:
global
else:
global.toJson()
let argsJsonString = $argsJson
let res {.used.} = editor_model_findDeclaration_void_ModelDocumentEditor_bool_wasm(
argsJsonString.cstring)

110 changes: 98 additions & 12 deletions src/model_document.nim
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,12 @@ method save*(self: ModelDocument, filename: string = "", app: bool = false) =
template cursor*(self: ModelDocumentEditor): CellCursor = self.mSelection.last
template selection*(self: ModelDocumentEditor): CellSelection = self.mSelection

proc requestEditorForModel(self: ModelDocumentEditor, model: Model): Option[ModelDocumentEditor] =
let editor: Option[DocumentEditor] = self.app.openWorkspaceFile(model.path, self.document.workspace.get)
if editor.getSome(editor) and editor of ModelDocumentEditor:
return editor.ModelDocumentEditor.some
return ModelDocumentEditor.none

proc startBlinkCursorTask(self: ModelDocumentEditor) =
if not self.blinkCursor:
return
Expand All @@ -340,7 +346,7 @@ proc startBlinkCursorTask(self: ModelDocumentEditor) =
self.blinkCursorTask.reschedule()

proc updateScrollOffset*(self: ModelDocumentEditor, scrollToCursor: bool = true) =
if self.cellWidgetContext.isNil:
if self.cellWidgetContext.isNil or self.scrolledNode.parent.isNil:
return

let newCell = self.selection.last.targetCell
Expand All @@ -349,15 +355,19 @@ proc updateScrollOffset*(self: ModelDocumentEditor, scrollToCursor: bool = true)

if newCell.isNotNil and self.cellWidgetContext.cellToWidget.contains(newCell.id):
let newUINode = self.cellWidgetContext.cellToWidget[newCell.id]
let newY = newUINode.transformBounds(self.scrolledNode.parent).y

let buffer = 5.0
if newY < buffer * self.app.platform.builder.textHeight:
self.targetCellPath = newCell.rootPath.path
self.scrollOffset = buffer * self.app.platform.builder.textHeight
elif newY > self.scrolledNode.parent.h - buffer * self.app.platform.builder.textHeight:
self.targetCellPath = newCell.rootPath.path
self.scrollOffset = self.scrolledNode.parent.h - buffer * self.app.platform.builder.textHeight
if newUINode.isDescendant(self.scrolledNode.parent):
let newY = newUINode.transformBounds(self.scrolledNode.parent).y

let buffer = 5.0
if newY < buffer * self.app.platform.builder.textHeight:
self.targetCellPath = newCell.rootPath.path
self.scrollOffset = buffer * self.app.platform.builder.textHeight
elif newY > self.scrolledNode.parent.h - buffer * self.app.platform.builder.textHeight:
self.targetCellPath = newCell.rootPath.path
self.scrollOffset = self.scrolledNode.parent.h - buffer * self.app.platform.builder.textHeight
else:
self.targetCellPath = self.selection.last.targetCell.rootPath.path
self.scrollOffset = self.scrolledNode.parent.h / 2

elif scrollToCursor:
# discard
Expand Down Expand Up @@ -1823,8 +1833,11 @@ proc gotoDefinition*(self: ModelDocumentEditor, select: bool = false) {.expose("
self.cursor = self.getFirstEditableCellOfNode(target).get
self.updateScrollOffset()
else:
# todo: open node in new/existing editor
discard
if self.requestEditorForModel(target.model).getSome(editor):
editor.cursor = editor.getFirstEditableCellOfNode(target).get
editor.updateScrollOffset(true)
editor.markDirty()
self.app.tryActivateEditor(editor)

self.markDirty()

Expand Down Expand Up @@ -3223,10 +3236,17 @@ proc importModel*(self: ModelDocumentEditor) {.expose("editor.model").} =
type ModelNodeClassSelectorItem* = ref object of NamedSelectorItem
class*: NodeClass

type AstNodeSelectorItem* = ref object of NamedSelectorItem
node*: AstNode

method changed*(self: ModelNodeClassSelectorItem, other: SelectorItem): bool =
let other = other.ModelNodeClassSelectorItem
return self.class != other.class

method changed*(self: AstNodeSelectorItem, other: SelectorItem): bool =
let other = other.AstNodeSelectorItem
return self.node != other.node

proc compileLanguage*(self: ModelDocumentEditor) {.expose("editor.model").} =
if not self.document.model.hasLanguage(IdLangLanguage):
return
Expand Down Expand Up @@ -3306,6 +3326,72 @@ proc loadBaseLanguageModel*(self: ModelDocumentEditor) {.expose("editor.model").

self.document.onModelChanged.invoke (self.document)

proc findDeclaration*(self: ModelDocumentEditor, global: bool) {.expose("editor.model").} =
var popup = self.app.createSelectorPopup().SelectorPopup

popup.getCompletions = proc(popup: SelectorPopup, text: string): seq[SelectorItem] =
var models = newSeq[Model]()
if global:
for model in self.document.project.models.values:
models.add model
else:
models.add self.document.model

for model in models:
for rootNode in model.rootNodes:
debugf"collect children of root {rootNode}"
for children in rootNode.childLists.mitems:
for child in children.nodes:
let class = child.nodeClass
if class.isNotNil and class.isSubclassOf(IdINamed):
let name = child.property(IdINamedName).get.stringValue
let score = matchPath(name, text)
result.add AstNodeSelectorItem(name: name, score: score, node: child)

popup.handleItemSelected = proc(item: SelectorItem) =
log lvlInfo, fmt"Select node {item.AstNodeSelectorItem.name}"
let node = item.AstNodeSelectorItem.node

if node.model.isNil:
log lvlError, fmt"Node is no longer part of a model"
return

if node.model == self.document.model and self.getFirstEditableCellOfNode(node).getSome(cursor):
self.cursor = cursor
self.updateScrollOffset(true)
self.markDirty()
elif node.model != self.document.model:
if self.requestEditorForModel(node.model).getSome(editor):
editor.cursor = editor.getFirstEditableCellOfNode(node).get
editor.updateScrollOffset(true)
editor.markDirty()
self.app.tryActivateEditor(editor)

popup.handleItemConfirmed = proc(item: SelectorItem) =
log lvlInfo, fmt"Select node {item.AstNodeSelectorItem.name}"
let node = item.AstNodeSelectorItem.node

if node.model.isNil:
log lvlError, fmt"Node is no longer part of a model"
return

if node.model == self.document.model and self.getFirstEditableCellOfNode(node).getSome(cursor):
self.cursor = cursor
self.updateScrollOffset(true)
self.markDirty()
elif node.model != self.document.model:
if self.requestEditorForModel(node.model).getSome(editor):
editor.cursor = editor.getFirstEditableCellOfNode(node).get
editor.updateScrollOffset(true)
editor.markDirty()
self.app.tryActivateEditor(editor)

popup.updateCompletions()
popup.sortFunction = proc(a, b: SelectorItem): int = cmp(a.score, b.score)
popup.enableAutoSort()

self.app.pushPopup popup

genDispatcher("editor.model")
addActiveDispatchTable "editor.model", genDispatchTable("editor.model")

Expand Down
8 changes: 8 additions & 0 deletions src/ui/node.nim
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,14 @@ iterator rchildren*(node: UINode): UINode =
yield current
current = prev

proc isDescendant*(node: UINode, ancestor: UINode): bool =
var curr = node
while curr.isNotNil:
if curr.parent == ancestor:
return true
curr = curr.parent
return false

proc transformPos*(vec: Vec2, src: UINode, dst: UINode): Vec2 =
result = vec
var curr = src
Expand Down

0 comments on commit 7d8a364

Please sign in to comment.