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]
name = "scryer-prolog"
version = "0.8.11"
version = "0.8.12"
authors = ["Mark Thom <markjordanthom@gmail.com>"]
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"

View File

@@ -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,

View File

@@ -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();
}

View File

@@ -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)
TermString(String)
}
#[derive(Clone, Copy)]
pub enum LineMode {
Single,
Multi
}
#[cfg(feature = "readline_rs_compat")]
pub mod readline
{
use readline_rs_compat::readline::*;
static mut LINE_MODE: LineMode = LineMode::Single;
static mut END_OF_LINE: bool = false;
#[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;
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
}
}
unsafe extern "C" fn bind_end_chord(_: i32, _: i32) -> i32 {
if let LineMode::Multi = LINE_MODE {
rl_done = 1;
}
0
}
unsafe extern "C" fn bind_end_key(_: i32, _: i32) -> i32 {
insert_text_rl(".");
if let LineMode::Single = LINE_MODE {
END_OF_LINE = true;
}
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");
}
0
}
pub fn readline_initialize() {
let rc = initialize_rl(); // initialize editline.
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);
}
unsafe extern "C" fn insert_query_prompt() -> i32 {
if let LineMode::Single = LINE_MODE {
insert_text_rl("?- ");
}
0
}
pub fn read_batch(prompt: &str) -> Result<Vec<u8>, ::SessionError> {
match readline_rl(prompt) {
Some(input) => Ok(Vec::from(input.as_bytes())),
None => Err(::SessionError::UserPrompt)
}
}
pub fn read_line(prompt: &str) -> Result<String, ::SessionError> {
match readline_rl(prompt) {
Some(input) => Ok(String::from(input)),
None => Err(::SessionError::UserPrompt)
}
}
}
fn is_directive(buf: &str) -> bool {
match buf {
"?- [user]." | "?- [clear]." => true,
_ => false
}
}
#[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![];
unsafe extern "C" fn bind_end_chord(_: i32, _: i32) -> i32 {
if let LineMode::Multi = LINE_MODE {
rl_done = 1;
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<String, ::SessionError> {
print!("?- ");
stdout().flush().unwrap();
unsafe extern "C" fn bind_end_key(_: i32, _: i32) -> i32 {
insert_text_rl(".");
if let LineMode::Single = LINE_MODE {
END_OF_LINE = true;
}
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;
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)
}
}
println!("");
rl_done = 1;
} else {
insert_text_rl("\n");
Ok(buf)
}
0
}
pub fn readline_initialize() {
let rc = initialize_rl(); // initialize editline.
if rc != 0 {
panic!("initialize_rl() failed with return code {}", rc);
}
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);
}
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 {
if let LineMode::Single = LINE_MODE {
insert_text_rl("?- ");
}
0
}
pub fn toplevel_read_line() -> Result<Input, SessionError>
{
unsafe {
rl_startup_hook = insert_query_prompt;
}
let buffer = read_line("")?;
let buffer = readline::read_line("")?;
Ok(match &*buffer.trim() {
"?- [clear]." => Input::Clear,