Skip to content

Commit

Permalink
refactor: change over to Flags and flags!
Browse files Browse the repository at this point in the history
  • Loading branch information
RoloEdits committed Dec 19, 2024
1 parent 88fce66 commit db92b37
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 249 deletions.
20 changes: 18 additions & 2 deletions helix-core/src/shellwords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,16 @@ impl<'a> Args<'a> {
}
}

pub fn flags<'f, F: Iterator<Item = &'f str>>(&mut self, mut flags: F) -> Option<&'a str> {
/// Takes in an iterator of flags and checks to see if the next argument to be yielded matches, returning it.
///
/// # Behavior
///
/// - **No Match**: Iterator is only advanced if a match is found; calling `flag` and then `next` when there are no matching flags would produce the expected next argument.
///
/// - **Termination**: This check is terminated upon encountering a `--` in the arguments. Upon encountering, it will also consume the `--`, so subsequent calls on `Self` will yield the arguments beyond `--`.
///
/// - **Match**: Argument is consumed and returned as a flag. This advances the iterator.
pub fn flag<F: IntoFlags>(&mut self, flags: &F) -> Option<&'a str> {
if self.is_empty() {
return None;
}
Expand All @@ -210,7 +219,10 @@ impl<'a> Args<'a> {
return None;
}

if flags.any(|f| f == arg.trim_start_matches('-').trim_start_matches("--")) {
if flags
.into_flags()
.any(|f| f == arg.trim_start_matches('-').trim_start_matches("--"))
{
return self
.next()
.map(|flag| flag.trim_start_matches('-').trim_start_matches("--"));
Expand Down Expand Up @@ -522,6 +534,10 @@ pub fn unescape(input: &str) -> Cow<'_, str> {
}
}

pub trait IntoFlags: Copy {
fn into_flags(self) -> impl Iterator<Item = &'static str>;
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
148 changes: 88 additions & 60 deletions helix-term/src/commands/flag.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
use helix_core::shellwords::IntoFlags;

#[derive(Debug, Clone, Copy)]
pub struct Flags(&'static [Flag]);

impl Flags {
#[inline]
pub const fn new(flags: &'static [Flag]) -> Self {
Self(flags)
}

#[inline]
pub const fn empty() -> Self {
Self(&[])
}

#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}

#[inline]
pub fn names(&self) -> impl Iterator<Item = &'static str> {
self.0
.iter()
.map(|flag| flag.long)
.chain(self.0.iter().filter_map(|flag| flag.short))
}
}

impl IntoIterator for &Flags {
type Item = &'static Flag;

type IntoIter = std::slice::Iter<'static, Flag>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}

impl IntoFlags for Flags {
#[inline]
fn into_flags(self) -> impl Iterator<Item = &'static str> {
self.names()
}
}

#[derive(Debug, Clone, Copy)]
pub struct Flag {
pub long: &'static str,
Expand All @@ -7,57 +56,30 @@ pub struct Flag {
}

#[macro_export]
macro_rules! flag {
// Case: All fields provided
(
long: $long:expr,
short: $short:expr,
desc: $desc:expr,
takes: $takes:expr $(,)?
) => {
$crate::commands::flag::Flag {
long: $long,
short: Some($short),
desc: $desc,
takes: $takes,
}
};
// Case: All fields except takes
(
long: $long:expr,
short: $short:expr,
desc: $desc:expr $(,)?
) => {
$crate::commands::flag::Flag {
long: $long,
short: Some($short),
desc: $desc,
takes: false,
}
macro_rules! flags {
// Empty case
[] => {
$crate::commands::flag::Flags::empty()
};
// Case: Only long, desc, and takes
(
long: $long:expr,
desc: $desc:expr,
takes: $takes:expr $(,)?
) => {
$crate::commands::flag::Flag {
long: $long,
short: None,
desc: $desc,
takes: $takes,
}
};
// Case: Only long and desc
(
long: $long:expr,
desc: $desc:expr $(,)?
) => {
$crate::commands::flag::Flag {
long: $long,
short: None,
desc: $desc,
takes: false,
// Multiple flags case
[$({ long: $long:expr, $(short: $short:expr,)? desc: $desc:expr $(, takes: $takes:expr)? $(,)?}),* $(,)?] => {
{
static FLAGS: &[$crate::commands::flag::Flag] = &[
$(
$crate::commands::flag::Flag {
long: $long,
short: {
#[allow(unused_mut)]
let mut short = None;
$(let _ = short.replace($short);)?
short
},
desc: $desc,
takes: false $(|| $takes)?,
}
),*
];
$crate::commands::flag::Flags::new(FLAGS)
}
};
}
Expand All @@ -67,22 +89,28 @@ mod tests {

#[test]
fn should_turn_macro_to_struct() {
let full = flag! {
long: "--all",
short: "-a",
desc: "clears all registers",
takes: true,
};
let flags = flags! [
{
long: "--all",
short: "-a",
desc: "clears all registers",
takes: true,
},
{
long: "--all",
desc: "clears all registers",
}
];

let mut iter = flags.into_iter();

let full = iter.next().unwrap();
assert_eq!("--all", full.long);
assert_eq!(Some("-a"), full.short);
assert_eq!("clears all registers", full.desc);
assert!(full.takes);

let partial = flag! {
long: "--all",
desc: "clears all registers"
};
let partial = iter.next().unwrap();

assert_eq!("--all", partial.long);
assert_eq!(None, partial.short);
Expand Down
Loading

0 comments on commit db92b37

Please sign in to comment.