Skip to content

Commit aa5c30a

Browse files
committed
Make detection of prompt types more robust
1 parent e252354 commit aa5c30a

File tree

1 file changed

+49
-35
lines changed

1 file changed

+49
-35
lines changed

crates/ark/src/interface.rs

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,13 @@ impl RMain {
597597
buflen: c_int,
598598
_hist: c_int,
599599
) -> ConsoleResult {
600+
// TODO!: Document why incomplete is fine (vec is necessarily empty, if
601+
// there's a syntax error R will throw and vec will be flushed)
602+
603+
// TODO!: If we detect an incomplete prompt and we no longer have any
604+
// inputs to send, then it's a panic. We should have replied with an
605+
// error to the frontend ahead of time.
606+
600607
if let Some(console_result) = self.handle_pending_line(buf, buflen) {
601608
return console_result;
602609
}
@@ -849,7 +856,7 @@ impl RMain {
849856
self.error_occurred = false;
850857

851858
match input {
852-
ConsoleInput::Input(mut code) => {
859+
ConsoleInput::Input(code) => {
853860
// Handle commands for the debug interpreter
854861
if self.dap.is_debugging() {
855862
let continue_cmds = vec!["n", "f", "c", "cont"];
@@ -858,13 +865,7 @@ impl RMain {
858865
}
859866
}
860867

861-
// In notebooks, wrap in braces so that only the last complete
862-
// expression is auto-printed
863-
if let SessionMode::Notebook = self.session_mode {
864-
code = format!("{{ {code} }}");
865-
}
866-
867-
// WIP: Split input into multiple lines
868+
// TODO!: Check for incomplete inputs and immediately error
868869
let code = self.handle_input(code);
869870

870871
Self::on_console_input(buf, buflen, code);
@@ -1348,33 +1349,46 @@ This is a Positron limitation we plan to fix. In the meantime, you can:
13481349
}
13491350
}
13501351

1351-
// If we are at top-level, we're handling visible output auto-printed by
1352-
// the R REPL. We accumulate this output (it typically comes in multiple
1353-
// parts) so we can emit it later on as part of the execution reply
1354-
// message sent to Shell, as opposed to an Stdout message sent on IOPub.
1355-
//
1356-
// However, if autoprint is dealing with an intermediate expression
1357-
// (i.e. `a` and `b` in `a\nb\nc`), we should emit it on IOPub. We
1358-
// only accumulate autoprint output for the very last expression. The
1359-
// way to distinguish between these cases is whether there are still
1360-
// lines of input pending. In that case, that means we are on an
1361-
// intermediate expression.
1362-
//
1363-
// Note that we implement this behaviour (streaming autoprint results of
1364-
// intermediate expressions) specifically for Positron, and specifically
1365-
// for versions that send multiple expressions selected by the user in
1366-
// one request. Other Jupyter frontends do not want to see output for
1367-
// these intermediate expressions. And future versions of Positron will
1368-
// never send multiple expressions in one request
1369-
// (https://github.com/posit-dev/positron/issues/1326).
1370-
//
1371-
// Note that warnings emitted lazily on stdout will appear to be part of
1372-
// autoprint. We currently emit them on stderr, which allows us to
1373-
// differentiate, but that could change in the future:
1374-
// https://github.com/posit-dev/positron/issues/1881
1375-
if otype == 0 && is_auto_printing() && self.pending_lines.is_empty() {
1376-
self.autoprint_output.push_str(&content);
1377-
return;
1352+
if stream == Stream::Stdout && is_auto_printing() {
1353+
// If we are at top-level, we're handling visible output auto-printed by
1354+
// the R REPL. We accumulate this output (it typically comes in multiple
1355+
// parts) so we can emit it later on as part of the execution reply
1356+
// message sent to Shell, as opposed to an Stdout message sent on IOPub.
1357+
//
1358+
// However, if autoprint is dealing with an intermediate expression
1359+
// (i.e. `a` and `b` in `a\nb\nc`), we should emit it on IOPub. We
1360+
// only accumulate autoprint output for the very last expression. The
1361+
// way to distinguish between these cases is whether there are still
1362+
// lines of input pending. In that case, that means we are on an
1363+
// intermediate expression.
1364+
//
1365+
// Note that we implement this behaviour (streaming autoprint results of
1366+
// intermediate expressions) specifically for Positron, and specifically
1367+
// for versions that send multiple expressions selected by the user in
1368+
// one request. Other Jupyter frontends do not want to see output for
1369+
// these intermediate expressions. And future versions of Positron will
1370+
// never send multiple expressions in one request
1371+
// (https://github.com/posit-dev/positron/issues/1326).
1372+
//
1373+
// Note that warnings emitted lazily on stdout will appear to be part of
1374+
// autoprint. We currently emit them on stderr, which allows us to
1375+
// differentiate, but that could change in the future:
1376+
// https://github.com/posit-dev/positron/issues/1881
1377+
1378+
// Handle last expression
1379+
if self.pending_lines.is_empty() {
1380+
self.autoprint_output.push_str(&content);
1381+
return;
1382+
}
1383+
1384+
// In notebooks, we don't emit results of intermediate expressions
1385+
if self.session_mode == SessionMode::Notebook {
1386+
return;
1387+
}
1388+
1389+
// In Positron, fall through if we have pending input. This allows
1390+
// autoprint output for intermediate expressions to be emitted on
1391+
// IOPub.
13781392
}
13791393

13801394
// Stream output via the IOPub channel.

0 commit comments

Comments
 (0)