Skip to content

Commit

Permalink
Server-aware editing in VSCode and static app script generation (#139)
Browse files Browse the repository at this point in the history
* Just send script and ast to client
* Remove most R code due to simpler messages
* Add static script generation to hosted version of editor
  • Loading branch information
nstrayer authored Feb 13, 2023
1 parent da902c2 commit bda7582
Show file tree
Hide file tree
Showing 265 changed files with 74,539 additions and 18,823 deletions.
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
^docs$
^pkgdown$
^\.github$
^\.devcontainer$
^vignettes/ui-editor-live-demo\.Rmd$
^\.hintrc$
^\.yarnrc\.yml$
Expand All @@ -19,6 +20,7 @@
^yarn\.lock$
^inst\/editor\/(?!build).+$
^inst\/build-utils$
^inst\/ast-parsing$
^inst\/communication-types$
^inst\/communication-types$
^inst\/vscode-extension$
Expand Down
3 changes: 1 addition & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: shinyuieditor
Title: Build and Modify your Shiny UI, visually
Version: 0.3.2
Version: 0.4.0
Authors@R:
person(given = "Nick",
family = "Strayer",
Expand All @@ -20,7 +20,6 @@ Imports:
later,
rlang,
shiny,
styler,
utils,
gridlayout (>= 0.1.0),
Suggests:
Expand Down
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# Generated by roxygen2: do not edit by hand

export(launch_editor)
export(parse_ui_fn)
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# shinyuieditor 0.4.0

### Major new features and improvements

- VSCode extension can now highlight output definitions and input uses in the server code.
- In embedded mode (on the main website) the ui editor now provides full code to reproduce the current app.

### Minor new features and improvements

### Bug fixes

# shinyuieditor 0.3.3

### Major new features and improvements
Expand Down
81 changes: 66 additions & 15 deletions R/FileChangeWatcher.R
Original file line number Diff line number Diff line change
@@ -1,35 +1,45 @@
FileChangeWatcher <- function() {
FileChangeWatcher <- function(dir_root) {
watcher_subscription <- NULL
file_path <- NULL
file_root <- fs::dir_create(dir_root)
watched_files <- NULL
last_known_edit <- NULL

get_last_edit_time <- function() {
if (is.null(file_path)) {
if (is.null(watched_files)) {
return(NULL)
}

fs::file_info(file_path)$modification_time
max(file.mtime(watched_files))
}

update_last_known_edit <- function() {
update_last_known_edit_time <- function() {
last_known_edit <<- get_last_edit_time()
}

start_watching <- function(path_to_watch, on_update) {
set_watched_files <- function(files_to_watch) {
# Make sure files exist
watched_files <<- fs::file_create(fs::path(file_root, files_to_watch))
names(watched_files) <<- files_to_watch
}

get_file_contents <- function() {
lapply(watched_files, readLines)
}

start_watching <- function(on_update) {
# Make sure we cleanup any old watchers if they exist
cleanup()

file_path <<- path_to_watch
update_last_known_edit()
if (is.null(watched_files)) {
stop("File path to watch is uninitialized")
}
update_last_known_edit_time()

watcher_subscription <<- create_output_subscribers(
source_fn = get_last_edit_time,
filter_fn = function(last_edited_new) {
time_delta <- as.numeric(last_known_edit - last_edited_new)
edited_since_last_known <- time_delta != 0

edited_since_last_known
no_changes_to_file <- identical(last_known_edit, last_edited_new)
return(!no_changes_to_file)
},
delay = 0.25
)
Expand All @@ -38,12 +48,50 @@ FileChangeWatcher <- function() {
function(last_edited_new) {
on_update()
# Update the last edit time so this doesn't get called twice
update_last_known_edit()
update_last_known_edit_time()
}
)
}


update_files <- function(named_contents) {
for (file_name in names(named_contents)) {
path_to_file <- watched_files[paste0(file_name, ".R")]
if (is.null(path_to_file)) {
stop("Tried to update an unwatched file")
}
writeLines(
text = named_contents[[file_name]],
con = path_to_file
)
}

update_last_known_edit_time()
}

# Delete the files and stop watching them as well
delete_files <- function(delete_root = FALSE) {
if (is.null(watched_files)) {
return()
}
cleanup()
fs::file_delete(watched_files)

if (!delete_root) {
return()
}

root_dir_now_empty <- identical(length(fs::dir_ls(file_root)), 0L)

# We don't want to delete our current working directory on accident, so
# check that
root_dir_is_cwd <- identical(file_root, ".") ||
identical(getwd(), file_root)

if (root_dir_now_empty && !root_dir_is_cwd) {
fs::dir_delete(file_root)
}
}

cleanup <- function() {
if (!is.null(watcher_subscription)) {
watcher_subscription$cancel_all()
Expand All @@ -52,8 +100,11 @@ FileChangeWatcher <- function() {
}

list(
"set_watched_files" = set_watched_files,
"get_file_contents" = get_file_contents,
"start_watching" = start_watching,
"update_last_edit_time" = update_last_known_edit,
"update_files" = update_files,
"delete_files" = delete_files,
"cleanup" = cleanup
)
}
88 changes: 0 additions & 88 deletions R/app_file_helpers.R

This file was deleted.

91 changes: 0 additions & 91 deletions R/deparse_ui_fn.R

This file was deleted.

40 changes: 40 additions & 0 deletions R/get_app_file_type.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#' Get the file type a shiny app directory
#'
#' @param app_loc Path to a shiny app
#' @param error_on_missing Should the lack of
#' app ui file trigger an error? If not returns a type of "missing" and no path
#'
#' @return either "SINGLE-FILE" (`app.R``), "MULTI-FILE" (`ui.R` and
#' `server.R`), or "MISSING" (empty directory)
#'
#' @keywords internal
#'
get_app_file_type <- function(app_loc, error_on_missing = FALSE) {
if (
fs::file_exists(fs::path(app_loc, "app.r")) ||
fs::file_exists(fs::path(app_loc, "app.R"))
) {
return("SINGLE-FILE")
}

if (
fs::file_exists(fs::path(app_loc, "ui.r")) ||
fs::file_exists(fs::path(app_loc, "ui.R"))
) {
return("MULTI-FILE")
}

if (error_on_missing) {
stop(
"Can't find an app.R or ui.R file in the provided app_loc. ",
"Make sure your working directory is properly set"
)
}

"MISSING"
}

app_type_to_files <- list(
"SINGLE-FILE" = "app.R",
"MULTI-FILE" = c("ui.R", "server.R")
)
Loading

0 comments on commit bda7582

Please sign in to comment.