Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a few more OpenRPC methods for rstudioapi shims #286

Merged
merged 3 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
47 changes: 47 additions & 0 deletions crates/amalthea/src/comm/ui_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ pub struct OpenEditorParams {
pub column: i64,
}

/// Parameters for the NewDocument method.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct NewDocumentParams {
/// Document contents
pub contents: String,

/// Language identifier
pub language_id: String,
}

/// Parameters for the ShowMessage method.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct ShowMessageParams {
Expand Down Expand Up @@ -191,6 +201,22 @@ pub struct ExecuteCommandParams {
pub command: String,
}

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

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

/// Whether to focus the runtime's console
pub focus: bool,

/// Whether to bypass runtime code completeness checks
pub allow_incomplete: bool,
}

/// Parameters for the OpenWorkspace method.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct OpenWorkspaceParams {
Expand Down Expand Up @@ -258,6 +284,13 @@ pub enum UiBackendReply {
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(tag = "method", content = "params")]
pub enum UiFrontendRequest {
/// Create a new document with text contents
///
/// Use this to create a new document with the given language ID and text
/// contents
#[serde(rename = "new_document")]
NewDocument(NewDocumentParams),

/// Show a question
///
/// Use this for a modal dialog that the user can accept or cancel
Expand All @@ -276,6 +309,12 @@ pub enum UiFrontendRequest {
#[serde(rename = "debug_sleep")]
DebugSleep(DebugSleepParams),

/// Execute code in a Positron runtime
///
/// Use this to execute code in a Positron runtime
#[serde(rename = "execute_code")]
ExecuteCode(ExecuteCodeParams),

/// Path to the workspace folder
///
/// Returns the path to the workspace folder, or first folder if there are
Expand Down Expand Up @@ -304,6 +343,9 @@ pub enum UiFrontendRequest {
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(tag = "method", content = "result")]
pub enum UiFrontendReply {
/// Reply for the new_document method (no result)
NewDocumentReply(),

/// Whether the user accepted or rejected the dialog.
ShowQuestionReply(bool),

Expand All @@ -313,6 +355,9 @@ pub enum UiFrontendReply {
/// Reply for the debug_sleep method (no result)
DebugSleepReply(),

/// Reply for the execute_code method (no result)
ExecuteCodeReply(),

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

Expand Down Expand Up @@ -387,9 +432,11 @@ pub fn ui_frontend_reply_from_value(
request: &UiFrontendRequest,
) -> anyhow::Result<UiFrontendReply> {
match request {
UiFrontendRequest::NewDocument(_) => Ok(UiFrontendReply::NewDocumentReply()),
UiFrontendRequest::ShowQuestion(_) => Ok(UiFrontendReply::ShowQuestionReply(serde_json::from_value(reply)?)),
UiFrontendRequest::ShowDialog(_) => Ok(UiFrontendReply::ShowDialogReply()),
UiFrontendRequest::DebugSleep(_) => Ok(UiFrontendReply::DebugSleepReply()),
UiFrontendRequest::ExecuteCode(_) => Ok(UiFrontendReply::ExecuteCodeReply()),
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
10 changes: 10 additions & 0 deletions crates/ark/src/modules/positron/frontend-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,21 @@
.ps.Call("ps_ui_navigate_to_file", file, line, column)
}

#' @export
.ps.ui.newDocument <- function(contents, languageId, line, column) {
.ps.Call("ps_ui_new_document", contents, languageId, line, column)
}

#' @export
.ps.ui.executeCommand <- function(command) {
.ps.Call("ps_ui_execute_command", command)
}

#' @export
.ps.ui.executeCode <- function(code, focus) {
.ps.Call("ps_ui_execute_code", code, focus)
}

#' @export
.ps.ui.showMessage <- function(message) {
.ps.Call("ps_ui_show_message", message)
Expand Down
12 changes: 4 additions & 8 deletions crates/ark/src/modules/rstudio/document-api.R
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,12 @@ selection_as_range <- function(ps_sel) {
}

#' @export
.rs.api.documentNew <- function(text,
type = c("r", "rmarkdown", "sql"),
position = rstudioapi::document_position(0, 0),
execute = FALSE) {
type <- match.arg(type)
# TODO: Support execute & position
stopifnot(!execute && position != rstudioapi::document_position(0, 0))
.rs.api.documentNew <- function(type, code, row = 0, column = 0, execute = FALSE) {
# TODO: Support execute
stopifnot(!execute)

languageId <- if (type == "rmarkdown") "rmd" else type
invisible(.ps.ui.documentNew(text, languageId))
invisible(.ps.ui.newDocument(paste(code, collapse = "\n"), languageId, row, column))
}

#' @export
Expand Down
9 changes: 9 additions & 0 deletions crates/ark/src/modules/rstudio/stubs.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
invisible(.ps.ui.navigateToFile(file, line, column))
}

#' @export
.rs.api.sendToConsole <- function(code, echo = TRUE, execute = TRUE, focus = TRUE, animate = FALSE) {
# TODO: support other args
stopifnot(echo && execute && !animate)

# If we add new args later, remember to put them **after** the existing args
invisible(.ps.ui.executeCode(paste(code, collapse = "\n"), focus))
}

#' @export
.rs.api.restartSession <- function(command = "") {
# TODO: support followup `command` argument
Expand Down
33 changes: 33 additions & 0 deletions crates/ark/src/ui/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
//

use amalthea::comm::ui_comm::DebugSleepParams;
use amalthea::comm::ui_comm::ExecuteCodeParams;
use amalthea::comm::ui_comm::ModifyEditorSelectionsParams;
use amalthea::comm::ui_comm::NewDocumentParams;
use amalthea::comm::ui_comm::ShowDialogParams;
use amalthea::comm::ui_comm::ShowQuestionParams;
use amalthea::comm::ui_comm::UiFrontendRequest;
Expand Down Expand Up @@ -89,6 +91,37 @@ pub unsafe extern "C" fn ps_ui_show_question(
Ok(out.sexp)
}

#[harp::register]
pub unsafe extern "C" fn ps_ui_new_document(
contents: SEXP,
language_id: SEXP,
_line: SEXP,
_column: SEXP,
juliasilge marked this conversation as resolved.
Show resolved Hide resolved
) -> anyhow::Result<SEXP> {
let params = NewDocumentParams {
contents: RObject::view(contents).try_into()?,
language_id: RObject::view(language_id).try_into()?,
};

let main = RMain::get();
let out = main.call_frontend_method(UiFrontendRequest::NewDocument(params))?;
Ok(out.sexp)
}

#[harp::register]
pub unsafe extern "C" fn ps_ui_execute_code(code: SEXP, focus: SEXP) -> anyhow::Result<SEXP> {
let params = ExecuteCodeParams {
language_id: String::from("r"),
code: RObject::view(code).try_into()?,
focus: RObject::view(focus).try_into()?,
allow_incomplete: false,
Copy link
Contributor Author

@juliasilge juliasilge Apr 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using false here to be consistent with the RStudio behavior for rstudioapi::sendToConsole("1 + ")

};

let main = RMain::get();
let out = main.call_frontend_method(UiFrontendRequest::ExecuteCode(params))?;
Ok(out.sexp)
}

#[harp::register]
pub unsafe extern "C" fn ps_ui_debug_sleep(ms: SEXP) -> anyhow::Result<SEXP> {
let params = DebugSleepParams {
Expand Down
Loading