diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buffer/container.nim | 3 | ||||
-rw-r--r-- | src/display/client.nim | 19 | ||||
-rw-r--r-- | src/display/pager.nim | 108 |
3 files changed, 83 insertions, 47 deletions
diff --git a/src/buffer/container.nim b/src/buffer/container.nim index 61097186..d5c6becf 100644 --- a/src/buffer/container.nim +++ b/src/buffer/container.nim @@ -260,6 +260,9 @@ func getHoverText*(container: Container): string = if container.hovertext[t] != "": return container.hovertext[t] +func isHoverURL*(container: Container, url: URL): bool = + return $url == container.hovertext[HOVER_LINK] + proc triggerEvent(container: Container, event: ContainerEvent) = container.events.addLast(event) diff --git a/src/display/client.nim b/src/display/client.nim index ab12e2f8..311d8ffc 100644 --- a/src/display/client.nim +++ b/src/display/client.nim @@ -156,8 +156,15 @@ proc input(client: Client) = restoreStdin(client.console.tty.getFileHandle()) while true: let c = client.console.readChar() - client.s &= c - if client.pager.lineedit.isSome: + if client.pager.askpromise != nil: + if c == 'y': + client.pager.fulfillAsk(true) + client.runJSJobs() + elif c == 'n': + client.pager.fulfillAsk(false) + client.runJSJobs() + elif client.pager.lineedit.isSome: + client.s &= c let edit = client.pager.lineedit.get client.line = edit if edit.escNext: @@ -171,23 +178,25 @@ proc input(client: Client) = client.s = "" else: client.feedNext = true - elif not client.feedNext: + elif not client.feednext: client.evalJSFree(action, "<command>") if client.pager.lineedit.isNone: client.line = nil if not client.feedNext: client.pager.updateReadLine() else: + client.s &= c let action = getNormalAction(client.config, client.s) client.evalJSFree(action, "<command>") if not client.feedNext: client.handlePagerEvents() client.pager.refreshStatusMsg() - if not client.feedNext: + if not client.feednext: client.s = "" break else: - client.feedNext = false + client.feednext = false + client.s = "" proc setTimeout[T: JSValue|string](client: Client, handler: T, timeout = 0): int {.jsfunc.} = let id = client.timeoutid diff --git a/src/display/pager.nim b/src/display/pager.nim index eadec817..6e04f072 100644 --- a/src/display/pager.nim +++ b/src/display/pager.nim @@ -14,6 +14,7 @@ import buffer/container import config/config import display/term import io/lineedit +import io/promise import io/request import io/window import ips/editor @@ -34,6 +35,9 @@ type SEARCH_B, ISEARCH_F, ISEARCH_B, GOTO_LINE Pager* = ref object + askpromise*: Promise[bool] + askprompt: string + askcursor: int jsctx: JSContext numload*: int alerts: seq[string] @@ -53,7 +57,6 @@ type tty: File procmap*: Table[Pid, Container] unreg*: seq[(Pid, SocketStream)] - icpos: CursorPosition display: FixedGrid redraw*: bool term*: Terminal @@ -243,28 +246,35 @@ proc refreshDisplay(pager: Pager, container = pager.container) = pager.display[dls + i - startw].format = hlformat inc by -proc clearStatusMessage(pager: Pager) = - pager.statusgrid = newFixedGrid(pager.statusgrid.width) - -proc writeStatusMessage(pager: Pager, str: string, format: Format = newFormat()) = - pager.clearStatusMessage() - var i = 0 +proc writeStatusMessage(pager: Pager, str: string, + format: Format = newFormat(), start = 0, + maxwidth = -1, clip = '$'): int {.discardable.} = + var maxwidth = maxwidth + if maxwidth == -1: + maxwidth = pager.statusgrid.len + var i = start for r in str.runes: - if i >= pager.statusgrid.len: - pager.statusgrid[^1].str = "$" + if i >= maxwidth: + pager.statusgrid[^1].str = $clip break - if r.isControlChar() or r == Rune('\n'): - pager.statusgrid[i].str &= "^" - pager.statusgrid[i].str &= getControlLetter(char(r)) + if r.isControlChar(): + pager.statusgrid[i].str = "^" & getControlLetter(char(r)) else: - pager.statusgrid[i].str &= r + pager.statusgrid[i].str = $r pager.statusgrid[i].format = format i += r.twidth(i) + result = i + var def = newFormat() + while i < maxwidth: + pager.statusgrid[i].str = "" + pager.statusgrid[i].format = def + inc i proc refreshStatusMsg*(pager: Pager) = let container = pager.container if container == nil: return if pager.tty == nil: return + if pager.askpromise != nil: return if container.loadinfo != "": pager.alerton = false pager.writeStatusMessage(container.loadinfo) @@ -273,37 +283,22 @@ proc refreshStatusMsg*(pager: Pager) = pager.writeStatusMessage(pager.alerts[0]) pager.alerts.delete(0) else: + var format = newFormat() + format.reverse = true pager.alerton = false container.clearHover() var msg = $(container.cursory + 1) & "/" & $container.numLines & " (" & $container.atPercentOf() & "%)" - let mw = msg.width() - let t = container.getTitle() - let tt = " <" & t & ">" - let tw = tt.width() - let ht = container.getHoverText() - if ht.len == 0: # hover text is empty. - msg &= tt + let mw = pager.writeStatusMessage(msg, format) + let title = " <" & container.getTitle() & ">" + let hover = container.getHoverText() + if hover.len == 0: + pager.writeStatusMessage(title, format, mw) else: - let h = " " & ht - let hw = h.width() - if mw + tw + hw < pager.statusgrid.width: - msg &= tt - elif mw + hw + 3 < pager.statusgrid.width: - # squeezing the title would mean we still have some space for it. - var t2 = " <" - var w = mw + hw + 2 # t2 has a width of 2 - for r in t.runes: - if w >= pager.statusgrid.width - 1: # ends with another > - t2 &= ">" - break - t2 &= r - w += r.width() - msg &= t2 - msg &= h - var format = newFormat() - format.reverse = true - pager.writeStatusMessage(msg, format) + let hover2 = " " & hover + let maxwidth = pager.statusgrid.width - mw - hover2.width() + let tw = pager.writeStatusMessage(title, format, mw, maxwidth, '>') + pager.writeStatusMessage(hover2, format, tw) # Call refreshStatusMsg if no alert is being displayed on the screen. proc showAlerts*(pager: Pager) = @@ -342,12 +337,16 @@ proc draw*(pager: Pager) = if pager.redraw: pager.refreshDisplay() pager.term.writeGrid(pager.display) - if pager.lineedit.isSome: + if pager.askpromise != nil: + discard + elif pager.lineedit.isSome: pager.term.writeGrid(pager.lineedit.get.generateOutput(), 0, pager.attrs.height - 1) else: pager.term.writeGrid(pager.statusgrid, 0, pager.attrs.height - 1) pager.term.outputGrid() - if pager.lineedit.isSome: + if pager.askpromise != nil: + pager.term.setCursor(pager.askcursor, pager.attrs.height - 1) + elif pager.lineedit.isSome: pager.term.setCursor(pager.lineedit.get.getCursorX(), pager.attrs.height - 1) else: pager.term.setCursor(pager.container.acursorx, pager.container.acursory) @@ -355,6 +354,24 @@ proc draw*(pager: Pager) = pager.term.flush() pager.redraw = false +proc writeAskPrompt(pager: Pager) = + let yn = " (y/n)" + let maxwidth = pager.statusgrid.width - yn.len + let i = pager.writeStatusMessage(pager.askprompt, maxwidth = maxwidth) + pager.askcursor = pager.writeStatusMessage(yn, start = i) + pager.term.writeGrid(pager.statusgrid, 0, pager.attrs.height - 1) + +proc ask(pager: Pager, prompt: string): Promise[bool] {.jsfunc.} = + pager.askprompt = prompt + pager.writeAskPrompt() + pager.askpromise = Promise[bool]() + return pager.askpromise + +proc fulfillAsk*(pager: Pager, y: bool) = + pager.askpromise.resolve(y) + pager.askpromise = nil + pager.askprompt = "" + proc registerContainer*(pager: Pager, container: Container) = pager.procmap[container.process] = container @@ -511,6 +528,8 @@ proc windowChange*(pager: Pager, attrs: WindowAttributes) = pager.statusgrid = newFixedGrid(attrs.width) for container in pager.containers: container.windowChange(attrs) + if pager.askprompt != "": + pager.writeAskPrompt() pager.refreshStatusMsg() proc applySiteconf(pager: Pager, request: Request): BufferConfig = @@ -805,7 +824,12 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo pager.container.readCanceled() pager.redraw = true of OPEN: - pager.gotoURL(event.request, some(container.source.location), referrer = pager.container) + if pager.container == nil or not pager.container.isHoverURL(event.request.url): + pager.ask("Open pop-up? " & $event.request.url).then(proc(x: bool) = + if x: + pager.gotoURL(event.request, some(container.source.location), referrer = pager.container)) + else: + pager.gotoURL(event.request, some(container.source.location), referrer = pager.container) of INVALID_COMMAND: discard of STATUS: if pager.container == container: |