Skip to content

Commit f46da74

Browse files
author
Tal Hadad
committed
wip: start working on connection to the requests by a tcp server.
Fixes #1359
1 parent 3779678 commit f46da74

9 files changed

Lines changed: 305 additions & 125 deletions

File tree

R/session/init.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ init_last <- function() {
9595
)
9696

9797
# Attach to vscode
98-
exports$.vsc.attach()
98+
#exports$.vsc.attach()
9999

100100
invisible()
101101
}

R/session/vsc.R

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ dir_watcher <- Sys.getenv("VSCODE_WATCHER_DIR", file.path(homedir, ".vscode-R"))
88
request_file <- file.path(dir_watcher, "request.log")
99
request_lock_file <- file.path(dir_watcher, "request.lock")
1010
settings_file <- file.path(dir_watcher, "settings.json")
11+
request_tcp_connection <- NA
1112
user_options <- names(options())
1213

1314
logger <- if (getOption("vsc.debug", FALSE)) {
@@ -208,9 +209,12 @@ request <- function(command, ...) {
208209
command = command,
209210
...
210211
)
211-
jsonlite::write_json(obj, request_file,
212-
auto_unbox = TRUE, null = "null", force = TRUE)
213-
cat(get_timestamp(), file = request_lock_file)
212+
request_target <- if (is.na(request_tcp_connection)) request_file else request_tcp_connection
213+
jsonlite::write_json(obj, request_target,
214+
auto_unbox = TRUE, na = "string", null = "null", force = TRUE)
215+
if (is.na(request_tcp_connection)) {
216+
cat(get_timestamp(), file = request_lock_file)
217+
}
214218
}
215219

216220
try_catch_timeout <- function(expr, timeout = Inf, ...) {
@@ -369,8 +373,12 @@ update_workspace <- function(...) {
369373
loaded_namespaces = loadedNamespaces(),
370374
globalenv = if (show_globalenv) inspect_env(.GlobalEnv, globalenv_cache) else NULL
371375
)
372-
jsonlite::write_json(data, workspace_file, force = TRUE, pretty = FALSE)
373-
cat(get_timestamp(), file = workspace_lock_file)
376+
if (is.na(request_tcp_connection)) {
377+
jsonlite::write_json(data, workspace_file, force = TRUE, pretty = FALSE)
378+
cat(get_timestamp(), file = workspace_lock_file)
379+
} else {
380+
request("updateWorkspace", workspaceData = data)
381+
}
374382
}, error = message)
375383
TRUE
376384
}
@@ -419,6 +427,7 @@ if (use_httpgd && "httpgd" %in% .packages(all.available = TRUE)) {
419427
}
420428
)
421429

430+
# TODO: Make this be available by TCP only as well
422431
update_plot <- function(...) {
423432
tryCatch({
424433
if (plot_updated && check_null_dev()) {
@@ -595,47 +604,64 @@ if (show_view) {
595604
)
596605
}
597606
}
607+
send_data_request <- function(data, source, type, ...) {
608+
if (is.na(request_tcp_connection)) {
609+
file <- tempfile(tmpdir = tempdir, ...)
610+
if (type == "json") {
611+
jsonlite::write_json(data, file, na = "string", null = "null", auto_unbox = TRUE, force = TRUE)
612+
} else {
613+
writeLines(code, file)
614+
}
615+
request("dataview", source = source, type = type,
616+
title = title, file = file, viewer = viewer, uuid = uuid)
617+
} else {
618+
request("dataview", source = source, type = type,
619+
title = title, data = data, viewer = viewer, uuid = uuid)
620+
}
621+
}
598622
if (is.data.frame(x) || is.matrix(x)) {
599623
x <- as_truncated_data(x)
600624
data <- dataview_table(x)
601-
file <- tempfile(tmpdir = tempdir, fileext = ".json")
602-
jsonlite::write_json(data, file, na = "string", null = "null", auto_unbox = TRUE, force = TRUE)
603-
request("dataview", source = "table", type = "json",
604-
title = title, file = file, viewer = viewer, uuid = uuid)
625+
send_data_request(data, source = "table", type = "json", fileext = ".json")
605626
} else if (is.list(x)) {
606627
tryCatch({
607-
file <- tempfile(tmpdir = tempdir, fileext = ".json")
608-
jsonlite::write_json(x, file, na = "string", null = "null", auto_unbox = TRUE, force = TRUE)
609-
request("dataview", source = "list", type = "json",
610-
title = title, file = file, viewer = viewer, uuid = uuid)
628+
send_data_request(x, source = "list", type = "json", fileext = ".json")
611629
}, error = function(e) {
612-
file <- file.path(tempdir, paste0(make.names(title), ".txt"))
613630
text <- utils::capture.output(print(x))
614-
writeLines(text, file)
615-
request("dataview", source = "object", type = "txt",
616-
title = title, file = file, viewer = viewer, uuid = uuid)
631+
send_data_request(text, source = "object", type = "txt", paste0(make.names(title)), fileext = ".txt")
617632
})
618633
} else {
619-
file <- file.path(tempdir, paste0(make.names(title), ".R"))
620634
if (is.primitive(x)) {
621635
code <- utils::capture.output(print(x))
622636
} else {
623637
code <- deparse(x)
624638
}
625-
writeLines(code, file)
626-
request("dataview", source = "object", type = "R",
627-
title = title, file = file, viewer = viewer, uuid = uuid)
639+
send_data_request(code, source = "object", type = "R", paste0(make.names(title)), fileext = ".R")
628640
}
629641
}
630642

631643
rebind("View", show_dataview, "utils")
632644
}
633645

