Expose completion/history metadata to autocmd hooks and add broader Var conversion impls
This commit is contained in:
@@ -544,9 +544,15 @@ pub trait Completer {
|
|||||||
fn reset(&mut self);
|
fn reset(&mut self);
|
||||||
fn reset_stay_active(&mut self);
|
fn reset_stay_active(&mut self);
|
||||||
fn is_active(&self) -> bool;
|
fn is_active(&self) -> bool;
|
||||||
|
fn all_candidates(&self) -> Vec<String> { vec![] }
|
||||||
fn selected_candidate(&self) -> Option<String>;
|
fn selected_candidate(&self) -> Option<String>;
|
||||||
fn token_span(&self) -> (usize, usize);
|
fn token_span(&self) -> (usize, usize);
|
||||||
fn original_input(&self) -> &str;
|
fn original_input(&self) -> &str;
|
||||||
|
fn token(&self) -> &str {
|
||||||
|
let orig = self.original_input();
|
||||||
|
let (s,e) = self.token_span();
|
||||||
|
orig.get(s..e).unwrap_or(orig)
|
||||||
|
}
|
||||||
fn draw(&mut self, writer: &mut TermWriter) -> ShResult<()>;
|
fn draw(&mut self, writer: &mut TermWriter) -> ShResult<()>;
|
||||||
fn clear(&mut self, _writer: &mut TermWriter) -> ShResult<()> {
|
fn clear(&mut self, _writer: &mut TermWriter) -> ShResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -558,8 +564,8 @@ pub trait Completer {
|
|||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct ScoredCandidate {
|
pub struct ScoredCandidate {
|
||||||
content: String,
|
pub content: String,
|
||||||
score: Option<i32>,
|
pub score: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScoredCandidate {
|
impl ScoredCandidate {
|
||||||
@@ -766,6 +772,22 @@ impl FuzzySelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn candidates(&self) -> &[String] {
|
||||||
|
&self.candidates
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filtered(&self) -> &[ScoredCandidate] {
|
||||||
|
&self.filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filtered_len(&self) -> usize {
|
||||||
|
self.filtered.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn candidates_len(&self) -> usize {
|
||||||
|
self.candidates.len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn activate(&mut self, candidates: Vec<String>) {
|
pub fn activate(&mut self, candidates: Vec<String>) {
|
||||||
self.active = true;
|
self.active = true;
|
||||||
self.candidates = candidates;
|
self.candidates = candidates;
|
||||||
@@ -1119,6 +1141,9 @@ impl Default for FuzzyCompleter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Completer for FuzzyCompleter {
|
impl Completer for FuzzyCompleter {
|
||||||
|
fn all_candidates(&self) -> Vec<String> {
|
||||||
|
self.selector.candidates.clone()
|
||||||
|
}
|
||||||
fn set_prompt_line_context(&mut self, line_width: u16, cursor_col: u16) {
|
fn set_prompt_line_context(&mut self, line_width: u16, cursor_col: u16) {
|
||||||
self
|
self
|
||||||
.selector
|
.selector
|
||||||
@@ -1209,6 +1234,9 @@ pub struct SimpleCompleter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Completer for SimpleCompleter {
|
impl Completer for SimpleCompleter {
|
||||||
|
fn all_candidates(&self) -> Vec<String> {
|
||||||
|
self.candidates.clone()
|
||||||
|
}
|
||||||
fn reset_stay_active(&mut self) {
|
fn reset_stay_active(&mut self) {
|
||||||
let active = self.is_active();
|
let active = self.is_active();
|
||||||
self.reset();
|
self.reset();
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ use crate::readline::complete::{FuzzyCompleter, SelectorResponse};
|
|||||||
use crate::readline::term::{Pos, TermReader, calc_str_width};
|
use crate::readline::term::{Pos, TermReader, calc_str_width};
|
||||||
use crate::readline::vimode::{ViEx, ViVerbatim};
|
use crate::readline::vimode::{ViEx, ViVerbatim};
|
||||||
use crate::state::{
|
use crate::state::{
|
||||||
AutoCmdKind, ShellParam, VarFlags, VarKind, read_logic, read_shopts, with_vars, write_meta,
|
AutoCmdKind, ShellParam, Var, VarFlags, VarKind, read_logic, read_shopts, with_vars, write_meta, write_vars
|
||||||
write_vars,
|
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
libsh::error::ShResult,
|
libsh::error::ShResult,
|
||||||
@@ -319,6 +318,10 @@ impl ShedVi {
|
|||||||
self.completer.reset_stay_active();
|
self.completer.reset_stay_active();
|
||||||
self.needs_redraw = true;
|
self.needs_redraw = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else if self.history.fuzzy_finder.is_active() {
|
||||||
|
self.history.fuzzy_finder.reset_stay_active();
|
||||||
|
self.needs_redraw = true;
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
self.reset(full_redraw)
|
self.reset(full_redraw)
|
||||||
}
|
}
|
||||||
@@ -646,10 +649,16 @@ impl ShedVi {
|
|||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnCompletionStart));
|
let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnCompletionStart));
|
||||||
|
let candidates = self.completer.all_candidates();
|
||||||
|
let num_candidates = candidates.len();
|
||||||
|
with_vars([
|
||||||
|
("_NUM_MATCHES".into(), Into::<Var>::into(num_candidates)),
|
||||||
|
("_MATCHES".into(), Into::<Var>::into(candidates)),
|
||||||
|
("_SEARCH_STR".into(), Into::<Var>::into(self.completer.token())),
|
||||||
|
], || {
|
||||||
|
post_cmds.exec();
|
||||||
|
});
|
||||||
|
|
||||||
post_cmds.exec();
|
|
||||||
|
|
||||||
self.writer.send_bell().ok();
|
|
||||||
if self.completer.is_active() {
|
if self.completer.is_active() {
|
||||||
write_vars(|v| {
|
write_vars(|v| {
|
||||||
v.set_var(
|
v.set_var(
|
||||||
@@ -662,7 +671,9 @@ impl ShedVi {
|
|||||||
self.prompt.refresh();
|
self.prompt.refresh();
|
||||||
self.needs_redraw = true;
|
self.needs_redraw = true;
|
||||||
self.editor.set_hint(None);
|
self.editor.set_hint(None);
|
||||||
}
|
} else {
|
||||||
|
self.writer.send_bell().ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +684,9 @@ impl ShedVi {
|
|||||||
match self.history.start_search(initial) {
|
match self.history.start_search(initial) {
|
||||||
Some(entry) => {
|
Some(entry) => {
|
||||||
let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnHistorySelect));
|
let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnHistorySelect));
|
||||||
with_vars([("_HIST_ENTRY".into(), entry.clone())], || {
|
with_vars([
|
||||||
|
("_HIST_ENTRY".into(), entry.clone()),
|
||||||
|
], || {
|
||||||
post_cmds.exec_with(&entry);
|
post_cmds.exec_with(&entry);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -686,9 +699,26 @@ impl ShedVi {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnHistoryOpen));
|
let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnHistoryOpen));
|
||||||
post_cmds.exec();
|
let entries = self.history.fuzzy_finder.candidates();
|
||||||
|
let matches = self.history.fuzzy_finder
|
||||||
|
.filtered()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|sc| sc.content)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let num_entries = entries.len();
|
||||||
|
let num_matches = matches.len();
|
||||||
|
with_vars([
|
||||||
|
("_ENTRIES".into(),Into::<Var>::into(entries)),
|
||||||
|
("_NUM_ENTRIES".into(),Into::<Var>::into(num_entries)),
|
||||||
|
("_MATCHES".into(),Into::<Var>::into(matches)),
|
||||||
|
("_NUM_MATCHES".into(),Into::<Var>::into(num_matches)),
|
||||||
|
("_SEARCH_STR".into(), Into::<Var>::into(initial)),
|
||||||
|
], || {
|
||||||
|
post_cmds.exec();
|
||||||
|
});
|
||||||
|
|
||||||
self.writer.send_bell().ok();
|
|
||||||
if self.history.fuzzy_finder.is_active() {
|
if self.history.fuzzy_finder.is_active() {
|
||||||
write_vars(|v| {
|
write_vars(|v| {
|
||||||
v.set_var(
|
v.set_var(
|
||||||
@@ -701,7 +731,9 @@ impl ShedVi {
|
|||||||
self.prompt.refresh();
|
self.prompt.refresh();
|
||||||
self.needs_redraw = true;
|
self.needs_redraw = true;
|
||||||
self.editor.set_hint(None);
|
self.editor.set_hint(None);
|
||||||
}
|
} else {
|
||||||
|
self.writer.send_bell().ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
src/state.rs
52
src/state.rs
@@ -1,11 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell, collections::{HashMap, HashSet, VecDeque, hash_map::Entry}, fmt::Display, ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign}, os::unix::fs::PermissionsExt, str::FromStr, time::Duration
|
||||||
collections::{HashMap, HashSet, VecDeque, hash_map::Entry},
|
|
||||||
fmt::Display,
|
|
||||||
ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign},
|
|
||||||
os::unix::fs::PermissionsExt,
|
|
||||||
str::FromStr,
|
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use nix::unistd::{User, gethostname, getppid};
|
use nix::unistd::{User, gethostname, getppid};
|
||||||
@@ -920,18 +914,46 @@ impl Display for Var {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Var {
|
impl From<Vec<String>> for Var {
|
||||||
fn from(value: String) -> Self {
|
fn from(value: Vec<String>) -> Self {
|
||||||
Self::new(VarKind::Str(value), VarFlags::NONE)
|
Self::new(VarKind::Arr(value.into()), VarFlags::NONE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Var {
|
impl From<&[String]> for Var {
|
||||||
fn from(value: &str) -> Self {
|
fn from(value: &[String]) -> Self {
|
||||||
Self::new(VarKind::Str(value.into()), VarFlags::NONE)
|
let mut new = VecDeque::new();
|
||||||
}
|
new.extend(value.iter().cloned());
|
||||||
|
Self::new(VarKind::Arr(new), VarFlags::NONE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_var_from {
|
||||||
|
($($t:ty),*) => {
|
||||||
|
$(impl From<$t> for Var {
|
||||||
|
fn from(value: $t) -> Self {
|
||||||
|
Self::new(VarKind::Str(value.to_string()), VarFlags::NONE)
|
||||||
|
}
|
||||||
|
})*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_var_from!(
|
||||||
|
i8,
|
||||||
|
i16,
|
||||||
|
i32,
|
||||||
|
i64,
|
||||||
|
isize,
|
||||||
|
u8,
|
||||||
|
u16,
|
||||||
|
u32,
|
||||||
|
u64,
|
||||||
|
usize,
|
||||||
|
String,
|
||||||
|
&str,
|
||||||
|
bool
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct VarTab {
|
pub struct VarTab {
|
||||||
vars: HashMap<String, Var>,
|
vars: HashMap<String, Var>,
|
||||||
|
|||||||
Reference in New Issue
Block a user