Cleaned up warnings
This commit is contained in:
@@ -1,6 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use crate::{builtin::setup_builtin, getopt::{get_opts_from_tokens, Opt, ECHO_OPTS}, jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt}, parse::{NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state};
|
||||||
|
|
||||||
use crate::{builtin::setup_builtin, getopt::{get_opts_from_tokens, Opt, ECHO_OPTS}, jobs::{ChildProc, JobBldr}, libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt}, parse::{execute::prepare_argv, NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state};
|
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct EchoFlags: u32 {
|
pub struct EchoFlags: u32 {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{jobs::{ChildProc, JobBldr}, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{execute::prepare_argv, NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state};
|
use crate::{jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state};
|
||||||
|
|
||||||
use super::setup_builtin;
|
use super::setup_builtin;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{builtin::setup_builtin, jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{execute::prepare_argv, NdRule, Node}, prelude::*, procio::IoStack, state};
|
use crate::{libsh::error::{ShErr, ShErrKind, ShResult}, parse::{execute::prepare_argv, NdRule, Node}, prelude::*};
|
||||||
|
|
||||||
pub fn flowctl(node: Node, kind: ShErrKind) -> ShResult<()> {
|
pub fn flowctl(node: Node, kind: ShErrKind) -> ShResult<()> {
|
||||||
use ShErrKind::*;
|
use ShErrKind::*;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{jobs::{ChildProc, JobBldr, JobCmdFlags, JobID}, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{execute::prepare_argv, lex::Span, NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state::{self, read_jobs, write_jobs}};
|
use crate::{jobs::{JobBldr, JobCmdFlags, JobID}, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{lex::Span, NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state::{self, read_jobs, write_jobs}};
|
||||||
|
|
||||||
use super::setup_builtin;
|
use super::setup_builtin;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::{jobs::{ChildProc, JobBldr}, libsh::error::ShResult, parse::{NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state};
|
use crate::{jobs::JobBldr, libsh::error::ShResult, parse::{NdRule, Node}, prelude::*, procio::{borrow_fd, IoStack}, state};
|
||||||
|
|
||||||
use super::setup_builtin;
|
use super::setup_builtin;
|
||||||
|
|
||||||
pub fn pwd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
pub fn pwd(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
||||||
let NdRule::Command { assignments, argv } = node.class else {
|
let NdRule::Command { assignments: _, argv } = node.class else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{jobs::{ChildProc, JobBldr}, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{execute::prepare_argv, NdRule, Node}, prelude::*, state::{self, write_vars}};
|
use crate::{jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{NdRule, Node}, state::{self, write_vars}};
|
||||||
|
|
||||||
use super::setup_builtin;
|
use super::setup_builtin;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{jobs::{ChildProc, JobBldr}, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{execute::prepare_argv, NdRule, Node}, prelude::*, state::{self, source_file}};
|
use crate::{jobs::JobBldr, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{NdRule, Node}, prelude::*, state::{self, source_file}};
|
||||||
|
|
||||||
use super::setup_builtin;
|
use super::setup_builtin;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::collections::{HashSet, VecDeque};
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::{exec_input, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{lex::{is_field_sep, is_hard_sep, is_keyword, LexFlags, LexStream, Span, Tk, TkFlags, TkRule}, Redir, RedirType}, prelude::*, procio::{IoBuf, IoFrame, IoMode}, state::{read_logic, read_meta, read_vars, write_meta}};
|
use crate::{exec_input, libsh::error::{ShErr, ShErrKind, ShResult}, parse::{lex::{is_field_sep, is_hard_sep, LexFlags, LexStream, Span, Tk, TkFlags, TkRule}, Redir, RedirType}, prelude::*, procio::{IoBuf, IoFrame, IoMode}, state::{read_logic, read_vars, write_meta}};
|
||||||
|
|
||||||
/// Variable substitution marker
|
/// Variable substitution marker
|
||||||
pub const VAR_SUB: char = '\u{fdd0}';
|
pub const VAR_SUB: char = '\u{fdd0}';
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ pub fn save_termios() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
pub fn get_saved_termios() -> Option<Termios> {
|
pub fn get_saved_termios() -> Option<Termios> {
|
||||||
unsafe {
|
unsafe {
|
||||||
// This is only used when the shell exits so it's fine
|
// This is only used when the shell exits so it's fine
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::{ops::Deref, str::FromStr, sync::{Arc, LazyLock}};
|
use std::sync::{Arc, LazyLock};
|
||||||
|
|
||||||
use fmt::Display;
|
use fmt::Display;
|
||||||
|
|
||||||
use crate::{libsh::error::ShResult, parse::lex::Tk, prelude::*};
|
use crate::{parse::lex::Tk, prelude::*};
|
||||||
|
|
||||||
type OptSet = Arc<[Opt]>;
|
type OptSet = Arc<[Opt]>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
|
||||||
use crate::{builtin::{alias::alias, cd::cd, echo::echo, export::export, flowctl::flowctl, jobctl::{continue_job, jobs, JobBehavior}, pwd::pwd, shift::shift, source::source}, exec_input, jobs::{dispatch_job, ChildProc, Job, JobBldr, JobStack}, libsh::{error::{ShErr, ShErrKind, ShResult, ShResultExt}, utils::RedirVecUtils}, prelude::*, procio::{IoFrame, IoMode, IoStack}, state::{self, read_logic, read_vars, write_logic, write_vars, ShFunc, VarTab}};
|
use crate::{builtin::{alias::alias, cd::cd, echo::echo, export::export, flowctl::flowctl, jobctl::{continue_job, jobs, JobBehavior}, pwd::pwd, shift::shift, source::source}, jobs::{dispatch_job, ChildProc, JobBldr, JobStack}, libsh::{error::{ShErr, ShErrKind, ShResult, ShResultExt}, utils::RedirVecUtils}, prelude::*, procio::{IoFrame, IoMode, IoStack}, state::{self, read_logic, read_vars, write_logic, write_vars, ShFunc, VarTab}};
|
||||||
|
|
||||||
use super::{lex::{LexFlags, LexStream, Span, Tk, TkFlags, KEYWORDS}, AssignKind, CaseNode, CondNode, ConjunctNode, ConjunctOp, LoopKind, NdFlags, NdRule, Node, ParseStream, ParsedSrc, Redir, RedirType};
|
use super::{lex::{Span, Tk, TkFlags, KEYWORDS}, AssignKind, CaseNode, CondNode, ConjunctNode, ConjunctOp, LoopKind, NdFlags, NdRule, Node, ParsedSrc, Redir, RedirType};
|
||||||
|
|
||||||
pub enum AssignBehavior {
|
pub enum AssignBehavior {
|
||||||
Export,
|
Export,
|
||||||
@@ -476,7 +476,7 @@ pub fn run_fork<'t,C,P>(
|
|||||||
) -> ShResult<()>
|
) -> ShResult<()>
|
||||||
where
|
where
|
||||||
C: Fn(IoFrame,Option<ExecArgs>),
|
C: Fn(IoFrame,Option<ExecArgs>),
|
||||||
P: Fn(IoFrame,&mut JobBldr,Option<&str>,Pid) -> ShResult<()>
|
P: Fn(&mut JobBldr,Option<&str>,Pid) -> ShResult<()>
|
||||||
{
|
{
|
||||||
match unsafe { fork()? } {
|
match unsafe { fork()? } {
|
||||||
ForkResult::Child => {
|
ForkResult::Child => {
|
||||||
@@ -489,7 +489,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
parent_action(io_frame,job,cmd.as_deref(),child)
|
parent_action(job,cmd.as_deref(),child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,7 +529,6 @@ pub fn def_child_action(mut io_frame: IoFrame, exec_args: Option<ExecArgs>) {
|
|||||||
|
|
||||||
/// The default behavior for the parent process after forking
|
/// The default behavior for the parent process after forking
|
||||||
pub fn def_parent_action(
|
pub fn def_parent_action(
|
||||||
io_frame: IoFrame,
|
|
||||||
job: &mut JobBldr,
|
job: &mut JobBldr,
|
||||||
cmd: Option<&str>,
|
cmd: Option<&str>,
|
||||||
child_pid: Pid
|
child_pid: Pid
|
||||||
|
|||||||
@@ -311,7 +311,6 @@ impl LexStream {
|
|||||||
let slice = self.slice_from_cursor().unwrap().to_string();
|
let slice = self.slice_from_cursor().unwrap().to_string();
|
||||||
let mut pos = self.cursor;
|
let mut pos = self.cursor;
|
||||||
let mut chars = slice.chars().peekable();
|
let mut chars = slice.chars().peekable();
|
||||||
let mut quote_pos = None;
|
|
||||||
|
|
||||||
if let Some(count) = case_pat_lookahead(chars.clone()) {
|
if let Some(count) = case_pat_lookahead(chars.clone()) {
|
||||||
pos += count;
|
pos += count;
|
||||||
@@ -434,7 +433,6 @@ impl LexStream {
|
|||||||
}
|
}
|
||||||
'"' | '\'' => {
|
'"' | '\'' => {
|
||||||
self.in_quote = true;
|
self.in_quote = true;
|
||||||
quote_pos = Some(pos);
|
|
||||||
pos += 1;
|
pos += 1;
|
||||||
while let Some(q_ch) = chars.next() {
|
while let Some(q_ch) = chars.next() {
|
||||||
match q_ch {
|
match q_ch {
|
||||||
|
|||||||
@@ -570,7 +570,7 @@ impl ParseStream {
|
|||||||
let mut node_tks: Vec<Tk> = vec![];
|
let mut node_tks: Vec<Tk> = vec![];
|
||||||
let pattern: Tk;
|
let pattern: Tk;
|
||||||
let mut case_blocks: Vec<CaseNode> = vec![];
|
let mut case_blocks: Vec<CaseNode> = vec![];
|
||||||
let mut redirs: Vec<Redir> = vec![];
|
let redirs: Vec<Redir> = vec![];
|
||||||
|
|
||||||
if !self.check_keyword("case") || !self.next_tk_is_some() {
|
if !self.check_keyword("case") || !self.next_tk_is_some() {
|
||||||
return Ok(None)
|
return Ok(None)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::{fmt::Debug, ops::{Deref, DerefMut}};
|
use std::{fmt::Debug, ops::{Deref, DerefMut}};
|
||||||
|
|
||||||
use crate::{libsh::{error::{ShErr, ShErrKind, ShResult}, utils::RedirVecUtils}, parse::{Redir, RedirType}, prelude::*};
|
use crate::{libsh::{error::{ShErr, ShErrKind, ShResult}, utils::RedirVecUtils}, parse::Redir, prelude::*};
|
||||||
|
|
||||||
// Credit to fish-shell for many of the implementation ideas present in this module
|
// Credit to fish-shell for many of the implementation ideas present in this module
|
||||||
// https://fishshell.com/
|
// https://fishshell.com/
|
||||||
|
|||||||
@@ -1,260 +0,0 @@
|
|||||||
use std::{fs::File, ops::{Deref, DerefMut}, path::PathBuf};
|
|
||||||
|
|
||||||
use bitflags::bitflags;
|
|
||||||
use rustyline::history::{History, SearchResult};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{libsh::error::{ShErr, ShErrKind, ShResult}, prelude::*};
|
|
||||||
|
|
||||||
#[derive(Deserialize,Serialize,Debug)]
|
|
||||||
pub struct HistEntry {
|
|
||||||
body: String,
|
|
||||||
id: usize
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HistEntry {
|
|
||||||
pub fn new(body: String, id: usize) -> Self {
|
|
||||||
Self { body, id }
|
|
||||||
}
|
|
||||||
pub fn cmd(&self) -> &str {
|
|
||||||
&self.body
|
|
||||||
}
|
|
||||||
pub fn id(&self) -> usize {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize,Serialize,Default)]
|
|
||||||
pub struct HistEntries {
|
|
||||||
entries: Vec<HistEntry>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HistEntries {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { entries: vec![] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for HistEntries {
|
|
||||||
type Target = Vec<HistEntry>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.entries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for HistEntries {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.entries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FernHist {
|
|
||||||
file_path: Option<PathBuf>,
|
|
||||||
entries: HistEntries,
|
|
||||||
max_len: usize,
|
|
||||||
pub flags: HistFlags
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct HistFlags: u32 {
|
|
||||||
const NO_DUPES = 0b0000001;
|
|
||||||
const IGNORE_SPACE = 0b0000010;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'e> FernHist {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { file_path: None, entries: HistEntries::new(), max_len: 1000, flags: HistFlags::empty() }
|
|
||||||
}
|
|
||||||
pub fn from_path(file_path: PathBuf) -> ShResult<Self> {
|
|
||||||
let mut new_hist = FernHist::new();
|
|
||||||
new_hist.file_path = Some(file_path);
|
|
||||||
new_hist.load_hist()?;
|
|
||||||
Ok(new_hist)
|
|
||||||
}
|
|
||||||
pub fn create_entry(&self, body: &str) -> HistEntry {
|
|
||||||
let id = self.len() + 1;
|
|
||||||
HistEntry::new(body.to_string(), id)
|
|
||||||
}
|
|
||||||
pub fn init_hist_file(&mut self) -> ShResult<()> {
|
|
||||||
let Some(path) = self.file_path.clone() else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
self.save(&path)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
pub fn load_hist(&mut self) -> ShResult<()> {
|
|
||||||
let Some(file_path) = self.file_path.clone() else {
|
|
||||||
return Err(
|
|
||||||
ShErr::simple(
|
|
||||||
ShErrKind::InternalErr,
|
|
||||||
"History file not set"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if !file_path.is_file() {
|
|
||||||
self.init_hist_file()?;
|
|
||||||
}
|
|
||||||
let hist_file = File::open(&file_path)?;
|
|
||||||
self.entries = serde_yaml::from_reader(hist_file).unwrap_or_default();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for FernHist {
|
|
||||||
fn default() -> Self {
|
|
||||||
let home = std::env::var("HOME").unwrap();
|
|
||||||
let file_path = PathBuf::from(&format!("{home}/.fernhist"));
|
|
||||||
Self::from_path(file_path).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl History for FernHist {
|
|
||||||
fn add(&mut self, line: &str) -> rustyline::Result<bool> {
|
|
||||||
let new_entry = self.create_entry(line);
|
|
||||||
if self.flags.contains(HistFlags::NO_DUPES) {
|
|
||||||
let most_recent = self.get(self.len(), rustyline::history::SearchDirection::Reverse)?.unwrap();
|
|
||||||
dbg!(&most_recent);
|
|
||||||
if new_entry.body == most_recent.entry.to_string() {
|
|
||||||
return Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.entries.push(new_entry);
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self, index: usize, dir: rustyline::history::SearchDirection) -> rustyline::Result<Option<rustyline::history::SearchResult>> {
|
|
||||||
Ok(self.entries.iter().find(|ent| ent.id() == index).map(|ent| {
|
|
||||||
SearchResult { entry: ent.cmd().to_string().into(), idx: index, pos: 0 }
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_owned(&mut self, line: String) -> rustyline::Result<bool> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
self.entries.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
self.entries.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_max_len(&mut self, len: usize) -> rustyline::Result<()> {
|
|
||||||
self.max_len = len;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ignore_dups(&mut self, yes: bool) -> rustyline::Result<()> {
|
|
||||||
if yes {
|
|
||||||
self.flags |= HistFlags::NO_DUPES;
|
|
||||||
} else {
|
|
||||||
self.flags &= !HistFlags::NO_DUPES;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ignore_space(&mut self, yes: bool) {
|
|
||||||
if yes {
|
|
||||||
self.flags |= HistFlags::IGNORE_SPACE;
|
|
||||||
} else {
|
|
||||||
self.flags &= !HistFlags::IGNORE_SPACE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save(&mut self, path: &std::path::Path) -> rustyline::Result<()> {
|
|
||||||
let hist_file = File::create(path)?;
|
|
||||||
serde_yaml::to_writer(hist_file, &self.entries).unwrap();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append(&mut self, path: &std::path::Path) -> rustyline::Result<()> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load(&mut self, path: &std::path::Path) -> rustyline::Result<()> {
|
|
||||||
let path = path.to_path_buf();
|
|
||||||
self.file_path = Some(path);
|
|
||||||
self.load_hist().map_err(|_| rustyline::error::ReadlineError::Io(std::io::Error::last_os_error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&mut self) -> rustyline::Result<()> {
|
|
||||||
self.entries.clear();
|
|
||||||
if self.file_path.is_some() {
|
|
||||||
self.save(&self.file_path.clone().unwrap())?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn search(
|
|
||||||
&self,
|
|
||||||
term: &str,
|
|
||||||
start: usize,
|
|
||||||
dir: rustyline::history::SearchDirection,
|
|
||||||
) -> rustyline::Result<Option<rustyline::history::SearchResult>> {
|
|
||||||
if term.is_empty() {
|
|
||||||
return Ok(None)
|
|
||||||
}
|
|
||||||
let mut matches: Vec<&HistEntry> = self.entries.iter()
|
|
||||||
.filter(|ent| is_subsequence(&ent.body, term))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
matches.sort_by(|ent_a, ent_b| {
|
|
||||||
let ent_a_rank = fuzzy_rank(term, &ent_a.body);
|
|
||||||
let ent_b_rank = fuzzy_rank(term, &ent_b.body);
|
|
||||||
ent_a_rank.cmp(&ent_b_rank)
|
|
||||||
.then(ent_a.id().cmp(&ent_b.id()))
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(matches.last().map(|ent| {
|
|
||||||
SearchResult {
|
|
||||||
entry: ent.body.clone().into(),
|
|
||||||
idx: ent.id(),
|
|
||||||
pos: start
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn starts_with(
|
|
||||||
&self,
|
|
||||||
term: &str,
|
|
||||||
start: usize,
|
|
||||||
dir: rustyline::history::SearchDirection,
|
|
||||||
) -> rustyline::Result<Option<rustyline::history::SearchResult>> {
|
|
||||||
let mut matches: Vec<&HistEntry> = self.entries.iter()
|
|
||||||
.filter(|ent| ent.body.starts_with(term))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
matches.sort_by(|ent_a, ent_b| ent_a.id().cmp(&ent_b.id()));
|
|
||||||
dbg!(&matches);
|
|
||||||
Ok(matches.first().map(|ent| {
|
|
||||||
SearchResult {
|
|
||||||
entry: ent.body.clone().into(),
|
|
||||||
idx: ent.id(),
|
|
||||||
pos: start
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fuzzy_rank(search_term: &str, search_result: &str) -> u8 {
|
|
||||||
if search_result == search_term {
|
|
||||||
4
|
|
||||||
} else if search_result.starts_with(search_term) {
|
|
||||||
3
|
|
||||||
} else if search_result.contains(search_term) {
|
|
||||||
2
|
|
||||||
} else if is_subsequence(search_result, search_term) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if a search term is a subsequence of the body (characters in order but not necessarily adjacent)
|
|
||||||
fn is_subsequence(search_result: &str, search_term: &str) -> bool {
|
|
||||||
let mut result_chars = search_result.chars();
|
|
||||||
search_term.chars().all(|ch| result_chars.any(|c| c == ch))
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
pub mod history;
|
|
||||||
pub mod readline;
|
pub mod readline;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|||||||
@@ -59,14 +59,13 @@ impl Hinter for FernReadline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Highlighter for FernReadline {
|
impl Highlighter for FernReadline {
|
||||||
fn highlight<'l>(&self, line: &'l str, pos: usize) -> std::borrow::Cow<'l, str> {
|
fn highlight<'l>(&self, line: &'l str, _pos: usize) -> std::borrow::Cow<'l, str> {
|
||||||
Cow::Owned(line.to_string())
|
Cow::Owned(line.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validator for FernReadline {
|
impl Validator for FernReadline {
|
||||||
fn validate(&self, ctx: &mut rustyline::validate::ValidationContext) -> rustyline::Result<rustyline::validate::ValidationResult> {
|
fn validate(&self, ctx: &mut rustyline::validate::ValidationContext) -> rustyline::Result<rustyline::validate::ValidationResult> {
|
||||||
return Ok(ValidationResult::Valid(None));
|
|
||||||
let mut tokens = vec![];
|
let mut tokens = vec![];
|
||||||
let tk_stream = LexStream::new(Arc::new(ctx.input().to_string()), LexFlags::empty());
|
let tk_stream = LexStream::new(Arc::new(ctx.input().to_string()), LexFlags::empty());
|
||||||
for tk in tk_stream {
|
for tk in tk_stream {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::{collections::{HashMap, VecDeque}, ops::{Deref, Range}, sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard}, time::Duration};
|
use std::{collections::{HashMap, VecDeque}, ops::Deref, sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard}, time::Duration};
|
||||||
|
|
||||||
use nix::unistd::{gethostname, getppid, User};
|
use nix::unistd::{gethostname, getppid, User};
|
||||||
|
|
||||||
use crate::{exec_input, jobs::JobTab, libsh::{error::{ShErr, ShErrKind, ShResult}, utils::VecDequeExt}, parse::{lex::{get_char, Tk}, ConjunctNode, NdRule, Node, ParsedSrc}, prelude::*};
|
use crate::{exec_input, jobs::JobTab, libsh::{error::{ShErr, ShErrKind, ShResult}, utils::VecDequeExt}, parse::{lex::get_char, ConjunctNode, NdRule, Node, ParsedSrc}, prelude::*};
|
||||||
|
|
||||||
pub static JOB_TABLE: LazyLock<RwLock<JobTab>> = LazyLock::new(|| RwLock::new(JobTab::new()));
|
pub static JOB_TABLE: LazyLock<RwLock<JobTab>> = LazyLock::new(|| RwLock::new(JobTab::new()));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user