├── .Rbuildignore ├── .codecov.yml ├── .gitignore ├── .travis.yml ├── CONDUCT.md ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── aaa.R ├── ec-append.R ├── ec-cmd.R ├── ec-delete.R ├── ec-edit.R ├── ec-exists.R ├── ec-export.R ├── ec-list.R ├── ec-new.R ├── ec-running.R ├── ec-start.R ├── ethercalc-host.R ├── ethercalc-package.R ├── to-csv-text.R └── utils-pipe.R ├── README.Rmd ├── README.md ├── ethercalc.Rproj ├── man ├── ec_append.Rd ├── ec_cmd.Rd ├── ec_delete.Rd ├── ec_edit.Rd ├── ec_exists.Rd ├── ec_export.Rd ├── ec_list.Rd ├── ec_new.Rd ├── ec_read.Rd ├── ec_running.Rd ├── ec_start.Rd ├── ec_view.Rd ├── ethercalc.Rd ├── ethercalc_host.Rd ├── figures │ ├── ethercalc-example.gif │ └── ethercalc-hero.png └── pipe.Rd └── tests ├── test-all.R └── testthat └── test-ethercalc.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.vscode$ 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | ^\.travis\.yml$ 5 | ^README\.*Rmd$ 6 | ^README\.*html$ 7 | ^NOTES\.*Rmd$ 8 | ^NOTES\.*html$ 9 | ^\.codecov\.yml$ 10 | ^README_files$ 11 | ^doc$ 12 | ^docs$ 13 | ^tmp$ 14 | ^notes$ 15 | ^CONDUCT.*$ 16 | ^CODE.*$ 17 | ^\.gitlab-ci\.yml$ 18 | ^LICENSE\.md$ 19 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .Rproj.user 3 | .Rhistory 4 | .RData 5 | .Rproj 6 | README_cache 7 | src/*.o 8 | src/*.so 9 | src/*.dll 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: R 2 | sudo: false 3 | cache: packages 4 | 5 | after_success: 6 | - Rscript -e 'covr::codecov()' 7 | -------------------------------------------------------------------------------- /CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http:contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ethercalc 2 | Type: Package 3 | Title: Orchestrate and Exchange Data with 'EtherCalc' Instances 4 | Version: 0.1.0 5 | Date: 2019-06-12 6 | Authors@R: c( 7 | person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), 8 | comment = c(ORCID = "0000-0001-5670-2640")) 9 | ) 10 | Maintainer: Bob Rudis 11 | Description: The 'EtherCalc' () web application is a multi-user, 12 | collaborative spreadsheet that can be run locally on virtually any modern operating system. 13 | Methods are provided to orchestrate and exchange data with 'EtherCalc' instances. 14 | URL: https://gitlab.com/hrbrmstr/ethercalc 15 | BugReports: https://gitlab.com/hrbrmstr/ethercalc/issues 16 | Encoding: UTF-8 17 | License: MIT + file LICENSE 18 | Suggests: 19 | testthat, 20 | covr 21 | Depends: 22 | R (>= 3.2.0) 23 | Imports: 24 | httr, 25 | jsonlite, 26 | processx, 27 | utils, 28 | xml2, 29 | readr, 30 | magrittr, 31 | glue 32 | Roxygen: list(markdown = TRUE) 33 | RoxygenNote: 6.1.1 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2019 2 | COPYRIGHT HOLDER: Bob Rudis 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2019 Bob Rudis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(ec_append) 5 | export(ec_cmd) 6 | export(ec_delete) 7 | export(ec_edit) 8 | export(ec_exists) 9 | export(ec_export) 10 | export(ec_list) 11 | export(ec_new) 12 | export(ec_read) 13 | export(ec_running) 14 | export(ec_start) 15 | export(ec_view) 16 | export(ethercalc_host) 17 | import(httr) 18 | import(processx) 19 | importFrom(glue,glue) 20 | importFrom(jsonlite,fromJSON) 21 | importFrom(magrittr,"%>%") 22 | importFrom(readr,read_csv) 23 | importFrom(readr,write_csv) 24 | importFrom(utils,browseURL) 25 | importFrom(xml2,xml_find_first) 26 | importFrom(xml2,xml_text) 27 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | 0.1.0 2 | * Initial release 3 | -------------------------------------------------------------------------------- /R/aaa.R: -------------------------------------------------------------------------------- 1 | .EC_MAX_CELLS <- 500000 2 | 3 | c( 4 | "csv" = "csv", 5 | "json" = "csv.json", 6 | "html" = "html", 7 | "md" = "md", 8 | "xlsx" = "xlsx" 9 | ) -> .export_trans 10 | -------------------------------------------------------------------------------- /R/ec-append.R: -------------------------------------------------------------------------------- 1 | #' Append a data frame to a "room", optionally starting at a given row 2 | #' 3 | #' @note Since this is an append operation the header will not be sent. Set 4 | #' `col_names` and `append` (both) to `TRUE` 5 | #' @note You will receive an error if `x` has a total cell count over 500,000. 6 | #' @param x a data frame 7 | #' @param room name of an existing EtherCalc "room". 8 | #' @param at if not "`end`" then the row where the data will be inserted and pasted at. 9 | #' @param append,col_names see [readr::write_csv()] and this function's Note 10 | #' @param browse if `TRUE` (`FALSE` is the default) then open up a browser tab/window to 11 | #' the room 12 | #' @param ... passed on to [write.csv()] 13 | #' @param ec_host See [ethercalc_host()] 14 | #' @return the commands used by EtherCalc to process the append operation (invisibly) 15 | #' @family EthercCalc importers/exporters 16 | #' @export 17 | #' @examples \dontrun{ 18 | #' ec_edit(iris, "test") 19 | #' ec_append(iris, "test") 20 | #' } 21 | ec_append <- function(x, room, at = "end", append = TRUE, col_names = FALSE, 22 | browse = FALSE, ..., ec_host =ethercalc_host()) { 23 | 24 | stopifnot(is.data.frame(x)) 25 | 26 | cell_ct <- Reduce(`*`, dim(x)) 27 | 28 | if (cell_ct > .EC_MAX_CELLS) { 29 | stop( 30 | "EtherCalc's behaviour is unstable when posting a data frame with ", 31 | "more than 500,000 total cells. Your data frame has a total of ", 32 | formatC(cell_ct, format="d", big.mark=","), " cells and the sheet ", 33 | "you are appending to may already have cells.", 34 | call.=FALSE 35 | ) 36 | } 37 | 38 | at <- at[1] 39 | 40 | params <- list() 41 | if (at != "end") params[["row"]] <- at 42 | 43 | httr::POST( 44 | url = glue::glue("{ec_host}/_/{room}"), 45 | httr::content_type("text/csv"), 46 | httr::add_headers( 47 | `Accept-Encoding` = "", 48 | `User-Agent` = "" 49 | ), 50 | encode = "raw", 51 | query = params, 52 | body = to_csv_text(x, append = append, col_names = col_names) 53 | ) -> res 54 | 55 | httr::stop_for_status(res) 56 | 57 | out <- httr::content(res) 58 | 59 | if (out == "OK") out <- glue::glue("/{room}") 60 | 61 | out <- glue::glue("{ec_host}{out}") 62 | 63 | invisible(out) 64 | 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /R/ec-cmd.R: -------------------------------------------------------------------------------- 1 | #' Issue EtherCalc "commands" to a room 2 | #' 3 | #' TODO find a cmd ref 4 | #' 5 | #' @param commands character vector of valid EtherCalc commands 6 | #' @param room name of an EtherCalc "room" 7 | #' @param ec_host See [ethercalc_host()] 8 | #' @export 9 | #' @examples \dontrun{ 10 | #' ec_cmd(c("set A1:E1 font normal bold \* \*", "deleterow A12"), "test") 11 | #' } 12 | ec_cmd <- function(commands = "", room, ec_host = ethercalc_host()) { 13 | 14 | room <- room[1] 15 | 16 | httr::POST( 17 | url = glue::glue("{ec_host}/_/{room}"), 18 | encode = "json", 19 | body = list( 20 | "command" = commands 21 | ) 22 | ) -> res 23 | 24 | httr::stop_for_status(res) 25 | 26 | out <- httr::content(res) 27 | 28 | invisible(out) 29 | 30 | } -------------------------------------------------------------------------------- /R/ec-delete.R: -------------------------------------------------------------------------------- 1 | #' Delete a "room" from an EtherCalc instance 2 | #' 3 | #' @param room name of an EtherCalc "room" 4 | #' @param ec_host See [ethercalc_host()] 5 | #' @export 6 | #' @examples \dontrun{ 7 | #' ec_delete("test") 8 | #' } 9 | ec_delete <- function(room, ec_host = ethercalc_host()) { 10 | 11 | ec_host <- sub("/$", "", ec_host[1]) 12 | room <- room[1] 13 | 14 | httr::DELETE( 15 | url = glue::glue("{ec_host}/_/{room}") 16 | ) -> res 17 | 18 | httr::stop_for_status(res) 19 | 20 | out <- httr::content(res, as = "text") 21 | 22 | invisible(out) 23 | 24 | } 25 | -------------------------------------------------------------------------------- /R/ec-edit.R: -------------------------------------------------------------------------------- 1 | #' Edit a data frame in a new or existing EtherCalc "room" 2 | #' 3 | #' @param x a data frame 4 | #' @note You will receive an error if `x` has a total cell count over 500,000. 5 | #' @param room name of an existing EtherCalc "room" or `NULL` to create a new one 6 | #' @param browse if `TRUE` (default) then open up a browser tab/window to the new room 7 | #' @param ... passed on to [write.csv()] 8 | #' @param ec_host See [ethercalc_host()] 9 | #' @family EthercCalc importers/exporters 10 | #' @export 11 | #' @examples \dontrun{ 12 | #' ec_edit(iris, "test") 13 | #' } 14 | ec_edit <- function(x, room = NULL, browse = TRUE, ..., ec_host =ethercalc_host()) { 15 | 16 | stopifnot(is.data.frame(x)) 17 | 18 | cell_ct <- Reduce(`*`, dim(x)) 19 | 20 | if (cell_ct > .EC_MAX_CELLS) { 21 | stop( 22 | "EtherCalc's behaviour is unstable when posting a data frame with ", 23 | "more than 500,000 total cells. Your data frame has a total of ", 24 | formatC(cell_ct, format = "d", big.mark = ","), " cells.", 25 | call.=FALSE 26 | ) 27 | } 28 | 29 | verb <- NULL 30 | 31 | if (is.null(room)) { 32 | 33 | verb <- "POST" 34 | ec_url <- glue::glue("{ec_host}/_") 35 | 36 | } else { 37 | 38 | room <- room[1] 39 | verb <- "PUT" 40 | ec_url <- glue::glue("{ec_host}/_/{room}") 41 | 42 | } 43 | 44 | httr::VERB( 45 | verb = verb, 46 | url = ec_url, 47 | httr::content_type("text/csv"), 48 | httr::add_headers( 49 | `Accept-Encoding` = "", 50 | `User-Agent` = "" 51 | ), 52 | encode = "raw", 53 | body = to_csv_text(x) 54 | ) -> res 55 | 56 | httr::stop_for_status(res) 57 | 58 | out <- httr::content(res) 59 | 60 | if (out == "OK") out <- glue::glue("/{room}") 61 | 62 | out <- glue::glue("{ec_host}{out}") 63 | 64 | if (browse) browseURL(out) 65 | 66 | invisible(out) 67 | 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /R/ec-exists.R: -------------------------------------------------------------------------------- 1 | #' Does an EtherCalc "room" name exist? 2 | #' 3 | #' @param room name of an EtherCalc "room" 4 | #' @param ec_host See [ethercalc_host()] 5 | #' @export 6 | #' @examples \dontrun{ 7 | #' ec_exists("test") 8 | #' } 9 | ec_exists <- function(room, ec_host = ethercalc_host()) { 10 | 11 | room <- room[1] 12 | 13 | httr::GET( 14 | url = glue::glue("{ec_host}/_exists/{room}") 15 | ) -> res 16 | 17 | httr::stop_for_status(res) 18 | 19 | out <- httr::content(res, as = "text") 20 | out <- jsonlite::fromJSON(out) 21 | 22 | out 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /R/ec-export.R: -------------------------------------------------------------------------------- 1 | #' Read an EtherCalc "room" to a local data frame 2 | #' 3 | #' @param room name of an EtherCalc "room" 4 | #' @param ... passed on to [readr::read_csv()] 5 | #' @param ec_host See [ethercalc_host()] 6 | #' @family EthercCalc importers/exporters 7 | #' @export 8 | #' @examples \dontrun{ 9 | #' ec_edit(mtcars, "mtcars") 10 | #' ec_read("mtcars") 11 | #' } 12 | ec_read <- function(room, ..., ec_host = ethercalc_host()) { 13 | 14 | room <- room[1] 15 | 16 | httr::GET( 17 | url = glue::glue("{ec_host}/_/{room}/csv") 18 | ) -> res 19 | 20 | httr::stop_for_status(res) 21 | 22 | out <- httr::content(res, as = "raw") 23 | 24 | out <- readr::read_csv(out, ...) 25 | 26 | out 27 | 28 | } 29 | 30 | #' Export an EtherCalc "room" to a local file 31 | #' 32 | #' @param room name of an EtherCalc "room" 33 | #' @param type EtherCalc supports exporting as CSV, JSON, HTML, markdown, or Excel. 34 | #' Use "`csv`", "`json`", "`html`", "`md`", or "`xlsx`" (respectively). 35 | #' @param path place to save the file. Value will be [path.expand()]ed but you 36 | #' are responsible for naming the file (including extension). 37 | #' @param overwrite overwrite `path` if a file exists? Default: `TRUE`. 38 | #' @param ec_host See [ethercalc_host()] 39 | #' @return a `raw` vector containing the contents of what was written to `path`. 40 | #' @family EthercCalc importers/exporters 41 | #' @export 42 | #' @examples \dontrun{ 43 | #' ec_edit(mtcars, "mtcars") 44 | #' ec_export("mtcars", "csv", "mtcars.csv") 45 | #' ec_export("mtcars", "json", "mtcars.json") 46 | #' ec_export("mtcars", "html", "mtcars.html") 47 | #' ec_export("mtcars", "md", "mtcars.md") 48 | #' ec_export("mtcars", "xlsx", "mtcars.xlsx") 49 | #' } 50 | ec_export <- function(room, type = c("csv", "json", "html", "md", "xlsx"), 51 | path, overwrite = TRUE, ec_host = ethercalc_host()) { 52 | 53 | room <- room[1] 54 | 55 | type <- match.arg(type[1], c("csv", "json", "html", "md", "xlsx")) 56 | 57 | path <- path.expand(path) 58 | 59 | export <- .export_trans[[type]] 60 | 61 | httr::GET( 62 | url = glue::glue("{ec_host}/{room}.{export}"), 63 | httr::write_disk(path, overwrite = overwrite) 64 | ) -> res 65 | 66 | httr::stop_for_status(res) 67 | 68 | invisible(httr::content(res, as = "raw")) 69 | 70 | } 71 | -------------------------------------------------------------------------------- /R/ec-list.R: -------------------------------------------------------------------------------- 1 | #' List all of the available EtherCalc documents 2 | #' 3 | #' Connects to the `ec_host` EtherCalc instance and retrieves 4 | #' a list of all the available documents. Note that documents 5 | #' ending in `_formdata` are for internal API use only and should 6 | #' not be used as "room" names. 7 | #' 8 | #' @param all if `TRUE` then return a list of all "rooms" including the 9 | #' internal-use only `_formdata` rooms. 10 | #' @param ec_host See [ethercalc_host()] 11 | #' @export 12 | #' @examples \dontrun{ 13 | #' ec_list() 14 | #' } 15 | ec_list <- function(all = FALSE, ec_host = ethercalc_host()) { 16 | 17 | httr::GET( 18 | url = glue::glue("{ec_host}/_rooms") 19 | ) -> res 20 | 21 | httr::stop_for_status(res) 22 | 23 | out <- httr::content(res, as = "text") 24 | out <- jsonlite::fromJSON(out) 25 | 26 | if (all) return(out) 27 | 28 | grep("_formdata", out, value = TRUE, invert = TRUE) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /R/ec-new.R: -------------------------------------------------------------------------------- 1 | #' Create a new, empty EtherCalc "room" 2 | #' 3 | #' @param room name of an EtherCalc "room" 4 | #' @param browse if `TRUE` (default) then open up a browser tab/window to the new room 5 | #' @param ec_host See [ethercalc_host()] 6 | #' @return the full URL to the newly created room (invisibly) 7 | #' @export 8 | #' @examples \dontrun{ 9 | #' ec_new("test") 10 | #' } 11 | ec_new <- function(room, browse = TRUE, ec_host = ethercalc_host()) { 12 | 13 | room <- room[1] 14 | 15 | if (browse) ec_view(room = room, ec_host = ec_host) 16 | 17 | invisible(glue::glue("{ec_host}/{room}")) 18 | 19 | } 20 | 21 | #' Open a browser window/tab to an EtherCalc "room" 22 | #' 23 | #' @param room name of an EtherCalc "room" 24 | #' @param ec_host See [ethercalc_host()] 25 | #' @export 26 | ec_view <- function(room, ec_host = ethercalc_host()) { 27 | 28 | room <- room[1] 29 | 30 | browseURL(glue::glue("{ec_host}/{room}")) 31 | 32 | } 33 | -------------------------------------------------------------------------------- /R/ec-running.R: -------------------------------------------------------------------------------- 1 | #' Export an EtherCalc "room" to a local data frame 2 | #' 3 | #' @param timeout how long to wait (useful if accessing a remote ethercalc) 4 | #' @param ec_host See [ethercalc_host()] 5 | #' @export 6 | #' @examples \dontrun{ 7 | #' ec_running() 8 | #' } 9 | ec_running <- function(timeout = 1, ec_host = ethercalc_host()) { 10 | 11 | res <- try(httr::GET(ec_host, httr::timeout(timeout)), silent = TRUE) 12 | if (inherits(res, "try-error")) { 13 | message("ethercalc is not running.") 14 | return(invisible(FALSE)) 15 | } else { 16 | pg <- httr::content(res) 17 | title_node <- xml2::xml_find_first(pg, ".//title") 18 | title_text <- xml2::xml_text(title_node) 19 | out <- any(grepl("ethercalc", title_text, ignore.case=TRUE)) 20 | if (out) message("ethercalc is running.") else message("ethercalc is not running.") 21 | return(invisible(out)) 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /R/ec-start.R: -------------------------------------------------------------------------------- 1 | #' Start an EtherCalc instance (requires you to install EtherCalc first) 2 | #' 3 | #' If you have a working Node.js installation and have performed an "`npm i -g ethercalc`" 4 | #' this function will look for the `ethercalc` executable and run start it in the background. 5 | #' You should save the return value since that will allow you to stop the instance (the 6 | #' instance will stop when the R session is termianted). You can 7 | #' also add arguments to the call via the `args` parameter. 8 | #' 9 | #' You _really_ should consider installing and running a local copy of `redis` to get 10 | #' an efficient, persistent store for your spreadsheets. 11 | #' 12 | #' @param host,port interface and port for `ethercalc` to bind to. Defaults 13 | #' to `localhost` and `8000`. 14 | #' @param args optional arguments to pass in to the `ethercalc` executable 15 | #' @return a `processx` `process` object 16 | #' @export 17 | #' @examples \dontrun{ 18 | #' ec_start() 19 | #' } 20 | ec_start <- function(host = "localhost", port = 8000, args = NULL) { 21 | 22 | ec_cmd <- Sys.which("ethercalc") 23 | if (ec_cmd == "") { 24 | 25 | advice <- "" 26 | if (Sys.which("npm") == "") { 27 | advice <- paste0(c( 28 | "'npm'/Node.js not found.", 29 | "Please install Node.js (https://nodejs.org/) and ", 30 | "'npm' (https://www.npmjs.com/) for your platform, then run 'npm i -g ethercalc'." 31 | ), collapse = " ") 32 | } else { 33 | advice <- "Please run 'npm i -g ethercalc' to install EtherCalc." 34 | } 35 | 36 | stop( 37 | "'ethercalc' executable not found.\n", advice, call.=FALSE 38 | ) 39 | 40 | } 41 | 42 | processx::process$new( 43 | command = ec_cmd, 44 | args = c("--host", host, "--port", port, args), 45 | supervise = TRUE 46 | ) 47 | 48 | } -------------------------------------------------------------------------------- /R/ethercalc-host.R: -------------------------------------------------------------------------------- 1 | #' Get or set ETHERCALC_HOST value 2 | #' 3 | #' The API wrapper functions in this package all rely on using EtherCalc instance 4 | #' info residing in the environment variable `ETHERCALC_HOST`. The 5 | #' easiest way to accomplish this is to set it in the `.Renviron` file in your 6 | #' home directory. 7 | #' 8 | #' @md 9 | #' @param force Force setting a new EtherCalc ETHERCALC_HOST info for the current environment? 10 | #' @return atomic character vector containing the EtherCalc ETHERCALC_HOST value 11 | #' @export 12 | #' @examples \dontrun{ 13 | #' ethercalc_host("http://localhost:8000") 14 | #' } 15 | ethercalc_host <- function(force = FALSE) { 16 | 17 | env <- sub("/$", "", Sys.getenv("ETHERCALC_HOST")) 18 | 19 | if (!identical(env, "") && !force) return(env) 20 | 21 | if (!interactive()) { 22 | stop( 23 | "Please set env var ETHERCALC_HOST to the URL prefix of your EtherCalc instance", 24 | call. = FALSE 25 | ) 26 | } 27 | 28 | message( 29 | "Couldn't find env var ETHERCALC_HOST See ?ethercalc_host for more details.\n", 30 | "Please enter your URL prefix of your EtherCalc instance and press enter:" 31 | ) 32 | 33 | val <- readline(": ") 34 | 35 | if (identical(val, "")) { 36 | stop("URL prefix of your EtherCalc instance entry failed", call. = FALSE) 37 | } 38 | 39 | message("Updating ETHERCALC_HOST env var...") 40 | 41 | Sys.setenv(ETHERCALC_HOST = sub("/$", "", val)) 42 | 43 | val 44 | 45 | } -------------------------------------------------------------------------------- /R/ethercalc-package.R: -------------------------------------------------------------------------------- 1 | #' Orchestrate and Exchange Data with 'EtherCalc' Instances 2 | #' 3 | #' The 'EtherCalc' () web application is a multi-user, 4 | #' collaborative spreadsheet that can be run locally on virtually any modern operating system. 5 | #' Methods are provided to orchestrate and exchange data with 'EtherCalc' instances. 6 | #' 7 | #' \if{html}{ 8 | #' \figure{ethercalc-hero.png}{options: width="100\%" alt="Figure: EtherCalc"} 9 | #' } 10 | #' 11 | #' @md 12 | #' @name ethercalc 13 | #' @keywords internal 14 | #' @author Bob Rudis (bob@@rud.is) 15 | #' @import httr processx 16 | #' @importFrom glue glue 17 | #' @importFrom utils browseURL 18 | #' @importFrom jsonlite fromJSON 19 | #' @importFrom readr read_csv write_csv 20 | #' @importFrom xml2 xml_find_first xml_text 21 | "_PACKAGE" 22 | -------------------------------------------------------------------------------- /R/to-csv-text.R: -------------------------------------------------------------------------------- 1 | to_csv_text <- function(xdf, ...) { 2 | 3 | r <- rawConnection(raw(0), "r+") 4 | on.exit(close(r), add=TRUE) 5 | 6 | readr::write_csv( 7 | x = xdf, 8 | path = r, 9 | ... 10 | ) -> res 11 | 12 | invisible(rawConnectionValue(r)) 13 | 14 | } -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: rmarkdown::github_document 3 | editor_options: 4 | chunk_output_type: inline 5 | --- 6 | ```{r pkg-knitr-opts, include=FALSE} 7 | knitr::opts_chunk$set(collapse=TRUE, fig.retina=2, message=FALSE, warning=FALSE) 8 | options(width=120) 9 | ``` 10 | 11 | [![Travis-CI Build Status](https://travis-ci.org/hrbrmstr/ethercalc.svg?branch=master)](https://travis-ci.org/hrbrmstr/ethercalc) 12 | [![Coverage Status](https://codecov.io/gh/hrbrmstr/ethercalc/branch/master/graph/badge.svg)](https://codecov.io/gh/hrbrmstr/ethercalc) 13 | [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/ethercalc)](https://cran.r-project.org/package=ethercalc) 14 | 15 | # ethercalc 16 | 17 | Orchestrate and Exchange Data with 'EtherCalc' Instances 18 | 19 | ## Description 20 | 21 | The 'EtherCalc' () web application is a multi-user, 22 | collaborative spreadsheet that can be run locally on virtually any modern operating system. Methods are provided to orchestrate and exchange data with 'EtherCalc' instances. 23 | 24 | ![](man/figures/ethercalc-example.gif) 25 | 26 | ## What's Inside The Tin 27 | 28 | The following functions are implemented: 29 | 30 | 31 | - `ec_append`: Append a data frame to a "room", optionally starting at a given row 32 | - `ec_cmd`: Issue EtherCalc "commands" to a room 33 | - `ec_delete`: Delete a "room" from an EtherCalc instance 34 | - `ec_edit`: Edit a data frame in a new or existing EtherCalc "room" 35 | - `ec_exists`: Does an EtherCalc "room" name exist? 36 | - `ec_export`: Export an EtherCalc "room" to a local file 37 | - `ec_list`: List all of the available EtherCalc documents 38 | - `ec_new`: Create a new, empty EtherCalc "room" 39 | - `ec_read`: Read an EtherCalc "room" to a local data frame 40 | - `ec_running`: Export an EtherCalc "room" to a local data frame 41 | - `ec_start`: Start an EtherCalc instance (requires you to install EtherCalc first) 42 | - `ec_view`: Open a browser window/tab to an EtherCalc "room" 43 | - `ethercalc_host`: Get or set ETHERCALC_HOST value 44 | 45 | ## Installation 46 | 47 | ```{r install-ex, eval=FALSE} 48 | devtools::install_git("https://git.sr.ht/~hrbrmstr/ethercalc.git") 49 | # or 50 | devtools::install_git("https://git.rud.is/hrbrmstr/ethercalc.git") 51 | # or 52 | devtools::install_gitlab("hrbrmstr/ethercalc") 53 | # or 54 | devtools::install_bitbucket("hrbrmstr/ethercalc") 55 | # or 56 | devtools::install_github("hrbrmstr/ethercalc") 57 | ``` 58 | 59 | ## Usage 60 | 61 | ```{r lib-ex} 62 | library(ethercalc) 63 | 64 | # current version 65 | packageVersion("ethercalc") 66 | 67 | ``` 68 | 69 | ## ethercalc Metrics 70 | 71 | ```{r cloc, echo=FALSE} 72 | cloc::cloc_pkg_md() 73 | ``` 74 | 75 | ## Code of Conduct 76 | 77 | Please note that this project is released with a [Contributor Code of Conduct](CONDUCT.md). 78 | By participating in this project you agree to abide by its terms. 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Travis-CI Build 3 | Status](https://travis-ci.org/hrbrmstr/ethercalc.svg?branch=master)](https://travis-ci.org/hrbrmstr/ethercalc) 4 | [![Coverage 5 | Status](https://codecov.io/gh/hrbrmstr/ethercalc/branch/master/graph/badge.svg)](https://codecov.io/gh/hrbrmstr/ethercalc) 6 | [![CRAN\_Status\_Badge](https://www.r-pkg.org/badges/version/ethercalc)](https://cran.r-project.org/package=ethercalc) 7 | 8 | # ethercalc 9 | 10 | Orchestrate and Exchange Data with ‘EtherCalc’ Instances 11 | 12 | ## Description 13 | 14 | The ‘EtherCalc’ () web application is a 15 | multi-user, collaborative spreadsheet that can be run locally on 16 | virtually any modern operating system. Methods are provided to 17 | orchestrate and exchange data with ‘EtherCalc’ instances. 18 | 19 | ![](man/figures/ethercalc-example.gif) 20 | 21 | ## What’s Inside The Tin 22 | 23 | The following functions are implemented: 24 | 25 | - `ec_append`: Append a data frame to a “room”, optionally starting at 26 | a given row 27 | - `ec_cmd`: Issue EtherCalc “commands” to a room 28 | - `ec_delete`: Delete a “room” from an EtherCalc instance 29 | - `ec_edit`: Edit a data frame in a new or existing EtherCalc “room” 30 | - `ec_exists`: Does an EtherCalc “room” name exist? 31 | - `ec_export`: Export an EtherCalc “room” to a local file 32 | - `ec_list`: List all of the available EtherCalc documents 33 | - `ec_new`: Create a new, empty EtherCalc “room” 34 | - `ec_read`: Read an EtherCalc “room” to a local data frame 35 | - `ec_running`: Export an EtherCalc “room” to a local data frame 36 | - `ec_start`: Start an EtherCalc instance (requires you to install 37 | EtherCalc first) 38 | - `ec_view`: Open a browser window/tab to an EtherCalc “room” 39 | - `ethercalc_host`: Get or set ETHERCALC\_HOST value 40 | 41 | ## Installation 42 | 43 | ``` r 44 | devtools::install_git("https://git.sr.ht/~hrbrmstr/ethercalc.git") 45 | # or 46 | devtools::install_git("https://git.rud.is/hrbrmstr/ethercalc.git") 47 | # or 48 | devtools::install_gitlab("hrbrmstr/ethercalc") 49 | # or 50 | devtools::install_bitbucket("hrbrmstr/ethercalc") 51 | # or 52 | devtools::install_github("hrbrmstr/ethercalc") 53 | ``` 54 | 55 | ## Usage 56 | 57 | ``` r 58 | library(ethercalc) 59 | 60 | # current version 61 | packageVersion("ethercalc") 62 | ## [1] '0.1.0' 63 | ``` 64 | 65 | ## ethercalc Metrics 66 | 67 | | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | 68 | | :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | 69 | | R | 17 | 0.94 | 229 | 0.96 | 108 | 0.84 | 174 | 0.78 | 70 | | Rmd | 1 | 0.06 | 10 | 0.04 | 20 | 0.16 | 48 | 0.22 | 71 | 72 | ## Code of Conduct 73 | 74 | Please note that this project is released with a [Contributor Code of 75 | Conduct](CONDUCT.md). By participating in this project you agree to 76 | abide by its terms. 77 | -------------------------------------------------------------------------------- /ethercalc.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | StripTrailingWhitespace: Yes 16 | 17 | BuildType: Package 18 | PackageUseDevtools: Yes 19 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageBuildArgs: --resave-data 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /man/ec_append.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-append.R 3 | \name{ec_append} 4 | \alias{ec_append} 5 | \title{Append a data frame to a "room", optionally starting at a given row} 6 | \usage{ 7 | ec_append(x, room, at = "end", append = TRUE, col_names = FALSE, 8 | browse = FALSE, ..., ec_host = ethercalc_host()) 9 | } 10 | \arguments{ 11 | \item{x}{a data frame} 12 | 13 | \item{room}{name of an existing EtherCalc "room".} 14 | 15 | \item{at}{if not "\code{end}" then the row where the data will be inserted and pasted at.} 16 | 17 | \item{append, col_names}{see \code{\link[readr:write_csv]{readr::write_csv()}} and this function's Note} 18 | 19 | \item{browse}{if \code{TRUE} (\code{FALSE} is the default) then open up a browser tab/window to 20 | the room} 21 | 22 | \item{...}{passed on to \code{\link[=write.csv]{write.csv()}}} 23 | 24 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 25 | } 26 | \value{ 27 | the commands used by EtherCalc to process the append operation (invisibly) 28 | } 29 | \description{ 30 | Append a data frame to a "room", optionally starting at a given row 31 | } 32 | \note{ 33 | Since this is an append operation the header will not be sent. Set 34 | \code{col_names} and \code{append} (both) to \code{TRUE} 35 | 36 | You will receive an error if \code{x} has a total cell count over 500,000. 37 | } 38 | \examples{ 39 | \dontrun{ 40 | ec_edit(iris, "test") 41 | ec_append(iris, "test") 42 | } 43 | } 44 | \seealso{ 45 | Other EthercCalc importers/exporters: \code{\link{ec_edit}}, 46 | \code{\link{ec_export}}, \code{\link{ec_read}} 47 | } 48 | \concept{EthercCalc importers/exporters} 49 | -------------------------------------------------------------------------------- /man/ec_cmd.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-cmd.R 3 | \name{ec_cmd} 4 | \alias{ec_cmd} 5 | \title{Issue EtherCalc "commands" to a room} 6 | \usage{ 7 | ec_cmd(commands = "", room, ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{commands}{character vector of valid EtherCalc commands} 11 | 12 | \item{room}{name of an EtherCalc "room"} 13 | 14 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 15 | } 16 | \description{ 17 | TODO find a cmd ref 18 | } 19 | \examples{ 20 | \dontrun{ 21 | ec_cmd(c("set A1:E1 font normal bold \\* \\*", "deleterow A12"), "test") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /man/ec_delete.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-delete.R 3 | \name{ec_delete} 4 | \alias{ec_delete} 5 | \title{Delete a "room" from an EtherCalc instance} 6 | \usage{ 7 | ec_delete(room, ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{room}{name of an EtherCalc "room"} 11 | 12 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 13 | } 14 | \description{ 15 | Delete a "room" from an EtherCalc instance 16 | } 17 | \examples{ 18 | \dontrun{ 19 | ec_delete("test") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /man/ec_edit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-edit.R 3 | \name{ec_edit} 4 | \alias{ec_edit} 5 | \title{Edit a data frame in a new or existing EtherCalc "room"} 6 | \usage{ 7 | ec_edit(x, room = NULL, browse = TRUE, ..., 8 | ec_host = ethercalc_host()) 9 | } 10 | \arguments{ 11 | \item{x}{a data frame} 12 | 13 | \item{room}{name of an existing EtherCalc "room" or \code{NULL} to create a new one} 14 | 15 | \item{browse}{if \code{TRUE} (default) then open up a browser tab/window to the new room} 16 | 17 | \item{...}{passed on to \code{\link[=write.csv]{write.csv()}}} 18 | 19 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 20 | } 21 | \description{ 22 | Edit a data frame in a new or existing EtherCalc "room" 23 | } 24 | \note{ 25 | You will receive an error if \code{x} has a total cell count over 500,000. 26 | } 27 | \examples{ 28 | \dontrun{ 29 | ec_edit(iris, "test") 30 | } 31 | } 32 | \seealso{ 33 | Other EthercCalc importers/exporters: \code{\link{ec_append}}, 34 | \code{\link{ec_export}}, \code{\link{ec_read}} 35 | } 36 | \concept{EthercCalc importers/exporters} 37 | -------------------------------------------------------------------------------- /man/ec_exists.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-exists.R 3 | \name{ec_exists} 4 | \alias{ec_exists} 5 | \title{Does an EtherCalc "room" name exist?} 6 | \usage{ 7 | ec_exists(room, ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{room}{name of an EtherCalc "room"} 11 | 12 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 13 | } 14 | \description{ 15 | Does an EtherCalc "room" name exist? 16 | } 17 | \examples{ 18 | \dontrun{ 19 | ec_exists("test") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /man/ec_export.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-export.R 3 | \name{ec_export} 4 | \alias{ec_export} 5 | \title{Export an EtherCalc "room" to a local file} 6 | \usage{ 7 | ec_export(room, type = c("csv", "json", "html", "md", "xlsx"), path, 8 | overwrite = TRUE, ec_host = ethercalc_host()) 9 | } 10 | \arguments{ 11 | \item{room}{name of an EtherCalc "room"} 12 | 13 | \item{type}{EtherCalc supports exporting as CSV, JSON, HTML, markdown, or Excel. 14 | Use "\code{csv}", "\code{json}", "\code{html}", "\code{md}", or "\code{xlsx}" (respectively).} 15 | 16 | \item{path}{place to save the file. Value will be \code{\link[=path.expand]{path.expand()}}ed but you 17 | are responsible for naming the file (including extension).} 18 | 19 | \item{overwrite}{overwrite \code{path} if a file exists? Default: \code{TRUE}.} 20 | 21 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 22 | } 23 | \value{ 24 | a \code{raw} vector containing the contents of what was written to \code{path}. 25 | } 26 | \description{ 27 | Export an EtherCalc "room" to a local file 28 | } 29 | \examples{ 30 | \dontrun{ 31 | ec_edit(mtcars, "mtcars") 32 | ec_export("mtcars", "csv", "mtcars.csv") 33 | ec_export("mtcars", "json", "mtcars.json") 34 | ec_export("mtcars", "html", "mtcars.html") 35 | ec_export("mtcars", "md", "mtcars.md") 36 | ec_export("mtcars", "xlsx", "mtcars.xlsx") 37 | } 38 | } 39 | \seealso{ 40 | Other EthercCalc importers/exporters: \code{\link{ec_append}}, 41 | \code{\link{ec_edit}}, \code{\link{ec_read}} 42 | } 43 | \concept{EthercCalc importers/exporters} 44 | -------------------------------------------------------------------------------- /man/ec_list.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-list.R 3 | \name{ec_list} 4 | \alias{ec_list} 5 | \title{List all of the available EtherCalc documents} 6 | \usage{ 7 | ec_list(all = FALSE, ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{all}{if \code{TRUE} then return a list of all "rooms" including the 11 | internal-use only \code{_formdata} rooms.} 12 | 13 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 14 | } 15 | \description{ 16 | Connects to the \code{ec_host} EtherCalc instance and retrieves 17 | a list of all the available documents. Note that documents 18 | ending in \code{_formdata} are for internal API use only and should 19 | not be used as "room" names. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | ec_list() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /man/ec_new.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-new.R 3 | \name{ec_new} 4 | \alias{ec_new} 5 | \title{Create a new, empty EtherCalc "room"} 6 | \usage{ 7 | ec_new(room, browse = TRUE, ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{room}{name of an EtherCalc "room"} 11 | 12 | \item{browse}{if \code{TRUE} (default) then open up a browser tab/window to the new room} 13 | 14 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 15 | } 16 | \value{ 17 | the full URL to the newly created room (invisibly) 18 | } 19 | \description{ 20 | Create a new, empty EtherCalc "room" 21 | } 22 | \examples{ 23 | \dontrun{ 24 | ec_new("test") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /man/ec_read.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-export.R 3 | \name{ec_read} 4 | \alias{ec_read} 5 | \title{Read an EtherCalc "room" to a local data frame} 6 | \usage{ 7 | ec_read(room, ..., ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{room}{name of an EtherCalc "room"} 11 | 12 | \item{...}{passed on to \code{\link[readr:read_csv]{readr::read_csv()}}} 13 | 14 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 15 | } 16 | \description{ 17 | Read an EtherCalc "room" to a local data frame 18 | } 19 | \examples{ 20 | \dontrun{ 21 | ec_edit(mtcars, "mtcars") 22 | ec_read("mtcars") 23 | } 24 | } 25 | \seealso{ 26 | Other EthercCalc importers/exporters: \code{\link{ec_append}}, 27 | \code{\link{ec_edit}}, \code{\link{ec_export}} 28 | } 29 | \concept{EthercCalc importers/exporters} 30 | -------------------------------------------------------------------------------- /man/ec_running.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-running.R 3 | \name{ec_running} 4 | \alias{ec_running} 5 | \title{Export an EtherCalc "room" to a local data frame} 6 | \usage{ 7 | ec_running(timeout = 1, ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{timeout}{how long to wait (useful if accessing a remote ethercalc)} 11 | 12 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 13 | } 14 | \description{ 15 | Export an EtherCalc "room" to a local data frame 16 | } 17 | \examples{ 18 | \dontrun{ 19 | ec_running() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /man/ec_start.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-start.R 3 | \name{ec_start} 4 | \alias{ec_start} 5 | \title{Start an EtherCalc instance (requires you to install EtherCalc first)} 6 | \usage{ 7 | ec_start(host = "localhost", port = 8000, args = NULL) 8 | } 9 | \arguments{ 10 | \item{host, port}{interface and port for \code{ethercalc} to bind to. Defaults 11 | to \code{localhost} and \code{8000}.} 12 | 13 | \item{args}{optional arguments to pass in to the \code{ethercalc} executable} 14 | } 15 | \value{ 16 | a \code{processx} \code{process} object 17 | } 18 | \description{ 19 | If you have a working Node.js installation and have performed an "\code{npm i -g ethercalc}" 20 | this function will look for the \code{ethercalc} executable and run start it in the background. 21 | You should save the return value since that will allow you to stop the instance (the 22 | instance will stop when the R session is termianted). You can 23 | also add arguments to the call via the \code{args} parameter. 24 | } 25 | \details{ 26 | You \emph{really} should consider installing and running a local copy of \code{redis} to get 27 | an efficient, persistent store for your spreadsheets. 28 | } 29 | \examples{ 30 | \dontrun{ 31 | ec_start() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /man/ec_view.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ec-new.R 3 | \name{ec_view} 4 | \alias{ec_view} 5 | \title{Open a browser window/tab to an EtherCalc "room"} 6 | \usage{ 7 | ec_view(room, ec_host = ethercalc_host()) 8 | } 9 | \arguments{ 10 | \item{room}{name of an EtherCalc "room"} 11 | 12 | \item{ec_host}{See \code{\link[=ethercalc_host]{ethercalc_host()}}} 13 | } 14 | \description{ 15 | Open a browser window/tab to an EtherCalc "room" 16 | } 17 | -------------------------------------------------------------------------------- /man/ethercalc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ethercalc-package.R 3 | \docType{package} 4 | \name{ethercalc} 5 | \alias{ethercalc} 6 | \alias{ethercalc-package} 7 | \title{Orchestrate and Exchange Data with 'EtherCalc' Instances} 8 | \description{ 9 | The 'EtherCalc' (\url{https://ethercalc.net/}) web application is a multi-user, 10 | collaborative spreadsheet that can be run locally on virtually any modern operating system. 11 | Methods are provided to orchestrate and exchange data with 'EtherCalc' instances. 12 | } 13 | \details{ 14 | \if{html}{ 15 | \figure{ethercalc-hero.png}{options: width="100\%" alt="Figure: EtherCalc"} 16 | } 17 | } 18 | \seealso{ 19 | Useful links: 20 | \itemize{ 21 | \item \url{https://gitlab.com/hrbrmstr/ethercalc} 22 | \item Report bugs at \url{https://gitlab.com/hrbrmstr/ethercalc/issues} 23 | } 24 | 25 | } 26 | \author{ 27 | Bob Rudis (bob@rud.is) 28 | } 29 | \keyword{internal} 30 | -------------------------------------------------------------------------------- /man/ethercalc_host.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ethercalc-host.R 3 | \name{ethercalc_host} 4 | \alias{ethercalc_host} 5 | \title{Get or set ETHERCALC_HOST value} 6 | \usage{ 7 | ethercalc_host(force = FALSE) 8 | } 9 | \arguments{ 10 | \item{force}{Force setting a new EtherCalc ETHERCALC_HOST info for the current environment?} 11 | } 12 | \value{ 13 | atomic character vector containing the EtherCalc ETHERCALC_HOST value 14 | } 15 | \description{ 16 | The API wrapper functions in this package all rely on using EtherCalc instance 17 | info residing in the environment variable \code{ETHERCALC_HOST}. The 18 | easiest way to accomplish this is to set it in the \code{.Renviron} file in your 19 | home directory. 20 | } 21 | \examples{ 22 | \dontrun{ 23 | ethercalc_host("http://localhost:8000") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /man/figures/ethercalc-example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/ethercalc/a99f5605548cc55468db5d5a0aab21a27671e74a/man/figures/ethercalc-example.gif -------------------------------------------------------------------------------- /man/figures/ethercalc-hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/ethercalc/a99f5605548cc55468db5d5a0aab21a27671e74a/man/figures/ethercalc-hero.png -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /tests/test-all.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | test_check("ethercalc") 3 | -------------------------------------------------------------------------------- /tests/testthat/test-ethercalc.R: -------------------------------------------------------------------------------- 1 | context("minimal package functionality") 2 | test_that("we can do something", { 3 | 4 | #expect_that(some_function(), is_a("data.frame")) 5 | 6 | }) 7 | --------------------------------------------------------------------------------