sysl

Module

sysl.term.edit

editor Editor Iterate for Editor

Import import sysl.term.edit

Index

editor Editor Iterate for Editor

Functions

editor

editor(r: *Reader, w: *Writer) -> Editor

An editor over a byte source and a place to echo to.

The two are separate parameters because on a host they are separate things – a reader on one descriptor and a writer on another. A caller whose console is one value that is both hands it over twice.

It prints no prompt and is not told one. Every movement here is relative, so the editor never needs to know how far along the row the line starts, and a caller goes on printing its own prompt exactly as it would before console_lines. That is what makes a continuation prompt – a REPL holding an unfinished expression – a property of the caller rather than a field here. The history belongs to the editor and so outlives a line but not a session, which is the right lifetime for it: one console, one history, and nothing to save or load. A program wanting it to survive a restart would have to write it somewhere, and where is a question about that program.

Types

Editor

struct Editor
    src: *Reader
    sink: *Writer
    line: Buf[char]
    at: usize
    chunk: []u8
    have: []const u8
    pos: usize
    owed_lf: bool
    done: bool
    hist: Deque[string]
    browse: usize
    draft: string

A line editor over a byte source and a place to echo to.

It borrows both rather than owning them, for the reason sysl.io.Lines gives: a for loop iterates a copy of its iterator, so an owned reader would latch its failure on a copy the caller cannot reach, and failed would be decorative. Two parameters rather than one value implementing both traits, because a source and a sink are usually two different things – a file descriptor each on a host – and a caller with one value that is both hands it over twice.

Three pieces of state outlive a line, which is why this is a struct rather than a function. The CRLF debt straddles two lines by construction; the tail of the last read holds bytes that have been taken from the reader and not yet looked at, which an escape sequence arriving in two pieces depends on; and the Buf[char] is reused, so a session allocates once rather than once per line.

MemberSignatureDescription
next_bytenext_byte(*self) -> Option[u8]The next byte of input, refilling from the reader when what was read is spent.
char_fromchar_from(*self, b0: u8) -> charThe character a byte begins, read the rest of the way off the source.
getlinegetline(*self) -> Option[string]One line, without its terminator, echoed as it is typed.
finishfinish(*self) -> stringThe characters gathered back into a string, which is one StrBuilder and no validation — and the one place a finished line enters the history, so that every way of ending a line records it and no future way can forget to.
editedit(*self, b: u8)One keystroke’s worth of editing.
escapeescape(*self)An escape sequence – both of the two forms a terminal sends for the same key.
numberednumbered(*self, first: u8)A parameterised sequence – ESC [ 3 ~ for Delete, and the numbered spellings of Home and End that some terminals send instead of the lettered ones.
final_keyfinal_key(*self, c: u8)The last byte of a sequence, where the key is when it is not a number.
putput(*self, bytes: []const u8)
put_charput_char(*self, c: char)
backback(*self, n: usize)n columns back, which is n backspaces.
blankblank(*self, n: usize)n columns painted over.
new_linenew_line(*self)CRLF, so that whatever the program prints next starts on a line of its own.
width_atwidth_at(self, i: usize) -> usizeHow wide the character at i is drawn.
columns_fromcolumns_from(self, from: usize) -> usizeHow many columns the line occupies from from to its end.
put_fromput_from(*self, from: usize)The line from from to its end, echoed where the cursor stands.
leftleft(*self)
rightright(*self)
to_startto_start(*self)
to_endto_end(*self)
redrawredraw(*self, blanks: usize)## Changing After an edit at the cursor, everything to its right has moved, so the tail is written out again and the cursor walked back to where it belongs.
insertinsert(*self, c: char)
backspacebackspace(*self)
delete_atdelete_at(*self)
kill_linekill_line(*self)Ctrl-U – everything gone.
kill_to_endkill_to_end(*self)Ctrl-K – everything from the cursor on.
replacereplace(*self, text: string)The whole line replaced by text, redrawn where it stands.
text_oftext_of(self) -> stringThe line as text, for putting into the history or keeping as the draft.
earlierearlier(*self)Up: one step towards the oldest.
laterlater(*self)Down: one step towards the line being typed, and then to the draft itself.
rememberremember(*self, line: string)What a finished line leaves behind.

Implementations

Iterate for Editor

impl Iterate for Editor

Search

Esc
to navigate to open Esc to close