on master help sign in
Tokio migration.
355ad3cBlaž Hrastnik
Cargo.lock+51−257
@@ -17,112 +17,6 @@ version = "1.0.40"
17source = "registry+https://github.com/rust-lang/crates.io-index"
17source = "registry+https://github.com/rust-lang/crates.io-index"
18checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
18checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
19
19
20−[[package]]
21−name = "async-channel"
22−version = "1.6.1"
23−source = "registry+https://github.com/rust-lang/crates.io-index"
24−checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
25−dependencies = [
26− "concurrent-queue",
27− "event-listener",
28− "futures-core",
29−]
30−
31−[[package]]
32−name = "async-executor"
33−version = "1.4.1"
34−source = "registry+https://github.com/rust-lang/crates.io-index"
35−checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
36−dependencies = [
37− "async-task",
38− "concurrent-queue",
39− "fastrand",
40− "futures-lite",
41− "once_cell",
42− "slab",
43−]
44−
45−[[package]]
46−name = "async-fs"
47−version = "1.5.0"
48−source = "registry+https://github.com/rust-lang/crates.io-index"
49−checksum = "8b3ca4f8ff117c37c278a2f7415ce9be55560b846b5bc4412aaa5d29c1c3dae2"
50−dependencies = [
51− "async-lock",
52− "blocking",
53− "futures-lite",
54−]
55−
56−[[package]]
57−name = "async-io"
58−version = "1.4.1"
59−source = "registry+https://github.com/rust-lang/crates.io-index"
60−checksum = "4bbfd5cf2794b1e908ea8457e6c45f8f8f1f6ec5f74617bf4662623f47503c3b"
61−dependencies = [
62− "concurrent-queue",
63− "fastrand",
64− "futures-lite",
65− "libc",
66− "log",
67− "once_cell",
68− "parking",
69− "polling",
70− "slab",
71− "socket2",
72− "waker-fn",
73− "winapi",
74−]
75−
76−[[package]]
77−name = "async-lock"
78−version = "2.4.0"
79−source = "registry+https://github.com/rust-lang/crates.io-index"
80−checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b"
81−dependencies = [
82− "event-listener",
83−]
84−
85−[[package]]
86−name = "async-net"
87−version = "1.6.0"
88−source = "registry+https://github.com/rust-lang/crates.io-index"
89−checksum = "69b0a74e7f70af3c8cf1aa539edbd044795706659ac52b78a71dc1a205ecefdf"
90−dependencies = [
91− "async-io",
92− "blocking",
93− "fastrand",
94− "futures-lite",
95−]
96−
97−[[package]]
98−name = "async-process"
99−version = "1.1.0"
100−source = "registry+https://github.com/rust-lang/crates.io-index"
101−checksum = "a8f38756dd9ac84671c428afbf7c9f7495feff9ec5b0710f17100098e5b354ac"
102−dependencies = [
103− "async-io",
104− "blocking",
105− "cfg-if",
106− "event-listener",
107− "futures-lite",
108− "libc",
109− "once_cell",
110− "signal-hook 0.3.8",
111− "winapi",
112−]
113−
114−[[package]]
115−name = "async-task"
116−version = "4.0.3"
117−source = "registry+https://github.com/rust-lang/crates.io-index"
118−checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
119−
120−[[package]]
121−name = "atomic-waker"
122−version = "1.0.0"
123−source = "registry+https://github.com/rust-lang/crates.io-index"
124−checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
125−
126[[package]]
20[[package]]
127name = "autocfg"
21name = "autocfg"
128version = "1.0.1"
22version = "1.0.1"
@@ -135,20 +29,6 @@ version = "1.2.1"
135source = "registry+https://github.com/rust-lang/crates.io-index"
29source = "registry+https://github.com/rust-lang/crates.io-index"
136checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
30checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
137
31
138−[[package]]
139−name = "blocking"
140−version = "1.0.2"
141−source = "registry+https://github.com/rust-lang/crates.io-index"
142−checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9"
143−dependencies = [
144− "async-channel",
145− "async-task",
146− "atomic-waker",
147− "fastrand",
148− "futures-lite",
149− "once_cell",
150−]
151−
152[[package]]
32[[package]]
153name = "bstr"
33name = "bstr"
154version = "0.2.16"
34version = "0.2.16"
@@ -159,10 +39,10 @@ dependencies = [
159]
39]
160
40
161[[package]]
41[[package]]
162−name = "cache-padded"
42+name = "bytes"
163−version = "1.1.1"
43+version = "1.0.1"
164source = "registry+https://github.com/rust-lang/crates.io-index"
44source = "registry+https://github.com/rust-lang/crates.io-index"
165−checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
45+checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
166
46
167[[package]]
47[[package]]
168name = "cassowary"
48name = "cassowary"
@@ -212,15 +92,6 @@ dependencies = [
212 "vec_map",
92 "vec_map",
213]
93]
214
94
215−[[package]]
216−name = "concurrent-queue"
217−version = "1.2.2"
218−source = "registry+https://github.com/rust-lang/crates.io-index"
219−checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
220−dependencies = [
221− "cache-padded",
222−]
223−
224[[package]]
95[[package]]
225name = "crossbeam-utils"
96name = "crossbeam-utils"
226version = "0.8.4"
97version = "0.8.4"
@@ -245,7 +116,7 @@ dependencies = [
245 "libc",
116 "libc",
246 "mio",
117 "mio",
247 "parking_lot",
118 "parking_lot",
248− "signal-hook 0.1.17",
119+ "signal-hook",
249 "winapi",
120 "winapi",
250]
121]
251
122
@@ -279,21 +150,6 @@ dependencies = [
279 "winapi",
150 "winapi",
280]
151]
281
152
282−[[package]]
283−name = "event-listener"
284−version = "2.5.1"
285−source = "registry+https://github.com/rust-lang/crates.io-index"
286−checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
287−
288−[[package]]
289−name = "fastrand"
290−version = "1.4.1"
291−source = "registry+https://github.com/rust-lang/crates.io-index"
292−checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb"
293−dependencies = [
294− "instant",
295−]
296−
297[[package]]
153[[package]]
298name = "fern"
154name = "fern"
299version = "0.6.0"
155version = "0.6.0"
@@ -377,21 +233,6 @@ version = "0.3.14"
377source = "registry+https://github.com/rust-lang/crates.io-index"
233source = "registry+https://github.com/rust-lang/crates.io-index"
378checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
234checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
379
235
380−[[package]]
381−name = "futures-lite"
382−version = "1.11.3"
383−source = "registry+https://github.com/rust-lang/crates.io-index"
384−checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb"
385−dependencies = [
386− "fastrand",
387− "futures-core",
388− "futures-io",
389− "memchr",
390− "parking",
391− "pin-project-lite 0.2.6",
392− "waker-fn",
393−]
394−
395[[package]]
236[[package]]
396name = "futures-macro"
237name = "futures-macro"
397version = "0.3.14"
238version = "0.3.14"
@@ -429,7 +270,7 @@ dependencies = [
429 "futures-sink",
270 "futures-sink",
430 "futures-task",
271 "futures-task",
431 "memchr",
272 "memchr",
432− "pin-project-lite 0.2.6",
273+ "pin-project-lite",
433 "pin-utils",
274 "pin-utils",
434 "proc-macro-hack",
275 "proc-macro-hack",
435 "proc-macro-nested",
276 "proc-macro-nested",
@@ -515,9 +356,9 @@ dependencies = [
515 "serde",
356 "serde",
516 "serde_json",
357 "serde_json",
517 "shellexpand",
358 "shellexpand",
518− "smol",
519− "smol-timeout",
520 "thiserror",
359 "thiserror",
360+ "tokio",
361+ "tokio-stream",
521 "url",
362 "url",
522]
363]
523
364
@@ -553,8 +394,7 @@ dependencies = [
553 "pulldown-cmark",
394 "pulldown-cmark",
554 "serde",
395 "serde",
555 "serde_json",
396 "serde_json",
556− "smol",
397+ "tokio",
557− "smol-timeout",
558 "toml",
398 "toml",
559 "tui",
399 "tui",
560]
400]
@@ -571,7 +411,7 @@ dependencies = [
571 "once_cell",
411 "once_cell",
572 "serde",
412 "serde",
573 "slotmap",
413 "slotmap",
574− "smol",
414+ "tokio",
575 "toml",
415 "toml",
576 "tui",
416 "tui",
577 "url",
417 "url",
@@ -801,12 +641,6 @@ version = "2.4.0"
801source = "registry+https://github.com/rust-lang/crates.io-index"
641source = "registry+https://github.com/rust-lang/crates.io-index"
802checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
642checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
803
643
804−[[package]]
805−name = "parking"
806−version = "2.0.0"
807−source = "registry+https://github.com/rust-lang/crates.io-index"
808−checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
809−
810[[package]]
644[[package]]
811name = "parking_lot"
645name = "parking_lot"
812version = "0.11.1"
646version = "0.11.1"
@@ -844,12 +678,6 @@ version = "2.1.0"
844source = "registry+https://github.com/rust-lang/crates.io-index"
678source = "registry+https://github.com/rust-lang/crates.io-index"
845checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
679checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
846
680
847−[[package]]
848−name = "pin-project-lite"
849−version = "0.1.12"
850−source = "registry+https://github.com/rust-lang/crates.io-index"
851−checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777"
852−
853[[package]]
681[[package]]
854name = "pin-project-lite"
682name = "pin-project-lite"
855version = "0.2.6"
683version = "0.2.6"
@@ -862,19 +690,6 @@ version = "0.1.0"
862source = "registry+https://github.com/rust-lang/crates.io-index"
690source = "registry+https://github.com/rust-lang/crates.io-index"
863checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
691checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
864
692
865−[[package]]
866−name = "polling"
867−version = "2.0.3"
868−source = "registry+https://github.com/rust-lang/crates.io-index"
869−checksum = "4fc12d774e799ee9ebae13f4076ca003b40d18a11ac0f3641e6f899618580b7b"
870−dependencies = [
871− "cfg-if",
872− "libc",
873− "log",
874− "wepoll-sys",
875− "winapi",
876−]
877−
878[[package]]
693[[package]]
879name = "proc-macro-hack"
694name = "proc-macro-hack"
880version = "0.5.19"
695version = "0.5.19"
@@ -1044,16 +859,6 @@ dependencies = [
1044 "signal-hook-registry",
859 "signal-hook-registry",
1045]
860]
1046
861
1047−[[package]]
1048−name = "signal-hook"
1049−version = "0.3.8"
1050−source = "registry+https://github.com/rust-lang/crates.io-index"
1051−checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac"
1052−dependencies = [
1053− "libc",
1054− "signal-hook-registry",
1055−]
1056−
1057[[package]]
862[[package]]
1058name = "signal-hook-registry"
863name = "signal-hook-registry"
1059version = "1.3.0"
864version = "1.3.0"
@@ -1084,44 +889,6 @@ version = "1.6.1"
1084source = "registry+https://github.com/rust-lang/crates.io-index"
889source = "registry+https://github.com/rust-lang/crates.io-index"
1085checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
890checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
1086
891
1087−[[package]]
1088−name = "smol"
1089−version = "1.2.5"
1090−source = "registry+https://github.com/rust-lang/crates.io-index"
1091−checksum = "85cf3b5351f3e783c1d79ab5fc604eeed8b8ae9abd36b166e8b87a089efd85e4"
1092−dependencies = [
1093− "async-channel",
1094− "async-executor",
1095− "async-fs",
1096− "async-io",
1097− "async-lock",
1098− "async-net",
1099− "async-process",
1100− "blocking",
1101− "futures-lite",
1102− "once_cell",
1103−]
1104−
1105−[[package]]
1106−name = "smol-timeout"
1107−version = "0.6.0"
1108−source = "registry+https://github.com/rust-lang/crates.io-index"
1109−checksum = "847d777e2c6c166bad26264479e80a9820f3d364fcb4a0e23cd57bbfa8e94961"
1110−dependencies = [
1111− "async-io",
1112− "pin-project-lite 0.1.12",
1113−]
1114−
1115−[[package]]
1116−name = "socket2"
1117−version = "0.4.0"
1118−source = "registry+https://github.com/rust-lang/crates.io-index"
1119−checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
1120−dependencies = [
1121− "libc",
1122− "winapi",
1123−]
1124−
1125[[package]]
892[[package]]
1126name = "syn"
893name = "syn"
1127version = "1.0.71"
894version = "1.0.71"
@@ -1206,6 +973,48 @@ version = "0.1.0"
1206source = "registry+https://github.com/rust-lang/crates.io-index"
973source = "registry+https://github.com/rust-lang/crates.io-index"
1207checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
974checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
1208
975
976+[[package]]
977+name = "tokio"
978+version = "1.5.0"
979+source = "registry+https://github.com/rust-lang/crates.io-index"
980+checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
981+dependencies = [
982+ "autocfg",
983+ "bytes",
984+ "libc",
985+ "memchr",
986+ "mio",
987+ "num_cpus",
988+ "once_cell",
989+ "parking_lot",
990+ "pin-project-lite",
991+ "signal-hook-registry",
992+ "tokio-macros",
993+ "winapi",
994+]
995+
996+[[package]]
997+name = "tokio-macros"
998+version = "1.1.0"
999+source = "registry+https://github.com/rust-lang/crates.io-index"
1000+checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
1001+dependencies = [
1002+ "proc-macro2",
1003+ "quote",
1004+ "syn",
1005+]
1006+
1007+[[package]]
1008+name = "tokio-stream"
1009+version = "0.1.5"
1010+source = "registry+https://github.com/rust-lang/crates.io-index"
1011+checksum = "e177a5d8c3bf36de9ebe6d58537d8879e964332f93fb3339e43f618c81361af0"
1012+dependencies = [
1013+ "futures-core",
1014+ "pin-project-lite",
1015+ "tokio",
1016+]
1017+
1209[[package]]
1018[[package]]
1210name = "toml"
1019name = "toml"
1211version = "0.5.8"
1020version = "0.5.8"
@@ -1314,12 +1123,6 @@ version = "0.9.3"
1314source = "registry+https://github.com/rust-lang/crates.io-index"
1123source = "registry+https://github.com/rust-lang/crates.io-index"
1315checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
1124checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
1316
1125
1317−[[package]]
1318−name = "waker-fn"
1319−version = "1.1.0"
1320−source = "registry+https://github.com/rust-lang/crates.io-index"
1321−checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
1322−
1323[[package]]
1126[[package]]
1324name = "walkdir"
1127name = "walkdir"
1325version = "2.3.2"
1128version = "2.3.2"
@@ -1337,15 +1140,6 @@ version = "0.10.2+wasi-snapshot-preview1"
1337source = "registry+https://github.com/rust-lang/crates.io-index"
1140source = "registry+https://github.com/rust-lang/crates.io-index"
1338checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
1141checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
1339
1142
1340−[[package]]
1341−name = "wepoll-sys"
1342−version = "3.0.1"
1343−source = "registry+https://github.com/rust-lang/crates.io-index"
1344−checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
1345−dependencies = [
1346− "cc",
1347−]
1348−
1349[[package]]
1143[[package]]
1350name = "winapi"
1144name = "winapi"
1351version = "0.3.9"
1145version = "0.3.9"
helix-lsp/Cargo.toml+2−2
@@ -12,8 +12,8 @@ helix-core = { path = "../helix-core" }
12once_cell = "1.4"
12once_cell = "1.4"
13
13
14lsp-types = { version = "0.89", features = ["proposed"] }
14lsp-types = { version = "0.89", features = ["proposed"] }
15−smol = "1.2"
15+tokio = { version = "1", features = ["full"] }
16−smol-timeout = "0.6"
16+tokio-stream = "0.1.5"
17url = "2"
17url = "2"
18pathdiff = "0.2"
18pathdiff = "0.2"
19shellexpand = "2.0"
19shellexpand = "2.0"
helix-lsp/src/client.rs+42−37
@@ -13,18 +13,18 @@ use jsonrpc_core as jsonrpc;
13use lsp_types as lsp;
13use lsp_types as lsp;
14use serde_json::Value;
14use serde_json::Value;
15
15
16−use smol::{
16+use std::process::Stdio;
17− channel::{Receiver, Sender},
17+use tokio::{
18 io::{BufReader, BufWriter},
18 io::{BufReader, BufWriter},
19 // prelude::*,
19 // prelude::*,
20− process::{Child, Command, Stdio},
20+ process::{Child, Command},
21− Executor,
21+ sync::mpsc::{channel, UnboundedReceiver, UnboundedSender},
22};
22};
23
23
24pub struct Client {
24pub struct Client {
25 _process: Child,
25 _process: Child,
26
26
27− outgoing: Sender<Payload>,
27+ outgoing: UnboundedSender<Payload>,
28 // pub incoming: Receiver<Call>,
28 // pub incoming: Receiver<Call>,
29 pub request_counter: AtomicU64,
29 pub request_counter: AtomicU64,
30
30
@@ -33,13 +33,14 @@ pub struct Client {
33}
33}
34
34
35impl Client {
35impl Client {
36− pub fn start(ex: &Executor, cmd: &str, args: &[String]) -> Result<(Self, Receiver<Call>)> {
36+ pub fn start(cmd: &str, args: &[String]) -> Result<(Self, UnboundedReceiver<Call>)> {
37− // smol makes sure the process is reaped on drop, but using kill_on_drop(true) maybe?
38 let process = Command::new(cmd)
37 let process = Command::new(cmd)
39 .args(args)
38 .args(args)
40 .stdin(Stdio::piped())
39 .stdin(Stdio::piped())
41 .stdout(Stdio::piped())
40 .stdout(Stdio::piped())
42 .stderr(Stdio::piped())
41 .stderr(Stdio::piped())
42+ // make sure the process is reaped on drop
43+ .kill_on_drop(true)
43 .spawn();
44 .spawn();
44
45
45 // use std::io::ErrorKind;
46 // use std::io::ErrorKind;
@@ -58,7 +59,7 @@ impl Client {
58 let reader = BufReader::new(process.stdout.take().expect("Failed to open stdout"));
59 let reader = BufReader::new(process.stdout.take().expect("Failed to open stdout"));
59 let stderr = BufReader::new(process.stderr.take().expect("Failed to open stderr"));
60 let stderr = BufReader::new(process.stderr.take().expect("Failed to open stderr"));
60
61
61− let (incoming, outgoing) = Transport::start(ex, reader, writer, stderr);
62+ let (incoming, outgoing) = Transport::start(reader, writer, stderr);
62
63
63 let client = Client {
64 let client = Client {
64 _process: process,
65 _process: process,
@@ -134,49 +135,53 @@ impl Client {
134 params: Self::value_into_params(params),
135 params: Self::value_into_params(params),
135 };
136 };
136
137
137− let (tx, rx) = smol::channel::bounded::<Result<Value>>(1);
138+ let (tx, mut rx) = channel::<Result<Value>>(1);
138
139
139 self.outgoing
140 self.outgoing
140 .send(Payload::Request {
141 .send(Payload::Request {
141 chan: tx,
142 chan: tx,
142 value: request,
143 value: request,
143 })
144 })
144− .await
145 .map_err(|e| Error::Other(e.into()))?;
145 .map_err(|e| Error::Other(e.into()))?;
146
146
147− use smol_timeout::TimeoutExt;
148 use std::time::Duration;
147 use std::time::Duration;
148+ use tokio::time::timeout;
149
149
150 let future = async move {
150 let future = async move {
151− rx.recv()
152− .timeout(Duration::from_secs(2))
151+ timeout(Duration::from_secs(2), rx.recv())
153 .await
152 .await
154− .ok_or(Error::Timeout)? // return Timeout
153+ .map_err(|e| Error::Timeout)? // return Timeout
155− .map_err(|e| Error::Other(e.into()))?
154+ .unwrap() // TODO: None if channel closed
156 };
155 };
157
156
158 Ok(future)
157 Ok(future)
159 }
158 }
160
159
161 /// Send a RPC notification to the language server.
160 /// Send a RPC notification to the language server.
162− pub async fn notify<R: lsp::notification::Notification>(&self, params: R::Params) -> Result<()>
161+ pub fn notify<R: lsp::notification::Notification>(
162+ &self,
163+ params: R::Params,
164+ ) -> impl Future<Output = Result<()>>
163 where
165 where
164 R::Params: serde::Serialize,
166 R::Params: serde::Serialize,
165 {
167 {
166− let params = serde_json::to_value(params)?;
168+ let outgoing = self.outgoing.clone();
167
169
168− let notification = jsonrpc::Notification {
170+ async move {
169− jsonrpc: Some(jsonrpc::Version::V2),
171+ let params = serde_json::to_value(params)?;
170− method: R::METHOD.to_string(),
171− params: Self::value_into_params(params),
172− };
173
172
174− self.outgoing
173+ let notification = jsonrpc::Notification {
175− .send(Payload::Notification(notification))
174+ jsonrpc: Some(jsonrpc::Version::V2),
176− .await
175+ method: R::METHOD.to_string(),
177− .map_err(|e| Error::Other(e.into()))?;
176+ params: Self::value_into_params(params),
177+ };
178
178
179+ outgoing
180+ .send(Payload::Notification(notification))
181+ .map_err(|e| Error::Other(e.into()))?;
182+
179− Ok(())
183+ Ok(())
184+ }
180 }
185 }
181
186
182 /// Reply to a language server RPC call.
187 /// Reply to a language server RPC call.
@@ -202,7 +207,6 @@ impl Client {
202
207
203 self.outgoing
208 self.outgoing
204 .send(Payload::Response(output))
209 .send(Payload::Response(output))
205− .await
206 .map_err(|e| Error::Other(e.into()))?;
210 .map_err(|e| Error::Other(e.into()))?;
207
211
208 Ok(())
212 Ok(())
@@ -387,13 +391,13 @@ impl Client {
387 changes
391 changes
388 }
392 }
389
393
390− pub async fn text_document_did_change(
394+ pub fn text_document_did_change(
391 &self,
395 &self,
392 text_document: lsp::VersionedTextDocumentIdentifier,
396 text_document: lsp::VersionedTextDocumentIdentifier,
393 old_text: &Rope,
397 old_text: &Rope,
394 new_text: &Rope,
398 new_text: &Rope,
395 changes: &ChangeSet,
399 changes: &ChangeSet,
396− ) -> Result<()> {
400+ ) -> Option<impl Future<Output = Result<()>>> {
397 // figure out what kind of sync the server supports
401 // figure out what kind of sync the server supports
398
402
399 let capabilities = self.capabilities.as_ref().unwrap();
403 let capabilities = self.capabilities.as_ref().unwrap();
@@ -405,7 +409,7 @@ impl Client {
405 ..
409 ..
406 })) => kind,
410 })) => kind,
407 // None | SyncOptions { changes: None }
411 // None | SyncOptions { changes: None }
408− _ => return Ok(()),
412+ _ => return None,
409 };
413 };
410
414
411 let changes = match sync_capabilities {
415 let changes = match sync_capabilities {
@@ -420,14 +424,15 @@ impl Client {
420 lsp::TextDocumentSyncKind::Incremental => {
424 lsp::TextDocumentSyncKind::Incremental => {
421 Self::changeset_to_changes(old_text, new_text, changes, self.offset_encoding)
425 Self::changeset_to_changes(old_text, new_text, changes, self.offset_encoding)
422 }
426 }
423− lsp::TextDocumentSyncKind::None => return Ok(()),
427+ lsp::TextDocumentSyncKind::None => return None,
424 };
428 };
425
429
426− self.notify::<lsp::notification::DidChangeTextDocument>(lsp::DidChangeTextDocumentParams {
430+ Some(self.notify::<lsp::notification::DidChangeTextDocument>(
431+ lsp::DidChangeTextDocumentParams {
427− text_document,
432+ text_document,
428− content_changes: changes,
433+ content_changes: changes,
429− })
434+ },
430− .await
435+ ))
431 }
436 }
432
437
433 pub async fn text_document_did_close(
438 pub async fn text_document_did_close(
helix-lsp/src/lib.rs+8−10
@@ -18,6 +18,8 @@ use std::{collections::HashMap, sync::Arc};
18
18
19use serde::{Deserialize, Serialize};
19use serde::{Deserialize, Serialize};
20
20
21+use tokio_stream::wrappers::UnboundedReceiverStream;
22+
21#[derive(Error, Debug)]
23#[derive(Error, Debug)]
22pub enum Error {
24pub enum Error {
23 #[error("protocol error: {0}")]
25 #[error("protocol error: {0}")]
@@ -163,12 +165,11 @@ pub use jsonrpc::Call;
163type LanguageId = String;
165type LanguageId = String;
164
166
165use crate::select_all::SelectAll;
167use crate::select_all::SelectAll;
166−use smol::channel::Receiver;
167
168
168pub struct Registry {
169pub struct Registry {
169 inner: HashMap<LanguageId, Option<Arc<Client>>>,
170 inner: HashMap<LanguageId, Option<Arc<Client>>>,
170
171
171− pub incoming: SelectAll<Receiver<Call>>,
172+ pub incoming: SelectAll<UnboundedReceiverStream<Call>>,
172}
173}
173
174
174impl Default for Registry {
175impl Default for Registry {
@@ -185,11 +186,7 @@ impl Registry {
185 }
186 }
186 }
187 }
187
188
188− pub fn get(
189− &mut self,
190− language_config: &LanguageConfiguration,
189+ pub fn get(&mut self, language_config: &LanguageConfiguration) -> Option<Arc<Client>> {
191− ex: &smol::Executor,
192− ) -> Option<Arc<Client>> {
193 // TODO: propagate the error
190 // TODO: propagate the error
194 if let Some(config) = &language_config.language_server {
191 if let Some(config) = &language_config.language_server {
195 // avoid borrow issues
192 // avoid borrow issues
@@ -203,12 +200,13 @@ impl Registry {
203
200
204 // initialize a new client
201 // initialize a new client
205 let (mut client, incoming) =
202 let (mut client, incoming) =
206− Client::start(&ex, &config.command, &config.args).ok()?;
203+ Client::start(&config.command, &config.args).ok()?;
207
204
208 // TODO: run this async without blocking
205 // TODO: run this async without blocking
206+ let rt = tokio::runtime::Handle::current();
209− smol::block_on(client.initialize()).unwrap();
207+ rt.block_on(client.initialize()).unwrap();
210
208
211− s_incoming.push(incoming);
209+ s_incoming.push(UnboundedReceiverStream::new(incoming));
212
210
213 Some(Arc::new(client))
211 Some(Arc::new(client))
214 })
212 })
helix-lsp/src/select_all.rs+1−1
@@ -6,10 +6,10 @@ use core::{
6 pin::Pin,
6 pin::Pin,
7};
7};
8
8
9−use smol::{ready, stream::Stream};
10use std::task::{Context, Poll};
9use std::task::{Context, Poll};
11
10
12use futures_util::stream::{FusedStream, FuturesUnordered, StreamExt, StreamFuture};
11use futures_util::stream::{FusedStream, FuturesUnordered, StreamExt, StreamFuture};
12+use futures_util::{ready, stream::Stream};
13
13
14/// An unbounded set of streams
14/// An unbounded set of streams
15///
15///
helix-lsp/src/transport.rs+15−19
@@ -10,15 +10,13 @@ type Result<T> = core::result::Result<T, Error>;
10use jsonrpc_core as jsonrpc;
10use jsonrpc_core as jsonrpc;
11use serde_json::Value;
11use serde_json::Value;
12
12
13−use smol::prelude::*;
13+use tokio::{
14−
15−use smol::{
16− channel::{Receiver, Sender},
17− io::{BufReader, BufWriter},
14+ io::{AsyncBufRead, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader, BufWriter},
18 process::{ChildStderr, ChildStdin, ChildStdout},
15 process::{ChildStderr, ChildStdin, ChildStdout},
19− Executor,
16+ sync::mpsc::{unbounded_channel, Sender, UnboundedReceiver, UnboundedSender},
20};
17};
21
18
19+#[derive(Debug)]
22pub enum Payload {
20pub enum Payload {
23 Request {
21 Request {
24 chan: Sender<Result<Value>>,
22 chan: Sender<Result<Value>>,
@@ -41,8 +39,8 @@ enum Message {
41}
39}
42
40
43pub struct Transport {
41pub struct Transport {
44− incoming: Sender<jsonrpc::Call>,
42+ incoming: UnboundedSender<jsonrpc::Call>,
45− outgoing: Receiver<Payload>,
43+ outgoing: UnboundedReceiver<Payload>,
46
44
47 pending_requests: HashMap<jsonrpc::Id, Sender<Result<Value>>>,
45 pending_requests: HashMap<jsonrpc::Id, Sender<Result<Value>>>,
48 headers: HashMap<String, String>,
46 headers: HashMap<String, String>,
@@ -54,13 +52,12 @@ pub struct Transport {
54
52
55impl Transport {
53impl Transport {
56 pub fn start(
54 pub fn start(
57− ex: &Executor,
58 reader: BufReader<ChildStdout>,
55 reader: BufReader<ChildStdout>,
59 writer: BufWriter<ChildStdin>,
56 writer: BufWriter<ChildStdin>,
60 stderr: BufReader<ChildStderr>,
57 stderr: BufReader<ChildStderr>,
61− ) -> (Receiver<jsonrpc::Call>, Sender<Payload>) {
58+ ) -> (UnboundedReceiver<jsonrpc::Call>, UnboundedSender<Payload>) {
62− let (incoming, rx) = smol::channel::unbounded();
59+ let (incoming, rx) = unbounded_channel();
63− let (tx, outgoing) = smol::channel::unbounded();
60+ let (tx, outgoing) = unbounded_channel();
64
61
65 let transport = Self {
62 let transport = Self {
66 reader,
63 reader,
@@ -72,7 +69,7 @@ impl Transport {
72 headers: HashMap::default(),
69 headers: HashMap::default(),
73 };
70 };
74
71
75− ex.spawn(transport.duplex()).detach();
72+ tokio::spawn(transport.duplex());
76
73
77 (rx, tx)
74 (rx, tx)
78 }
75 }
@@ -168,7 +165,7 @@ impl Transport {
168 match msg {
165 match msg {
169 Message::Output(output) => self.recv_response(output).await?,
166 Message::Output(output) => self.recv_response(output).await?,
170 Message::Call(call) => {
167 Message::Call(call) => {
171− self.incoming.send(call).await?;
168+ self.incoming.send(call).unwrap();
172 // let notification = Notification::parse(&method, params);
169 // let notification = Notification::parse(&method, params);
173 }
170 }
174 };
171 };
@@ -204,11 +201,10 @@ impl Transport {
204 }
201 }
205
202
206 pub async fn duplex(mut self) {
203 pub async fn duplex(mut self) {
207− use futures_util::{select, FutureExt};
208 loop {
204 loop {
209− select! {
205+ tokio::select! {
210 // client -> server
206 // client -> server
211− msg = self.outgoing.next().fuse() => {
207+ msg = self.outgoing.recv() => {
212 if msg.is_none() {
208 if msg.is_none() {
213 break;
209 break;
214 }
210 }
@@ -217,7 +213,7 @@ impl Transport {
217 self.send_payload(msg).await.unwrap();
213 self.send_payload(msg).await.unwrap();
218 }
214 }
219 // server <- client
215 // server <- client
220− msg = Self::recv(&mut self.reader, &mut self.headers).fuse() => {
216+ msg = Self::recv(&mut self.reader, &mut self.headers) => {
221 if msg.is_err() {
217 if msg.is_err() {
222 error!("err: <- {:?}", msg);
218 error!("err: <- {:?}", msg);
223 break;
219 break;
@@ -226,7 +222,7 @@ impl Transport {
226
222
227 self.recv_msg(msg).await.unwrap();
223 self.recv_msg(msg).await.unwrap();
228 }
224 }
229− _msg = Self::err(&mut self.stderr).fuse() => {}
225+ _msg = Self::err(&mut self.stderr) => {}
230 }
226 }
231 }
227 }
232 }
228 }
helix-term/Cargo.toml+1−2
@@ -19,8 +19,7 @@ helix-lsp = { path = "../helix-lsp"}
19anyhow = "1"
19anyhow = "1"
20once_cell = "1.4"
20once_cell = "1.4"
21
21
22−smol = "1"
22+tokio = { version = "1", features = ["full"] }
23−smol-timeout = "0.6"
24num_cpus = "1"
23num_cpus = "1"
25tui = { version = "0.15", default-features = false, features = ["crossterm"] }
24tui = { version = "0.15", default-features = false, features = ["crossterm"] }
26crossterm = { version = "0.19", features = ["event-stream"] }
25crossterm = { version = "0.19", features = ["event-stream"] }
helix-term/src/application.rs+4−10
@@ -7,14 +7,13 @@ use crate::{compositor::Compositor, ui};
7use log::{error, info};
7use log::{error, info};
8
8
9use std::{
9use std::{
10+ future::Future,
10 io::{self, stdout, Stdout, Write},
11 io::{self, stdout, Stdout, Write},
11 path::PathBuf,
12 path::PathBuf,
12 sync::Arc,
13 sync::Arc,
13 time::Duration,
14 time::Duration,
14};
15};
15
16
16−use smol::prelude::*;
17−
18use anyhow::Error;
17use anyhow::Error;
19
18
20use crossterm::{
19use crossterm::{
@@ -39,16 +38,15 @@ pub struct Application {
39 compositor: Compositor,
38 compositor: Compositor,
40 editor: Editor,
39 editor: Editor,
41
40
42− executor: &'static smol::Executor<'static>,
43 callbacks: LspCallbacks,
41 callbacks: LspCallbacks,
44}
42}
45
43
46impl Application {
44impl Application {
47− pub fn new(mut args: Args, executor: &'static smol::Executor<'static>) -> Result<Self, Error> {
45+ pub fn new(mut args: Args) -> Result<Self, Error> {
48 use helix_view::editor::Action;
46 use helix_view::editor::Action;
49 let mut compositor = Compositor::new()?;
47 let mut compositor = Compositor::new()?;
50 let size = compositor.size();
48 let size = compositor.size();
51− let mut editor = Editor::new(executor, size);
49+ let mut editor = Editor::new(size);
52
50
53 if let Ok(files) = args.values_of_t::<PathBuf>("files") {
51 if let Ok(files) = args.values_of_t::<PathBuf>("files") {
54 for file in files {
52 for file in files {
@@ -64,7 +62,6 @@ impl Application {
64 compositor,
62 compositor,
65 editor,
63 editor,
66
64
67− executor,
68 callbacks: FuturesUnordered::new(),
65 callbacks: FuturesUnordered::new(),
69 };
66 };
70
67
@@ -72,14 +69,12 @@ impl Application {
72 }
69 }
73
70
74 fn render(&mut self) {
71 fn render(&mut self) {
75− let executor = &self.executor;
76 let editor = &mut self.editor;
72 let editor = &mut self.editor;
77 let compositor = &mut self.compositor;
73 let compositor = &mut self.compositor;
78 let callbacks = &mut self.callbacks;
74 let callbacks = &mut self.callbacks;
79
75
80 let mut cx = crate::compositor::Context {
76 let mut cx = crate::compositor::Context {
81 editor,
77 editor,
82− executor,
83 callbacks,
78 callbacks,
84 scroll: None,
79 scroll: None,
85 };
80 };
@@ -97,7 +92,7 @@ impl Application {
97 break;
92 break;
98 }
93 }
99
94
100− use futures_util::{select, FutureExt};
95+ use futures_util::{select, FutureExt, StreamExt};
101 select! {
96 select! {
102 event = reader.next().fuse() => {
97 event = reader.next().fuse() => {
103 self.handle_terminal_events(event)
98 self.handle_terminal_events(event)
@@ -125,7 +120,6 @@ impl Application {
125 pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::ErrorKind>>) {
120 pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::ErrorKind>>) {
126 let mut cx = crate::compositor::Context {
121 let mut cx = crate::compositor::Context {
127 editor: &mut self.editor,
122 editor: &mut self.editor,
128− executor: self.executor,
129 callbacks: &mut self.callbacks,
123 callbacks: &mut self.callbacks,
130 scroll: None,
124 scroll: None,
131 };
125 };
helix-term/src/commands.rs+25−17
@@ -108,6 +108,16 @@ impl<'a> Context<'a> {
108/// state (usually by creating and applying a transaction).
108/// state (usually by creating and applying a transaction).
109pub type Command = fn(cx: &mut Context);
109pub type Command = fn(cx: &mut Context);
110
110
111+#[inline]
112+fn block_on<T>(future: impl Future<Output = T>) -> T {
113+ use tokio::runtime::Runtime;
114+ // let rt = Runtime::new().unwrap();
115+ let rt = tokio::runtime::Handle::current();
116+ // let local = LocalSet::new();
117+ // local.block_on(&rt, future)
118+ rt.block_on(future)
119+}
120+
111pub fn move_char_left(cx: &mut Context) {
121pub fn move_char_left(cx: &mut Context) {
112 let count = cx.count;
122 let count = cx.count;
113 let (view, doc) = cx.current();
123 let (view, doc) = cx.current();
@@ -861,7 +871,6 @@ pub fn command_mode(cx: &mut Context) {
861 match *parts.as_slice() {
871 match *parts.as_slice() {
862 ["q"] | ["quit"] => {
872 ["q"] | ["quit"] => {
863 editor.close(editor.view().id);
873 editor.close(editor.view().id);
864− // editor.should_close = true,
865 }
874 }
866 ["o", path] | ["open", path] => {
875 ["o", path] | ["open", path] => {
867 use helix_view::editor::Action;
876 use helix_view::editor::Action;
@@ -871,7 +880,7 @@ pub fn command_mode(cx: &mut Context) {
871 // TODO: non-blocking via save() command
880 // TODO: non-blocking via save() command
872 let id = editor.view().doc;
881 let id = editor.view().doc;
873 let doc = &mut editor.documents[id];
882 let doc = &mut editor.documents[id];
874− smol::block_on(doc.save());
883+ block_on(doc.save());
875 }
884 }
876
885
877 _ => (),
886 _ => (),
@@ -1175,8 +1184,7 @@ pub fn goto_definition(cx: &mut Context) {
1175 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1184 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1176
1185
1177 // TODO: handle fails
1186 // TODO: handle fails
1178− let res =
1179− smol::block_on(language_server.goto_definition(doc.identifier(), pos)).unwrap_or_default();
1187+ let res = block_on(language_server.goto_definition(doc.identifier(), pos)).unwrap_or_default();
1180 _goto(cx, res, offset_encoding);
1188 _goto(cx, res, offset_encoding);
1181}
1189}
1182
1190
@@ -1192,8 +1200,8 @@ pub fn goto_type_definition(cx: &mut Context) {
1192 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1200 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1193
1201
1194 // TODO: handle fails
1202 // TODO: handle fails
1203+ let res =
1195− let res = smol::block_on(language_server.goto_type_definition(doc.identifier(), pos))
1204+ block_on(language_server.goto_type_definition(doc.identifier(), pos)).unwrap_or_default();
1196− .unwrap_or_default();
1197 _goto(cx, res, offset_encoding);
1205 _goto(cx, res, offset_encoding);
1198}
1206}
1199
1207
@@ -1209,8 +1217,8 @@ pub fn goto_implementation(cx: &mut Context) {
1209 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1217 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1210
1218
1211 // TODO: handle fails
1219 // TODO: handle fails
1220+ let res =
1212− let res = smol::block_on(language_server.goto_implementation(doc.identifier(), pos))
1221+ block_on(language_server.goto_implementation(doc.identifier(), pos)).unwrap_or_default();
1213− .unwrap_or_default();
1214 _goto(cx, res, offset_encoding);
1222 _goto(cx, res, offset_encoding);
1215}
1223}
1216
1224
@@ -1226,8 +1234,7 @@ pub fn goto_reference(cx: &mut Context) {
1226 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1234 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1227
1235
1228 // TODO: handle fails
1236 // TODO: handle fails
1229− let res =
1230− smol::block_on(language_server.goto_reference(doc.identifier(), pos)).unwrap_or_default();
1237+ let res = block_on(language_server.goto_reference(doc.identifier(), pos)).unwrap_or_default();
1231 _goto(cx, res, offset_encoding);
1238 _goto(cx, res, offset_encoding);
1232}
1239}
1233
1240
@@ -1247,7 +1254,7 @@ pub fn signature_help(cx: &mut Context) {
1247
1254
1248 // TODO: handle fails
1255 // TODO: handle fails
1249
1256
1250− let res = smol::block_on(language_server.text_document_signature_help(doc.identifier(), pos))
1257+ let res = block_on(language_server.text_document_signature_help(doc.identifier(), pos))
1251 .unwrap_or_default();
1258 .unwrap_or_default();
1252
1259
1253 if let Some(signature_help) = res {
1260 if let Some(signature_help) = res {
@@ -1636,7 +1643,7 @@ pub fn format_selections(cx: &mut Context) {
1636 };
1643 };
1637 // TODO: handle fails
1644 // TODO: handle fails
1638 // TODO: concurrent map
1645 // TODO: concurrent map
1639− let edits = smol::block_on(language_server.text_document_range_formatting(
1646+ let edits = block_on(language_server.text_document_range_formatting(
1640 doc.identifier(),
1647 doc.identifier(),
1641 range,
1648 range,
1642 lsp::FormattingOptions::default(),
1649 lsp::FormattingOptions::default(),
@@ -1726,7 +1733,8 @@ pub fn save(cx: &mut Context) {
1726 // Spawns an async task to actually do the saving. This way we prevent blocking.
1733 // Spawns an async task to actually do the saving. This way we prevent blocking.
1727
1734
1728 // TODO: handle save errors somehow?
1735 // TODO: handle save errors somehow?
1729− cx.editor.executor.spawn(cx.doc().save()).detach();
1736+ // TODO: don't block
1737+ block_on(cx.doc().save());
1730}
1738}
1731
1739
1732pub fn completion(cx: &mut Context) {
1740pub fn completion(cx: &mut Context) {
@@ -1782,7 +1790,7 @@ pub fn completion(cx: &mut Context) {
1782 );
1790 );
1783
1791
1784 // TODO: handle fails
1792 // TODO: handle fails
1785− let res = smol::block_on(language_server.completion(doc.identifier(), pos)).unwrap();
1793+ let res = block_on(language_server.completion(doc.identifier(), pos)).unwrap();
1786
1794
1787 let trigger_offset = doc.selection(view.id).cursor();
1795 let trigger_offset = doc.selection(view.id).cursor();
1788
1796
@@ -1839,8 +1847,8 @@ pub fn hover(cx: &mut Context) {
1839 );
1847 );
1840
1848
1841 // TODO: handle fails
1849 // TODO: handle fails
1850+ let res =
1842− let res = smol::block_on(language_server.text_document_hover(doc.identifier(), pos))
1851+ block_on(language_server.text_document_hover(doc.identifier(), pos)).unwrap_or_default();
1843− .unwrap_or_default();
1844
1852
1845 if let Some(hover) = res {
1853 if let Some(hover) = res {
1846 // hover.contents / .range <- used for visualizing
1854 // hover.contents / .range <- used for visualizing
@@ -1963,7 +1971,7 @@ pub fn space_mode(cx: &mut Context) {
1963 'w' => {
1971 'w' => {
1964 // save current buffer
1972 // save current buffer
1965 let doc = cx.doc();
1973 let doc = cx.doc();
1966− smol::block_on(doc.save());
1974+ block_on(doc.save());
1967 }
1975 }
1968 'c' => {
1976 'c' => {
1969 // close current split
1977 // close current split
helix-term/src/compositor.rs−2
@@ -4,7 +4,6 @@
4
4
5use crossterm::event::Event;
5use crossterm::event::Event;
6use helix_core::Position;
6use helix_core::Position;
7−use smol::Executor;
8use tui::{buffer::Buffer as Surface, layout::Rect};
7use tui::{buffer::Buffer as Surface, layout::Rect};
9
8
10pub type Callback = Box<dyn FnOnce(&mut Compositor, &mut Editor)>;
9pub type Callback = Box<dyn FnOnce(&mut Compositor, &mut Editor)>;
@@ -29,7 +28,6 @@ use crate::application::LspCallbacks;
29
28
30pub struct Context<'a> {
29pub struct Context<'a> {
31 pub editor: &'a mut Editor,
30 pub editor: &'a mut Editor,
32− pub executor: &'static smol::Executor<'static>,
33 pub scroll: Option<usize>,
31 pub scroll: Option<usize>,
34 pub callbacks: &'a mut LspCallbacks,
32 pub callbacks: &'a mut LspCallbacks,
35}
33}
helix-term/src/main.rs+6−8
@@ -14,8 +14,6 @@ use std::path::PathBuf;
14
14
15use anyhow::Error;
15use anyhow::Error;
16
16
17−static EX: smol::Executor = smol::Executor::new();
18−
19fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
17fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
20 let mut base_config = fern::Dispatch::new();
18 let mut base_config = fern::Dispatch::new();
21
19
@@ -88,12 +86,12 @@ fn main() {
88 Loader::new(config)
86 Loader::new(config)
89 });
87 });
90
88
91− for _ in 0..num_cpus::get() {
89+ let runtime = tokio::runtime::Runtime::new().unwrap();
92− std::thread::spawn(move || smol::block_on(EX.run(smol::future::pending::<()>())));
93− }
94
90
91+ // TODO: use the thread local executor to spawn the application task separately from the work pool
92+ runtime.block_on(async move {
95− let mut app = Application::new(args, &EX).unwrap();
93+ let mut app = Application::new(args).unwrap();
96
94
97− // we use the thread local executor to spawn the application task separately from the work pool
98− smol::block_on(app.run());
95+ app.run().await;
96+ });
99}
97}
helix-term/src/ui/editor.rs+1−2
@@ -207,7 +207,7 @@ impl EditorView {
207 });
207 });
208
208
209 let style = if is_diagnostic {
209 let style = if is_diagnostic {
210− style.clone().add_modifier(Modifier::UNDERLINED)
210+ style.add_modifier(Modifier::UNDERLINED)
211 } else {
211 } else {
212 style
212 style
213 };
213 };
@@ -569,7 +569,6 @@ impl Component for EditorView {
569 let mut cx = Context {
569 let mut cx = Context {
570 editor: cxt.editor,
570 editor: cxt.editor,
571 callbacks: cxt.callbacks,
571 callbacks: cxt.callbacks,
572− executor: cx.executor,
573 scroll: None,
572 scroll: None,
574 };
573 };
575 let res = completion.handle_event(event, &mut cx);
574 let res = completion.handle_event(event, &mut cx);
helix-view/Cargo.toml+1−1
@@ -21,7 +21,7 @@ crossterm = { version = "0.19", features = ["event-stream"], optional = true }
21once_cell = "1.4"
21once_cell = "1.4"
22url = "2"
22url = "2"
23
23
24−smol = "1"
24+tokio = { version = "1", features = ["full"] }
25futures-util = "0.3"
25futures-util = "0.3"
26
26
27slotmap = "1"
27slotmap = "1"
helix-view/src/document.rs+4−2
@@ -134,7 +134,7 @@ impl Document {
134 self.last_saved_revision = self.history.current_revision();
134 self.last_saved_revision = self.history.current_revision();
135
135
136 async move {
136 async move {
137− use smol::{fs::File, prelude::*};
137+ use tokio::{fs::File, io::AsyncWriteExt};
138 let mut file = File::create(path).await?;
138 let mut file = File::create(path).await?;
139
139
140 // write all the rope chunks to file
140 // write all the rope chunks to file
@@ -232,7 +232,9 @@ impl Document {
232 transaction.changes(),
232 transaction.changes(),
233 );
233 );
234
234
235+ if let Some(notify) = notify {
236+ tokio::spawn(notify);
235− smol::block_on(notify).expect("failed to emit textDocument/didChange");
237+ } //.expect("failed to emit textDocument/didChange");
236 }
238 }
237 }
239 }
238 success
240 success
helix-view/src/editor.rs+8−8
@@ -13,7 +13,6 @@ pub struct Editor {
13 pub count: Option<usize>,
13 pub count: Option<usize>,
14 pub theme: Theme,
14 pub theme: Theme,
15 pub language_servers: helix_lsp::Registry,
15 pub language_servers: helix_lsp::Registry,
16− pub executor: &'static smol::Executor<'static>,
17}
16}
18
17
19#[derive(Copy, Clone)]
18#[derive(Copy, Clone)]
@@ -24,7 +23,7 @@ pub enum Action {
24}
23}
25
24
26impl Editor {
25impl Editor {
27− pub fn new(executor: &'static smol::Executor<'static>, mut area: tui::layout::Rect) -> Self {
26+ pub fn new(mut area: tui::layout::Rect) -> Self {
28 use helix_core::config_dir;
27 use helix_core::config_dir;
29 let config = std::fs::read(config_dir().join("theme.toml"));
28 let config = std::fs::read(config_dir().join("theme.toml"));
30 // load $HOME/.config/helix/theme.toml, fallback to default config
29 // load $HOME/.config/helix/theme.toml, fallback to default config
@@ -44,7 +43,6 @@ impl Editor {
44 count: None,
43 count: None,
45 theme,
44 theme,
46 language_servers,
45 language_servers,
47− executor,
48 }
46 }
49 }
47 }
50
48
@@ -122,7 +120,7 @@ impl Editor {
122 let language_server = doc
120 let language_server = doc
123 .language
121 .language
124 .as_ref()
122 .as_ref()
125− .and_then(|language| self.language_servers.get(language, self.executor));
123+ .and_then(|language| self.language_servers.get(language));
126
124
127 if let Some(language_server) = language_server {
125 if let Some(language_server) = language_server {
128 doc.set_language_server(Some(language_server.clone()));
126 doc.set_language_server(Some(language_server.clone()));
@@ -133,7 +131,8 @@ impl Editor {
133 .map(ToOwned::to_owned)
131 .map(ToOwned::to_owned)
134 .unwrap_or_default();
132 .unwrap_or_default();
135
133
134+ let rt = tokio::runtime::Handle::current();
136− smol::block_on(language_server.text_document_did_open(
135+ rt.block_on(language_server.text_document_did_open(
137 doc.url().unwrap(),
136 doc.url().unwrap(),
138 doc.version(),
137 doc.version(),
139 doc.text(),
138 doc.text(),
@@ -154,17 +153,18 @@ impl Editor {
154 let view = self.tree.get(self.tree.focus);
153 let view = self.tree.get(self.tree.focus);
155 // get around borrowck issues
154 // get around borrowck issues
156 let language_servers = &mut self.language_servers;
155 let language_servers = &mut self.language_servers;
157− let executor = self.executor;
158
156
159 let doc = &self.documents[view.doc];
157 let doc = &self.documents[view.doc];
160
158
161 let language_server = doc
159 let language_server = doc
162 .language
160 .language
163 .as_ref()
161 .as_ref()
164− .and_then(|language| language_servers.get(language, executor));
162+ .and_then(|language| language_servers.get(language));
165
163
166 if let Some(language_server) = language_server {
164 if let Some(language_server) = language_server {
165+ let rt = tokio::runtime::Handle::current();
167− smol::block_on(language_server.text_document_did_close(doc.identifier())).unwrap();
166+ rt.block_on(language_server.text_document_did_close(doc.identifier()))
167+ .unwrap();
168 }
168 }
169
169
170 // remove selection
170 // remove selection