diff --git a/Cargo.lock b/Cargo.lock index 324b526bc4..f57f90d866 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,6 +37,14 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ansi_term" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "anymap" version = "0.12.1" @@ -1003,6 +1011,7 @@ dependencies = [ name = "gluon_repl" version = "0.12.0" dependencies = [ + "ansi_term 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3131,6 +3140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum ansi_term 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaa72766c3585a1f812a3387a7e2c6cab780f899c2f43ff6ea06c8d071fcbb36" "checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" diff --git a/repl/Cargo.toml b/repl/Cargo.toml index 22b14aa3e8..02168db1c6 100644 --- a/repl/Cargo.toml +++ b/repl/Cargo.toml @@ -20,7 +20,6 @@ path = "src/main.rs" doc = false [dependencies] - gluon = { version = "0.12.0", path = "..", features = ["serialization"] } # GLUON gluon_vm = { version = "0.12.0", path = "../vm", features = ["serialization"] } # GLUON gluon_completion = { path = "../completion", version = "0.12.0" } # GLUON @@ -28,6 +27,7 @@ gluon_codegen = { path = "../codegen", version = "0.12.0" } # GLUON gluon_format = { version = "0.12.0", path = "../format" } # GLUON gluon_doc = { version = "0.12.0", path = "../doc" } # GLUON +ansi_term = "0.12" app_dirs = "1.0.0" futures = "0.1.11" futures-cpupool = "0.1" diff --git a/repl/src/repl.rs b/repl/src/repl.rs index 76e7330f37..be2dac8a67 100644 --- a/repl/src/repl.rs +++ b/repl/src/repl.rs @@ -1,10 +1,6 @@ -extern crate codespan_reporting; -extern crate futures_cpupool; -extern crate rustyline; - extern crate gluon_completion as completion; -use std::{error::Error as StdError, path::PathBuf, str::FromStr, sync::Mutex}; +use std::{borrow::Cow, error::Error as StdError, path::PathBuf, str::FromStr, sync::Mutex}; use futures::{ future::{self, Either}, @@ -165,13 +161,55 @@ fn complete(thread: &Thread, name: &str, fileinput: &str, pos: usize) -> GluonRe .collect()) } -struct Completer(RootedThread); +struct Completer { + thread: RootedThread, + hinter: rustyline::hint::HistoryHinter, + highlighter: rustyline::highlight::MatchingBracketHighlighter, +} impl rustyline::Helper for Completer {} -impl rustyline::hint::Hinter for Completer {} +impl rustyline::hint::Hinter for Completer { + fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context) -> Option { + self.hinter.hint(line, pos, ctx) + } +} + +impl rustyline::highlight::Highlighter for Completer { + fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> { + self.highlighter.highlight(line, pos) + } + + fn highlight_prompt<'b, 's: 'b, 'p: 'b>( + &'s self, + prompt: &'p str, + default: bool, + ) -> Cow<'b, str> { + self.highlighter.highlight_prompt(prompt, default) + } -impl rustyline::highlight::Highlighter for Completer {} + fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { + // TODO Detect when windows supports ANSI escapes + if cfg!(windows) { + Cow::Borrowed(hint) + } else { + use ansi_term::Style; + Cow::Owned(Style::new().dimmed().paint(hint).to_string()) + } + } + + fn highlight_candidate<'c>( + &self, + candidate: &'c str, + completion: rustyline::CompletionType, + ) -> Cow<'c, str> { + self.highlighter.highlight_candidate(candidate, completion) + } + + fn highlight_char(&self, line: &str, pos: usize) -> bool { + self.highlighter.highlight_char(line, pos) + } +} impl rustyline::completion::Completer for Completer { type Candidate = String; @@ -182,7 +220,7 @@ impl rustyline::completion::Completer for Completer { pos: usize, _: &rustyline::Context, ) -> rustyline::Result<(usize, Vec)> { - let result = complete(&self.0, "", line, pos); + let result = complete(&self.thread, "", line, pos); // Get the start of the completed identifier let ident_start = line[..pos] @@ -214,7 +252,7 @@ impl_userdata! { Editor } #[derive(Userdata, Trace, VmType)] #[gluon(vm_type = "CpuPool")] #[gluon_trace(skip)] -struct CpuPool(self::futures_cpupool::CpuPool); +struct CpuPool(futures_cpupool::CpuPool); impl_userdata! { CpuPool } @@ -262,7 +300,11 @@ fn new_editor(vm: WithVM<()>) -> IO { if let Err(err) = history_result { warn!("Unable to load history: {}", err); } - editor.set_helper(Some(Completer(vm.vm.root_thread()))); + editor.set_helper(Some(Completer { + thread: vm.vm.root_thread(), + hinter: rustyline::hint::HistoryHinter {}, + highlighter: rustyline::highlight::MatchingBracketHighlighter::default(), + })); IO::Value(Editor { editor: Mutex::new(editor), }) @@ -286,7 +328,7 @@ fn readline(editor: &Editor, prompt: &str) -> IO> } fn new_cpu_pool(size: usize) -> IO { - IO::Value(CpuPool(self::futures_cpupool::CpuPool::new(size))) + IO::Value(CpuPool(futures_cpupool::CpuPool::new(size))) } fn eval_line(