enable an option to disable readline

This commit is contained in:
Mark Thom
2019-03-21 19:46:42 -06:00
parent 4b2fb8b1c7
commit 33b581effc
4 changed files with 165 additions and 98 deletions

View File

@@ -1,17 +1,21 @@
[package] [package]
name = "scryer-prolog" name = "scryer-prolog"
version = "0.8.11" version = "0.8.12"
authors = ["Mark Thom <markjordanthom@gmail.com>"] authors = ["Mark Thom <markjordanthom@gmail.com>"]
repository = "https://github.com/mthom/scryer-prolog" repository = "https://github.com/mthom/scryer-prolog"
description = "A modern Prolog implementation written mostly in Rust." description = "A modern Prolog implementation written mostly in Rust."
license = "BSD-3-Clause" license = "BSD-3-Clause"
[features]
default = ["readline_rs_compat"]
[dependencies] [dependencies]
cfg-if = "0.1.7"
downcast = "0.9.1" downcast = "0.9.1"
num = "0.2" num = "0.2"
ordered-float = "0.5.0" ordered-float = "0.5.0"
prolog_parser = "0.8.1" prolog_parser = "0.8.1"
readline_rs_compat = "0.1.5" readline_rs_compat = { version = "0.1.5", optional = true }
[dependencies.termion] [dependencies.termion]
version = "1.4.0" version = "1.4.0"

View File

@@ -114,6 +114,13 @@ readline:
/opt/local/lib /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`. You can find the `scryer-prolog` executable in `~/.cargo/bin`.
Note on compatibility: Scryer Prolog should work on Linux, Mac OS X, Note on compatibility: Scryer Prolog should work on Linux, Mac OS X,

View File

@@ -1,7 +1,13 @@
#[macro_use] extern crate cfg_if;
#[macro_use] extern crate downcast; #[macro_use] extern crate downcast;
#[macro_use] extern crate prolog_parser; #[macro_use] extern crate prolog_parser;
cfg_if! {
if #[cfg(feature = "readline_rs_compat")] {
extern crate readline_rs_compat; extern crate readline_rs_compat;
}
}
extern crate termion; extern crate termion;
mod prolog; mod prolog;
@@ -20,7 +26,8 @@ fn prolog_repl() {
let mut wam = Machine::new(); let mut wam = Machine::new();
loop { loop {
set_line_mode(LineMode::Single); #[cfg(feature = "readline_rs_compat")]
readline::set_line_mode(readline::LineMode::Single);
match toplevel_read_line() { match toplevel_read_line() {
Ok(Input::TermString(buffer)) => { Ok(Input::TermString(buffer)) => {
@@ -32,9 +39,10 @@ fn prolog_repl() {
print(&mut wam, result) print(&mut wam, result)
}, },
Ok(Input::Batch) => { 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, Ok(src) => src,
Err(e) => { Err(e) => {
println!("{}", e); println!("{}", e);
@@ -42,7 +50,7 @@ fn prolog_repl() {
} }
}; };
let result = compile_user_module(&mut wam, src.as_bytes()); let result = compile_user_module(&mut wam, &src[0 ..]);
print(&mut wam, result); print(&mut wam, result);
}, },
Ok(Input::Clear) => { Ok(Input::Clear) => {
@@ -57,6 +65,7 @@ fn prolog_repl() {
} }
fn main() { fn main() {
readline_initialize(); #[cfg(feature = "readline_rs_compat")]
readline::readline_initialize();
prolog_repl(); prolog_repl();
} }

View File

@@ -11,8 +11,6 @@ use prolog::machine::machine_state::MachineState;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::io::Read; use std::io::Read;
use readline_rs_compat::readline::*;
type SubtermDeque = VecDeque<(usize, usize)>; type SubtermDeque = VecDeque<(usize, usize)>;
impl<'a> TermRef<'a> { impl<'a> TermRef<'a> {
@@ -29,9 +27,14 @@ impl<'a> TermRef<'a> {
pub enum Input { pub enum Input {
Clear, Clear,
Batch, Batch,
TermString(&'static str) TermString(String)
} }
#[cfg(feature = "readline_rs_compat")]
pub mod readline
{
use readline_rs_compat::readline::*;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum LineMode { pub enum LineMode {
Single, Single,
@@ -100,26 +103,16 @@ pub fn readline_initialize() {
panic!("initialize_rl() failed with return code {}", rc); 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('.' as i32, bind_end_key);
bind_key_rl('\n' as i32, bind_cr); bind_key_rl('\n' as i32, bind_cr);
bind_key_rl('\r' as i32, bind_cr); bind_key_rl('\r' as i32, bind_cr);
bind_keyseq_rl("\\C-d", bind_end_chord); bind_keyseq_rl("\\C-d", bind_end_chord);
} }
pub fn read_batch(prompt: &str) -> Result<&'static str, SessionError> {
match readline_rl(prompt) {
Some(input) => Ok(input),
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)
}
}
unsafe extern "C" fn insert_query_prompt() -> i32 { unsafe extern "C" fn insert_query_prompt() -> i32 {
if let LineMode::Single = LINE_MODE { if let LineMode::Single = LINE_MODE {
insert_text_rl("?- "); insert_text_rl("?- ");
@@ -128,13 +121,67 @@ unsafe extern "C" fn insert_query_prompt() -> i32 {
0 0
} }
pub fn toplevel_read_line() -> Result<Input, SessionError> pub fn read_batch(prompt: &str) -> Result<Vec<u8>, ::SessionError> {
{ match readline_rl(prompt) {
unsafe { Some(input) => Ok(Vec::from(input.as_bytes())),
rl_startup_hook = insert_query_prompt; None => Err(::SessionError::UserPrompt)
}
} }
let buffer = read_line("")?; pub fn read_line(prompt: &str) -> Result<String, ::SessionError> {
match readline_rl(prompt) {
Some(input) => Ok(String::from(input)),
None => Err(::SessionError::UserPrompt)
}
}
}
#[cfg(not(feature = "readline_rs_compat"))]
pub mod readline
{
use std::io::{BufRead, Read, stdin, stdout, Write};
pub fn read_batch(_: &str) -> Result<Vec<u8>, ::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)
}
}
pub fn read_line(_: &str) -> Result<String, ::SessionError> {
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<Input, SessionError>
{
let buffer = readline::read_line("")?;
Ok(match &*buffer.trim() { Ok(match &*buffer.trim() {
"?- [clear]." => Input::Clear, "?- [clear]." => Input::Clear,