/
languageclient.R
123 lines (108 loc) · 3.79 KB
/
languageclient.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# for testing purpose
LanguageClient <- R6::R6Class("LanguageClient",
inherit = LanguageBase,
private = list(
read_char_buf = raw(0),
finalize = function() {
if (!is.null(self$process)) {
self$process$kill_tree()
}
super$finalize()
}
),
public = list(
process = NULL,
rootUri = NULL,
ClientCapabilities = NULL,
ServerCapabilities = NULL,
diagnostics = NULL,
initialize = function(cmd = NULL, args = NULL) {
if (!is.null(cmd)) {
self$process <- processx::process$new(cmd, args,
stdin = "|", stdout = "|")
}
self$diagnostics <- collections::dict()
super$initialize()
},
check_connection = function() {
if (!is.null(self$process) && !self$process$is_alive())
stop("Server is dead.")
},
write_text = function(text) {
self$check_connection()
self$process$write_input(text)
},
read_output_lines = function() {
self$check_connection()
if (self$process$is_alive() && self$process$poll_io(1)[1] != "ready") return(NULL)
self$process$read_output_lines(1)
},
read_line = function() {
self$check_connection()
buf <- private$read_char_buf
if (length(buf) > 0 && as.raw(10) %in% buf) {
first_match <- min(which(buf == charToRaw("\n")))
line <- buf[seq_len(first_match - 1)]
if (length(line) > 0 && line[length(line)] == charToRaw("\r")) {
line <- line[-length(line)]
}
private$read_char_buf <- buf[seq_safe(first_match + 1, length(buf))]
return(rawToChar(line))
}
line <- self$read_output_lines()
if (length(line) > 0) {
line <- paste0(rawToChar(buf), line)
private$read_char_buf <- raw(0)
trimws(line, "right")
}
},
read_output = function(n) {
self$process$read_output(n)
},
read_char = function(n) {
self$check_connection()
if (length(private$read_char_buf) < n) {
data <- c(private$read_char_buf, charToRaw(self$read_output(n - length(private$read_char_buf))))
} else {
data <- private$read_char_buf
}
if (length(data) > n) {
private$read_char_buf <- data[seq_safe(n + 1, length(data))]
rawToChar(data[seq_len(n)])
} else {
private$read_char_buf <- raw(0)
rawToChar(data)
}
},
read_error = function() {
self$check_connection()
paste0(self$process$read_error_lines(), collapse = "\n")
},
welcome = function() {
self$deliver(
self$request(
"initialize",
list(
rootUri = self$rootUri,
capabilities = self$ClientCapabilities
)
),
callback = function(self, result) {
self$ServerCapabilities <- result$capabilities
}
)
},
start = function(working_dir = getwd(), capabilities = NULL) {
self$rootUri <- path_to_uri(working_dir)
self$ClientCapabilities <- capabilities
self$welcome()
},
run = function() {
# placeholder
}
)
)
LanguageClient$set("public", "register_handlers", function() {
self$request_handlers <- list()
self$notification_handlers <- list()
})