wip: basic completion of predicates
This commit is contained in:
@@ -28,6 +28,7 @@ mod iterators;
|
|||||||
pub mod machine;
|
pub mod machine;
|
||||||
mod raw_block;
|
mod raw_block;
|
||||||
pub mod read;
|
pub mod read;
|
||||||
|
mod repl_helper;
|
||||||
mod targets;
|
mod targets;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
|||||||
@@ -454,6 +454,21 @@ impl MachineState {
|
|||||||
self.b0 = self.b;
|
self.b0 = self.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_term_from_user_input(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
||||||
|
let atoms: Vec<_> = self.atom_tbl.table.iter().map(|a| a.as_str().to_string()).collect();
|
||||||
|
|
||||||
|
if let Stream::Readline(ptr) = stream {
|
||||||
|
unsafe {
|
||||||
|
let readline = ptr.as_ptr().as_mut().unwrap();
|
||||||
|
readline.set_atoms_for_completion(atoms);
|
||||||
|
let ret = self.read_term(stream, indices);
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!("Stream must be a Stream::Readline(_)")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
||||||
fn push_var_eq_functors<'a>(
|
fn push_var_eq_functors<'a>(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
|
|||||||
@@ -4239,7 +4239,8 @@ impl Machine {
|
|||||||
self.user_input.reset();
|
self.user_input.reset();
|
||||||
|
|
||||||
set_prompt(true);
|
set_prompt(true);
|
||||||
let result = self.machine_st.read_term(self.user_input, &mut self.indices);
|
// let result = self.machine_st.read_term(self.user_input, &mut self.indices);
|
||||||
|
let result = self.machine_st.read_term_from_user_input(self.user_input, &mut self.indices);
|
||||||
set_prompt(false);
|
set_prompt(false);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
|||||||
17
src/read.rs
17
src/read.rs
@@ -9,12 +9,13 @@ use crate::machine::machine_indices::*;
|
|||||||
use crate::machine::machine_state::MachineState;
|
use crate::machine::machine_state::MachineState;
|
||||||
use crate::machine::streams::*;
|
use crate::machine::streams::*;
|
||||||
use crate::parser::char_reader::*;
|
use crate::parser::char_reader::*;
|
||||||
|
use crate::repl_helper::Helper;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
|
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::{Cmd, Config, Editor, KeyEvent};
|
use rustyline::{Config, Editor};
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io::{Cursor, Error, ErrorKind, Read};
|
use std::io::{Cursor, Error, ErrorKind, Read};
|
||||||
@@ -77,7 +78,7 @@ fn get_prompt() -> &'static str {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ReadlineStream {
|
pub struct ReadlineStream {
|
||||||
rl: Editor<()>,
|
rl: Editor<Helper>,
|
||||||
pending_input: Cursor<String>,
|
pending_input: Cursor<String>,
|
||||||
add_history: bool,
|
add_history: bool,
|
||||||
}
|
}
|
||||||
@@ -86,7 +87,10 @@ impl ReadlineStream {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(pending_input: &str, add_history: bool) -> Self {
|
pub fn new(pending_input: &str, add_history: bool) -> Self {
|
||||||
let config = Config::builder().check_cursor_position(true).build();
|
let config = Config::builder().check_cursor_position(true).build();
|
||||||
let mut rl = Editor::<()>::with_config(config);
|
let helper = Helper::new();
|
||||||
|
|
||||||
|
let mut rl = Editor::with_config(config);
|
||||||
|
rl.set_helper(Some(helper));
|
||||||
|
|
||||||
if let Some(mut path) = dirs_next::home_dir() {
|
if let Some(mut path) = dirs_next::home_dir() {
|
||||||
path.push(HISTORY_FILE);
|
path.push(HISTORY_FILE);
|
||||||
@@ -95,7 +99,7 @@ impl ReadlineStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.bind_sequence(KeyEvent::from('\t'), Cmd::Insert(1, "\t".to_string()));
|
// rl.bind_sequence(KeyEvent::from('\t'), Cmd::Insert(1, "\t".to_string()));
|
||||||
|
|
||||||
ReadlineStream {
|
ReadlineStream {
|
||||||
rl,
|
rl,
|
||||||
@@ -104,6 +108,11 @@ impl ReadlineStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_atoms_for_completion(&mut self, atoms: Vec<String>) {
|
||||||
|
let helper = self.rl.helper_mut().unwrap();
|
||||||
|
helper.atoms = atoms;
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.pending_input.get_mut().clear();
|
self.pending_input.get_mut().clear();
|
||||||
|
|||||||
136
src/repl_helper.rs
Normal file
136
src/repl_helper.rs
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
use rustyline::completion::Completer;
|
||||||
|
use rustyline::hint::Hinter;
|
||||||
|
use rustyline::validate::Validator;
|
||||||
|
use rustyline::highlight::{MatchingBracketHighlighter, Highlighter};
|
||||||
|
use rustyline::{Helper as RlHelper, Result, Context};
|
||||||
|
|
||||||
|
// pub struct Atoms {
|
||||||
|
// atoms: *const *const str,
|
||||||
|
// len: usize,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl Atoms {
|
||||||
|
// pub fn new() -> Self {
|
||||||
|
// Self {
|
||||||
|
// atoms: std::ptr::null(),
|
||||||
|
// len: 0,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub struct AtomsIterator<'a> {
|
||||||
|
// atoms: &'a Atoms,
|
||||||
|
// idx: usize,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<'a> Iterator for AtomsIterator<'a> {
|
||||||
|
// type Item = &'a str;
|
||||||
|
|
||||||
|
// fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
// self.idx += 1;
|
||||||
|
|
||||||
|
// if self.idx == self.atoms.len {
|
||||||
|
// None
|
||||||
|
// } else {
|
||||||
|
// unsafe {
|
||||||
|
// let next = self.atoms.atoms.offset(self.idx as isize);
|
||||||
|
// (*next).as_ref()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<'a> IntoIterator for &'a Atoms {
|
||||||
|
// type Item = &'a str;
|
||||||
|
// type IntoIter = AtomsIterator<'a>;
|
||||||
|
|
||||||
|
// fn into_iter(self) -> Self::IntoIter {
|
||||||
|
// Self::IntoIter {
|
||||||
|
// atoms: self,
|
||||||
|
// idx: 0,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: Maybe add validation to the helper
|
||||||
|
pub struct Helper {
|
||||||
|
highligher: MatchingBracketHighlighter,
|
||||||
|
pub atoms: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Helper {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
highligher: MatchingBracketHighlighter::new(),
|
||||||
|
atoms: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn set_atoms(&mut self, atoms_ptr: *const *const str, len: usize) {
|
||||||
|
// self.atoms.atoms = atoms_ptr;
|
||||||
|
// self.atoms.len = len;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RlHelper for Helper {}
|
||||||
|
|
||||||
|
fn get_prefix(line: &str, pos: usize) -> Option<usize> {
|
||||||
|
let mut start_of_atom = None;
|
||||||
|
let mut first_letter = true;
|
||||||
|
|
||||||
|
for (i, char) in line.chars().enumerate() {
|
||||||
|
if first_letter {
|
||||||
|
if char.is_alphabetic() && char.is_lowercase() {
|
||||||
|
start_of_atom = Some(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
first_letter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !char.is_alphanumeric() && char != '_' {
|
||||||
|
first_letter = true;
|
||||||
|
start_of_atom = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == pos {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if first_letter || pos == 0 {
|
||||||
|
start_of_atom = Some(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
start_of_atom
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Completer for Helper {
|
||||||
|
type Candidate = String;
|
||||||
|
|
||||||
|
fn complete(&self, line: &str, pos: usize, _ctx: &Context<'_>) -> Result<(usize, Vec<Self::Candidate>)> {
|
||||||
|
let start_of_prefix = get_prefix(line, pos);
|
||||||
|
if let Some(idx) = start_of_prefix {
|
||||||
|
let sub_str = line.get(idx..pos).unwrap();
|
||||||
|
let matching = self.atoms.iter().filter(|a| a.starts_with(sub_str)).map(|s| s.to_string()).collect();
|
||||||
|
Ok((idx, matching))
|
||||||
|
} else {
|
||||||
|
Ok((0, vec![]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Highlighter for Helper {
|
||||||
|
fn highlight<'l>(&self, line: &'l str, pos: usize) -> std::borrow::Cow<'l, str> {
|
||||||
|
self.highligher.highlight(line, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn highlight_char(&self, line: &str, pos: usize) -> bool {
|
||||||
|
self.highligher.highlight_char(line, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Validator for Helper {}
|
||||||
|
|
||||||
|
impl Hinter for Helper {
|
||||||
|
type Hint = String;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user