This repository has been archived by the owner on May 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvariables.rs
171 lines (164 loc) · 6.03 KB
/
variables.rs
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
use crate::context::*;
use crate::debug_adapter_comms;
use crate::kakoune;
use crate::types::{Scope, Variable};
use json::object;
// Handles the "scopes" response.
pub fn handle_scopes_response(msg: json::JsonValue, ctx: &mut Context) {
// Update the "scopes" array in the context
ctx.scopes.clear();
ctx.variables.clear();
let scopes_members = msg["body"]["scopes"].members();
for val in scopes_members {
let value = val.clone();
// Enter this scope in the scopes array
let scope = Scope {
variable_reference: val["variablesReference"]
.to_string()
.parse::<u64>()
.unwrap(),
contents: value,
};
ctx.scopes.push(scope);
// Request variables for this scope
let var_ref = val["variablesReference"]
.to_string()
.parse::<u64>()
.unwrap();
let var_args = object! {
"variablesReference": var_ref
};
ctx.var_reqs += 1;
debug_adapter_comms::do_request("variables", &var_args, ctx);
}
}
// Handles the "variables" response.
pub fn handle_variables_response(msg: json::JsonValue, ctx: &mut Context) {
ctx.var_reqs -= 1;
// Find the variables request that spawned this response
let cur_requests = &ctx.cur_requests.clone();
let val_req = cur_requests
.into_iter()
.find(|x| &x["seq"] == &msg["request_seq"])
.unwrap();
// Loop over every variable in this response
let variables = &msg["body"]["variables"];
let variables_members = variables.members();
for val in variables_members {
let val_cln = val.clone();
// Construct an Expandable instance containing this variable's properties
let variable = Variable {
variable_reference: val["variablesReference"]
.to_string()
.parse::<u64>()
.unwrap(),
par_variable_reference: val_req["arguments"]["variablesReference"]
.to_string()
.parse::<u64>()
.unwrap(),
contents: val_cln,
};
ctx.variables.push(variable);
}
// If we've serviced all pending variable requests, render the scopes and variables in the variables buffer
if ctx.var_reqs == 0 {
serialize_variables(ctx);
}
}
// Constructs the command that renders all the scopes and variables in the variables buffer.
pub fn serialize_variables(ctx: &mut Context) {
let mut cmd = "dap-show-variables '".to_string();
let mut cmd_val = "".to_string();
for scope in &ctx.scopes {
let scope_name = &scope.contents["name"];
cmd_val.push_str(&"Scope: ".to_string());
cmd_val.push_str(&scope_name.to_string());
cmd_val.push_str("\n");
// First confirm that this scope has child variables
let mut has_child = false;
for var in &ctx.variables {
if var.par_variable_reference == scope.variable_reference {
has_child = true;
break;
}
}
if has_child {
let val = serialize_variable(ctx, scope.variable_reference, 2);
cmd_val.push_str(&val);
}
}
cmd.push_str(&kakoune::editor_escape(&cmd_val));
cmd.push_str("'");
kakoune::kak_command(&cmd, &ctx.session);
}
// Constructs the command that renders all the child variables of the given variable reference in the variables buffer.
pub fn serialize_variable(ctx: &Context, par_ref: u64, indent: u64) -> String {
let mut val = "".to_string();
let mut icon = " ";
for var in &ctx.variables {
if var.par_variable_reference == par_ref {
for _i in 0..indent {
val.push_str(" ");
}
// If this variable is expandable
if var.variable_reference > 0 {
icon = "+";
// Determine if this variable has any child variables currently
for varr in &ctx.variables {
if varr.par_variable_reference == var.variable_reference {
icon = "-";
break;
}
}
}
val.push_str(&format!("{} ", icon));
val.push_str("<");
val.push_str(&var.variable_reference.to_string());
val.push_str("> ");
val.push_str(&var.contents["name"].to_string());
val.push_str(" (");
val.push_str(&var.contents["type"].to_string());
val.push_str("): ");
val.push_str(&var.contents["value"].to_string());
val.push_str("\n");
if var.variable_reference > 0 {
val.push_str(&serialize_variable(ctx, var.variable_reference, indent + 2));
}
}
}
val
}
// Handles the "expand" command from the editor.
pub fn expand_variable(cmd: &String, ctx: &mut Context) {
let mut var = cmd.to_string();
var = var.trim().to_string();
// If the string starts with a '<', this is an expandable variable
let first_char = var.chars().next().unwrap();
if first_char == '<' {
// Extract the variable reference
var = var[1..].to_string();
let var_ref = var.parse::<u64>().unwrap();
// If the variables list contains any child variables of this variable reference, then it's expanded
let mut is_expanded = false;
for varr in &ctx.variables {
if varr.par_variable_reference == var_ref {
is_expanded = true;
break;
}
}
// If this variable isn't expanded, then expand it
if !is_expanded {
let var_args = object! {
"variablesReference": var_ref
};
ctx.var_reqs += 1;
debug_adapter_comms::do_request("variables", &var_args, ctx);
}
// Otherwise, collapse it
else {
ctx.variables
.retain(|x| x.par_variable_reference != var_ref);
serialize_variables(ctx);
}
}
}