This repository has been archived by the owner on Jun 15, 2021. It is now read-only.
/
event_handler.rs
181 lines (154 loc) · 5.39 KB
/
event_handler.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
172
173
174
175
176
177
178
179
180
181
use ncurses::*;
use serde_json::Value;
use xi_rpc::{RemoteError, RpcCall, RpcCtx};
#[derive(Default)]
pub struct EventHandler {
screen_start: i32,
cursor_x: i32,
cursor_y: i32,
buffer: Vec<String>,
}
impl xi_rpc::Handler for EventHandler {
type Notification = RpcCall;
type Request = RpcCall;
fn handle_notification(&mut self, ctx: &RpcCtx, rpc: Self::Notification) {
match rpc.method.as_str() {
"available_languages" => debug!("{} -> {}", &rpc.method, &rpc.params),
"available_themes" => debug!("{}", &rpc.method),
"available_plugins" => debug!("{} -> {}", &rpc.method, &rpc.params),
"config_changed" => debug!("{}", &rpc.method),
"scroll_to" => self.handle_cursor_move(&ctx, &rpc.params),
"language_changed" => debug!("{}", &rpc.method),
"update" => self.handle_update(&rpc.params),
_ => debug!("unhandled notif {} -> {:#?}", &rpc.method, &rpc.params),
};
refresh();
}
fn handle_request(&mut self, _ctx: &RpcCtx, rpc: Self::Request) -> Result<Value, RemoteError> {
debug!("[request] {} -> {:#?}", rpc.method, rpc.params);
Ok(json!({}))
}
}
impl EventHandler {
fn handle_cursor_move(&mut self, ctx: &RpcCtx, body: &Value) {
#[derive(Deserialize, Debug)]
struct ScrollInfo {
view_id: String,
col: i32,
line: i32,
}
let event: ScrollInfo = serde_json::from_value(body.clone()).unwrap();
let size_y = getmaxy(stdscr());
let mut cursor_y = event.line - self.screen_start;
let mut scroll: bool = false;
if cursor_y == size_y {
self.screen_start += 1;
scroll = true;
cursor_y -= 1
} else if cursor_y <= -1 {
self.screen_start -= 1;
scroll = true;
cursor_y += 1
}
self.cursor_x = event.col as i32;
self.cursor_y = cursor_y;
if scroll {
// In case of scroll it need to redraw the screen and after it
// the cursor is automatically reset at (self.cursor_y/self.cursor_x).
ctx.get_peer().send_rpc_notification(
"edit",
&json!({
"method": "scroll",
"view_id": event.view_id,
"params": [self.screen_start , self.screen_start + size_y]
}),
);
self.redraw_view();
} else {
// No scroll needed so it move the cursor without any redraw.
mv(self.cursor_y, self.cursor_x);
}
}
fn handle_update(&mut self, body: &Value) {
#[derive(Deserialize, Debug)]
struct Annotation {
#[serde(rename = "type")]
annotation_type: String,
n: usize,
payloads: Option<()>,
ranges: Vec<Vec<i32>>,
}
#[derive(Deserialize, Debug)]
struct Line {
cursor: Option<Vec<i32>>,
ln: i32,
styles: Vec<String>,
text: String,
}
#[derive(Deserialize, Debug)]
struct Operation {
#[serde(rename = "op")]
kind: String,
n: usize,
lines: Option<Vec<Line>>,
}
#[derive(Deserialize, Debug)]
struct Update {
annotations: Vec<Annotation>,
#[serde(rename = "ops")]
operations: Vec<Operation>,
}
#[derive(Deserialize, Debug)]
struct UpdateEvent {
view_id: String,
update: Update,
}
let event: UpdateEvent = serde_json::from_value(body.clone()).unwrap();
let mut new_buffer: Vec<String> = Vec::new();
let mut old_ix: usize = 0;
for operation in event.update.operations {
match operation.kind.as_str() {
"copy" => {
for i in 0..operation.n {
new_buffer.push(self.buffer[old_ix + i].to_owned());
}
old_ix += operation.n;
}
"skip" => old_ix += operation.n,
"invalidate" => {
for _ in 0..operation.n {
let line = String::from("????INVALID LINE???????\n").to_owned();
new_buffer.push(line);
}
}
"ins" => {
for line in operation.lines.unwrap() {
let tmp = line.text.to_owned();
new_buffer.push(tmp);
}
}
_ => warn!("unhandled update 2: {:?}", operation),
}
}
self.buffer = new_buffer;
self.redraw_view();
}
fn redraw_view(&mut self) {
clear();
let size_y = getmaxy(stdscr()) - 1;
let buffer_size = self.buffer.len() as i32;
let nb_lines_to_draw = if size_y > buffer_size - self.screen_start {
buffer_size - self.screen_start
} else {
self.screen_start + size_y
};
let mut output = String::new();
self.buffer
.iter()
.skip(self.screen_start as usize)
.take(nb_lines_to_draw as usize)
.for_each(|x| output.push_str(&x));
addstr(output.as_str());
mv(self.cursor_y, self.cursor_x);
}
}