Skip to content

Commit d2a0ce4

Browse files
committed
Split write_console() between pre-init and post-init handlers
1 parent a64a25e commit d2a0ce4

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

crates/ark/src/interface.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ use crate::srcref::ns_populate_srcref;
119119
use crate::srcref::resource_loaded_namespaces;
120120
use crate::startup;
121121
use crate::sys::console::console_to_utf8;
122+
use crate::sys::interface::complete_r_init;
122123

123124
/// An enum representing the different modes in which the R session can run.
124125
#[derive(PartialEq, Clone)]
@@ -455,6 +456,9 @@ impl RMain {
455456
log::info!("Sending kernel info: {version}");
456457
self.kernel_init_tx.broadcast(kernel_info);
457458

459+
// Set post-init REPL handlers like `write_console()`
460+
complete_r_init();
461+
458462
// Thread-safe initialisation flag for R
459463
R_INIT.set(()).expect("`R_INIT` can only be set once");
460464
}
@@ -1318,12 +1322,6 @@ This is a Positron limitation we plan to fix. In the meantime, you can:
13181322
Stream::Stderr
13191323
};
13201324

1321-
if !RMain::is_initialized() {
1322-
// During init, consider all output to be part of the startup banner
1323-
self.banner_output.push_str(&content);
1324-
return;
1325-
}
1326-
13271325
// If active execution request is silent don't broadcast
13281326
// any output
13291327
if let Some(ref req) = self.active_request {
@@ -1354,6 +1352,18 @@ This is a Positron limitation we plan to fix. In the meantime, you can:
13541352
self.iopub_tx.send(message).unwrap();
13551353
}
13561354

1355+
/// Invoked by R to write output to the console.
1356+
/// Only used during initialization to capture the startup banner.
1357+
fn write_console_init(&mut self, buf: *const c_char) {
1358+
let content = match console_to_utf8(buf) {
1359+
Ok(content) => content,
1360+
Err(err) => panic!("Failed to read from R buffer: {err:?}"),
1361+
};
1362+
1363+
// During init, consider all output to be part of the startup banner
1364+
self.banner_output.push_str(&content);
1365+
}
1366+
13571367
/// Invoked by R to change busy state
13581368
fn busy(&mut self, which: i32) {
13591369
// Ensure signal handlers are initialized.
@@ -1679,6 +1689,12 @@ pub extern "C" fn r_write_console(buf: *const c_char, buflen: i32, otype: i32) {
16791689
main.write_console(buf, buflen, otype);
16801690
}
16811691

1692+
#[no_mangle]
1693+
pub extern "C" fn r_write_console_init(buf: *const c_char, _buflen: i32, _otype: i32) {
1694+
let main = RMain::get_mut();
1695+
main.write_console_init(buf);
1696+
}
1697+
16821698
#[no_mangle]
16831699
pub extern "C" fn r_show_message(buf: *const c_char) {
16841700
let main = RMain::get();

crates/ark/src/sys/unix/interface.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::interface::r_read_console;
3535
use crate::interface::r_show_message;
3636
use crate::interface::r_suicide;
3737
use crate::interface::r_write_console;
38+
use crate::interface::r_write_console_init;
3839
use crate::signals::initialize_signal_handlers;
3940

4041
pub fn setup_r(mut args: Vec<*mut c_char>) {
@@ -64,8 +65,10 @@ pub fn setup_r(mut args: Vec<*mut c_char>) {
6465
libr::set(R_Consolefile, std::ptr::null_mut());
6566
libr::set(R_Outputfile, std::ptr::null_mut());
6667

68+
// Set pre-init WriteConsole handler
6769
libr::set(ptr_R_WriteConsole, None);
68-
libr::set(ptr_R_WriteConsoleEx, Some(r_write_console));
70+
libr::set(ptr_R_WriteConsoleEx, Some(r_write_console_init));
71+
6972
libr::set(ptr_R_ReadConsole, Some(r_read_console));
7073
libr::set(ptr_R_ShowMessage, Some(r_show_message));
7174
libr::set(ptr_R_Busy, Some(r_busy));
@@ -87,6 +90,12 @@ pub fn setup_r(mut args: Vec<*mut c_char>) {
8790
}
8891
}
8992

93+
pub fn complete_r_init() {
94+
unsafe {
95+
libr::set(ptr_R_WriteConsoleEx, Some(r_write_console));
96+
}
97+
}
98+
9099
pub fn run_r() {
91100
unsafe {
92101
// Listen for polled events

crates/ark/src/sys/windows/interface.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ pub fn setup_r(mut _args: Vec<*mut c_char>) {
6969
(*params).R_Interactive = 1;
7070
(*params).CharacterMode = libr::UImode_RGui;
7171

72+
// Set pre-init WriteConsole handler
7273
(*params).WriteConsole = None;
73-
(*params).WriteConsoleEx = Some(r_write_console);
74+
(*params).WriteConsoleEx = Some(r_write_console_init);
75+
7476
(*params).ReadConsole = Some(r_read_console);
7577
(*params).ShowMessage = Some(r_show_message);
7678
(*params).YesNoCancel = Some(r_yes_no_cancel);
@@ -101,6 +103,13 @@ pub fn setup_r(mut _args: Vec<*mut c_char>) {
101103
}
102104
}
103105

106+
pub fn complete_r_init() {
107+
unsafe {
108+
let params: libr::Rstart = params_struct.as_mut_ptr();
109+
(*params).WriteConsoleEx = Some(r_write_console);
110+
}
111+
}
112+
104113
pub fn run_r() {
105114
unsafe {
106115
run_Rmainloop();

0 commit comments

Comments
 (0)