diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buffer/buffer.nim | 53 | ||||
-rw-r--r-- | src/buffer/container.nim | 34 | ||||
-rw-r--r-- | src/display/client.nim | 17 | ||||
-rw-r--r-- | src/display/pager.nim | 12 |
4 files changed, 73 insertions, 43 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim index 8bfd3f6e..f20804c7 100644 --- a/src/buffer/buffer.nim +++ b/src/buffer/buffer.nim @@ -51,6 +51,10 @@ type GET_SOURCE, GET_LINES, UPDATE_HOVER, PASS_FD, CONNECT, GOTO_ANCHOR, CANCEL, GET_TITLE + HoverType* = enum + HOVER_TITLE = "TITLE" + HOVER_LINK = "URL" + BufferMatch* = object success*: bool x*: int @@ -88,7 +92,7 @@ type timeouts: Table[int, (proc())] tasks: array[BufferCommand, int] #TODO this should have arguments savetask: bool - hovertext: string + hovertext: array[HoverType, string] # async, but worse EmptyPromise = ref object of RootObj @@ -280,15 +284,6 @@ func getTitleAttr(node: StyledNode): string = return element.attr("title") #TODO pseudo-elements -func getLink(node: StyledNode): HTMLAnchorElement = - if node == nil: - return nil - if node.t == STYLED_ELEMENT and node.node != nil and Element(node.node).tagType == TAG_A: - return HTMLAnchorElement(node.node) - if node.node != nil: - return HTMLAnchorElement(node.node.findAncestor({TAG_A})) - #TODO ::before links? - const ClickableElements = { TAG_A, TAG_INPUT, TAG_OPTION, TAG_BUTTON, TAG_TEXTAREA } @@ -302,6 +297,22 @@ func getClickable(styledNode: StyledNode): Element = return element styledNode.node.findAncestor(ClickableElements) +func getClickHover(styledNode: StyledNode): string = + let clickable = styledNode.getClickable() + if clickable != nil: + case clickable.tagType + of TAG_A: + return HTMLAnchorElement(clickable).href + of TAG_INPUT: + return "<input>" + of TAG_OPTION: + return "<option>" + of TAG_BUTTON: + return "<button>" + of TAG_TEXTAREA: + return "<textarea>" + else: discard + func getCursorClickable(buffer: Buffer, cursorx, cursory: int): Element = let i = buffer.lines[cursory].findFormatN(cursorx) - 1 if i >= 0: @@ -489,7 +500,8 @@ proc windowChange*(buffer: Buffer, attrs: WindowAttributes) {.proxy.} = buffer.height = buffer.attrs.height - 1 type UpdateHoverResult* = object - hover*: Option[string] + link*: Option[string] + title*: Option[string] repaint*: bool proc updateHover*(buffer: Buffer, cursorx, cursory: int): UpdateHoverResult {.proxy.} = @@ -508,19 +520,14 @@ proc updateHover*(buffer: Buffer, cursorx, cursory: int): UpdateHoverResult {.pr elem.hover = true result.repaint = true - var upd = false let title = thisnode.getTitleAttr() - if title != "": - upd = true - buffer.hovertext = title - elif (let link = thisnode.getLink(); link != nil): - upd = true - buffer.hovertext = link.href - else: - upd = buffer.hovertext != "" - buffer.hovertext = "" - if upd: - result.hover = some(buffer.hovertext) + if buffer.hovertext[HOVER_TITLE] != title: + result.title = some(title) + buffer.hovertext[HOVER_TITLE] = title + let click = thisnode.getClickHover() + if buffer.hovertext[HOVER_LINK] != click: + result.link = some(click) + buffer.hovertext[HOVER_LINK] = click for styledNode in prevnode.branch: if styledNode.t == STYLED_ELEMENT and styledNode.node != nil: diff --git a/src/buffer/container.nim b/src/buffer/container.nim index 80044b60..66ef2780 100644 --- a/src/buffer/container.nim +++ b/src/buffer/container.nim @@ -72,7 +72,8 @@ type height*: int contenttype*: Option[string] title*: string - hovertext*: string + hovertext*: array[HoverType, string] + lastpeek: HoverType source*: BufferSource pos: CursorPosition bpos: seq[CursorPosition] @@ -257,6 +258,11 @@ func findHighlights*(container: Container, y: int): seq[Highlight] = if y in hl: result.add(hl) +func getHoverText*(container: Container): string = + for t in HoverType: + if container.hovertext[t] != "": + return container.hovertext[t] + proc triggerEvent(container: Container, event: ContainerEvent) = container.events.addLast(event) @@ -291,8 +297,11 @@ proc redraw*(container: Container) {.jsfunc.} = proc sendCursorPosition(container: Container) = container.iface.updateHover(container.cursorx, container.cursory).then(proc(res: UpdateHoverResult) = - if res.hover.isSome: - container.hovertext = res.hover.get + if res.link.isSome: + container.hovertext[HOVER_LINK] = res.link.get + if res.title.isSome: + container.hovertext[HOVER_TITLE] = res.title.get + if res.link.isSome or res.title.isSome: container.triggerEvent(STATUS) if res.repaint: container.needslines = true) @@ -754,9 +763,24 @@ proc windowChange*(container: Container, attrs: WindowAttributes) = proc peek*(container: Container) {.jsfunc.} = container.alert($container.source.location) +proc clearHover*(container: Container) = + container.lastpeek = low(HoverType) + proc peekCursor*(container: Container) {.jsfunc.} = - if container.hovertext != "": - container.alert(container.hovertext) + var p = container.lastpeek + while true: + if container.hovertext[p] != "": + container.alert($p & ": " & container.hovertext[p]) + break + if p < high(HoverType): + inc p + else: + p = low(HoverType) + if p == container.lastpeek: break + if container.lastpeek < high(HoverType): + inc container.lastpeek + else: + container.lastpeek = low(HoverType) proc handleCommand(container: Container) = var packetid, len: int diff --git a/src/display/client.nim b/src/display/client.nim index 5162d4aa..cf27eac4 100644 --- a/src/display/client.nim +++ b/src/display/client.nim @@ -140,6 +140,11 @@ proc feedNext(client: Client) {.jsfunc.} = proc alert(client: Client, msg: string) {.jsfunc.} = client.pager.alert(msg) +proc handlePagerEvents(client: Client) = + let container = client.pager.container + if container != nil and not client.pager.handleEvents(container): + client.quit(1) + proc input(client: Client) = restoreStdin(client.console.tty.getFileHandle()) while true: @@ -169,6 +174,7 @@ proc input(client: Client) = let action = getNormalAction(client.config, client.s) client.evalJSFree(action, "<command>") if not client.feedNext: + client.handlePagerEvents() client.pager.refreshStatusMsg() if not client.feedNext: client.s = "" @@ -282,10 +288,7 @@ proc inputLoop(client: Client) = if Read in event.events: if event.fd == client.console.tty.getFileHandle(): client.input() - let container = client.pager.container - if container != nil and not client.pager.handleEvents(container): - client.quit(1) - stdout.flushFile() + client.handlePagerEvents() else: let container = client.fdmap[event.fd] if not client.pager.handleEvent(container): @@ -310,7 +313,7 @@ proc inputLoop(client: Client) = if client.pager.scommand != "": client.command(client.pager.scommand) client.pager.scommand = "" - client.pager.refreshStatusMsg() + client.handlePagerEvents() client.pager.draw() client.acceptBuffers() @@ -334,10 +337,6 @@ proc dumpLoop(client: Client) = let timeout = client.timeouts[id] timeout.handler() client.clearTimeout(id) - if client.pager.scommand != "": - client.command(client.pager.scommand) - client.pager.scommand = "" - client.pager.refreshStatusMsg() client.acceptBuffers() proc headlessLoop(client: Client) = diff --git a/src/display/pager.nim b/src/display/pager.nim index f61304aa..53388052 100644 --- a/src/display/pager.nim +++ b/src/display/pager.nim @@ -250,7 +250,7 @@ proc refreshDisplay(pager: Pager, container = pager.container) = proc clearStatusMessage(pager: Pager) = pager.statusgrid = newFixedGrid(pager.statusgrid.width) -proc writeStatusMessage(pager: Pager, str: string, format: Format = Format()) = +proc writeStatusMessage(pager: Pager, str: string, format: Format = newFormat()) = pager.clearStatusMessage() var i = 0 for r in str.runes: @@ -275,11 +275,13 @@ proc refreshStatusMsg*(pager: Pager) = pager.writeStatusMessage(pager.alerts[0]) pager.alerts.delete(0) else: + container.clearHover() var msg = $(container.cursory + 1) & "/" & $container.numLines & " (" & $container.atPercentOf() & "%) " & "<" & container.getTitle() & ">" - if container.hovertext.len > 0: - msg &= " " & container.hovertext - var format: Format + let h = container.getHoverText() + if h != "": + msg &= " " & h + var format = newFormat() format.reverse = true pager.writeStatusMessage(msg, format) @@ -717,7 +719,6 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo pager.gotoURL(newRequest(container.retry.pop()), ctype = container.contenttype) else: pager.alert("Can't load " & $container.source.location & " (error code " & $container.code & ")") - pager.refreshStatusMsg() if pager.container == nil: return false of SUCCESS: @@ -785,7 +786,6 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo of ALERT: if pager.container == container: pager.alert(event.msg) - pager.refreshStatusMsg() of NO_EVENT: discard return true |