Skip to content

Commit b5e7ecd

Browse files
committed
add channel to indicate when help is/isn't shown
1 parent e02bd0b commit b5e7ecd

File tree

6 files changed

+59
-17
lines changed

6 files changed

+59
-17
lines changed

crates/ark/src/browser.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use anyhow::Result;
1111
use harp::object::RObject;
1212
use libR_sys::*;
1313

14+
use crate::help::message::HelpReply;
1415
use crate::help::message::HelpRequest;
1516
use crate::interface::R_MAIN;
1617

@@ -46,7 +47,16 @@ unsafe fn handle_help_url(url: &str) -> Result<bool> {
4647
return Ok(false);
4748
}
4849

49-
Ok(true)
50+
// Wait up to 1 second for a reply from the help thread
51+
let reply = main
52+
.help_rx
53+
.as_ref()
54+
.unwrap()
55+
.recv_timeout(std::time::Duration::from_secs(1))?;
56+
57+
match reply {
58+
HelpReply::ShowHelpUrlReply(found) => Ok(found),
59+
}
5060
}
5161

5262
unsafe fn ps_browse_url_impl(url: SEXP) -> Result<()> {

crates/ark/src/help/message.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ pub enum HelpMessage {
3232
pub enum HelpRequest {
3333
/// Request to show the given URL to the user in the Help pane.
3434
ShowHelpUrlRequest(String),
35+
}
36+
37+
/**
38+
* Enum representing replies from the Help thread.
39+
*/
40+
pub enum HelpReply {
41+
/// Reply to ShowHelpUrlRequest; indicates whether the URL was successfully
42+
/// shown.
3543
ShowHelpUrlReply(bool),
3644
}
3745

crates/ark/src/help/r_help.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use stdext::spawn;
2222

2323
use crate::browser;
2424
use crate::help::message::HelpMessage;
25+
use crate::help::message::HelpReply;
2526
use crate::help::message::HelpRequest;
2627
use crate::help::message::ShowHelpContent;
2728
use crate::help::message::ShowTopicReply;
@@ -36,6 +37,7 @@ pub struct RHelp {
3637
comm: CommSocket,
3738
r_help_port: u16,
3839
help_request_rx: Receiver<HelpRequest>,
40+
help_reply_tx: Sender<HelpReply>,
3941
}
4042

4143
impl RHelp {
@@ -45,7 +47,7 @@ impl RHelp {
4547
*
4648
* - `comm`: The socket for communicating with the front end.
4749
*/
48-
pub fn start(comm: CommSocket) -> Result<Sender<HelpRequest>> {
50+
pub fn start(comm: CommSocket) -> Result<(Sender<HelpRequest>, Receiver<HelpReply>)> {
4951
// Check to see whether the help server has started. We set the port
5052
// number when it starts, so if it's still at the default value (0), it
5153
// hasn't started.
@@ -79,6 +81,7 @@ impl RHelp {
7981
// Create the channels that will be used to communicate with the help
8082
// thread from other threads.
8183
let (help_request_tx, help_request_rx) = crossbeam::channel::unbounded();
84+
let (help_reply_tx, help_reply_rx) = crossbeam::channel::unbounded();
8285

8386
// Start the help request thread and wait for requests from the front
8487
// end.
@@ -87,12 +90,13 @@ impl RHelp {
8790
comm,
8891
r_help_port,
8992
help_request_rx,
93+
help_reply_tx,
9094
};
9195
help.execution_thread();
9296
});
9397

9498
// Return the channel for sending help requests to the help thread.
95-
Ok(help_request_tx)
99+
Ok((help_request_tx, help_reply_rx))
96100
}
97101

98102
/**
@@ -199,20 +203,33 @@ impl RHelp {
199203

200204
fn handle_request(&self, message: HelpRequest) -> Result<()> {
201205
match message {
202-
HelpRequest::ShowHelpUrlRequest(url) => self.show_help_url(url.as_str()),
203-
_ => Err(anyhow!("Help: Received unexpected request {:?}", message)),
206+
HelpRequest::ShowHelpUrlRequest(url) => {
207+
let found = match self.show_help_url(&url) {
208+
Ok(found) => found,
209+
Err(err) => {
210+
error!("Error showing help URL {}: {:?}", url, err);
211+
false
212+
},
213+
};
214+
self.help_reply_tx
215+
.send(HelpReply::ShowHelpUrlReply(found))?;
216+
},
204217
}
218+
Ok(())
205219
}
206220

207-
fn show_help_url(&self, url: &str) -> Result<()> {
208-
// Check for help URLs
221+
/// Shows a help URL by sending a message to the front end. Returns
222+
/// `Ok(true)` if the URL was handled, `Ok(false)` if it wasn't.
223+
fn show_help_url(&self, url: &str) -> Result<bool> {
224+
// Check for help URLs. If this is an R help URL, we'll re-direct it to
225+
// our help proxy server.
209226
let prefix = format!("http://127.0.0.1:{}/", self.r_help_port);
210227
if !url.starts_with(&prefix) {
211-
return Err(anyhow!(
212-
"Help URL '{}' doesn't have expected prefix '{}'",
213-
url,
214-
prefix
215-
));
228+
info!(
229+
"Help URL '{}' doesn't have expected prefix '{}'; not handling",
230+
url, prefix
231+
);
232+
return Ok(false);
216233
}
217234

218235
// Re-direct the help request to our help proxy server.
@@ -227,7 +244,9 @@ impl RHelp {
227244
});
228245
let json = serde_json::to_value(msg)?;
229246
self.comm.outgoing_tx.send(CommChannelMsg::Data(json))?;
230-
Ok(())
247+
248+
// The URL was handled.
249+
Ok(true)
231250
}
232251

233252
fn show_help_topic(&self, topic: String) -> Result<bool> {

crates/ark/src/interface.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use stdext::*;
6767
use crate::dap::dap::DapBackendEvent;
6868
use crate::dap::Dap;
6969
use crate::errors;
70+
use crate::help::message::HelpReply;
7071
use crate::help::message::HelpRequest;
7172
use crate::kernel::Kernel;
7273
use crate::lsp::events::EVENTS;
@@ -280,8 +281,9 @@ pub struct RMain {
280281
pub error_message: String, // `evalue` in the Jupyter protocol
281282
pub error_traceback: Vec<String>,
282283

283-
// Channel to communicate with the Help thread
284+
// Channels to communicate with the Help thread
284285
pub help_tx: Option<Sender<HelpRequest>>,
286+
pub help_rx: Option<Receiver<HelpReply>>,
285287

286288
dap: Arc<Mutex<Dap>>,
287289
is_debugging: bool,
@@ -380,6 +382,7 @@ impl RMain {
380382
error_message: String::new(),
381383
error_traceback: Vec::new(),
382384
help_tx: None,
385+
help_rx: None,
383386
dap,
384387
is_debugging: false,
385388
old_show_error_messages: None,

crates/ark/src/shell.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ impl ShellHandler for Shell {
328328
},
329329
Comm::Help => {
330330
// Start the R Help handler
331-
let help_request_tx = match RHelp::start(comm.clone()) {
331+
let (help_request_tx, help_reply_rx) = match RHelp::start(comm.clone()) {
332332
Ok(tx) => tx,
333333
Err(err) => {
334334
warn!("Could not start R Help handler: {}", err);
@@ -341,6 +341,7 @@ impl ShellHandler for Shell {
341341
r_task(|| unsafe {
342342
let main = R_MAIN.as_mut().unwrap();
343343
main.help_tx = Some(help_request_tx.clone());
344+
main.help_rx = Some(help_reply_rx.clone());
344345
});
345346

346347
Ok(true)

crates/ark/tests/help.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fn test_help_comm() {
4343
// Start the help comm. It's important to save the help request sender so
4444
// that the help comm doesn't exit before we're done with it; allowing the
4545
// sender to be dropped signals the help comm to exit.
46-
let help_request_tx = RHelp::start(comm).unwrap();
46+
let (help_request_tx, help_reply_rx) = RHelp::start(comm).unwrap();
4747

4848
// Send a request for the help topic 'library'
4949
let request = HelpMessage::ShowHelpTopicRequest(ShowTopicRequest {
@@ -76,6 +76,7 @@ fn test_help_comm() {
7676
},
7777
}
7878

79-
// No-op request to satisfy usage of help_request_tx
79+
// No-op request to keep variables in scope
8080
help_request_tx.len();
81+
help_reply_rx.len();
8182
}

0 commit comments

Comments
 (0)