Skip to content

Commit 56fe788

Browse files
committed
Make functions viewable in the Variables pane
1 parent 0951b70 commit 56fe788

File tree

5 files changed

+47
-8
lines changed

5 files changed

+47
-8
lines changed

crates/ark/src/modules/positron/view.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
# These are only passed if we could infer a variable name from the input and if
1010
# that variable exists in the calling environment. This is used for live
1111
# updating the objects, if supported (e.g. data frames in the data viewer).
12-
view <- function(x, title) {
12+
view <- function(x, title, name = NULL, env = parent.frame()) {
1313
# Derive the name of the object from the expression passed to View()
14-
name <- as_label(substitute(x))
14+
name <- name %||% as_label(substitute(x))
15+
stopifnot(is_string(name))
1516

1617
# Create a title from the name of the object if one is not provided
1718
if (missing(title)) {
@@ -25,9 +26,8 @@ view <- function(x, title) {
2526
# Note that this means that (for example) View(foo) will watch the variable
2627
# foo in the parent frame, but Viewing temporary variables like
2728
# View(cbind(foo, bar)) does not create something that can be watched.
28-
if (isTRUE(exists(name, envir = parent.frame(), inherits = FALSE))) {
29+
if (nzchar(name) && isTRUE(exists(name, envir = env, inherits = FALSE))) {
2930
var <- name
30-
env <- parent.frame()
3131
} else {
3232
var <- ""
3333
env <- NULL

crates/ark/src/variables/r_variables.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use harp::exec::RFunctionExt;
2929
use harp::get_option;
3030
use harp::object::RObject;
3131
use harp::utils::r_assert_type;
32+
use harp::utils::r_is_function;
3233
use harp::vector::CharacterVector;
3334
use harp::vector::Vector;
3435
use libr::R_GlobalEnv;
@@ -42,6 +43,7 @@ use crate::lsp::events::EVENTS;
4243
use crate::r_task;
4344
use crate::thread::RThreadSafe;
4445
use crate::variables::variable::PositronVariable;
46+
use crate::view::view;
4547

4648
/// Enumeration of treatments for the .Last.value variable
4749
pub enum LastValue {
@@ -368,15 +370,25 @@ impl RVariables {
368370
fn view(&mut self, path: &Vec<String>) -> Result<String, harp::error::Error> {
369371
r_task(|| {
370372
let env = self.env.get().clone();
371-
let data = PositronVariable::resolve_data_object(env, &path)?;
373+
let obj = PositronVariable::resolve_data_object(env.clone(), &path)?;
374+
375+
if r_is_function(obj.sexp) {
376+
harp::as_result(view(&obj, &path, &env))?;
377+
378+
// Return a falsy `viewerId`. Should ideally be a more explicit `None`.
379+
return Ok(String::from(""));
380+
}
381+
372382
let name = unsafe { path.get_unchecked(path.len() - 1) };
383+
373384
let binding = DataObjectEnvInfo {
374385
name: name.to_string(),
375-
env: RThreadSafe::new(self.env.get().clone()),
386+
env: RThreadSafe::new(env),
376387
};
388+
377389
let viewer_id = RDataExplorer::start(
378390
name.clone(),
379-
data,
391+
obj,
380392
Some(binding),
381393
self.comm_manager_tx.clone(),
382394
)?;

crates/ark/src/variables/variable.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use harp::utils::r_format_s4;
3333
use harp::utils::r_inherits;
3434
use harp::utils::r_is_altrep;
3535
use harp::utils::r_is_data_frame;
36+
use harp::utils::r_is_function;
3637
use harp::utils::r_is_matrix;
3738
use harp::utils::r_is_null;
3839
use harp::utils::r_is_s4;
@@ -589,6 +590,10 @@ fn has_children(value: SEXP) -> bool {
589590
}
590591

591592
fn has_viewer(value: SEXP) -> bool {
593+
if r_is_function(value) {
594+
return true;
595+
}
596+
592597
if !(r_is_data_frame(value) || r_is_matrix(value)) {
593598
return false;
594599
}

crates/ark/src/view.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,28 @@
55
//
66
//
77

8-
// Tests for `view.R`
8+
use harp::exec::RFunction;
9+
use harp::exec::RFunctionExt;
10+
use harp::RObject;
11+
12+
use crate::modules::ARK_ENVS;
13+
14+
pub(crate) fn view(x: &RObject, path: &Vec<String>, env: &RObject) -> anyhow::Result<()> {
15+
// Currently `view()` only supports identifiers
16+
let name = if path.len() == 1 {
17+
path.last().unwrap().clone()
18+
} else {
19+
String::from("")
20+
};
21+
22+
RFunction::new("", "view")
23+
.add(x.sexp)
24+
.param("name", name)
25+
.param("env", env.sexp)
26+
.call_in(ARK_ENVS.positron_ns)?;
27+
28+
Ok(())
29+
}
930

1031
#[cfg(test)]
1132
mod tests {

crates/harp/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub use vector::list::*;
5959
// resolve to the correct symbols
6060
extern crate self as harp;
6161

62+
pub use harp::error::as_result;
6263
pub use harp::exec::top_level_exec;
6364
pub use harp::exec::try_catch;
6465
pub use harp::exec::try_eval;

0 commit comments

Comments
 (0)