pub struct Input<'a> { /* private fields */ }Expand description
The pending text of one REPL entry, as the pipeline sees it.
Each time a line is fed to a Session, the session calls
the pipeline with an Input holding every line of the entry so far —
the first line, then the first two, and so on until the pipeline answers
Status::Complete. Lines are joined with '\n'
and the text always ends with one.
The input also carries its position in the session’s
SourceMap: base is the global
offset its first byte will occupy once the entry is committed. Lex with
cursor, or offset spans by base yourself, and every span
the pipeline produces — in tokens, in syntax trees, in diagnostics — is
already valid against Session::sources. There
is no second pass to rebase spans after the entry is accepted.
Input is a borrowed, Copy view; it lives only for the duration of the
pipeline call.
§Examples
use repl_lang::{Feed, Session, Status};
let mut session = Session::new();
let feed = session.feed("1 + 2", |input| {
assert_eq!(input.text(), "1 + 2\n");
assert_eq!(input.number(), 1);
Status::Complete(input.text().len())
})?;
assert!(matches!(feed, Feed::Complete { value: 6, .. }));Implementations§
Source§impl<'a> Input<'a>
impl<'a> Input<'a>
Sourcepub const fn text(&self) -> &'a str
pub const fn text(&self) -> &'a str
Every line of the entry so far, joined with '\n' and ending with one.
§Examples
use repl_lang::{Feed, Session, Status};
let mut session = Session::new();
let mut seen = Vec::new();
for line in ["(1 +", " 2)"] {
session.feed(line, |input| {
seen.push(input.text().to_owned());
if input.text().matches('(').count() > input.text().matches(')').count() {
Status::Incomplete
} else {
Status::Complete(())
}
})?;
}
assert_eq!(seen, ["(1 +\n", "(1 +\n 2)\n"]);Sourcepub const fn base(&self) -> BytePos
pub const fn base(&self) -> BytePos
The global position the first byte of this entry occupies in the session’s source map.
Entries are laid out end to end, so the base of entry n is the total length of entries 1 through n − 1.
§Examples
use repl_lang::{Session, Status};
let mut session = Session::new();
session.feed("abc", |_| Status::Complete(()))?; // occupies 0..4 ("abc\n")
session.feed("x", |input| {
assert_eq!(input.base().to_u32(), 4);
Status::Complete(())
})?;Sourcepub const fn number(&self) -> u32
pub const fn number(&self) -> u32
The entry number this input will be committed as, counting from 1.
Useful for prompts (In [3]:) and for names the evaluator binds per
entry (_3). The number does not advance while an entry is incomplete,
and blank lines never consume one.
§Examples
use repl_lang::{Session, Status};
let mut session = Session::new();
session.feed("a", |input| { assert_eq!(input.number(), 1); Status::Complete(()) })?;
session.feed("b", |input| { assert_eq!(input.number(), 2); Status::Complete(()) })?;Sourcepub fn cursor(&self) -> Cursor<'a>
pub fn cursor(&self) -> Cursor<'a>
A lexer_lang::Cursor over text, positioned at
base.
Every token span the cursor produces is a global span in the session’s
source map, so tokens, the syntax built from them, and any diagnostic
pointing at them render correctly against
Session::sources once the entry is
committed.
§Examples
use repl_lang::{Session, Status};
let mut session = Session::new();
session.feed("first", |_| Status::Complete(()))?; // 0..6
session.feed("ab", |input| {
let mut cursor = input.cursor();
cursor.eat_while(|c| c.is_alphabetic());
assert_eq!(cursor.lexeme(), "ab");
assert_eq!(cursor.token_span().start().to_u32(), 6); // global, not 0
Status::Complete(())
})?;Sourcepub fn is_incomplete(&self, errors: &[Diagnostic]) -> bool
pub fn is_incomplete(&self, errors: &[Diagnostic]) -> bool
Returns true if errors say the input ended too soon rather than that
it is wrong — the signal to ask for another line.
That is the case when there is at least one error-severity diagnostic,
and every one of them points at the end of the input: its primary span
starts at or after the last non-whitespace byte. A parser that reaches
the end of 1 + (2 * reports “expected expression” at the end, so the
user simply has not finished typing; a parser that trips over 1 + )
reports the error at the ), and more lines will never fix that.
Warnings, notes, and help messages are ignored.
The rule matches how parser_lang reports a missing token at the end
of input — an empty span just past the last token — and works with any
parser that does the same. Errors a lexer reports where a construct
starts, such as an unterminated string pointing at its opening quote,
are not recognised; return Status::Incomplete
for those directly.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use repl_lang::{Session, Span, Status};
let error_at = |at: u32| {
Diagnostic::new(Severity::Error, "expected expression", Label::new(Span::empty(at), "here"))
};
let mut session = Session::new();
session.feed("1 + (2 *", |input| {
// An error at the end (byte 8, before the trailing newline): incomplete.
assert!(input.is_incomplete(&[error_at(8)]));
// An error in the middle: the input is wrong, not unfinished.
assert!(!input.is_incomplete(&[error_at(2), error_at(8)]));
// No errors at all: complete.
assert!(!input.is_incomplete(&[]));
Status::Complete(())
})?;