From: Mark Thom Date: Fri, 22 Mar 2019 01:46:42 +0000 (-0600) Subject: enable an option to disable readline X-Git-Tag: v0.8.110~163 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=33b581effc54db15a59a316c10689b6e510857bc;p=scryer-prolog.git enable an option to disable readline --- diff --git a/Cargo.toml b/Cargo.toml index f168752f..88a1df3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,17 +1,21 @@ [package] name = "scryer-prolog" -version = "0.8.11" +version = "0.8.12" authors = ["Mark Thom "] repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." license = "BSD-3-Clause" +[features] +default = ["readline_rs_compat"] + [dependencies] +cfg-if = "0.1.7" downcast = "0.9.1" num = "0.2" ordered-float = "0.5.0" prolog_parser = "0.8.1" -readline_rs_compat = "0.1.5" +readline_rs_compat = { version = "0.1.5", optional = true } [dependencies.termion] version = "1.4.0" \ No newline at end of file diff --git a/README.md b/README.md index bdab1a6d..9e22f234 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,13 @@ readline: /opt/local/lib ``` +If you'd like to disable readline (and the need for linking to it), +install with the line + +``` +cargo install scryer-prolog --no-default-features +``` + You can find the `scryer-prolog` executable in `~/.cargo/bin`. Note on compatibility: Scryer Prolog should work on Linux, Mac OS X, diff --git a/src/main.rs b/src/main.rs index f0bb3fc3..71857b43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,13 @@ +#[macro_use] extern crate cfg_if; #[macro_use] extern crate downcast; #[macro_use] extern crate prolog_parser; -extern crate readline_rs_compat; +cfg_if! { + if #[cfg(feature = "readline_rs_compat")] { + extern crate readline_rs_compat; + } +} + extern crate termion; mod prolog; @@ -20,7 +26,8 @@ fn prolog_repl() { let mut wam = Machine::new(); loop { - set_line_mode(LineMode::Single); + #[cfg(feature = "readline_rs_compat")] + readline::set_line_mode(readline::LineMode::Single); match toplevel_read_line() { Ok(Input::TermString(buffer)) => { @@ -32,17 +39,18 @@ fn prolog_repl() { print(&mut wam, result) }, Ok(Input::Batch) => { - set_line_mode(LineMode::Multi); + #[cfg(feature = "readline_rs_compat")] + readline::set_line_mode(readline::LineMode::Multi); - let src = match read_batch("") { + let src = match readline::read_batch("") { Ok(src) => src, Err(e) => { println!("{}", e); continue; } }; - - let result = compile_user_module(&mut wam, src.as_bytes()); + + let result = compile_user_module(&mut wam, &src[0 ..]); print(&mut wam, result); }, Ok(Input::Clear) => { @@ -57,6 +65,7 @@ fn prolog_repl() { } fn main() { - readline_initialize(); + #[cfg(feature = "readline_rs_compat")] + readline::readline_initialize(); prolog_repl(); } diff --git a/src/prolog/read.rs b/src/prolog/read.rs index e0e422aa..7285946d 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -11,8 +11,6 @@ use prolog::machine::machine_state::MachineState; use std::collections::VecDeque; use std::io::Read; -use readline_rs_compat::readline::*; - type SubtermDeque = VecDeque<(usize, usize)>; impl<'a> TermRef<'a> { @@ -29,112 +27,161 @@ impl<'a> TermRef<'a> { pub enum Input { Clear, Batch, - TermString(&'static str) -} - -#[derive(Clone, Copy)] -pub enum LineMode { - Single, - Multi + TermString(String) } -static mut LINE_MODE: LineMode = LineMode::Single; -static mut END_OF_LINE: bool = false; +#[cfg(feature = "readline_rs_compat")] +pub mod readline +{ + use readline_rs_compat::readline::*; -pub fn set_line_mode(mode: LineMode) { - unsafe { - LINE_MODE = mode; - END_OF_LINE = false; - rl_done = 0; + #[derive(Clone, Copy)] + pub enum LineMode { + Single, + Multi + } + + static mut LINE_MODE: LineMode = LineMode::Single; + static mut END_OF_LINE: bool = false; + + pub fn set_line_mode(mode: LineMode) { + unsafe { + LINE_MODE = mode; + END_OF_LINE = false; + rl_done = 0; + } } -} -fn is_directive(buf: &str) -> bool { - match buf { - "?- [user]." | "?- [clear]." => true, - _ => false + fn is_directive(buf: &str) -> bool { + match buf { + "?- [user]." | "?- [clear]." => true, + _ => false + } } -} -unsafe extern "C" fn bind_end_chord(_: i32, _: i32) -> i32 { - if let LineMode::Multi = LINE_MODE { - rl_done = 1; + unsafe extern "C" fn bind_end_chord(_: i32, _: i32) -> i32 { + if let LineMode::Multi = LINE_MODE { + rl_done = 1; + } + + 0 } - 0 -} + unsafe extern "C" fn bind_end_key(_: i32, _: i32) -> i32 { + insert_text_rl("."); -unsafe extern "C" fn bind_end_key(_: i32, _: i32) -> i32 { - insert_text_rl("."); + if let LineMode::Single = LINE_MODE { + END_OF_LINE = true; + } - if let LineMode::Single = LINE_MODE { - END_OF_LINE = true; + 0 } - 0 -} - -unsafe extern "C" fn bind_cr(_: i32, _: i32) -> i32 { - if END_OF_LINE { - if let Some(buf) = rl_line_buffer_as_str() { - if is_directive(buf) { - println!(""); - rl_done = 1; - return 0; + unsafe extern "C" fn bind_cr(_: i32, _: i32) -> i32 { + if END_OF_LINE { + if let Some(buf) = rl_line_buffer_as_str() { + if is_directive(buf) { + println!(""); + rl_done = 1; + return 0; + } } + + println!(""); + rl_done = 1; + } else { + insert_text_rl("\n"); } - println!(""); - rl_done = 1; - } else { - insert_text_rl("\n"); + 0 } - 0 -} + pub fn readline_initialize() { + let rc = initialize_rl(); // initialize editline. -pub fn readline_initialize() { - let rc = initialize_rl(); // initialize editline. + if rc != 0 { + panic!("initialize_rl() failed with return code {}", rc); + } - if rc != 0 { - panic!("initialize_rl() failed with return code {}", rc); + unsafe { + rl_startup_hook = insert_query_prompt; + } + + bind_key_rl('.' as i32, bind_end_key); + bind_key_rl('\n' as i32, bind_cr); + bind_key_rl('\r' as i32, bind_cr); + bind_keyseq_rl("\\C-d", bind_end_chord); } - bind_key_rl('.' as i32, bind_end_key); - bind_key_rl('\n' as i32, bind_cr); - bind_key_rl('\r' as i32, bind_cr); - bind_keyseq_rl("\\C-d", bind_end_chord); -} + unsafe extern "C" fn insert_query_prompt() -> i32 { + if let LineMode::Single = LINE_MODE { + insert_text_rl("?- "); + } -pub fn read_batch(prompt: &str) -> Result<&'static str, SessionError> { - match readline_rl(prompt) { - Some(input) => Ok(input), - None => Err(SessionError::UserPrompt) + 0 + } + + pub fn read_batch(prompt: &str) -> Result, ::SessionError> { + match readline_rl(prompt) { + Some(input) => Ok(Vec::from(input.as_bytes())), + None => Err(::SessionError::UserPrompt) + } } -} -fn read_line(prompt: &str) -> Result<&'static str, SessionError> { - match readline_rl(prompt) { - Some(input) => Ok(input), - None => Err(SessionError::UserPrompt) + pub fn read_line(prompt: &str) -> Result { + match readline_rl(prompt) { + Some(input) => Ok(String::from(input)), + None => Err(::SessionError::UserPrompt) + } } } -unsafe extern "C" fn insert_query_prompt() -> i32 { - if let LineMode::Single = LINE_MODE { - insert_text_rl("?- "); +#[cfg(not(feature = "readline_rs_compat"))] +pub mod readline +{ + use std::io::{BufRead, Read, stdin, stdout, Write}; + + pub fn read_batch(_: &str) -> Result, ::SessionError> { + let mut buf = vec![]; + + let stdin = stdin(); + let mut stdin = stdin.lock(); + + match stdin.read_to_end(&mut buf) { + Ok(_) => Ok(buf), + _ => Err(::SessionError::UserPrompt) + } } - 0 + pub fn read_line(_: &str) -> Result { + print!("?- "); + stdout().flush().unwrap(); + + let stdin = stdin(); + let stdin = stdin.lock(); + + let mut buf = "?- ".to_string(); + + for line in stdin.lines() { + match line { + Ok(line) => { + buf += &line; + + if line.trim().ends_with(".") { + break; + } + }, + _ => return Err(::SessionError::UserPrompt) + } + } + + Ok(buf) + } } pub fn toplevel_read_line() -> Result { - unsafe { - rl_startup_hook = insert_query_prompt; - } - - let buffer = read_line("")?; + let buffer = readline::read_line("")?; Ok(match &*buffer.trim() { "?- [clear]." => Input::Clear,