'\" t .\" Automatically generated by Pandoc 3.7.0.1 .\" .TH "CHA-API" "7" .SH Chawan\(cqs command API As described in \f[B]cha\-config\f[R](5), keypress combinations can be bound to actions. .PP An action can be either a JavaScript expression, or a command defined in the \f[CR][cmd]\f[R] section of config.toml. For example, the following works: .IP .EX gpn = \(aqn => pager.alert(n)\(aq # e.g. 2gpn prints \(ga2\(aq to the status line .EE .PP Note however, that JavaScript functions must be called with an appropriate \f[CR]this\f[R] value. So e.g.\ the following does not work: .IP .EX gpn = \(aqpager.alert\(aq # broken!!! .EE .PP To work around this limitation, actions have to wrap the target function in a closure, as above. However, this has poor reusability; for more complex actions, you would have to copy and paste the entire function every time you re\-bind it or call it from a different function. .PP To fix this, it is possible to define a command in the \f[CR][cmd]\f[R] section: .IP .EX \f[B][cmd.my.namespace]\f[R] showNumber = \(aqn => pager.alert(n)\(aq .EE .PP \f[CR]my.namespace\f[R] can be anything you want; it is to avoid collisions when including multiple configs. The only restriction is that the first component (in this case, \(lqmy\(rq) must not contain an upper\-case letter. .PP Now you can call \f[CR]cmd.my.namespace.showNumber()\f[R] from any other function, or include it in a keybinding (in that case, \f[CR]cmd.\f[R] is optional): .IP .EX \(aqgpn\(aq = \(aqmy.namespace.showNumber\(aq \f[I]# same as\f[R] \(aqgpn\(aq = \(aqcmd.my.namespace.showNumber\(aq .EE .SS Interfaces .SS Client The global object (\f[CR]globalThis\f[R]) implements the \f[CR]Client\f[R] interface. Documented functions of this are: .PP .TS tab(@); lw(35.0n) lw(35.0n). T{ Property T}@T{ Description T} _ T{ \f[CR]quit()\f[R] T}@T{ Exit the browser. T} _ T{ \f[CR]suspend()\f[R] T}@T{ Temporarily suspend the browser, by delivering the client process a SIGTSTP signal. .PP Note: this suspends the entire process group. T} _ T{ \f[CR]readFile(path)\f[R] T}@T{ Read a file at \f[CR]path\f[R]. .PP Returns the file\(cqs content as a string, or null if the file does not exist. T} _ T{ \f[CR]writeFile(path, content)\f[R] T}@T{ Write \f[CR]content\f[R] to the file at \f[CR]path\f[R]. .PP Throws a TypeError if this failed for whatever reason. T} _ T{ \f[CR]openEditor(text)\f[R] T}@T{ Open \(lqtext\(rq in the command configured as \f[CR]external.editor\f[R] (this is typically just \f[CR]$EDITOR\f[R].) .PP If the editor signals an error (crash or non\-zero exit code), \f[CR]null\f[R] is returned. Otherwise, the user\(cqs input is returned as a string. T} _ T{ \f[CR]getenv(name, fallback = null)\f[R] T}@T{ Get an environment variable by \f[CR]name\f[R]. .PP Returns \f[CR]fallback\f[R] if the variable does not exist. T} _ T{ \f[CR]setenv(name, value)\f[R] T}@T{ Set an environment variable by \f[CR]name\f[R]. .PP Throws a type error if the operation failed (e.g.\ because the variable\(cqs size exceeded an OS\-specified limit.) T} _ T{ \f[CR]pager\f[R] T}@T{ The pager object. Implements \f[CR]Pager\f[R], as described below. T} _ T{ \f[CR]line\f[R] T}@T{ The line editor. Implements \f[CR]LineEdit\f[R], as described below. T} _ T{ \f[CR]config\f[R] T}@T{ The config object. .PP A currently incomplete interface for retrieving and setting configuration options. In general, names are the same as in config.toml, except all \f[CR]\-\f[R] (ASCII hyphen) characters are stripped and the next character is upper\-cased. e.g.\ \f[CR]external.cgi\-dir\f[R] can be queried as \f[CR]config.external.cgiDir\f[R], etc. .PP Setting individual options sometimes works, but sometimes they do not get propagated as expected. Consider this an experimental API. .PP Currently, \f[CR]siteconf\f[R], \f[CR]protocol\f[R] and \f[CR]omnirule\f[R] values are not exposed to JS. .PP The configuration directory itself can be queried as \f[CR]config.dir\f[R]. T} .TE .PP \f[CR]Client\f[R] also implements various web standards normally available on the \f[CR]Window\f[R] object on websites, e.g.\ fetch(). Note however that it does \f[I]not\f[R] give access to JS objects in buffers, so e.g.\ \f[CR]globalThis.document\f[R] is not available. .SS Pager \f[CR]Pager\f[R] is a separate interface from \f[CR]Client\f[R] that gives access to the pager (i.e.\ browser chrome). It is accessible as \f[CR]globalThis.pager\f[R], or simply \f[CR]pager\f[R]. .PP Note that there is a quirk of questionable value, where accessing properties that do not exist on the pager will dispatch those to the current buffer (\f[CR]pager.buffer\f[R]). So if you see e.g.\ \f[CR]pager.url\f[R], that is actually equivalent to \f[CR]pager.buffer.url\f[R], because \f[CR]Pager\f[R] has no \f[CR]url\f[R] getter. .PP Following properties (functions/getters) are defined by \f[CR]Pager\f[R]: .PP .TS tab(@); lw(35.0n) lw(35.0n). T{ Property T}@T{ Description T} _ T{ \f[CR]load(url = pager.buffer.url)\f[R] T}@T{ Put the specified address into the URL bar, and optionally load it. .PP Note that this performs auto\-expansion of URLs, so Chawan will expand any matching omni\-rules (e.g.\ search), try to open schemeless URLs with the default scheme/local files, etc. .PP Opens a prompt with the current URL when no parameters are specified; otherwise, the string passed is displayed in the prompt. .PP \f[B]Deprecated quirk\f[R]: If this string ends with a newline (e.g.\ \f[CR]pager.load(\(dqabout:chawan\(rsn\(dq)\f[R]), the URL is loaded directly. This usage isn\(cqt recommended; use loadSubmit instead. T} _ T{ \f[CR]loadSubmit(url)\f[R] T}@T{ Act as if \f[CR]url\f[R] had been entered to the URL bar. \f[CR]loadSubmit\f[R] differs from \f[CR]gotoURL\f[R] in that it also evaluates omni\-rules, tries to prepend a scheme, etc. T} _ T{ \f[CR]gotoURL(url, options = {replace: null, contentType: null, save: false})\f[R] T}@T{ Go to the specified URL immediately (without a prompt). This differs from \f[CR]loadSubmit\f[R] in that it loads the exact URL as passed (no prepending https, etc.) .PP When \f[CR]replace\f[R] is set, the new buffer may replace the old one if it loads successfully. .PP When \f[CR]contentType\f[R] is set, the new buffer\(cqs content type is forcefully set to that string. .PP When \f[CR]save\f[R] is true, the user is prompted to save the resource instead of displaying it in a buffer. T} _ T{ \f[CR]traverse(dir)\f[R] T}@T{ Switch to the next buffer in direction \f[CR]dir\f[R], interpreted as in \f[CR]Buffer#find\f[R]. T} _ T{ \f[CR]nextBuffer()\f[R], \f[CR]prevBuffer()\f[R], \f[CR]nextSiblingBuffer()\f[R], \f[CR]prevSiblingBuffer()\f[R], \f[CR]parentBuffer()\f[R] T}@T{ Same as \f[CR]traverse(\(dqnext\(dq)\f[R], \f[CR]traverse(\(dqprev\(dq)\f[R], \f[CR]traverse(\(dqnext\-sibling\(dq)\f[R], \f[CR]traverse(\(dqprev\-sibling\(dq)\f[R], and \f[CR]traverse(\(dqparent\(dq)\f[R]. T} _ T{ \f[CR]dupeBuffer()\f[R] T}@T{ Duplicate the current buffer by loading its source in a new buffer. T} _ T{ \f[CR]discardBuffer(buffer = pager.buffer, dir = pager.navDirection)\f[R] T}@T{ Discard \f[CR]buffer\f[R], then move back to the buffer opposite to \f[CR]dir\f[R] (interpreted as in \f[CR]Buffer#find\f[R]). T} _ T{ \f[CR]discardTree()\f[R] T}@T{ Discard all next siblings of the current buffer. This function is deprecated, and may be removed in the future. T} _ T{ \f[CR]addTab(target)\f[R] T}@T{ Open a new tab. .PP If \f[CR]target\f[R] is a buffer, it is removed from its current tab and added to the newly created tab. Otherwise, \f[CR]target\f[R] is interpreted as a URL to open with \f[CR]gotoURL\f[R]. T} _ T{ \f[CR]prevTab()\f[R], \f[CR]nextTab()\f[R] T}@T{ Switch to the previous/next tab in the tab list. T} _ T{ \f[CR]discardTab()\f[R] T}@T{ Discard the current tab. T} _ T{ \f[CR]reload()\f[R] T}@T{ Open a new buffer with the current buffer\(cqs URL, replacing the current buffer. T} _ T{ \f[CR]reshape()\f[R] T}@T{ Reshape the current buffer (=render the current page anew.) T} _ T{ \f[CR]redraw()\f[R] T}@T{ Redraw screen contents. Useful if something messed up the display. T} _ T{ \f[CR]toggleSource()\f[R] T}@T{ If viewing an HTML buffer, open a new buffer with its source. Otherwise, open the current buffer\(cqs contents as HTML. T} _ T{ \f[CR]lineInfo()\f[R] T}@T{ Display information about the current line. T} _ T{ \f[CR]searchForward()\f[R], \f[CR]searchBackward()\f[R] T}@T{ Search forward/backward for a string in the current buffer. T} _ T{ \f[CR]isearchForward()\f[R], \f[CR]isearchBackward()\f[R] T}@T{ Incremental\-search forward/backward for a string, highlighting the first result. T} _ T{ \f[CR]gotoLine(n?)\f[R] T}@T{ Go to the line passed as the first argument. .PP If no arguments were specified, an input window for entering a line is shown. T} _ T{ \f[CR]searchNext(n = 1)\f[R], \f[CR]searchPrev(n = 1)\f[R] T}@T{ Jump to the nth next/previous search result. T} _ T{ \f[CR]peek()\f[R] T}@T{ Display an alert message of the current URL. T} _ T{ \f[CR]peekCursor()\f[R] T}@T{ Display an alert message of the URL or title under the cursor. Multiple calls allow cycling through the two. (i.e.\ by default, press u once \-> title, press again \-> URL) T} _ T{ \f[CR]showFullAlert()\f[R] T}@T{ Show the last alert inside the line editor. T} _ T{ \f[CR]ask(prompt)\f[R] T}@T{ Ask the user for confirmation. Returns a promise which resolves to a boolean value indicating whether the user responded with yes. .PP Can be used to implement an exit prompt like this: .IP .EX q = \(aqpager.ask(\(dqDo you want to exit Chawan?\(dq).then(x => x ? pager.quit() : void(0))\(aq .EE T} _ T{ \f[CR]askChar(prompt)\f[R] T}@T{ Ask the user for any character. .PP Like \f[CR]pager.ask\f[R], but the return value is a character. T} _ T{ \f[CR]clipboardWrite(s)\f[R] T}@T{ Write \f[CR]s\f[R] to the clipboard (copy). By default, it tries using OSC 52; if that fails, it tries to run \f[CR]external.copy\-cmd\f[R] (defaults to \f[CR]xsel\f[R]). .PP Returns true if the copy succeeded, false otherwise. (There may be false positives in case OSC 52 is used and the terminal doesn\(cqt consume the text.) T} _ T{ \f[CR]extern(cmd, options = {env: { ... }, suspend: true, wait: false})\f[R] T}@T{ Run an external command \f[CR]cmd\f[R]. .PP By default, the \f[CR]$CHA_URL\f[R] and \f[CR]$CHA_CHARSET\f[R] variables are set; change this using the \f[CR]env\f[R] option. .PP \f[CR]options.suspend\f[R] suspends the pager while the command is being executed, and \f[CR]options.wait\f[R] makes it so the user must press a key before the pager is resumed. .PP Returns true if the command exited successfully, false otherwise. T} _ T{ \f[CR]externCapture(cmd)\f[R] T}@T{ Like extern(), but redirect the command\(cqs stdout string into the result. null is returned if the command wasn\(cqt executed successfully, or if the command returned a non\-zero exit value. T} _ T{ \f[CR]externInto(cmd, ins)\f[R] T}@T{ Like extern(), but redirect \f[CR]ins\f[R] into the command\(cqs standard input stream. \f[CR]true\f[R] is returned if the command exits successfully, otherwise the return value is \f[CR]false\f[R]. T} _ T{ \f[CR]externFilterSource(cmd, buffer = null, contentType = null)\f[R] T}@T{ Redirects the specified (or if \f[CR]buffer\f[R] is null, the current) buffer\(cqs source into \f[CR]cmd\f[R]. .PP Then, it pipes the output into a new buffer, with the content type \f[CR]contentType\f[R] (or, if \f[CR]contentType\f[R] is null, the original buffer\(cqs content type). .PP Returns \f[CR]undefined\f[R]. (It should return a promise; TODO.) T} _ T{ \f[CR]openMenu(x = pager.cursorx \- pager.fromx, y = pager.cursory \- pager.fromy)\f[R] T}@T{ Opens the context menu at the specified x/y positions. T} _ T{ \f[CR]closeMenu()\f[R] T}@T{ Closes the menu if it is opened. T} _ T{ \f[CR]buffer\f[R] T}@T{ Getter for the currently displayed buffer. Returns a \f[CR]Buffer\f[R] object; see below. T} _ T{ \f[CR]menu\f[R] T}@T{ Getter for the currently displayed menu. Returns a \f[CR]Select\f[R] object. T} _ T{ \f[CR]navDirection\f[R] T}@T{ The direction the user last moved in the buffer list using \f[CR]traverse\f[R]. Possible values are \f[CR]prev\f[R], \f[CR]next\f[R], \f[CR]prev\-sibling\f[R], \f[CR]next\-sibling\f[R], \f[CR]parent\f[R], \f[CR]any\f[R]. T} _ T{ \f[CR]revDirection\f[R] T}@T{ Equivalent to \f[CR]Pager.oppositeDir(pager.navDirection)\f[R]. T} .TE .PP Also, the following static function is defined on \f[CR]Pager\f[R] itself: .PP .TS tab(@); lw(35.0n) lw(35.0n). T{ Property T}@T{ Description T} _ T{ \f[CR]Pager.oppositeDir(dir)\f[R] T}@T{ Return a string representing the direction opposite to \f[CR]dir\f[R]. .PP For \(lqnext\(rq, this is \(lqprev\(rq; for \(lqparent\(rq, \(lqnext\(rq; for \(lqprev\-sibling\(rq, \(lqnext\-sibling\(rq; for \(lqany\(rq, it is the same; for the rest, vice versa. T} .TE .SS Buffer Each buffer is exposed as an object that implements the \f[CR]Buffer\f[R] interface. To get a reference to the currently displayed buffer, use \f[CR]pager.buffer\f[R]. .PP Note the quirk mentioned above where \f[CR]Pager\f[R] dispatches unknown properties onto the current buffer. .PP Following properties (functions/getters) are defined by \f[CR]Buffer\f[R]: .PP .TS tab(@); lw(35.0n) lw(35.0n). T{ Property T}@T{ Description T} _ T{ \f[CR]cursorUp(n = 1)\f[R], \f[CR]cursorDown(n = 1)\f[R] T}@T{ Move the cursor upwards/downwards by n lines, or if n is unspecified, by 1. T} _ T{ \f[CR]cursorLeft(n = 1)\f[R], \f[CR]cursorRight(n = 1)\f[R] T}@T{ Move the cursor to the left/right by n cells, or if n is unspecified, by 1. .PP Note: \f[CR]n\f[R] right now represents cells, but really it should represent characters. (The difference is that right now numbered cursorLeft/cursorRight is broken for double\-width chars.) T} _ T{ \f[CR]cursorLineBegin()\f[R], \f[CR]cursorLineEnd()\f[R] T}@T{ Move the cursor to the first/last cell of the line. T} _ T{ \f[CR]cursorLineTextStart()\f[R] T}@T{ Move the cursor to the first non\-blank character of the line. T} _ T{ \f[CR]cursorNextWord()\f[R], \f[CR]cursorNextViWord()\f[R], \f[CR]cursorNextBigWord()\f[R] T}@T{ Move the cursor to the beginning of the next word. T} _ T{ \f[CR]cursorPrevWord()\f[R], \f[CR]cursorPrevViWord()\f[R], \f[CR]cursorPrevBigWord()\f[R] T}@T{ Move the cursor to the end of the previous word. T} _ T{ \f[CR]cursorWordEnd()\f[R], \f[CR]cursorViWordEnd()\f[R], \f[CR]cursorBigWordEnd()\f[R] T}@T{ Move the cursor to the end of the current word, or if already there, to the end of the next word. T} _ T{ \f[CR]cursorWordBegin()\f[R], \f[CR]cursorViWordBegin()\f[R], \f[CR]cursorBigWordBegin()\f[R] T}@T{ Move the cursor to the beginning of the current word, or if already there, to the end of the previous word. T} _ T{ \f[CR]cursorNextLink()\f[R], \f[CR]cursorPrevLink()\f[R] T}@T{ Move the cursor to the beginning of the next/previous clickable element. T} _ T{ \f[CR]cursorLinkNavDown(n = 1)\f[R], \f[CR]cursorLinkNavUp(n = 1)\f[R] T}@T{ Move the cursor to the beginning of the next/previous clickable element. Buffer scrolls pagewise, wrap to beginning/end if content is less than one page length. T} _ T{ \f[CR]cursorNextParagraph(n = 1)\f[R], \f[CR]cursorPrevParagraph(n = 1)\f[R] T}@T{ Move the cursor to the beginning/end of the nth next/previous paragraph. T} _ T{ \f[CR]cursorNthLink(n = 1)\f[R] T}@T{ Move the cursor to the nth link of the document. T} _ T{ \f[CR]cursorRevNthLink(n = 1)\f[R] T}@T{ Move the cursor to the nth link of the document, counting backwards from the document\(cqs last line. T} _ T{ \f[CR]pageUp(n = 1)\f[R], \f[CR]pageDown(n = 1)\f[R], \f[CR]pageLeft(n = 1)\f[R], \f[CR]pageRight(n = 1)\f[R] T}@T{ Scroll up/down/left/right by n pages. T} _ T{ \f[CR]halfPageUp(n = 1)\f[R], \f[CR]halfPageDown(n = 1)\f[R], \f[CR]halfPageLeft(n = 1)\f[R], \f[CR]halfPageRight(n = 1)\f[R] T}@T{ Scroll up/down/left/right by n half pages. T} _ T{ \f[CR]scrollUp(n = 1)\f[R], \f[CR]scrollDown(n = 1)\f[R], \f[CR]scrollLeft(n = 1)\f[R], \f[CR]scrollRight(n = 1)\f[R] T}@T{ Scroll up/down/left/right by n lines. T} _ T{ \f[CR]click(n = 1)\f[R] T}@T{ Click the HTML element currently under the cursor. \f[CR]n\f[R] controls the number of clicks, e.g.\ \f[CR]n = 2\f[R] is a double click. (The number of clicks is only relevant in JS apps.) T} _ T{ \f[CR]cursorFirstLine()\f[R], \f[CR]cursorLastLine()\f[R] T}@T{ Move to the first/last line in the buffer. T} _ T{ \f[CR]cursorTop()\f[R], \f[CR]cursorMiddle()\f[R], \f[CR]cursorBottom()\f[R] T}@T{ Move to the first/middle/bottom line on the screen. (Equivalent to H/M/L in vi.) T} _ T{ \f[CR]lowerPage(n = this.cursory)\f[R] T}@T{ Move cursor to line n, then scroll up so that the cursor is on the top line on the screen. (\f[CR]zt\f[R] in vim.) T} _ T{ \f[CR]lowerPageBegin(n = this.cursory)\f[R] T}@T{ Move cursor to the first non\-blank character of line n, then scroll up so that the cursor is on the top line on the screen. (\f[CR]z\f[R] in vi.) T} _ T{ \f[CR]centerLine(n = this.cursory)\f[R] T}@T{ Center screen around line n.\ (\f[CR]zz\f[R] in vim.) T} _ T{ \f[CR]centerLineBegin(n = this.cursory)\f[R] T}@T{ Center screen around line n, and move the cursor to the line\(cqs first non\-blank character. (\f[CR]z.\f[R] in vi.) T} _ T{ \f[CR]raisePage(n = this.cursory)\f[R] T}@T{ Move cursor to line n, then scroll down so that the cursor is on the top line on the screen. (zb in vim.) T} _ T{ \f[CR]lowerPageBegin(n = this.cursory)\f[R] T}@T{ Move cursor to the first non\-blank character of line n, then scroll up so that the cursor is on the last line on the screen. (\f[CR]z\(ha\f[R] in vi.) T} _ T{ \f[CR]nextPageBegin(n = this.cursory)\f[R] T}@T{ If n was given, move to the screen before the nth line and raise the page. Otherwise, go to the previous screen\(cqs last line and raise the page. (\f[CR]z+\f[R] in vi.) T} _ T{ \f[CR]cursorLeftEdge()\f[R], \f[CR]cursorMiddleColumn()\f[R], \f[CR]cursorRightEdge()\f[R] T}@T{ Move to the first/middle/last column on the screen. T} _ T{ \f[CR]centerColumn()\f[R] T}@T{ Center screen around the current column. T} _ T{ \f[CR]findNextMark(x = this.cursorx, y = this.cursory)\f[R], \f[CR]findPrevMark(x = this.cursorx, y = this.cursory)\f[R] T}@T{ Find the next/previous mark after/before \f[CR]x\f[R], \f[CR]y\f[R], if any; and return its id (or null if none were found.) T} _ T{ \f[CR]setMark(id, x = this.cursorx, y = this.cursory)\f[R] T}@T{ Set a mark at (x, y) using the name \f[CR]id\f[R]. .PP Returns true if no other mark exists with \f[CR]id\f[R]. If one already exists, it will be overridden and the function returns false. T} _ T{ \f[CR]clearMark(id)\f[R] T}@T{ Clear the mark with the name \f[CR]id\f[R]. Returns true if the mark existed, false otherwise. T} _ T{ \f[CR]gotoMark(id)\f[R] T}@T{ If the mark \f[CR]id\f[R] exists, jump to its position and return true. Otherwise, do nothing and return false. T} _ T{ \f[CR]gotoMarkY(id)\f[R] T}@T{ If the mark \f[CR]id\f[R] exists, jump to the beginning of the line at its Y position and return true. Otherwise, do nothing and return false. T} _ T{ \f[CR]getMarkPos(id)\f[R] T}@T{ If the mark \f[CR]id\f[R] exists, return its position as an array where the first element is the X position and the second element is the Y position. If the mark does not exist, return null. T} _ T{ \f[CR]cursorToggleSelection(n = 1, opts = {selectionType: \(dqnormal\(dq})\f[R] T}@T{ Start a vim\-style visual selection. The cursor is moved to the right by \f[CR]n\f[R] cells. .PP selectionType may be \(lqnormal\(rq (regular selection), \(lqline\(rq (line\-based selection) and \(lqcolumn\(rq (column\-based selection). T} _ T{ \f[CR]getSelectionText()\f[R] T}@T{ Get the currently selected text. .PP Returns a promise, so consumers must \f[CR]await\f[R] it to get the text. T} _ T{ \f[CR]markURL()\f[R] T}@T{ Convert URL\-like strings to anchors on the current page. T} _ T{ \f[CR]showLinkHints()\f[R] T}@T{ Display link hints on the page. Mainly intended for the built\-in toggleLinkHints command. .PP Returns an array of objects with \f[CR]x\f[R] representing the x position, \f[CR]y\f[R] the y position of a link. T} _ T{ \f[CR]toggleImages()\f[R] T}@T{ Toggle display of images in this buffer. T} _ T{ \f[CR]saveLink()\f[R] T}@T{ Save URL pointed to by the cursor. T} _ T{ \f[CR]saveSource()\f[R] T}@T{ Save the source of this buffer. T} _ T{ \f[CR]setCursorX(x)\f[R], \f[CR]setCursorY(y)\f[R], \f[CR]setCursorXY(x, y)\f[R], \f[CR]setCursorXCenter(x)\f[R], \f[CR]setCursorYCenter(y)\f[R], \f[CR]setCursorXYCenter(x, y)\f[R] T}@T{ Set the cursor position to \f[CR]x\f[R] and \f[CR]y\f[R] respectively, scrolling the view if necessary. .PP Variants that end with \(lqCenter\(rq will also center the screen around the position if it is outside the screen. T} _ T{ \f[CR]find(dir)\f[R] T}@T{ Find the next buffer in the list in a specific direction. .PP Possible values of \f[CR]dir\f[R] are: \f[CR]prev\f[R], \f[CR]next\f[R], \f[CR]prev\-sibling\f[R], \f[CR]next\-sibling\f[R], \f[CR]parent\f[R], \f[CR]any\f[R]. .PP \(lqnext\(rq and \(lqprev\(rq return the next/previous buffer respectively. .PP \(lqprev\-sibling\(rq, \(lqparent\(rq are deprecated aliases for \(lqprev\(rq, while \(lqnext\-sibling\(rq is a deprecated alias for \(lqnext\(rq. .PP Finally, \(lqany\(rq returns either \(lqprev\(rq, or if it\(cqs null, \(lqnext\(rq. T} _ T{ \f[CR]url\f[R] T}@T{ Getter for the buffer\(cqs URL. Note: this returns a \f[CR]URL\f[R] object, not a string. T} _ T{ \f[CR]hoverTitle\f[R], \f[CR]hoverLink\f[R], \f[CR]hoverImage\f[R] T}@T{ Getter for the string representation of the element title/link/image currently under the cursor. Returns the empty string if no title is found. T} _ T{ \f[CR]cursorx\f[R], \f[CR]cursory\f[R] T}@T{ The x/y position of the cursor inside the buffer. .PP Note that although the status line is 1\-based, these values are 0\-based. T} _ T{ \f[CR]fromx\f[R], \f[CR]fromy\f[R] T}@T{ The x/y position of the first line displayed on the screen. T} _ T{ \f[CR]numLines\f[R] T}@T{ The number of lines currently loaded in the buffer. T} _ T{ \f[CR]width\f[R], \f[CR]height\f[R] T}@T{ The width and height of the buffer\(cqs window (i.e.\ the visible part of the canvas). T} _ T{ \f[CR]process\f[R] T}@T{ The process ID of the buffer. T} _ T{ \f[CR]title\f[R] T}@T{ Text from the \f[CR]title\f[R] element, or the buffer\(cqs URL if there is no title. T} _ T{ \f[CR]next\f[R] T}@T{ Next buffer in the buffer list. May be \f[CR]null\f[R]. T} _ T{ \f[CR]prev\f[R] T}@T{ Previous buffer in the buffer list. May be \f[CR]null\f[R]. T} _ T{ \f[CR]select\f[R] T}@T{ Reference to the current \f[CR]select\f[R] element\(cqs widget, or null if no \f[CR]select\f[R] element is open. .PP This object implements the \f[CR]Select\f[R] interface, which is somewhat compatible with the \f[CR]Buffer\f[R] interface with some exceptions. (TODO: elaborate) T} .TE .SS LineEdit The line editor at the bottom of the screen is exposed to the JavaScript context as \f[CR]globalThis.line\f[R], or simply \f[CR]line\f[R], and implements the \f[CR]LineEdit\f[R] interface. .PP Note that there is no single \f[CR]LineEdit\f[R] object; a new one is created every time the line editor is opened, and when the line editor is closed, \f[CR]globalThis.line\f[R] simply returns \f[CR]null\f[R]. .PP Following properties (functions/getters) are defined by \f[CR]LineEdit\f[R]: .PP .TS tab(@); l l. T{ Property T}@T{ Description T} _ T{ \f[CR]submit()\f[R] T}@T{ Submit line. T} _ T{ \f[CR]cancel()\f[R] T}@T{ Cancel operation. T} _ T{ \f[CR]backspace()\f[R] T}@T{ Delete character before cursor. T} _ T{ \f[CR]delete()\f[R] T}@T{ Delete character after cursor. T} _ T{ \f[CR]clear()\f[R] T}@T{ Clear text before cursor. T} _ T{ \f[CR]kill()\f[R] T}@T{ Clear text after cursor. T} _ T{ \f[CR]clearWord()\f[R] T}@T{ Delete word before cursor. T} _ T{ \f[CR]killWord()\f[R] T}@T{ Delete word after cursor. T} _ T{ \f[CR]backward()\f[R], \f[CR]forward()\f[R] T}@T{ Move cursor backward/forward by one character. T} _ T{ \f[CR]nextWord()\f[R], \f[CR]prevWord()\f[R] T}@T{ Move cursor to the next/previous word by one character. T} _ T{ \f[CR]begin()\f[R], \f[CR]end()\f[R] T}@T{ Move cursor to the beginning/end of the line. T} _ T{ \f[CR]escape()\f[R] T}@T{ Ignore keybindings for next character. T} _ T{ \f[CR]nextHist()\f[R], \f[CR]prevHist()\f[R] T}@T{ Jump to the previous/next history entry. T} _ T{ \f[CR]text\f[R] T}@T{ The currently entered text. T} .TE .SS See also \f[B]cha\f[R](1) \f[B]cha\-config\f[R](5)