forked from simonpcouch/pal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
interface for custom pals (simonpcouch#26)
- Loading branch information
1 parent
ae9794a
commit e38edaf
Showing
13 changed files
with
267 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
.pal <- function() { | ||
pal_fn <- .pal_app() | ||
if (is.null(pal_fn) || identical(pal_fn, "rs_pal_")) { | ||
return(NULL) | ||
} | ||
try_fetch( | ||
do.call(pal_fn, args = list()), | ||
error = function(e) { | ||
cli::cli_abort("Unable to locate the requested pal.") | ||
} | ||
) | ||
} | ||
|
||
.pal_app <- function() { | ||
pal_choices <- list_pals() | ||
|
||
ui <- miniUI::miniPage( | ||
miniUI::miniContentPanel( | ||
shiny::selectizeInput("pal", "Select a pal:", | ||
choices = NULL, | ||
selected = NULL, | ||
multiple = FALSE | ||
), | ||
shiny::verbatimTextOutput("result"), | ||
shiny::tags$script(shiny::HTML(" | ||
$(document).on('keyup', function(e) { | ||
if(e.key == 'Enter'){ | ||
Shiny.setInputValue('done', true, {priority: 'event'}); | ||
} | ||
}); | ||
")) | ||
) | ||
) | ||
|
||
server <- function(input, output, session) { | ||
shiny::updateSelectizeInput( | ||
session, 'pal', | ||
choices = pal_choices, | ||
server = TRUE | ||
) | ||
shiny::observeEvent(input$done, { | ||
shiny::stopApp(returnValue = paste0("rs_pal_", input$pal)) | ||
}) | ||
shiny::onStop(function() { | ||
shiny::stopApp(returnValue = NULL) | ||
}) | ||
} | ||
|
||
viewer <- shiny::dialogViewer("Pal", width = 300, height = 10) | ||
shiny::runGadget(ui, server, viewer = viewer) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#' Creating custom pals | ||
#' | ||
#' @description | ||
#' Users can create custom pals using the `pal_add()` function; after passing | ||
#' the function a role and prompt, the pal will be available on the command | ||
#' palette. | ||
#' | ||
#' @param role A single string giving the [pal()] role. | ||
# TODO: actually do this once elmer implements | ||
#' @param prompt A file path to a markdown file giving the system prompt or | ||
#' the output of [elmer::interpolate()]. | ||
# TODO: only add prefix when not supplied one | ||
#' @param interface One of `"replace"`, `"prefix"`, or `"suffix"`, describing | ||
#' how the pal will interact with the selection. For example, the | ||
#' [cli pal][pal_cli] `"replace"`s the selection, while the | ||
#' [roxygen pal][pal_roxygen] `"prefixes"` the selected code with documentation. | ||
#' | ||
#' @details | ||
#' `pal_add()` will register the add-in as coming from the pal package | ||
#' itself—because of this, custom pals will be deleted when the pal | ||
#' package is reinstalled. Include `pal_add()` code in your `.Rprofile` or | ||
#' make a pal extension package using `pal_add(package = TRUE)` to create | ||
#' persistent custom pals. | ||
#' | ||
#' @returns | ||
#' `NULL`, invisibly. Called for its side effect: a pal with role `role` | ||
#' is registered with the pal package. | ||
#' | ||
#' @export | ||
pal_add <- function( | ||
role, | ||
prompt = NULL, | ||
interface = c("replace", "prefix", "suffix") | ||
) { | ||
# TODO: need to check that there are no spaces (or things that can't be | ||
# included in a variable name) | ||
check_string(role, allow_empty = FALSE) | ||
|
||
# TODO: make this an elmer interpolate or an .md file | ||
prompt <- .stash_prompt(prompt, role) | ||
binding <- parse_interface(interface, role) | ||
|
||
invisible() | ||
} | ||
|
||
# TODO: fn to remove the addin associated with the role | ||
pal_remove <- function(role) { | ||
invisible() | ||
} | ||
|
||
supported_interfaces <- c("replace", "prefix", "suffix") | ||
|
||
# given an interface and role, attaches a function binding in pal's | ||
# additional search env | ||
parse_interface <- function(interface, role) { | ||
if (isTRUE(identical(interface, supported_interfaces))) { | ||
interface <- interface[1] | ||
} | ||
if (isTRUE( | ||
length(interface) != 1 || | ||
!interface %in% supported_interfaces | ||
)) { | ||
cli::cli_abort( | ||
"{.arg interface} should be one of {.or {.val {supported_interfaces}}}." | ||
) | ||
} | ||
|
||
if (interface == "suffix") { | ||
# TODO: implement suffixing | ||
cli::cli_abort("Suffixing not implemented yet.") | ||
} | ||
|
||
.stash_binding( | ||
role, | ||
function(context = rstudioapi::getActiveDocumentContext()) { | ||
do.call( | ||
paste0("rs_", interface, "_selection"), | ||
args = list(context = context, role = role) | ||
) | ||
} | ||
) | ||
|
||
paste0("rs_pal_", role) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,63 @@ | ||
#' Save most recent results to search path | ||
#' | ||
#' @param x A pal. | ||
#' | ||
#' @return NULL, invisibly. | ||
#' | ||
#' @details The function will assign `x` to `.last_pal` and put it in | ||
#' the search path. | ||
#' | ||
#' @export | ||
#' @keywords internal | ||
# helpers for the pal environment ---------------------------------------------- | ||
.stash_last_pal <- function(x) { | ||
if (!"pkg:pal" %in% search()) { | ||
do.call("attach", list(new.env(), pos = length(search()), | ||
name = "pkg:pal")) | ||
} | ||
env <- as.environment("pkg:pal") | ||
env[[paste0(".last_pal_", x$role)]] <- x | ||
env[[".last_pal"]] <- x | ||
pal_env <- pal_env() | ||
pal_env[[paste0(".last_pal_", x$role)]] <- x | ||
pal_env[[".last_pal"]] <- x | ||
invisible(NULL) | ||
} | ||
|
||
#' @export | ||
print.pal_response <- function(x, ...) { | ||
cat(x) | ||
.stash_binding <- function(role, fn) { | ||
pal_env <- pal_env() | ||
pal_env[[paste0("rs_pal_", role)]] <- fn | ||
invisible(NULL) | ||
} | ||
|
||
check_role <- function(role, call = caller_env()) { | ||
if (is_missing(role) || | ||
is.null(role) || | ||
!role %in% supported_roles | ||
) { | ||
cli::cli_abort( | ||
"{.arg role} must be one of {.or {.val {supported_roles}}}.", | ||
call = call | ||
) | ||
} | ||
.stash_prompt <- function(prompt, role) { | ||
pal_env <- pal_env() | ||
pal_env[[paste0("system_prompt_", role)]] <- prompt | ||
invisible(NULL) | ||
} | ||
|
||
last_pal <- function(pal, call = caller_env()) { | ||
if (!is.null(pal)) { | ||
return(pal) | ||
pal_env <- function() { | ||
if (!"pkg:pal" %in% search()) { | ||
do.call( | ||
"attach", | ||
list(new.env(), pos = length(search()), name = "pkg:pal") | ||
) | ||
} | ||
as.environment("pkg:pal") | ||
} | ||
|
||
pal_role <- pal$role | ||
list_pals <- function() { | ||
pal_env <- pal_env() | ||
pal_env_names <- names(pal_env) | ||
prompt_names <- grep("system_prompt_", names(pal_env), value = TRUE) | ||
gsub("system_prompt_", "", prompt_names) | ||
} | ||
|
||
if (exists(paste0(".last_pal_", pal_role))) { | ||
return(get(paste0(".last_pal_", pal_role))) | ||
# ad-hoc check functions ------------------------------------------------------- | ||
check_prompt <- function(prompt, call = caller_env()) { | ||
if (inherits(prompt, "pal_prompt")) { | ||
return(prompt) | ||
} | ||
|
||
if (exists(".last_pal")) { | ||
return(.last_pal) | ||
if (is_markdown_file(prompt)) { | ||
if (file.exists(prompt)) { | ||
cli::cli_abort( | ||
"The markdown file supplied as {.arg prompt} does not exist.", | ||
call = call | ||
) | ||
} | ||
prompt <- readLines(prompt) | ||
} | ||
|
||
cli::cli_abort( | ||
"Create a pal with {.fn pal} to use this function.", | ||
"{.arg prompt} should either be a {.code .md} file or | ||
the output of {.fn .pal_prompt}.", | ||
call = call | ||
) | ||
} | ||
|
||
is_markdown_file <- function(x) { | ||
grepl("\\.(md|markdown)$", x, ignore.case = TRUE) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,4 @@ | ||
Name: Pal: convert to cli | ||
Description: Replaces selected erroring code with a version adapted to cli | ||
Binding: rs_pal_cli | ||
Interactive: false | ||
|
||
Name: Pal: convert to testthat | ||
Description: Replaces selected unit testing code with a version adapted to testthat 3 | ||
Binding: rs_pal_testthat | ||
Interactive: false | ||
|
||
Name: Pal: template roxygen documentation | ||
Description: Prefixes selected function with templated roxygen2 documentation | ||
Binding: rs_pal_roxygen | ||
Name: Pal | ||
Description: LLM assistants for R | ||
Binding: .pal | ||
Interactive: false |
Oops, something went wrong.