]> Repositorios git - scryer-prolog.git/commitdiff
enable an option to disable readline
authorMark Thom <[email protected]>
Fri, 22 Mar 2019 01:46:42 +0000 (19:46 -0600)
committerMark Thom <[email protected]>
Fri, 22 Mar 2019 01:46:42 +0000 (19:46 -0600)
Cargo.toml
README.md
src/main.rs
src/prolog/read.rs

index f168752f62ffd4770a977b16d35cecfb577dec8e..88a1df3e7488037586830f4bacaf46937eb94789 100644 (file)
@@ -1,17 +1,21 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.11"
+version = "0.8.12"
 authors = ["Mark Thom <[email protected]>"]
 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
index bdab1a6d76d1ee287fbc49160217142c01a79574..9e22f234e13973e5789cef660d1a4b55f2ff3f1f 100644 (file)
--- 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,
index f0bb3fc37c74f3c24dbc85ea44aabf9f0c144dad..71857b438bf5da4f51568121a9e18ba1e3d70bd5 100644 (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();
 }
index e0e422aac97a1691268f8f76a97638bd01e475f0..7285946d49f6336b31a0d05e6320c88fa09de95d 100644 (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)
-}
-
-#[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<Vec<u8>, ::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<String, ::SessionError> {
+        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<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)
+        }
     }
 
-    0
+    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>
 {
-    unsafe {
-        rl_startup_hook = insert_query_prompt;
-    }
-
-    let buffer = read_line("")?;
+    let buffer = readline::read_line("")?;
 
     Ok(match &*buffer.trim() {
         "?- [clear]." => Input::Clear,