Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions crates/amalthea/src/comm/ui_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,19 @@ pub struct ExecuteCodeParams {
pub allow_incomplete: bool,
}

/// Parameters for the ExecuteCodeInNewSession method.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct ExecuteCodeInNewSessionParams {
/// The language ID of the code to execute
pub language_id: String,

/// The code to execute
pub code: String,

/// The name of the new session
pub session_name: String,
}

/// Parameters for the OpenWorkspace method.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct OpenWorkspaceParams {
Expand Down Expand Up @@ -537,6 +550,18 @@ pub enum UiFrontendRequest {
#[serde(rename = "execute_code")]
ExecuteCode(ExecuteCodeParams),

/// Execute code in a new session
///
/// Start a new console session in the background, without making it the
/// foreground session, and queue code in it. When a session sends the
/// request, the new session uses that session's runtime, and the request
/// fails if that session is for another language. Otherwise the new
/// session uses the preferred runtime for the language. Returns once the
/// code is queued. The code must be complete; it is run as-is without
/// completeness checks.
#[serde(rename = "execute_code_in_new_session")]
ExecuteCodeInNewSession(ExecuteCodeInNewSessionParams),

/// Path to the workspace folder
///
/// Returns the path to the workspace folder, or first folder if there are
Expand Down Expand Up @@ -596,6 +621,8 @@ pub enum UiFrontendReply {
/// Reply for the execute_code method (no result)
ExecuteCodeReply(),

ExecuteCodeInNewSessionReply(String),

/// The path to the workspace folder
WorkspaceFolderReply(Option<String>),

Expand Down Expand Up @@ -710,6 +737,7 @@ pub fn ui_frontend_reply_from_value(
UiFrontendRequest::ExecuteCommand(_) => Ok(UiFrontendReply::ExecuteCommandReply()),
UiFrontendRequest::EvaluateWhenClause(_) => Ok(UiFrontendReply::EvaluateWhenClauseReply(serde_json::from_value(reply)?)),
UiFrontendRequest::ExecuteCode(_) => Ok(UiFrontendReply::ExecuteCodeReply()),
UiFrontendRequest::ExecuteCodeInNewSession(_) => Ok(UiFrontendReply::ExecuteCodeInNewSessionReply(serde_json::from_value(reply)?)),
UiFrontendRequest::WorkspaceFolder => Ok(UiFrontendReply::WorkspaceFolderReply(serde_json::from_value(reply)?)),
UiFrontendRequest::ModifyEditorSelections(_) => Ok(UiFrontendReply::ModifyEditorSelectionsReply()),
UiFrontendRequest::LastActiveEditorContext(_) => Ok(UiFrontendReply::LastActiveEditorContextReply(serde_json::from_value(reply)?)),
Expand Down
15 changes: 15 additions & 0 deletions crates/ark/src/modules/positron/frontend-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@
.ps.Call("ps_ui_execute_code", code, focus)
}

#' @export
.ps.ui.executeCodeInNewSession <- function(code, sessionName) {
tryCatch(
parse(text = code),
error = function(e) {
stop(
"Can't run code in a new session because it does not parse: ",
conditionMessage(e),
call. = FALSE
)
}
)
.ps.Call("ps_ui_execute_code_in_new_session", code, sessionName)
}

#' @export
.ps.ui.showMessage <- function(message) {
.ps.Call("ps_ui_show_message", message)
Expand Down
70 changes: 70 additions & 0 deletions crates/ark/src/modules/rstudio/stubs.R
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,73 @@
PACKAGE = "(embedding)"
))
}

#' @export
.rs.api.runScriptJob <- function(
path,
name = NULL,
encoding = "unknown",
workingDir = NULL,
importEnv = FALSE,
exportEnv = ""
) {
if (missing(path)) {
stop("Must specify path to R script to run.", call. = FALSE)
}
check_string <- function(x, arg) {
if (!is_string(x)) {
stop("`", arg, "` must be a single string.", call. = FALSE)
}
}
check_string(path, "path")
if (!is.null(name)) {
check_string(name, "name")
}
check_string(encoding, "encoding")
if (!is.null(workingDir)) {
check_string(workingDir, "workingDir")
}
if (!file.exists(path) || dir.exists(path)) {
stop("The R script '", path, "' does not exist.", call. = FALSE)
}
path <- normalizePath(path, winslash = "/")

if (is.null(name) || !nzchar(name)) {
name <- basename(path)
}
if (is.null(workingDir)) {
workingDir <- dirname(path)
}
if (!dir.exists(workingDir)) {
stop(
"The working directory '",
workingDir,
"' does not exist.",
call. = FALSE
)
}
workingDir <- normalizePath(workingDir, winslash = "/")

if (isTRUE(importEnv)) {
warning(
"`importEnv = TRUE` is not supported in Positron and is ignored.",
call. = FALSE
)
}
if (is_string(exportEnv) && nzchar(exportEnv)) {
warning(
"`exportEnv` is not supported in Positron and is ignored.",
call. = FALSE
)
}

# Braces make one expression so a failed setwd() stops the job before source()
code <- sprintf(
"{\n setwd(%s)\n source(%s, encoding = %s)\n}",
deparse(workingDir),
deparse(path),
deparse(encoding)
)

invisible(.ps.ui.executeCodeInNewSession(code, name))
}
18 changes: 18 additions & 0 deletions crates/ark/src/ui/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use amalthea::comm::ui_comm::AskForPasswordParams;
use amalthea::comm::ui_comm::DebugSleepParams;
use amalthea::comm::ui_comm::EvaluateWhenClauseParams;
use amalthea::comm::ui_comm::ExecuteCodeInNewSessionParams;
use amalthea::comm::ui_comm::ExecuteCodeParams;
use amalthea::comm::ui_comm::ExecuteCommandParams;
use amalthea::comm::ui_comm::LastActiveEditorContextParams;
Expand Down Expand Up @@ -200,6 +201,23 @@ pub unsafe extern "C-unwind" fn ps_ui_execute_code(
Ok(out.sexp)
}

#[harp::register]
pub unsafe extern "C-unwind" fn ps_ui_execute_code_in_new_session(
code: SEXP,
session_name: SEXP,
) -> anyhow::Result<SEXP> {
let params = ExecuteCodeInNewSessionParams {
language_id: String::from("r"),
code: RObject::view(code).try_into()?,
session_name: RObject::view(session_name).try_into()?,
};

let out = Console::get()
.try_ui_comm()?
.call_frontend_method(UiFrontendRequest::ExecuteCodeInNewSession(params))?;
Ok(out.sexp)
}

#[harp::register]
pub unsafe extern "C-unwind" fn ps_ui_evaluate_when_clause(
when_clause: SEXP,
Expand Down
Loading
Loading