diff --git a/src/servers/workspace_server.nim b/src/servers/workspace_server.nim index eaedd4c6..12cefe63 100644 --- a/src/servers/workspace_server.nim +++ b/src/servers/workspace_server.nim @@ -50,7 +50,7 @@ proc translatePath(path: string): Option[string] = return path.absolutePath.normalizedPath.some proc callback(req: Request): Future[void] {.async.} = - debug req.reqMethod, " ", req.url + debugf"{req.reqMethod} {req.url}" let (workspaceName, hostedFolders) = block: {.gcsafe.}: diff --git a/src/text/language/language_server_lsp.nim b/src/text/language/language_server_lsp.nim index f6dca6cf..8da86362 100644 --- a/src/text/language/language_server_lsp.nim +++ b/src/text/language/language_server_lsp.nim @@ -176,6 +176,7 @@ method getHover*(self: LanguageServerLSP, filename: string, location: Cursor): F let parsedResponse = response.result + # important: the order of these checks is important if parsedResponse.contents.asMarkedStringVariantSeq().getSome(markedStrings): for markedString in markedStrings: if markedString.asString().getSome(str): @@ -186,20 +187,20 @@ method getHover*(self: LanguageServerLSP, filename: string, location: Cursor): F return string.none + if parsedResponse.contents.asMarkupContent().getSome(markupContent): + return markupContent.value.some + if parsedResponse.contents.asMarkedStringVariant().getSome(markedString): debugf"marked string variant: {markedString}" - if markedString.asString().getSome(str): - debugf"string: {str}" - return str.some if markedString.asMarkedStringObject().getSome(str): debugf"string object lang: {str.language}, value: {str.value}" return str.value.some - return string.none + if markedString.asString().getSome(str): + debugf"string: {str}" + return str.some - if parsedResponse.contents.asMarkupContent().getSome(markupContent): - debugf"markup content: {markupContent}" - return markupContent.value.some + return string.none return string.none diff --git a/src/text/language/lsp_types.nim b/src/text/language/lsp_types.nim index ddea545f..3a8ff777 100644 --- a/src/text/language/lsp_types.nim +++ b/src/text/language/lsp_types.nim @@ -21,6 +21,7 @@ macro variant(name: untyped, types: varargs[untyped]): untyped = let procName = ident("as" & typeName.capitalizeAscii) let ast = genAst(procName, name, t, isSeqLit): + proc procName*(arg: name): Option[t] = try: when isSeqLit: @@ -29,6 +30,7 @@ macro variant(name: untyped, types: varargs[untyped]): untyped = return arg.node.jsonTo(t, Joptions(allowMissingKeys: true, allowExtraKeys: false)).some except CatchableError: return t.none + proc procName*(arg: Option[name]): Option[t] = if arg.isSome: return procName(arg.get) diff --git a/src/text/text_editor.nim b/src/text/text_editor.nim index a0837475..289cccdc 100644 --- a/src/text/text_editor.nim +++ b/src/text/text_editor.nim @@ -58,6 +58,7 @@ type TextDocumentEditor* = ref object of DocumentEditor showHover*: bool # whether to show hover info in ui hoverText*: string # the text to show in the hover info hoverLocation*: Cursor # where to show the hover info + hoverScrollOffset*: float # the scroll offset inside the hover window completionEventHandler: EventHandler modeEventHandler: EventHandler @@ -1523,6 +1524,7 @@ proc showHoverForAsync(self: TextDocumentEditor, cursor: Cursor): Future[void] { let hoverInfo = await ls.getHover(self.document.fullPath, cursor) if hoverInfo.getSome(hoverInfo): self.showHover = true + self.hoverScrollOffset = 0 self.hoverText = hoverInfo self.hoverLocation = cursor else: diff --git a/src/ui/widget_builder_text_document.nim b/src/ui/widget_builder_text_document.nim index 40eaa5e2..3c9fe7f6 100644 --- a/src/ui/widget_builder_text_document.nim +++ b/src/ui/widget_builder_text_document.nim @@ -192,6 +192,7 @@ proc renderLine*( self.showHoverForDelayed (line.index, offset) onEndHover: + # todo: hide after delay so the user has time to hover over the hover window for e.g. scrolling self.hideHover() if addBackgroundAsChildren: @@ -500,8 +501,9 @@ proc createHover(self: TextDocumentEditor, builder: UINodeBuilder, app: App, cur let docsColor = app.theme.color("editor.foreground", color(1, 1, 1)) let scopeColor = app.theme.color("string", color(175/255, 1, 175/255)) - const numLinesToShow = 1 - let (top, bottom) = (cursorBounds.yh.float, cursorBounds.yh.float + totalLineHeight * numLinesToShow) + let numLinesToShow = min(10, self.hoverText.countLines) + let (top, bottom) = (cursorBounds.yh.float, cursorBounds.yh.float + totalLineHeight * numLinesToShow.float) + let height = bottom - top const docsWidth = 50.0 let totalWidth = charWidth * docsWidth @@ -510,13 +512,18 @@ proc createHover(self: TextDocumentEditor, builder: UINodeBuilder, app: App, cur clampedX = max(builder.root.w - totalWidth, 0) var hoverPanel: UINode = nil - builder.panel(&{SizeToContentX, SizeToContentY, MaskContent}, x = clampedX, y = top, w = totalWidth, h = bottom - top, pivot = vec2(0, 0), userId = self.hoverId.newPrimaryId): + builder.panel(&{SizeToContentX, MaskContent, FillBackground, DrawBorder, MouseHover}, x = clampedX, y = top, h = height, pivot = vec2(0, 0), backgroundColor = backgroundColor, borderColor = scopeColor, userId = self.hoverId.newPrimaryId): hoverPanel = currentNode var textNode: UINode = nil - builder.panel(&{DrawText, FillBackground, DrawBorder, SizeToContentX, SizeToContentY}, x = 1, y = 1, text = self.hoverText, textColor = docsColor, backgroundColor = backgroundColor, borderColor = scopeColor) - textNode = currentNode - currentNode.boundsRaw.w = textNode.bounds.w + 2 - currentNode.boundsRaw.h = textNode.bounds.h + 2 + # todo: height + builder.panel(&{DrawText, SizeToContentX}, x = 0, y = self.hoverScrollOffset, h = 1000, text = self.hoverText, textColor = docsColor): + textNode = currentNode + + onScroll: + let scrollSpeed = app.asConfigProvider.getValue("text.hover-scroll-speed", 20.0) + # todo: clamp bottom + self.hoverScrollOffset = clamp(self.hoverScrollOffset + delta.y * scrollSpeed, -1000, 0) + self.markDirty() hoverPanel.rawY = cursorBounds.y hoverPanel.pivot = vec2(0, 1)