mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-04-19 06:31:13 -03:00
Port wilcard.{cpp,h} to Rust
- This is untested and unused, string ownership is very much subject to change - Ports the minimally necessary parts of complete.rs as well - This should fix an infinite loop in `create_directory` in `path.rs`, the first `wstat` loop only breaks if it fails with an error that's different from EAGAIN
This commit is contained in:
@@ -1258,7 +1258,7 @@ pub fn assert_is_background_thread() {
|
||||
|
||||
/// Format the specified size (in bytes, kilobytes, etc.) into the specified stringbuffer.
|
||||
#[widestrs]
|
||||
fn format_size(mut sz: i64) -> WString {
|
||||
pub fn format_size(mut sz: i64) -> WString {
|
||||
let mut result = WString::new();
|
||||
const sz_names: [&wstr; 8] = ["kB"L, "MB"L, "GB"L, "TB"L, "PB"L, "EB"L, "ZB"L, "YB"L];
|
||||
if sz < 0 {
|
||||
|
||||
181
fish-rust/src/complete.rs
Normal file
181
fish-rust/src/complete.rs
Normal file
@@ -0,0 +1,181 @@
|
||||
/// Prototypes for functions related to tab-completion.
|
||||
///
|
||||
/// These functions are used for storing and retrieving tab-completion data, as well as for
|
||||
/// performing tab-completion.
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wcstringutil::StringFuzzyMatch;
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct CompletionMode {
|
||||
/// If set, skip file completions.
|
||||
pub no_files: bool,
|
||||
pub force_files: bool,
|
||||
/// If set, require a parameter after completion.
|
||||
pub requires_param: bool,
|
||||
}
|
||||
|
||||
/// Character that separates the completion and description on programmable completions.
|
||||
pub const PROG_COMPLETE_SEP: char = '\t';
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct CompleteFlags: u8 {
|
||||
/// Do not insert space afterwards if this is the only completion. (The default is to try insert
|
||||
/// a space).
|
||||
const NO_SPACE = 1 << 0;
|
||||
/// This is not the suffix of a token, but replaces it entirely.
|
||||
const REPLACES_TOKEN = 1 << 1;
|
||||
/// This completion may or may not want a space at the end - guess by checking the last
|
||||
/// character of the completion.
|
||||
const AUTO_SPACE = 1 << 2;
|
||||
/// This completion should be inserted as-is, without escaping.
|
||||
const DONT_ESCAPE = 1 << 3;
|
||||
/// If you do escape, don't escape tildes.
|
||||
const DONT_ESCAPE_TILDES = 1 << 4;
|
||||
/// Do not sort supplied completions
|
||||
const DONT_SORT = 1 << 5;
|
||||
/// This completion looks to have the same string as an existing argument.
|
||||
const DUPLICATES_ARGUMENT = 1 << 6;
|
||||
/// This completes not just a token but replaces the entire commandline.
|
||||
const REPLACES_COMMANDLINE = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Completion {
|
||||
pub completion: WString,
|
||||
pub description: WString,
|
||||
pub r#match: StringFuzzyMatch,
|
||||
pub flags: CompleteFlags,
|
||||
}
|
||||
|
||||
impl Default for Completion {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
completion: Default::default(),
|
||||
description: Default::default(),
|
||||
r#match: StringFuzzyMatch::exact_match(),
|
||||
flags: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WString> for Completion {
|
||||
fn from(completion: WString) -> Completion {
|
||||
Completion {
|
||||
completion,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Completion {
|
||||
/// \return whether this replaces its token.
|
||||
pub fn replaces_token(&self) -> bool {
|
||||
self.flags.contains(CompleteFlags::REPLACES_TOKEN)
|
||||
}
|
||||
/// \return whether this replaces the entire commandline.
|
||||
pub fn replaces_commandline(&self) -> bool {
|
||||
self.flags.contains(CompleteFlags::REPLACES_COMMANDLINE)
|
||||
}
|
||||
|
||||
/// \return the completion's match rank. Lower ranks are better completions.
|
||||
pub fn rank(&self) -> u32 {
|
||||
self.r#match.rank()
|
||||
}
|
||||
|
||||
/// If this completion replaces the entire token, prepend a prefix. Otherwise do nothing.
|
||||
pub fn prepend_token_prefix(&mut self, prefix: impl AsRef<wstr>) {
|
||||
if self.flags.contains(CompleteFlags::REPLACES_TOKEN) {
|
||||
self.completion.insert_utfstr(0, prefix.as_ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A completion receiver accepts completions. It is essentially a wrapper around Vec with
|
||||
/// some conveniences.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct CompletionReceiver {
|
||||
/// Our list of completions.
|
||||
completions: Vec<Completion>,
|
||||
/// The maximum number of completions to add. If our list length exceeds this, then new
|
||||
/// completions are not added. Note 0 has no special significance here - use
|
||||
/// usize::MAX instead.
|
||||
limit: usize,
|
||||
}
|
||||
|
||||
// We are only wrapping a `Vec<Completion>`, any non-mutable methods can be safely deferred to the
|
||||
// Vec-impl
|
||||
impl std::ops::Deref for CompletionReceiver {
|
||||
type Target = Vec<Completion>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.completions
|
||||
}
|
||||
}
|
||||
|
||||
impl CompletionReceiver {
|
||||
pub fn new(limit: usize) -> Self {
|
||||
Self {
|
||||
limit,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a completion.
|
||||
/// \return true on success, false if this would overflow the limit.
|
||||
#[must_use]
|
||||
pub fn add(&mut self, comp: impl Into<Completion>) -> bool {
|
||||
if self.completions.len() >= self.limit {
|
||||
return false;
|
||||
}
|
||||
self.completions.push(comp.into());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Add a list of completions.
|
||||
/// \return true on success, false if this would overflow the limit.
|
||||
#[must_use]
|
||||
pub fn extend(
|
||||
&mut self,
|
||||
iter: impl IntoIterator<Item = Completion, IntoIter = impl ExactSizeIterator<Item = Completion>>,
|
||||
) -> bool {
|
||||
let iter = iter.into_iter();
|
||||
if iter.len() > self.limit - self.completions.len() {
|
||||
return false;
|
||||
}
|
||||
self.completions.extend(iter);
|
||||
// this only fails if the ExactSizeIterator impl is bogus
|
||||
assert!(
|
||||
self.completions.len() <= self.limit,
|
||||
"ExactSizeIterator returned more items than it should"
|
||||
);
|
||||
true
|
||||
}
|
||||
|
||||
/// Swap our completions with a new list.
|
||||
pub fn swap(&mut self, lst: &mut Vec<Completion>) {
|
||||
// XXX: This completly breaks our completions.len() <= self.limit invariant
|
||||
std::mem::swap(&mut self.completions, lst);
|
||||
}
|
||||
|
||||
/// Clear the list of completions. This retains the storage inside completions_ which can be
|
||||
/// useful to prevent allocations.
|
||||
pub fn clear(&mut self) {
|
||||
self.completions.clear();
|
||||
}
|
||||
|
||||
/// \return the list of completions, clearing it.
|
||||
pub fn take(&mut self) -> Vec<Completion> {
|
||||
std::mem::take(&mut self.completions)
|
||||
}
|
||||
|
||||
/// \return a new, empty receiver whose limit is our remaining capacity.
|
||||
/// This is useful for e.g. recursive calls when you want to act on the result before adding it.
|
||||
pub fn subreceiver(&self) -> Self {
|
||||
// XXX: this should not need to be saturating, we have a faulty invariant
|
||||
let remaining_capacity = self.limit.saturating_sub(self.completions.len());
|
||||
Self::new(remaining_capacity)
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
mod builtins;
|
||||
mod color;
|
||||
mod compat;
|
||||
mod complete;
|
||||
mod curses;
|
||||
mod env;
|
||||
mod env_dispatch;
|
||||
|
||||
@@ -98,10 +98,10 @@ pub enum CaseFold {
|
||||
}
|
||||
|
||||
/// A lightweight value-type describing how closely a string fuzzy-matches another string.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct StringFuzzyMatch {
|
||||
typ: ContainType,
|
||||
case_fold: CaseFold,
|
||||
pub typ: ContainType,
|
||||
pub case_fold: CaseFold,
|
||||
}
|
||||
|
||||
impl StringFuzzyMatch {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user