634-
attach <- function() {
646+
attach <- function(host = "127.0.0.1", port = NA) {
635647
load_settings()
636648
if (rstudioapi_enabled()) {
637649
rstudioapi_util_env$update_addin_registry(addin_registry)
638650
}
651+
if (!is.na(request_tcp_connection)) {
652+
close(request_tcp_connection)
653+
request_tcp_connection <<- NA
654+
}
655+
if (!is.na(port)) {
656+
request_tcp_connection <<- socketConnection(
657+
host = host,
658+
port = port,
659+
blocking = TRUE,
660+
server = FALSE,
661+
open = "a+"
662+
)
663+
}
664+
parent <- parent.env(environment())
639665
request("attach",
640666
version = sprintf("%s.%s", R.version$major, R.version$minor),
641667
tempdir = tempdir,
@@ -646,9 +672,9 @@ attach <- function() {
646672
),
647673
plot_url = if (identical(names(dev.cur()), "httpgd")) httpgd::hgd_url(),
648674
server = if (use_webserver) list(
649-
host = host,
650-
port = port,
651-
token = token
675+
host = parent$host,
676+
port = parent$port,
677+
token = parent$token
652678
) else NULL
653679
)
654680
}
@@ -929,4 +955,9 @@ print.hsearch <- function(x, ...) {
929955
invisible(NULL)
930956
}
931957

932-
reg.finalizer(.GlobalEnv, function(e) .vsc$request("detach"), onexit = TRUE)
958+
reg.finalizer(.GlobalEnv, function(e) {
959+
.vsc$request("detach")
960+
if (!is.na(request_tcp_connection)) {
961+
close(request_tcp_connection)
962+
}
963+
}, onexit = TRUE)

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,7 @@
21572157
"jquery.json-viewer": "^1.5.0",
21582158
"js-yaml": "^4.1.0",
21592159
"node-fetch": "^2.6.7",
2160+
"promise-socket": "^7.0.0",
21602161
"vscode-languageclient": "^8.1.0",
21612162
"vsls": "^1.0.4753",
21622163
"winreg": "^1.2.4"

src/extension.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import * as rShare from './liveShare';
2424
import * as httpgdViewer from './plotViewer';
2525
import * as languageService from './languageService';
2626
import { RTaskProvider } from './tasks';
27+
import { docProvider, docScheme } from './virtualDocs';
2728

2829

2930
// global objects used in other files
@@ -45,6 +46,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<apiImp
4546
void vscode.commands.executeCommand('workbench.extensions.search', '@installed R Tools');
4647
}
4748

49+
context.subscriptions.push(
50+
vscode.workspace.registerTextDocumentContentProvider(docScheme, docProvider)
51+
);
52+
4853
// create a new instance of RExtensionImplementation
4954
// is used to export an interface to the help panel
5055
// this export is used e.g. by vscode-r-debugger to show the help panel from within debug sessions

src/liveShare/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
export * from './shareCommands';
33
export * from './shareSession';
44
export * from './shareTree';
5-
export * from './virtualDocs';
65

76
import * as vscode from 'vscode';
87
import * as vsls from 'vsls';

src/liveShare/shareSession.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { asViewColumn, config, readContent } from '../util';
66
import { showBrowser, showDataView, showWebView, WorkspaceData } from '../session';
77
import { liveSession, UUID, rGuestService, _sessionStatusBarItem as sessionStatusBarItem } from '.';
88
import { autoShareBrowser } from './shareTree';
9-
import { docProvider, docScheme } from './virtualDocs';
109

1110
// Workspace Vars
1211
let guestPid: string;
@@ -19,7 +18,7 @@ let info: IRequest['info'];
1918
// Used to keep track of shared browsers
2019
export const browserDisposables: { Disposable: vscode.Disposable, url: string, name: string }[] = [];
2120

22-
export interface IRequest {
21+
export type IRequest = {
2322
command: string;
2423
time?: string;
2524
pid?: string;
@@ -30,6 +29,7 @@ export interface IRequest {
3029
file?: string;
3130
viewer?: string;
3231
plot?: string;
32+
workspaceData?: WorkspaceData;
3333
action?: string;
3434
args?: unknown;
3535
sd?: string;
@@ -43,7 +43,17 @@ export interface IRequest {
4343
command: string,
4444
start_time: string
4545
};
46-
}
46+
} & (
47+
{
48+
coomad: 'dataview';
49+
type: 'json';
50+
data: object;
51+
} | {
52+
coomad: 'dataview';
53+
type: 'txt' | 'R';
54+
data: string;
55+
}
56+
)
4757

4858
export function initGuest(context: vscode.ExtensionContext): void {
4959
// create status bar item that contains info about the *guest* session watcher
@@ -54,8 +64,7 @@ export function initGuest(context: vscode.ExtensionContext): void {
5464
sessionStatusBarItem.tooltip = 'Click to attach to host terminal';
5565
sessionStatusBarItem.show();
5666
context.subscriptions.push(
57-
sessionStatusBarItem,
58-
vscode.workspace.registerTextDocumentContentProvider(docScheme, docProvider)
67+
sessionStatusBarItem
5968
);
6069
rGuestService?.setStatusBarItem(sessionStatusBarItem);
6170
guestResDir = path.join(context.extensionPath, 'dist', 'resources');
@@ -149,7 +158,7 @@ export async function updateGuestRequest(file: string, force: boolean = false):
149158
if (request.source && request.type && request.title && request.file
150159
&& request.viewer !== undefined) {
151160
await showDataView(request.source,
152-
request.type, request.title, request.file, request.viewer);
161+
request.type, request.title, request.file, request.data, request.viewer);
153162
}
154163
break;
155164
}

0 commit comments

Comments
 (0)