1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 05:42:25 -05:00

feat: repl improvements

This commit is contained in:
snek 2024-08-12 22:34:49 +02:00
parent 507e5b74ff
commit d7d49be0f9
No known key found for this signature in database
10 changed files with 325 additions and 167 deletions

184
Cargo.lock generated
View file

@ -453,10 +453,10 @@ version = "0.69.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"cexpr",
"clang-sys",
"itertools",
"itertools 0.12.1",
"lazy_static",
"lazycell",
"log",
@ -493,9 +493,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
dependencies = [
"serde",
]
@ -649,6 +649,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chrono"
version = "0.4.37"
@ -1043,7 +1049,7 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"libloading 0.8.3",
"winapi",
]
@ -1206,7 +1212,6 @@ dependencies = [
"ring",
"runtimelib",
"rustyline",
"rustyline-derive",
"serde",
"serde_json",
"serde_repr",
@ -1612,7 +1617,7 @@ dependencies = [
"hyper 0.14.28",
"hyper 1.4.1",
"hyper-util",
"itertools",
"itertools 0.10.5",
"memmem",
"mime",
"once_cell",
@ -3238,7 +3243,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"gpu-alloc-types",
]
@ -3248,7 +3253,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
]
[[package]]
@ -3257,7 +3262,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"gpu-descriptor-types",
"hashbrown",
]
@ -3268,7 +3273,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
]
[[package]]
@ -3839,6 +3844,15 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
@ -4052,9 +4066,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libffi"
@ -4092,7 +4106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [
"cfg-if",
"windows-targets 0.52.4",
"windows-targets 0.48.5",
]
[[package]]
@ -4107,7 +4121,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"libc",
]
@ -4178,9 +4192,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.21"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
dependencies = [
"serde",
]
@ -4312,7 +4326,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"block",
"core-graphics-types",
"foreign-types",
@ -4375,7 +4389,7 @@ checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231"
dependencies = [
"arrayvec",
"bit-set",
"bitflags 2.5.0",
"bitflags 2.6.0",
"codespan-reporting",
"hexf-parse",
"indexmap",
@ -4464,12 +4478,13 @@ dependencies = [
[[package]]
name = "nix"
version = "0.27.1"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"cfg-if",
"cfg_aliases 0.2.1",
"libc",
]
@ -4518,7 +4533,7 @@ version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"crossbeam-channel",
"filetime",
"fsevent-sys",
@ -5277,7 +5292,7 @@ checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
dependencies = [
"bytes",
"heck 0.4.1",
"itertools",
"itertools 0.10.5",
"lazy_static",
"log",
"multimap",
@ -5298,7 +5313,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
dependencies = [
"anyhow",
"itertools",
"itertools 0.10.5",
"proc-macro2",
"quote",
"syn 1.0.109",
@ -5348,7 +5363,7 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"memchr",
"unicase",
]
@ -5704,7 +5719,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
"base64 0.21.7",
"bitflags 2.5.0",
"bitflags 2.6.0",
"serde",
"serde_derive",
]
@ -5772,7 +5787,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
@ -5825,7 +5840,7 @@ version = "0.38.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"errno 0.3.8",
"libc",
"linux-raw-sys",
@ -5907,11 +5922,9 @@ checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
[[package]]
name = "rustyline"
version = "13.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86"
version = "14.0.0"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"cfg-if",
"clipboard-win",
"fd-lock",
@ -5919,23 +5932,12 @@ dependencies = [
"libc",
"log",
"memchr",
"nix 0.27.1",
"nix 0.29.0",
"radix_trie",
"unicode-segmentation",
"unicode-width",
"utf8parse",
"winapi",
]
[[package]]
name = "rustyline-derive"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "107c3d5d7f370ac09efa62a78375f94d94b8a33c61d8c278b96683fb4dbf2d8d"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"windows-sys 0.59.0",
]
[[package]]
@ -6397,7 +6399,7 @@ version = "0.3.0+sdk-1.3.268.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
]
[[package]]
@ -6644,7 +6646,7 @@ version = "0.117.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5da2f0310e8cd84b8c803095e75b2cbca872c71fc7f7404d4c9c8117d894960"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"is-macro",
"num-bigint",
"phf 0.11.2",
@ -6730,7 +6732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6df81c1cbb920d9c47abe6fb105363b0f78df2c8f6b0910c4fdd2ad7cbdfb23d"
dependencies = [
"better_scoped_tls",
"bitflags 2.5.0",
"bitflags 2.6.0",
"indexmap",
"once_cell",
"phf 0.11.2",
@ -7392,7 +7394,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
dependencies = [
"async-compression",
"bitflags 2.5.0",
"bitflags 2.6.0",
"bytes",
"futures-core",
"http 1.1.0",
@ -7799,7 +7801,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88a710d5b95bff79a90708203cf9f74384e080d21fc6664aa4df463f2c66ac83"
dependencies = [
"bindgen",
"bitflags 2.5.0",
"bitflags 2.6.0",
"fslock",
"gzip-header",
"home",
@ -7815,7 +7817,7 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97599c400fc79925922b58303e98fcb8fa88f573379a08ddb652e72cbd2e70f6"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"encoding_rs",
"indexmap",
"num-bigint",
@ -8013,8 +8015,8 @@ checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39"
dependencies = [
"arrayvec",
"bit-vec",
"bitflags 2.5.0",
"cfg_aliases",
"bitflags 2.6.0",
"cfg_aliases 0.1.1",
"codespan-reporting",
"document-features",
"indexmap",
@ -8044,9 +8046,9 @@ dependencies = [
"arrayvec",
"ash",
"bit-set",
"bitflags 2.5.0",
"bitflags 2.6.0",
"block",
"cfg_aliases",
"cfg_aliases 0.1.1",
"core-graphics-types",
"d3d12",
"glow",
@ -8082,7 +8084,7 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef"
dependencies = [
"bitflags 2.5.0",
"bitflags 2.6.0",
"js-sys",
"serde",
"web-sys",
@ -8177,7 +8179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core",
"windows-targets 0.52.4",
"windows-targets 0.52.6",
]
[[package]]
@ -8186,7 +8188,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.4",
"windows-targets 0.52.6",
]
[[package]]
@ -8204,7 +8206,16 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.4",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
@ -8224,17 +8235,18 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.4",
"windows_aarch64_msvc 0.52.4",
"windows_i686_gnu 0.52.4",
"windows_i686_msvc 0.52.4",
"windows_x86_64_gnu 0.52.4",
"windows_x86_64_gnullvm 0.52.4",
"windows_x86_64_msvc 0.52.4",
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
@ -8245,9 +8257,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
@ -8257,9 +8269,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
@ -8269,9 +8281,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
@ -8281,9 +8299,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
@ -8293,9 +8311,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
@ -8305,9 +8323,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
@ -8317,9 +8335,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"

View file

@ -159,7 +159,7 @@ rustls = { version = "0.23.11", default-features = false, features = ["logging",
rustls-pemfile = "2"
rustls-tokio-stream = "=0.3.0"
rustls-webpki = "0.102"
rustyline = "=13.0.0"
rustyline = { path = "../../rustyline" } # "14.0.0"
saffron = "=0.1.0"
scopeguard = "1.2.0"
serde = { version = "1.0.149", features = ["derive"] }

View file

@ -138,7 +138,6 @@ rand = { workspace = true, features = ["small_rng"] }
regex.workspace = true
ring.workspace = true
rustyline.workspace = true
rustyline-derive = "=0.7.0"
serde.workspace = true
serde_repr.workspace = true
sha2.workspace = true

View file

@ -119,6 +119,7 @@ impl ReplLanguageServer {
&mut self,
line_text: &str,
position: usize,
explicit: bool,
) -> Vec<ReplCompletionItem> {
self.did_change(line_text).await;
let text_info = deno_ast::SourceTextInfo::from_string(format!(
@ -147,7 +148,11 @@ impl ReplLanguageServer {
partial_result_token: None,
},
context: Some(CompletionContext {
trigger_kind: CompletionTriggerKind::INVOKED,
trigger_kind: if explicit {
CompletionTriggerKind::INVOKED
} else {
CompletionTriggerKind::TRIGGER_CHARACTER
},
trigger_character: None,
}),
})
@ -155,28 +160,34 @@ impl ReplLanguageServer {
.ok()
.unwrap_or_default();
let mut items = match response {
let items = match response {
Some(CompletionResponse::Array(items)) => items,
Some(CompletionResponse::List(list)) => list.items,
None => Vec::new(),
None => return vec![],
};
items.sort_by_key(|item| {
if let Some(sort_text) = &item.sort_text {
sort_text.clone()
} else {
item.label.clone()
}
});
items
.into_iter()
.filter_map(|item| {
item.text_edit.and_then(|edit| match edit {
CompletionTextEdit::Edit(edit) => Some(ReplCompletionItem {
if let Some(CompletionTextEdit::Edit(edit)) = item.text_edit {
return Some(ReplCompletionItem {
new_text: edit.new_text,
range: lsp_range_to_std_range(&text_info, &edit.range),
}),
CompletionTextEdit::InsertAndReplace(_) => None,
});
}
None
/*
if let Some(text) = item.insert_text {
return Some(ReplCompletionItem {
range:line_and_column.column_index..(line_and_column.column_index + text.len()),
new_text: text,
})
}
Some(ReplCompletionItem {
range: line_and_column.column_index..(line_and_column.column_index + item.label.len()),
new_text: item.label,
})
*/
})
.filter(|item| {
// filter the results to only exact matches

View file

@ -407,7 +407,7 @@ impl JupyterReplSession {
self
.repl_session
.language_server
.completions(line_text, position)
.completions(line_text, position, true)
.await
}
@ -485,7 +485,7 @@ impl JupyterReplSession {
) -> Result<repl::TsEvaluateResponse, AnyError> {
self
.repl_session
.evaluate_line_with_object_wrapping(line)
.evaluate_line_with_object_wrapping(line, false)
.await
}

View file

@ -42,12 +42,17 @@ pub enum RustylineSyncMessage {
LspCompletions {
line_text: String,
position: usize,
explicit: bool,
},
Preview {
line_text: String,
},
}
pub enum RustylineSyncResponse {
PostMessage(Result<Value, AnyError>),
LspCompletions(Vec<ReplCompletionItem>),
Preview(Option<(String, usize)>),
}
pub struct RustylineSyncMessageSender {
@ -75,7 +80,7 @@ impl RustylineSyncMessageSender {
} else {
match self.response_rx.borrow_mut().blocking_recv().unwrap() {
RustylineSyncResponse::PostMessage(result) => result,
RustylineSyncResponse::LspCompletions(_) => unreachable!(),
_ => unreachable!(),
}
}
}
@ -84,12 +89,14 @@ impl RustylineSyncMessageSender {
&self,
line_text: &str,
position: usize,
explicit: bool,
) -> Vec<ReplCompletionItem> {
if self
.message_tx
.blocking_send(RustylineSyncMessage::LspCompletions {
line_text: line_text.to_string(),
position,
explicit,
})
.is_err()
{
@ -97,7 +104,24 @@ impl RustylineSyncMessageSender {
} else {
match self.response_rx.borrow_mut().blocking_recv().unwrap() {
RustylineSyncResponse::LspCompletions(result) => result,
RustylineSyncResponse::PostMessage(_) => unreachable!(),
_ => unreachable!(),
}
}
}
pub fn preview(&self, line_text: &str) -> Option<(String, usize)> {
if self
.message_tx
.blocking_send(RustylineSyncMessage::Preview {
line_text: line_text.to_string(),
})
.is_err()
{
None
} else {
match self.response_rx.borrow_mut().blocking_recv().unwrap() {
RustylineSyncResponse::Preview(result) => result,
_ => unreachable!(),
}
}
}

View file

@ -14,6 +14,8 @@ use deno_core::serde_json;
use rustyline::completion::Completer;
use rustyline::error::ReadlineError;
use rustyline::highlight::Highlighter;
use rustyline::hint::Hinter;
use rustyline::preview::Previewer;
use rustyline::validate::ValidationContext;
use rustyline::validate::ValidationResult;
use rustyline::validate::Validator;
@ -26,12 +28,11 @@ use rustyline::Editor;
use rustyline::Event;
use rustyline::EventContext;
use rustyline::EventHandler;
use rustyline::Helper;
use rustyline::KeyCode;
use rustyline::KeyEvent;
use rustyline::Modifiers;
use rustyline::RepeatCount;
use rustyline_derive::Helper;
use rustyline_derive::Hinter;
use std::borrow::Cow;
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;
@ -43,7 +44,6 @@ use super::session::REPL_INTERNALS_NAME;
// Provides helpers to the editor like validation for multi-line edits, completion candidates for
// tab completion.
#[derive(Helper, Hinter)]
pub struct EditorHelper {
pub context_id: u64,
pub sync_sender: RustylineSyncMessageSender,
@ -181,6 +181,8 @@ fn get_expr_from_line_at_pos(line: &str, cursor_pos: usize) -> &str {
word
}
impl Helper for EditorHelper {}
impl Completer for EditorHelper {
type Candidate = String;
@ -190,7 +192,7 @@ impl Completer for EditorHelper {
pos: usize,
_ctx: &Context<'_>,
) -> Result<(usize, Vec<String>), ReadlineError> {
let lsp_completions = self.sync_sender.lsp_completions(line, pos);
let lsp_completions = self.sync_sender.lsp_completions(line, pos, true);
if !lsp_completions.is_empty() {
// assumes all lsp completions have the same start position
return Ok((
@ -234,6 +236,51 @@ impl Completer for EditorHelper {
}
}
impl Hinter for EditorHelper {
type Hint = String;
fn hint(&self, line: &str, pos: usize, ctx: &Context) -> Option<Self::Hint> {
if line.trim().is_empty() || line.ends_with(')') || line.ends_with('}') {
return None;
}
let (p, completions) = self.complete(line, pos, ctx).ok()?;
let candidate = completions.into_iter().next()?;
// let lsp_completions = self.sync_sender.lsp_completions(line, pos, false);
//let completion = completions.into_iter().next()?;
// let p = completion.range.start;
// let candidate = completion.new_text;
let mut i = 0;
for (a, b) in line[p..].chars().zip(candidate.chars()) {
if a == b {
i += 1;
} else {
break;
}
}
Some(candidate[i..].to_owned())
}
}
impl Previewer for EditorHelper {
type Preview = String;
fn preview(
&self,
line: &str,
_pos: usize,
_ctx: &Context,
) -> Option<Self::Preview> {
if line.trim().is_empty() {
return None;
}
let (preview, counter) = self.sync_sender.preview(line)?;
Some(format!("Out[{counter}]: {preview}"))
}
}
impl Validator for EditorHelper {
fn validate(
&self,
@ -326,7 +373,11 @@ fn validate(input: &str) -> ValidationResult {
impl Highlighter for EditorHelper {
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
hint.into()
format!("{}", colors::gray(hint)).into()
}
fn highlight_preview<'h>(&self, hint: &'h str) -> Cow<'h, str> {
format!("{}", colors::gray(hint)).into()
}
fn highlight_candidate<'c>(
@ -477,8 +528,24 @@ impl ReplEditor {
})
}
pub fn readline(&self) -> Result<String, ReadlineError> {
self.inner.lock().readline("> ")
pub fn readline(&self, counter: usize) -> Result<String, ReadlineError> {
let prompt = format!(
"{}{}{}",
colors::green("In ["),
colors::green_bold(counter),
colors::green("]: ")
);
self.inner.lock().readline(&prompt)
}
pub fn output(&self, output: String, counter: usize) {
let prompt = format!(
"{}{}{}",
colors::red("Out["),
colors::red_bold(counter),
colors::red("]: ")
);
println!("{prompt}{output}\n");
}
pub fn update_history(&self, entry: String) {

View file

@ -44,18 +44,23 @@ struct Repl {
#[allow(clippy::print_stdout)]
impl Repl {
async fn run(&mut self) -> Result<(), AnyError> {
let mut counter = 1;
loop {
let line = read_line_and_poll(
&mut self.session,
&mut self.message_handler,
self.editor.clone(),
counter,
)
.await;
match line {
Ok(line) => {
self.editor.set_should_exit_on_interrupt(false);
self.editor.update_history(line.clone());
let output = self.session.evaluate_line_and_get_output(&line).await;
let output = self
.session
.evaluate_line_and_get_output(&line, counter)
.await;
// We check for close and break here instead of making it a loop condition to get
// consistent behavior in when the user evaluates a call to close().
@ -63,7 +68,15 @@ impl Repl {
break;
}
println!("{}", output);
match output {
EvaluationOutput::Value(s) => {
self.editor.output(s, counter);
}
EvaluationOutput::Error(s) => {
println!("{}\n", s);
}
};
counter += 1;
}
Err(ReadlineError::Interrupted) => {
if self.editor.should_exit_on_interrupt() {
@ -92,8 +105,9 @@ async fn read_line_and_poll(
repl_session: &mut ReplSession,
message_handler: &mut RustylineSyncMessageHandler,
editor: ReplEditor,
counter: usize,
) -> Result<String, ReadlineError> {
let mut line_fut = spawn_blocking(move || editor.readline());
let mut line_fut = spawn_blocking(move || editor.readline(counter));
let mut poll_worker = true;
let notifications_rc = repl_session.notifications.clone();
let mut notifications = notifications_rc.lock().await;
@ -114,10 +128,29 @@ async fn read_line_and_poll(
Some(RustylineSyncMessage::LspCompletions {
line_text,
position,
explicit,
}) => {
let result = repl_session.language_server.completions(&line_text, position).await;
let result = repl_session.language_server.completions(&line_text, position, explicit).await;
message_handler.send(RustylineSyncResponse::LspCompletions(result)).unwrap();
}
Some(RustylineSyncMessage::Preview { line_text }) => {
let result = repl_session.evaluate_line_with_object_wrapping(&line_text, true).await;
let result = match result {
Ok(evaluate_response) => {
let cdp::EvaluateResponse {
result,
exception_details,
} = evaluate_response.value;
if exception_details.is_some() {
None
} else {
repl_session.get_eval_value(&result, true).await.ok().map(|s| (s, counter))
}
},
_ => None,
};
message_handler.send(RustylineSyncResponse::Preview(result)).unwrap();
}
None => {}, // channel closed
}
@ -217,7 +250,7 @@ pub async fn run(
Ok(eval_source) => {
let output = repl
.session
.evaluate_line_and_get_output(&eval_source)
.evaluate_line_and_get_output(&eval_source, 0)
.await;
// only output errors
if let EvaluationOutput::Error(error_text) = output {
@ -232,7 +265,7 @@ pub async fn run(
}
if let Some(eval) = repl_flags.eval {
let output = repl.session.evaluate_line_and_get_output(&eval).await;
let output = repl.session.evaluate_line_and_get_output(&eval, 0).await;
// only output errors
if let EvaluationOutput::Error(error_text) = output {
println!("Error in --eval flag: {error_text}");

View file

@ -95,8 +95,6 @@ Object.defineProperty(globalThis, "{0}", {{
enumerable: false,
writable: false,
value: {{
lastEvalResult: undefined,
lastThrownError: undefined,
inspectArgs: Deno[Deno.internal].inspectArgs,
noColor: Deno.noColor,
get closed() {{
@ -104,35 +102,6 @@ Object.defineProperty(globalThis, "{0}", {{
}}
}},
}});
Object.defineProperty(globalThis, "_", {{
configurable: true,
get: () => {0}.lastEvalResult,
set: (value) => {{
Object.defineProperty(globalThis, "_", {{
value: value,
writable: true,
enumerable: true,
configurable: true,
}});
console.log("Last evaluation result is no longer saved to _.");
}},
}});
Object.defineProperty(globalThis, "_error", {{
configurable: true,
get: () => {0}.lastThrownError,
set: (value) => {{
Object.defineProperty(globalThis, "_error", {{
value: value,
writable: true,
enumerable: true,
configurable: true,
}});
console.log("Last thrown error is no longer saved to _error.");
}},
}});
globalThis.clear = console.clear.bind(console);
"#,
*REPL_INTERNALS_NAME
@ -289,7 +258,9 @@ impl ReplSession {
};
// inject prelude
repl_session.evaluate_expression(&get_prelude()).await?;
repl_session
.evaluate_expression(&get_prelude(), false)
.await?;
Ok(repl_session)
}
@ -304,7 +275,7 @@ impl ReplSession {
pub async fn closing(&mut self) -> Result<bool, AnyError> {
let expression = format!(r#"{}.closed"#, *REPL_INTERNALS_NAME);
let closed = self
.evaluate_expression(&expression)
.evaluate_expression(&expression, false)
.await?
.result
.value
@ -343,6 +314,7 @@ impl ReplSession {
pub async fn evaluate_line_and_get_output(
&mut self,
line: &str,
counter: usize,
) -> EvaluationOutput {
fn format_diagnostic(diagnostic: &deno_ast::ParseDiagnostic) -> String {
let display_position = diagnostic.display_position();
@ -358,8 +330,12 @@ impl ReplSession {
async fn inner(
session: &mut ReplSession,
line: &str,
counter: usize,
) -> Result<EvaluationOutput, AnyError> {
match session.evaluate_line_with_object_wrapping(line).await {
match session
.evaluate_line_with_object_wrapping(line, false)
.await
{
Ok(evaluate_response) => {
let cdp::EvaluateResponse {
result,
@ -390,8 +366,8 @@ impl ReplSession {
.commit_text(&evaluate_response.ts_code)
.await;
session.set_last_eval_result(&result).await?;
let value = session.get_eval_value(&result).await?;
session.set_last_eval_result(&result, counter).await?;
let value = session.get_eval_value(&result, false).await?;
EvaluationOutput::Value(value)
})
}
@ -417,13 +393,14 @@ impl ReplSession {
}
}
let result = inner(self, line).await;
let result = inner(self, line, counter).await;
result_to_evaluation_output(result)
}
pub async fn evaluate_line_with_object_wrapping(
&mut self,
line: &str,
throw_on_side_effect: bool,
) -> Result<TsEvaluateResponse, AnyError> {
// Expressions like { "foo": "bar" } are interpreted as block expressions at the
// statement level rather than an object literal so we interpret it as an expression statement
@ -436,7 +413,9 @@ impl ReplSession {
line.to_string()
};
let evaluate_response = self.evaluate_ts_expression(&wrapped_line).await;
let evaluate_response = self
.evaluate_ts_expression(&wrapped_line, throw_on_side_effect)
.await;
// If that fails, we retry it without wrapping in parens letting the error bubble up to the
// user if it is still an error.
@ -449,7 +428,9 @@ impl ReplSession {
.exception_details
.is_some())
{
self.evaluate_ts_expression(line).await
self
.evaluate_ts_expression(line, throw_on_side_effect)
.await
} else {
evaluate_response
};
@ -486,10 +467,17 @@ impl ReplSession {
.post_message_with_event_loop(
"Runtime.callFunctionOn",
Some(cdp::CallFunctionOnArgs {
function_declaration: format!(
r#"function (object) {{ {}.lastThrownError = object; }}"#,
*REPL_INTERNALS_NAME
),
function_declaration: r#"
function (object) {
Object.defineProperty(globalThis, '_error', {
value: object,
enumerable: false,
configurable: true,
writable: true,
});
}
"#
.to_string(),
object_id: None,
arguments: Some(vec![error.into()]),
silent: None,
@ -509,14 +497,25 @@ impl ReplSession {
async fn set_last_eval_result(
&mut self,
evaluate_result: &cdp::RemoteObject,
counter: usize,
) -> Result<(), AnyError> {
self
.post_message_with_event_loop(
"Runtime.callFunctionOn",
Some(cdp::CallFunctionOnArgs {
function_declaration: format!(
r#"function (object) {{ {}.lastEvalResult = object; }}"#,
*REPL_INTERNALS_NAME
r#"function (object) {{
const desc = {{
writable: true,
configurable: true,
enumerable: false,
value: object,
}};
Object.defineProperties(globalThis, {{
_: desc,
"_{counter}": desc,
}});
}}"#,
),
object_id: None,
arguments: Some(vec![evaluate_result.into()]),
@ -572,6 +571,7 @@ impl ReplSession {
pub async fn get_eval_value(
&mut self,
evaluate_result: &cdp::RemoteObject,
no_color: bool,
) -> Result<String, AnyError> {
// TODO(caspervonb) we should investigate using previews here but to keep things
// consistent with the previous implementation we just get the preview result from
@ -581,12 +581,12 @@ impl ReplSession {
format!(
r#"function (object) {{
try {{
return {0}.inspectArgs(["%o", object], {{ colors: !{0}.noColor }});
return {0}.inspectArgs(["%o", object], {{ colors: (!{0}.noColor && !{1}) }});
}} catch (err) {{
return {0}.inspectArgs(["%o", err]);
}}
}}"#,
*REPL_INTERNALS_NAME
*REPL_INTERNALS_NAME, no_color
),
&[evaluate_result.clone()],
)
@ -600,6 +600,7 @@ impl ReplSession {
async fn evaluate_ts_expression(
&mut self,
expression: &str,
throw_on_side_effect: bool,
) -> Result<TsEvaluateResponse, AnyError> {
let parsed_source =
match parse_source_as(expression.to_string(), deno_ast::MediaType::Tsx) {
@ -653,7 +654,7 @@ impl ReplSession {
.text;
let value = self
.evaluate_expression(&format!("'use strict'; void 0;{transpiled_src}"))
.evaluate_expression(&transpiled_src, throw_on_side_effect)
.await?;
Ok(TsEvaluateResponse {
@ -733,6 +734,7 @@ impl ReplSession {
async fn evaluate_expression(
&mut self,
expression: &str,
throw_on_side_effect: bool,
) -> Result<cdp::EvaluateResponse, AnyError> {
self
.post_message_with_event_loop(
@ -747,8 +749,12 @@ impl ReplSession {
generate_preview: None,
user_gesture: None,
await_promise: None,
throw_on_side_effect: None,
timeout: None,
throw_on_side_effect: Some(throw_on_side_effect),
timeout: if throw_on_side_effect {
Some(100)
} else {
None
},
disable_breaks: None,
repl_mode: Some(true),
allow_unsafe_eval_blocked_by_csp: None,

View file

@ -412,7 +412,7 @@ pub fn op_read_line_prompt(
let mut editor = Editor::<(), rustyline::history::DefaultHistory>::new()
.expect("Failed to create editor.");
editor.set_keyseq_timeout(1);
editor.set_keyseq_timeout(Some(1));
editor
.bind_sequence(KeyEvent(KeyCode::Esc, Modifiers::empty()), Cmd::Interrupt);