diff options
author | bptato <nincsnevem662@gmail.com> | 2022-12-15 17:35:41 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-12-15 17:35:41 +0100 |
commit | 5be29f675fc27974ff256cb2094ccd0854e19b07 (patch) | |
tree | f7ff0acf57a2440b681fc5e90b4a74e0943e106c | |
parent | e86bcfd40f699b88c984c4f79adc8647796353ae (diff) | |
download | chawan-5be29f675fc27974ff256cb2094ccd0854e19b07.tar.gz |
Add discardTree, update docs
-rw-r--r-- | doc/config.md | 395 | ||||
-rw-r--r-- | res/config.toml | 4 | ||||
-rw-r--r-- | src/buffer/container.nim | 4 | ||||
-rw-r--r-- | src/display/pager.nim | 53 |
4 files changed, 367 insertions, 89 deletions
diff --git a/doc/config.md b/doc/config.md index 95b55f92..d64d0d59 100644 --- a/doc/config.md +++ b/doc/config.md @@ -371,7 +371,7 @@ escape to the keybinding respectively (essentially making `M-` the same as `C-[`). Modifiers can be escaped with the `\` sign. ```Examples: -'C-M-j' = 'pager.changeLocation()' # change URL when Control, Escape and j are pressed +'C-M-j' = 'pager.load()' # change URL when Control, Escape and j are pressed 'gg' = 'pager.cursorFirstLine()' # go to the first line of the page when g is pressed twice ``` An action is a JavaScript function called by chawan every time the keybinding @@ -380,78 +380,341 @@ is typed in. A list of built-in pager functions can be found below. ### Pager actions <table> -<tr><th>**Name**<th>**Function** -<tr><td>`pager.quit()`<td>Exit the browser -<tr><td>`pager.cursorUp()`<td>Move the cursor to the previous line -<tr><td>`pager.cursorDown()`<td>Move cursor to the next line -<tr><td>`pager.cursorLeft()`<td>Move cursor to the previous cell -<tr><td>`pager.cursorRight()`<td>Move cursor to the next cell -<tr><td>`pager.cursorLineBegin()`<td>Move cursor to the first cell of the line -<tr><td>`pager.cursorLineEnd()`<td>Move cursor to the last cell of the line -<tr><td>`pager.cursorNextWord()`<td>Move cursor to the beginning of the next word -<tr><td>`pager.cursorPrevWord()`<td>Move cursor to the end of the previous word -<tr><td>`pager.cursorNextLink()`<td>Move cursor to the beginning of the next clickable element -<tr><td>`pager.cursorPrevLink()`<td>Move cursor to the beginning of the previous clickable element -<tr><td>`pager.pageDown()`<td>Move screen down by one page -<tr><td>`pager.pageUp()`<td>Move screen up by one page -<tr><td>`pager.pageLeft()`<td>Move screen to the left by one page -<tr><td>`pager.pageRight()`<td>Move screen to the right by one page -<tr><td>`pager.halfPageDown()`<td>Move screen down by half a page -<tr><td>`pager.halfPageUp()`<td>Move screen up by half a page -<tr><td>`pager.scrollDown()`<td>Move screen down by one line -<tr><td>`pager.scrollUp()`<td>Move screen up by one line -<tr><td>`pager.scrollLeft()`<td>Move screen to the left by one line -<tr><td>`pager.scrollRight()`<td>Move screen to the right by one line -<tr><td>`pager.click()`<td>Click element currently under cursor -<tr><td>`pager.changeLocation()`<td>Go to URL -<tr><td>`pager.dupeBuffer()`<td>Duplicate the current buffer -<tr><td>`pager.reload()`<td>Reload page -<tr><td>`pager.reshape()`<td>Reshape buffer (=render page anew) -<tr><td>`pager.redraw()`<td>Redraw buffer (=redraw screen) -<tr><td>`pager.toggleSource()`<td>Source view -<tr><td>`pager.cursorFirstLine()`<td>Move cursor to the first line of the buffer -<tr><td>`pager.cursorLastLine()`<td>Move cursor to the last line of the buffer -<tr><td>`pager.cursorTop()`<td>Move cursor to the first line of the page -<tr><td>`pager.cursorMiddle()`<td>Move cursor to the middle of the page -<tr><td>`pager.cursorBottom()`<td>Move cursor to the last line of the page -<tr><td>`pager.centerLine()`<td>Center screen around line -<tr><td>`pager.lineInfo()`<td>Display information about line -<tr><td>`pager.searchForward()`<td>Search for a string in the current buffer -<tr><td>`pager.searchBackward()`<td>Search for a string, backwards -<tr><td>`pager.isearchForward()`<td>Search for a string and highlight the first result -<tr><td>`pager.isearchBackward()`<td>Search and highlight the first result, backwards -<tr><td>`pager.searchPrev()`<td>Jump to the next search result -<tr><td>`pager.searchNext()`<td>Jump to the previous search result -<tr><td>`pager.peek()`<td>Display an alert of the current URL -<tr><td>`pager.peekCursor()`<td>Display an alert of the URL under the cursor + +<tr> +<th>**Name**</th> +<th>**Function**</th> +</tr> + +<tr> +<td>`pager.quit()`</td> +<td>Exit the browser.</td> +</tr> + +<tr> +<td>`pager.cursorUp()`</td> +<td>Move the cursor to the previous line.</td> +</tr> +<tr> +<td>`pager.cursorDown()`</td> +<td>Move cursor to the next line.</td> +</tr> + +<tr> +<td>`pager.cursorLeft()`</td> +<td>Move the cursor to the previous cell.</td> +</tr> + +<tr> +<td>`pager.cursorRight()`</td> +<td>Move the cursor to the next cell.</td> +</tr> + +<tr> +<td>`pager.cursorLineBegin()`</td> +<td>Move the cursor to the first cell of the line.</td> +</tr> + +<tr> +<td>`pager.cursorLineEnd()`</td> +<td>Move the cursor to the last cell of the line.</td> +</tr> + +<tr> +<td>`pager.cursorNextWord()`</td> +<td>Move the cursor to the beginning of the next word.</td> +</tr> + +<tr> +<td>`pager.cursorPrevWord()`</td> +<td>Move the cursor to the end of the previous word.</td> +</tr> + +<tr> +<td>`pager.cursorNextLink()`</td> +<td>Move the cursor to the beginning of the next clickable element.</td> +</tr> + +<tr> +<td>`pager.cursorPrevLink()`</td> +<td>Move the cursor to the beginning of the previous clickable element.</td> +</tr> + +<tr> +<td>`pager.pageDown()`</td> +<td>Scroll down by one page.</td> +</tr> + +<tr> +<td>`pager.pageUp()`</td> +<td>Scroll up by one page.</td> +</tr> + +<tr> +<td>`pager.pageLeft()`</td> +<td>Scroll to the left by one page.</td> +</tr> + +<tr> +<td>`pager.pageRight()`</td> +<td>Scroll to the right by one page.</td> +</tr> + +<tr> +<td>`pager.halfPageDown()`</td> +<td>Scroll forwards by half a page.</td> +</tr> + +<tr> +<td>`pager.halfPageUp()`</td> +<td>Scroll backwards by half a page.</td> +</tr> + +<tr> +<td>`pager.scrollDown()`</td> +<td>Scroll forwards by one line.</td> +</tr> + +<tr> +<td>`pager.scrollUp()`</td> +<td>Scroll backwards by one line.</td> +</tr> + +<tr> +<td>`pager.scrollLeft()`</td> +<td>Scroll to the left by one column.</td> +</tr> + +<tr> +<td>`pager.scrollRight()`</td> +<td>Scroll to the right by one column.</td> +</tr> + +<tr> +<td>`pager.click()`</td> +<td>Click the HTML element currently under the cursor.</td> +</tr> + +<tr> +<td>`pager.load(url)`</td> +<td>Go to the specified URL. Opens a prompt with the current URL when no +parameters are specified; otherwise, the string passed is displayed in +the prompt. If this string ends with a newline +(e.g. `pager.load("about:cha\n")`), the URL is loaded directly.</td> +</tr> + +<tr> +<td>`pager.dupeBuffer()`</td> +<td>Duplicate the current buffer by loading its source to a new buffer.</td> +</tr> + +<tr> +<td>`pager.discardBuffer()`</td> +<td>Discard the current buffer, and move back to its parent. If the current +buffer is a root buffer (i.e. it has no parent), move to the first child +buffer instead.</td> +</tr> + +<tr> +<td>`pager.reload()`</td> +<td>Open a new buffer with the current buffer's URL, replacing the current +buffer.</td> +</tr> + +<tr> +<td>`pager.reshape()`</td> +<td>Reshape the current buffer (=render the current page anew.)</td> +</tr> + +<tr> +<td>`pager.redraw()`</td> +<td>Redraw screen contents. Useful if something messed up the display.</td> +</tr> + +<tr> +<td>`pager.toggleSource()`</td> +<td>If viewing a HTML buffer, open a new buffer with its source. Otherwise, +open the current buffer's contents as HTML.</td> +</tr> + +<tr> +<td>`pager.cursorFirstLine()`</td> +<td>Move to the beginning in the buffer.</td> +</tr> + +<tr> +<td>`pager.cursorLastLine()`</td> +<td>Move to the last line in the buffer.</td> +</tr> + +<tr> +<td>`pager.cursorTop()`</td> +<td>Move to the first line on the screen. (Equivalent to H in vi.)</td> +</tr> + +<tr> +<td>`pager.cursorMiddle()`</td> +<td>Move to the middle of the screen. (Equivalent to M in vi.)</td> +</tr> + +<tr> +<td>`pager.cursorBottom()`</td> +<td>Move to the last line on the screen. (Equivalent to L in vi.)</td> +</tr> + +<tr> +<td>`pager.centerLine()`</td> +<td>Center screen around the current line.</td> +</tr> + +<tr> +<td>`pager.lineInfo()`</td> +<td>Display information about the current line.</td> +</tr> + +<tr> +<td>`pager.searchForward()`</td> +<td>Search for a string in the current buffer.</td> +</tr> + +<tr> +<td>`pager.searchBackward()`</td> +<td>Search for a string, backwards.</td> +</tr> + +<tr> +<td>`pager.isearchForward()`</td> +<td>Incremental-search for a string, highlighting the first result.</td> +</tr> + +<tr> +<td>`pager.isearchBackward()`</td> +<td>Incremental-search and highlight the first result, backwards.</td> +</tr> + +<tr> +<td>`pager.searchNext()`</td> +<td>Jump to the next search result.</td> +</tr> + +<tr> +<td>`pager.searchPrev()`</td> +<td>Jump to the previous search result.</td> +</tr> + +<tr> +<td>`pager.peek()`</td> +<td>Display an alert message of the current URL.</td> +</tr> + +<tr> +<td>`pager.peekCursor()`</td> +<td>Display an alert message of the URL under the cursor.</td> +</tr> + </table> + ### Line-editing actions <table> -<tr><th>**Name**<th>**Function** -<tr><td>`line.submit()`<td>Submit line -<tr><td>`line.cancel()`<td>Cancel operation -<tr><td>`line.backspace()`<td>Delete character before cursor -<tr><td>`line.delete()`<td>Delete character after cursor -<tr><td>`line.clear()`<td>Clear text before cursor -<tr><td>`line.kill()`<td>Clear text after cursor -<tr><td>`line.clearWord(bounds)`<td>Delete word before cursor -<tr><td>`line.killWord(bounds)`<td>Delete word after cursor -<tr><td>`line.backward()`<td>Move cursor back by one character -<tr><td>`line.forward()`<td>Move cursor forward by one character -<tr><td>`line.prevWord(bounds)`<td>Move cursor to the previous word by one character -<tr><td>`line.nextWord(bounds)`<td>Move cursor to the previous word by one character -<tr><td>`line.begin()`<td>Move cursor to the previous word by one character -<tr><td>`line.end()`<td>Move cursor to the previous word by one character -<tr><td>`line.escape()`<td>Ignore keybindings for next character -<tr><td>`line.prevHist()`<td>Jump to the previous history entry -<tr><td>`line.nextHist()`<td>Jump to the next history entry + +<tr> +<th>**Name**</th> +<th>**Function**</th> +</tr> + +<tr> +<td>`line.submit()`</td> +<td>Submit line</td> +</tr> + +<tr> +<td>`line.cancel()`</td> +<td>Cancel operation</td> +</tr> + +<tr> +<td>`line.backspace()`</td> +<td>Delete character before cursor</td> +</tr> + +<tr> +<td>`line.delete()`</td> +<td>Delete character after cursor</td> +</tr> + +<tr> +<td>`line.clear()`</td> +<td>Clear text before cursor</td> +</tr> + +<tr> +<td>`line.kill()`</td> +<td>Clear text after cursor</td> +</tr> + +<tr> +<td>`line.clearWord(bounds)`</td> +<td>Delete word before cursor</td> +</tr> + +<tr> +<td>`line.killWord(bounds)`</td> +<td>Delete word after cursor</td> +</tr> + +<tr> +<td>`line.backward()`</td> +<td>Move cursor back by one character</td> +</tr> + +<tr> +<td>`line.forward()`</td> +<td>Move cursor forward by one character</td> +</tr> + +<tr> +<td>`line.prevWord(bounds)`</td> +<td>Move cursor to the previous word by one character</td> +</tr> + +<tr> +<td>`line.nextWord(bounds)`</td> +<td>Move cursor to the previous word by one character</td> +</tr> + +<tr> +<td>`line.begin()`</td> +<td>Move cursor to the previous word by one character</td> +</tr> + +<tr> +<td>`line.end()`</td> +<td>Move cursor to the previous word by one character</td> +</tr> + +<tr> +<td>`line.escape()`</td> +<td>Ignore keybindings for next character</td> +</tr> + +<tr> +<td>`line.prevHist()`</td> +<td>Jump to the previous history entry</td> +</tr> + +<tr> +<td>`line.nextHist()`</td> +<td>Jump to the next history entry</td> +</tr> + </table> -Some entries have an optional `bounds` parameter. If passed, this must be a -JavaScript function that expects one parameter (the current unicode character), -and returns true if the passed character should count as a word boundary. +Some of these entries have an optional `bounds` parameter. If passed, this +must be a JavaScript function that expects one parameter (the current +unicode character), and returns true if the passed character should count +as a word boundary. ```Examples: # Control+A moves the cursor to the beginning of the line. diff --git a/res/config.toml b/res/config.toml index 7918bea3..17bfc574 100644 --- a/res/config.toml +++ b/res/config.toml @@ -71,7 +71,7 @@ M-b = 'pager.load("~/.w3m/bookmark.html\n")' U = 'pager.reload()' r = 'pager.redraw()' R = 'pager.reshape()' -M-D = 'pager.cancel()' +M-C-c = 'pager.cancel()' 1G = 'pager.cursorFirstLine()' g = 'pager.cursorFirstLine()' G = 'pager.cursorLastLine()' @@ -79,7 +79,7 @@ z = 'pager.centerLine()' C-g = 'pager.lineInfo()' v = 'pager.toggleSource()' D = 'pager.discardBuffer()' -M-d = 'pager.discardBuffer(true)' +M-d = 'pager.discardTree()' ',' = 'pager.prevBuffer()' 'M-,' = 'pager.prevSiblingBuffer()' '.' = 'pager.nextBuffer()' diff --git a/src/buffer/container.nim b/src/buffer/container.nim index 8084c068..7a3534be 100644 --- a/src/buffer/container.nim +++ b/src/buffer/container.nim @@ -63,6 +63,8 @@ type clear*: bool Container* = ref object + parent* {.jsget.}: Container + children* {.jsget.}: seq[Container] config*: BufferConfig iface*: BufferInterface attrs: WindowAttributes @@ -72,11 +74,9 @@ type title*: string hovertext*: string source*: BufferSource - children*: seq[Container] pos: CursorPosition bpos: seq[CursorPosition] highlights: seq[Highlight] - parent*: Container process* {.jsget.}: Pid loadinfo*: string lines: SimpleFlexibleGrid diff --git a/src/display/pager.nim b/src/display/pager.nim index 9c3e664b..9ce058f2 100644 --- a/src/display/pager.nim +++ b/src/display/pager.nim @@ -62,19 +62,28 @@ type func attrs(pager: Pager): WindowAttributes = pager.term.attrs -iterator containers*(pager: Pager): Container = +func getRoot(container: Container): Container = + var c = container + while c.parent != nil: c = c.parent + +iterator all_children(parent: Container): Container {.inline.} = + var stack = newSeqOfCap[Container](parent.children.len) + for i in countdown(parent.children.high, 0): + stack.add(parent.children[i]) + while stack.len > 0: + let c = stack.pop() + yield c + for i in countdown(c.children.high, 0): + stack.add(c.children[i]) + +iterator containers*(pager: Pager): Container {.inline.} = if pager.container != nil: - var c = pager.container - while c.parent != nil: c = c.parent - var stack: seq[Container] - stack.add(c) - while stack.len > 0: - c = stack.pop() + let root = getRoot(pager.container) + yield root + for c in root.all_children: yield c - for i in countdown(c.children.high, 0): - stack.add(c.children[i]) -proc setContainer*(pager: Pager, c: Container) = +proc setContainer*(pager: Pager, c: Container) {.jsfunc.} = pager.container = c pager.redraw = true @@ -404,7 +413,7 @@ proc alert*(pager: Pager, msg: string) {.jsfunc.} = proc lineInfo(pager: Pager) {.jsfunc.} = pager.alert(pager.container.lineInfo()) -proc deleteContainer(pager: Pager, container: Container, prevlevel = false) = +proc deleteContainer(pager: Pager, container: Container) = container.cancel() if container.sourcepair != nil: container.sourcepair.sourcepair = nil @@ -419,10 +428,7 @@ proc deleteContainer(pager: Pager, container: Container, prevlevel = false) = parent.children.insert(child, n + 1) parent.children.delete(n) if container == pager.container: - if prevlevel or n == 0: - pager.setContainer(parent) - else: - pager.setContainer(parent.children[n - 1]) + pager.setContainer(parent) elif container.children.len > 0: let parent = container.children[0] parent.parent = nil @@ -441,12 +447,21 @@ proc deleteContainer(pager: Pager, container: Container, prevlevel = false) = pager.unreg.add((container.process, SocketStream(container.iface.stream))) pager.dispatcher.forkserver.removeChild(container.process) -proc discardBuffer(pager: Pager, prevlevel = false) {.jsfunc.} = - if pager.container == nil or pager.container.parent == nil and - pager.container.children.len == 0: +proc discardBuffer(pager: Pager, container = none(Container)) {.jsfunc.} = + let c = container.get(pager.container) + if c == nil or c.parent == nil and c.children.len == 0: pager.alert("Cannot discard last buffer!") else: - pager.deleteContainer(pager.container, prevlevel) + pager.deleteContainer(c) + +proc discardTree(pager: Pager, container = none(Container)) {.jsfunc.} = + let container = container.get(pager.container) + if container != nil: + for c in container.all_children: + pager.deleteContainer(c) + pager.discardBuffer(some(container)) + else: + pager.alert("Cannot discard last buffer!") proc toggleSource*(pager: Pager) {.jsfunc.} = if pager.container.sourcepair != nil: |