I hope it's ok for me to post this in this issue tracker.
I spent the last couple days writing a graphics device driver for R that is accessible via HTTP.
The main use case would be IDE integration for VSCode and other editors.
It basically collects draw calls in a kind of "virtual DOM" and runs a http server in a background thread. On http request the DOM is rendered to SVG and sent to the client.
This already works surprisingly well.
The code is very experimental, I am not a very experienced C++ programmer and am not too familiar with the R/C++ API.
https://github.com/nx10/httpgd
What do you think of this? Any advice and suggestions from you are very welcome! The project is basically a "proof of concept" right now.
Automatic detection of redraw and window resize are implemented (window resize has some limitations).
Thanks for sharing your work on web-based R graphics device!
I try to install the package but it ends up with the following error:
> devtools::install_github("nx10/httpgd")
Downloading GitHub repo nx10/httpgd@master
checking for file ‘/private/var/folders/8n/fdyp8ztd42gd2s61p6nzqrgh0000gn/T/RtmpZSorca/remotes71a77858b6e0/nx10-httpgd-4b0d85b/DESCRIPTIO✔ checking for file ‘/private/var/folders/8n/fdyp8ztd42gd2s61p6nzqrgh0000gn/T/RtmpZSorca/remotes71a77858b6e0/nx10-httpgd-4b0d85b/DESCRIPTION’
─ preparing ‘httpgd’:
✔ checking DESCRIPTION meta-information ...
─ cleaning src
─ checking for LF line-endings in source and make files and shell scripts
─ checking for empty or unneeded directories
─ building ‘httpgd_1.0.tar.gz’
clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/RcppThread/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/gdtools/include' -I/usr/local/include -fPIC -Wall -g -O2 -c RcppExports.cpp -o RcppExports.o
clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/RcppThread/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/gdtools/include' -I/usr/local/include -fPIC -Wall -g -O2 -c drawdata.cpp -o drawdata.o
Error: Failed to install 'httpgd' from GitHub:
(converted from warning) installation of package '/var/folders/8n/fdyp8ztd42gd2s61p6nzqrgh0000gn/T//RtmpZSorca/file71a784e69da/httpgd_1.0.tar.gz' had non-zero exit status
Backtrace:
1: stop(remote_install_error(remotes[[i]], e))
2: value[[3L]](cond)
3: tryCatchOne(expr, names, parentenv, handlers[[1L]])
4: tryCatchList(expr, classes, parentenv, handlers)
5: tryCatch(res[[i]] <- install_remote(remotes[[i]], ...), error = function(e) {
6: install_remotes(remotes, auth_token = auth_token, host = host,
7: pkgbuild::with_build_tools({
8: devtools::install_github("nx10/httpgd")
Not sure if it is supposed to work on macOS and R 4.0?
My session info
R version 4.0.0 (2020-04-24)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.4
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods
[7] base
loaded via a namespace (and not attached):
[1] compiler_4.0.0 jsonlite_1.6.1
Thank you for your response!
I am unsure what causes this error. I only tested on my machine (Windows, R 4.0).
You might be missing a dependancy. Try installing gdtools and RcppThread from CRAN beforehand.
Edit: I just remembered I do have platform specific code that starts the webserver. Sorry for the inconveniences I will fix it soon and come back to you.
I tried installing the package on Ubuntu and the following error occurs:
✔ checking for file ‘/tmp/RtmpdDwdMP/file1ddef42d21cc0/DESCRIPTION’ ...
─ preparing ‘httpgd’:
✔ checking DESCRIPTION meta-information ...
─ cleaning src
─ checking for LF line-endings in source and make files and shell scripts
─ checking for empty or unneeded directories
─ building ‘httpgd_1.0.tar.gz’
Installing package into '/home/renkun/R/x86_64-pc-linux-gnu-library/4.0'
(as 'lib' is unspecified)
* installing *source* package 'httpgd' ...
** using staged installation
** libs
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/RcppThread/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c RcppExports.cpp -o RcppExports.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/RcppThread/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c drawdata.cpp -o drawdata.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/RcppThread/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c dummygd.cpp -o dummygd.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/RcppThread/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c httpgd.cpp -o httpgd.o
httpgd.cpp:5:10: fatal error: winsock2.h: No such file or directory
5 | #include <winsock2.h>
| ^~~~~~~~~~~~
compilation terminated.
make: *** [/usr/lib/R/etc/Makeconf:176: httpgd.o] Error 1
make: *** Waiting for unfinished jobs....
ERROR: compilation failed for package 'httpgd'
* removing '/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/httpgd'
Error: Failed to install 'unknown package' from Git:
(converted from warning) installation of package '/tmp/RtmpdDwdMP/file1ddef20234d71/httpgd_1.0.tar.gz' had non-zero exit status
Backtrace:
1: stop(remote_install_error(remotes[[i]], e))
2: value[[3L]](cond)
3: tryCatchOne(expr, names, parentenv, handlers[[1L]])
4: tryCatchList(expr, classes, parentenv, handlers)
5: tryCatch(res[[i]] <- install_remote(remotes[[i]], ...), error = function(e) {
6: install_remotes(remotes, credentials = credentials, dependencies = dependencies,
7: pkgbuild::with_build_tools({
8: devtools::install_git("https://github.com/nx10/httpgd.git")
Obviously, Windows header <winsock2.h> is used but unfortunately I don't have a Windows to try it.
I just pushed changes that enables it to successfully compile and run under linux (Ubuntu). It should also work with macOS but I do not have a suitable machine for testing.
I tried it on Ubuntu and it works! But no luck for macOS:
Downloading git repo https://github.com/nx10/httpgd.git
checking for file ‘/private/var/folders/8n/fdyp8ztd42gd2s61p6nzqrgh0000gn/T/RtmpJ✔ checking for file ‘/private/var/folders/8n/fdyp8ztd42gd2s61p6nzqrgh0000gn/T/RtmpJjEgoI/file7c6e3a1de62a/DESCRIPTION’
─ preparing ‘httpgd’:
✔ checking DESCRIPTION meta-information ...
─ cleaning src
─ checking for LF line-endings in source and make files and shell scripts
─ checking for empty or unneeded directories
─ building ‘httpgd_1.0.tar.gz’
clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/RcppThread/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/gdtools/include' -I/usr/local/include -fPIC -Wall -g -O2 -c RcppExports.cpp -o RcppExports.o
clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/RcppThread/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/gdtools/include' -I/usr/local/include -fPIC -Wall -g -O2 -c drawdata.cpp -o drawdata.o
Error: Failed to install 'unknown package' from Git:
(converted from warning) installation of package '/var/folders/8n/fdyp8ztd42gd2s61p6nzqrgh0000gn/T//RtmpJjEgoI/file7c6e37b75c5e/httpgd_1.0.tar.gz' had non-zero exit status
Backtrace:
1: stop(remote_install_error(remotes[[i]], e))
2: value[[3L]](cond)
3: tryCatchOne(expr, names, parentenv, handlers[[1L]])
4: tryCatchList(expr, classes, parentenv, handlers)
5: tryCatch(res[[i]] <- install_remote(remotes[[i]], ...), error = function(e) {
6: install_remotes(remotes, credentials = credentials, dependencies = dependencies,
7: pkgbuild::with_build_tools({
8: devtools::install_git("https://github.com/nx10/httpgd.git")
I just modified the DESCRIPTION file, can you try again to make sure its not caused by some caching?
I also cleaned up the project so that R CMD check gives me 0 warnings and 0 notes (yay) so maybe I fixed it while doing that.
I didn't clone the repo and install it from github (no cache issue) but it still does not compile on macOS. Maybe I'll clone the repo and take a closer look.
I was able to borrow a mac book and found the source of your problem with running the graphics device under mac OS:
It seems like a recent mac OS update (Catalina) removed shared libraries used by the package systemfonts (see: https://github.com/r-lib/systemfonts/issues/17).
You can install XQuartz as a workaround (https://www.xquartz.org/).
I have worked a lot on the graphics server in the last couple of days.
Automatic resizing, plot history and concurrently running multiple servers is now possible.
What next steps should I take for it to be considered for including it in vscode-R?
Should I work on a CRAN release? Are there API changes you want to see?
Thanks for the hard work!
I cannot install it on Ubuntu like the following:
Downloading git repo https://github.com/nx10/httpgd.git
✔ checking for file ‘/tmp/RtmpIBNuxG/file876ef25ef3176/DESCRIPTION’ ...
─ preparing ‘httpgd’:
✔ checking DESCRIPTION meta-information ...
─ cleaning src
Warning in system2(command, args, stdout = NULL, stderr = NULL, ...) :
error in running command
─ checking for LF line-endings in source and make files and shell scripts
─ checking for empty or unneeded directories
─ building ‘httpgd_0.3.1.tar.gz’
Installing package into '/home/renkun/R/x86_64-pc-linux-gnu-library/4.0'
(as 'lib' is unspecified)
* installing *source* package 'httpgd' ...
** using staged installation
** libs
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c FontAnalyzer.cpp -o FontAnalyzer.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c HttpgdDev.cpp -o HttpgdDev.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c HttpgdServer.cpp -o HttpgdServer.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c PlotHistory.cpp -o PlotHistory.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c RcppExports.cpp -o RcppExports.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c drawdata.cpp -o drawdata.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c dummygd.cpp -o dummygd.o
g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/later/include' -I'/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/gdtools/include' -fpic -g -O2 -fdebug-prefix-map=/build/r-base-Q1aiaj/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c httpgd.cpp -o httpgd.o
HttpgdServer.cpp:11:10: fatal error: DrawData.h: No such file or directory
11 | #include "DrawData.h"
| ^~~~~~~~~~~~
compilation terminated.
make: *** [/usr/lib/R/etc/Makeconf:176: HttpgdServer.o] Error 1
make: *** Waiting for unfinished jobs....
drawdata.cpp:11:10: fatal error: DrawData.h: No such file or directory
11 | #include "DrawData.h"
| ^~~~~~~~~~~~
compilation terminated.
make: *** [/usr/lib/R/etc/Makeconf:176: drawdata.o] Error 1
In file included from HttpgdDev.h:12,
from HttpgdDev.cpp:4:
HttpgdServer.h:11:10: fatal error: DrawData.h: No such file or directory
11 | #include "DrawData.h"
| ^~~~~~~~~~~~
compilation terminated.
In file included from HttpgdDev.h:12,
from httpgd.cpp:11:
HttpgdServer.h:11:10: fatal error: DrawData.h: No such file or directory
11 | #include "DrawData.h"
| ^~~~~~~~~~~~
compilation terminated.
make: *** [/usr/lib/R/etc/Makeconf:176: httpgd.o] Error 1
make: *** [/usr/lib/R/etc/Makeconf:176: HttpgdDev.o] Error 1
ERROR: compilation failed for package 'httpgd'
* removing '/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/httpgd'
* restoring previous '/home/renkun/R/x86_64-pc-linux-gnu-library/4.0/httpgd'
Error: Failed to install 'unknown package' from Git:
(converted from warning) installation of package '/tmp/RtmpIBNuxG/file876ef7abf998d/httpgd_0.3.1.tar.gz' had non-zero exit status
Backtrace:
1: stop(remote_install_error(remotes[[i]], e))
2: value[[3L]](cond)
3: tryCatchOne(expr, names, parentenv, handlers[[1L]])
4: tryCatchList(expr, classes, parentenv, handlers)
5: tryCatch(res[[i]] <- install_remote(remotes[[i]], ...), error = function(e) {
6: install_remotes(remotes, credentials = credentials, dependencies = dependencies,
7: pkgbuild::with_build_tools({
8: devtools::install_git("https://github.com/nx10/httpgd.git")
Sorry, just fixed it.
Thanks for the quick fix! It now works out of the box on Ubuntu and macOS (without xquartz, maybe due to the latest macOS Catalina 10.15.5 update? Never sure about that).
I'll do more testing and give feedback soon.
I'm trying overwriting device specified by session watcher with httpgd device and it works well.
options(device = function(...) {
httpgd::httpgd(...)
utils::browseURL(httpgd::httpgdURL())
}
But currently there's no way for user to change device in ~/.Rprofile if R: Create R terminal is used to start R session in VSCode.
I'll bring together several issues about controling the behavior of session watcher include default device, plot watcher and viewer, viewer position, browser position, etc. so that it is easier for user to customize session watcher features and behaviors.
When we have those, we could use something like
options(device = function(...) {
op <- options(vsc.browser.viewer = "beside")
on.exit(options(op))
httpgd::httpgd(...)
utils::browseURL(httpgd::httpgdURL())
}