import { Actions } from '../state/interfaces'; import { SearchRequest } from '../features/searching'; import { BlockFile } from './blockFile'; import { PagerInput } from './input'; import { PipeSpool } from './spool'; /** * The seekable-file side of the shared pager. * * It reuses Fable's BigView byte-position model. The ordinary controller * remains in charge of keys, prompts, options, help and rendering; this * object only answers operations that otherwise require reading through * every preceding byte. Each paint exposes a bounded local array to those * shared features; the underlying file remains byte-position based. */ export declare class FileInput implements PagerInput { private bf; private fileIndex; private spool; private view; private positions; private lineAnchors; private lineScanAborted; private lineScanMessaged; private selectedOscPos; private selectedOscStart; private incrementalOrigin; private headerRow; private headerPos; /** The layout generation this.seam's extents were measured under. */ private seamLayout; /** Rows at the bottom left blank by less's lclear. */ private blankBelow; /** The pad came from jump_loc's give-up branch, not from nblank. */ private blankGiveUp; private pending; private readonly saved; private activePath; private pendingForward; private pendingJump; private pendingPipeSearch; private growthPaint; private unsubscribeGrowth; private softEnd; private lastResolved; private seam; private padTop; private keepPad; constructor(bf: BlockFile, fileIndex: number, spool?: PipeSpool | null); /** True while the source is a pipe whose end has not been read. */ private spoolAlive; /** Keeps the upstream flowing until read-ahead covers the view. */ private requestAhead; ready(): void; /** Marks the spool drain a command started, owning the command * line like less's ch_end_seek: blank for G, ierror's note for %. */ private startDrain; /** Releases the drain's hold on the command line. */ private endDrain; /** A forward read reaching the spooled end after an interrupted * drain: less's ch_forw_get finally returns the real EOI and the * length becomes known (ch_fsize learned). */ private discoverEnd; /** ^C or --intr during a wait on the growing spool: less's READ_INTR * surfaces as EOI at the current position, so ch_end_seek returns * SUCCESS and G jumps to the BUFFERED end — only % fails its * ch_length check and errors; a blocked move simply stops. */ interrupt(): boolean; /** Takes the finished spool's length as the file's, like less's * ch_fsize after the read that returned EOI. */ private adoptSpoolEnd; /** Makes newly spooled bytes visible and completes commands which * were blocked at the provisional end of a non-seekable input. */ private onGrowth; handle(action: Actions, count: number): boolean; search(request: SearchRequest): boolean; /** Places a found match like less's search jump: normally the match * line at the -j target, a deep wrapped match bottoming its final * sub-row (get_lastlinepos), a chopped off-screen match shifted * into view (shift_visible). */ private landMatch; /** less's long-line landing (search.c plastlinepos + the * end_off >= swidth*sheight/4 heuristic): a wrapped match ending * deep in its line bottoms the final sub-row instead of topping. */ private bottomSub; /** * Shifts the screen horizontally so the match is visible, like * search.c's shift_visible: an off-screen match lands --match-shift * columns from the left edge. less only shifts in the chop branch; * wrapped long lines bottom-jump instead (bottomSub). */ private shiftMatch; restoreSearchOrigin(): void; /** Set while paintPartial is drawing, so the paint it triggers * cannot come back round into another sync. */ private painting; /** * Puts the rows read so far on the screen, before a read that is * going to take a while. * * less needs no equivalent: forw() writes each row as forw_line * returns it, so the rows above a slow one are already drawn when * it stalls. We materialize the screen and paint once, which is * fewer writes for the ordinary case and a blank terminal for this * one. Bare, because no prompt belongs on a screen still being * built - the same reason resolveBottom paints bare. */ private paintPartial; /** less's currline(BOTTOM) closing every forw()/back(): the eager * line-number resolution running after each move's paint. */ resolveBottom(): void; /** Continues a forward search that ran out of spooled bytes. */ private resumePipeSearch; bracket(open: string, close: string, forward: boolean, n: number): boolean; retopOffset(offset: number): void; rebuild(): boolean; close(): void; /** Supplies bounded startup data to the existing shared file switch. */ private loadSourceFile; /** Activates the BlockFile after common switch bookkeeping completes. */ private activateSourceFile; /** * The null rows an end jump leaves above BOF, like less's jump_loc * walking back sindex lines to put the last one at the bottom: when * back_line hits BOF first it BREAKS and hands the shortfall to * forw() as its nblank argument - "rely on forw() below to draw the * required number of blank lines at the top of the screen" * (jump.c:316). So a file shorter than the screen ends up at the * BOTTOM under tildes; gotoEnd on its own just clamps at BOF and * leaves the text at the top. */ private padShortScreen; /** * jump_loc's lastmark, in positions. * * A jump only records the last mark when it had to REPAINT. Both of * jump_loc's branches walk from the target towards the screen first, * and either returns early -- "Surprise! The desired line is close * enough to the current screen that we can just scroll there after * all" -- before reaching the lastmark() below the loop (jump.c:294, * jump.c:347). Recording unconditionally instead made `''` twice in * a row land in two different places from less, because our first jump * left a mark less's scroll never wrote. * * @param pos - The position being jumped to. * @param sindex - 0-based screen row the target will be placed on. */ private jumpLastMark; /** * jump_loc's lastmark for F's entry jump. * * less's F is forw_loop, which opens with jump_forw_buffered -> * jump_line_loc(end-1, sc_height-1) -> jump_loc. The ticks that * follow are forw(1), not a jump, so only the entry can mark. */ private followLastMark; private pinFollowEnd; private refreshFollow; private jumpTag; private forward; private backward; posClear(): void; /** * How far a backward move may go before a form feed stops it. * * less's back() breaks after printing a line that starts with \f, so * the form feed ends up the TOP row (forwback.c:444). * * The array session answers this from session.content, which is the * whole file there. Here it is only the materialized window -- on a * backward move that is the visible rows and nothing above them -- * so the walk goes back through the FILE a line at a time instead. * * @param rows - Display rows the move wants. * @returns The rows it may actually take. */ private ffCapBack; /** Re-expresses the seam in the row indices this paint will use. */ private publishSeam; private backwardFrom; /** * A batch of lines narrowed to the ones the active display filter * accepts, with their positions, or null when the filter itself gave * up (an interrupted or too-complex pattern). * * Four places walked a batch off disk and then applied the mask to * it: forward and backward for "the next accepted line", forward and * backward for a search. All four spelled the mask out again. * * @param lines - The batch as read. * @param positions - The byte position of each line in the batch. */ private acceptedBatch; /** less's to_newline scroll (forwback.c:302): rows reveal at the * bottom edge until `lines` of them end their file line, wrap * continuations riding free; the top may land mid-wrap. */ private newlineForward; private newlineBackward; private accepted; private nextAccepted; private prevAccepted; /** * One row back within the top's own line, like back_line landing on * the greatest row start below where it already is. */ private rowAbove; /** The offset of the last display row of the line at `pos`. */ private lastRowAt; private filteredForward; private filteredBackward; private fileBackward; private filteredEndTop; private gotoFilteredEnd; private bottomSourcePosition; /** Finds a 0-based file line without retaining the traversed text. */ /** * less's onscreen() (position.c:135): the screen row holding a byte, * or -1. Note it returns -1 when the byte is past EVERY row, not the * bottom row - the loop only ever answers from `pos < table[i]`, so * falling out the end means "not on screen". Getting that backwards * made a jump to the file's end look like a jump onto the screen. */ private onScreenRow; /** * less's jump_loc near-target branch (jump.c:337): a target that is * ALREADY DISPLAYED is scrolled to with force=TRUE rather than * repainted, which keeps the junction a backward move leaves behind * instead of regenerating the screen from the target. * * @returns True when it handled the jump. */ private jumpNear; private gotoLine; /** less's empty_screen(): nothing has been painted yet. */ private emptyScreen; /** * less's jump_loc branch for a target BEFORE the screen (jump.c:353). * * - `scroll`: the walk reached the old top within a screenful, so less * says "Surprise! ... we can just scroll there after all" and runs * back(nline, tpos) - a forced backward SCROLL, no lclear and no * pos_clear. `rows` is less's nline: sindex plus the display-row * distance from the target to the old top. * - `blank`: the walk ran off the END of the file first, so back() * draws null lines over the screen. * - `far`: neither - the walk used up a screenful without arriving. * less lclear()s and back()s a whole screen from where the walk * stopped, which lands the same top the fall-through seek does. */ private backWalk; private scrollRows; /** * less's give-up branch: back() from nowhere draws null lines, the * content is pushed off and the rows below keep what lclear left. */ private blankBack; private seekLine; private findLinePosition; private clampHeader; private markPosition; private sourceActive; private lineNumber; private lineCount; /** * Remembers a resolved position, like less's add_lnum (linenum.c). * * Sorted by position and CAPPED, both for less's reasons. The list * used to grow by one entry per resolution - and lineNumber() runs * once per rendered ROW - so a couple of hundred keys left thousands * of entries, each countTo scanning all of them linearly. Cost grew * with how long you had been scrolling: -N on a 113 MB file spent * 0.68s of CPU on 200 keys where less spent 0.01s. * * When full, less drops the entry whose removal leaves the smallest * gap (calcgap: next->pos - prev->pos, linenum.c:185), so what * survives stays spread across the file rather than clustered where * the user happened to be. */ private addAnchor; /** Index of the last anchor at or before `pos`, by binary search. */ private anchorIndex; /** Fable's cached find_linenum walk, retaining only sparse anchors. */ private countTo; private jumpMark; /** Resolves less's screen-relative search start into a byte position. */ private searchStart; private noSearchHeaderStart; private scanForward; private scanBackward; /** Fable's byte-position OSC 8 walk over the complete file. */ /** The line-start positions currently displayed, less's onscreen(). */ private onscreen; /** less's osc8_search (search.c:2005): continue within the selected * line first; an off-screen selection restarts at the -j line; a * found link only scrolls when it is NOT already on screen; a * miss errors WITHOUT clearing the selection. */ private findOsc8; /** * Selects the anchor an internal link names, scanning forward from * the current selection and wrapping once - less's osc8_search with * SRCH_FORW|SRCH_WRAP and a param (search.c:1949). The param mode * is also what re-admits an empty link: an id= anchor is one. */ private openInternalOsc8; private selectOsc8; /** * Materializes only the current view plus a small read-ahead. Header rows * are retained at the front so the shared overlay renderer can continue * to paint them after a distant seek. */ /** * less's delayed_msg (linenum.c:229) applied to the work a scroll * does: nothing for LONGTIME, then the loop names itself with * ierror's suffix (output.c:767). * * less leaves the command line BLANK while a command runs - cmd_exec * clear_bots before the walk (command.c:267) and prompt() writes * ":" only when it returns - so a long scroll shows an empty bottom * line and no sign of life. This fills that gap; it is not less's, * but the clock and the wording are. */ private noteLongWork; private workNoted; private sync; }