diff options
author | Canop <cano.petrole@gmail.com> | 2022-02-23 19:28:23 +0100 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2022-02-23 19:28:23 +0100 |
commit | 28124358e13c1d157735653b37c4cadbae931715 (patch) | |
tree | 3b339dc22bb3bcbe0691d63a8c941530b6439950 | |
parent | 0bd7a7fa4f3dfd1a9f3ccdae38dcf7d553da3f1b (diff) |
output all valid column names on bad argument
-rw-r--r-- | src/col.rs | 169 | ||||
-rw-r--r-- | src/cols.rs | 10 |
2 files changed, 91 insertions, 88 deletions
@@ -6,75 +6,91 @@ use { termimad::minimad::Alignment, }; -/// A column of the lfs table. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Col { - Id, - Dev, - Filesystem, // alias fs - Label, - Disk, - Type, - Used, - Use, - Free, - Size, - InodesFree, - InodesUsed, - InodesUse, // alias inode - InodesCount, - MountPoint, // alias mount +macro_rules! col_enum { + ($($variant:ident $name:literal $($alias:literal)* : $title:literal ,)*) => { + /// A column of the lfs table. + #[derive(Debug, Clone, Copy, PartialEq)] + pub enum Col { + $($variant,)* + } + pub static ALL_COLS: &[Col] = &[ + $(Col::$variant,)* + ]; + impl FromStr for Col { + type Err = ParseColError; + fn from_str(s: &str) -> Result<Self, ParseColError> { + match s { + $( + $name => Ok(Self::$variant), + $( + $alias => Ok(Self::$variant), + )* + )* + _ => Err(ParseColError::new(s)), + } + } + } + impl fmt::Display for Col { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + $( + Self::$variant => write!(f, "{}", self.title()), + )* + } + } + } + impl Col { + pub fn name(self) -> &'static str { + match self { + $( + Self::$variant => $name, + )* + } + } + pub fn title(self) -> &'static str { + match self { + $( + Self::$variant => $title, + )* + } + } + } + } } -pub static DEFAULT_COLS: &[Col] = &[ - Col::Filesystem, - Col::Disk, - Col::Type, - Col::Used, - Col::Use, - Col::Free, - Col::Size, - Col::MountPoint, -]; +// definition of all columns and their names +// in the --cols definition +col_enum!( + // syntax: Variant name [alias] : title + Id "id": "id", + Dev "dev": "dev", + Filesystem "fs" "filesystem": "filesystem", + Label "label": "label", + Disk "disk": "disk", + Type "type": "type", + Used "used": "used", + Use "use": "use%", + Free "free": "free", + Size "size": "size", + InodesUsed "inodes_used": "used inodes", + InodesUse "inodes" "inodes_use": "inodes%", + InodesFree "inodes_free": "free inodes", + InodesCount "inodes_total" "inodes_count": "inodes total", + MountPoint "mount" "mount_point": "mount point", +); -pub static ALL_COLS: &[Col] = &[ - Col::Id, - Col::Dev, +pub static DEFAULT_COLS: &[Col] = &[ Col::Filesystem, - Col::Label, Col::Disk, Col::Type, Col::Used, Col::Use, Col::Free, Col::Size, - Col::InodesUsed, - Col::InodesUse, - Col::InodesFree, - Col::InodesCount, Col::MountPoint, ]; impl Col { - pub fn title(self) -> &'static str { - match self { - Self::Id => "id", - Self::Dev => "dev", - Self::Filesystem => "filesystem", - Self::Label => "label", - Self::Disk => "disk", - Self::Type => "type", - Self::Used => "used", - Self::Use => "use%", - Self::Free => "free", - Self::Size => "size", - Self::InodesUsed => "used inodes", - Self::InodesUse => "inodes%", - Self::InodesFree => "free inodes", - Self::InodesCount => "inodes total", - Self::MountPoint => "mount point", - } - } pub fn header_align(self) -> Alignment { match self { Self::Label => Alignment::Left, @@ -103,11 +119,6 @@ impl Col { } } -impl fmt::Display for Col { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.title()) - } -} #[derive(Debug)] pub struct ParseColError { @@ -121,31 +132,21 @@ impl ParseColError { } impl fmt::Display for ParseColError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?} can't be parsed as a column", self.raw) + write!(f, "{:?} can't be parsed as a column; expected one of ", self.raw)?; + let mut names = ALL_COLS.iter().map(|c| c.name()).peekable(); + write!(f, "{:?}", names.next().unwrap())?; + loop { + if let Some(name) = names.next() { + if names.peek().is_none() { + write!(f, ", or {:?}", name)?; + break; + } else { + write!(f, ", {:?}", name)?; + } + } + } + Ok(()) } } impl std::error::Error for ParseColError {} -impl FromStr for Col { - type Err = ParseColError; - fn from_str(s: &str) -> Result<Self, ParseColError> { - match s { - "id" => Ok(Self::Id), - "dev" | "device" => Ok(Self::Dev), - "fs" | "filesystem" => Ok(Self::Filesystem), - "label" => Ok(Self::Label), - "disk" => Ok(Self::Disk), - "type" => Ok(Self::Type), - "used" => Ok(Self::Used), - "use" => Ok(Self::Use), - "free" => Ok(Self::Free), - "size" => Ok(Self::Size), - "inodes_free" => Ok(Self::InodesFree), - "inodes_used" => Ok(Self::InodesUsed), - "inodes" | "inode_use" | "inodes_use" => Ok(Self::InodesUse), - "inode_count" | "inodes_count" => Ok(Self::InodesCount), - "mount" | "mountpoint" => Ok(Self::MountPoint), - _ => Err(ParseColError::new(s)), - } - } -} diff --git a/src/cols.rs b/src/cols.rs index cecb8a2..2a14981 100644 --- a/src/cols.rs +++ b/src/cols.rs @@ -167,9 +167,11 @@ mod cols_parsing { #[test] fn bad_cols(){ - assert_eq!( - "nothing".parse::<Cols>().unwrap_err().to_string(), - r#""nothing" can't be parsed as a column"#, + assert!( + "nothing".parse::<Cols>() + .unwrap_err() + .to_string() + .starts_with(r#""nothing" can't be parsed as a column; expected"#), ); } @@ -264,7 +266,7 @@ mod cols_parsing { vec![Filesystem, Disk, Type, Used, Use, Free, MountPoint, InodesFree, Size] ); check( - "+dev-size+inodes", + "+dev-size+inodes_use", vec![Filesystem, Disk, Type, Used, Use, Free, MountPoint, Dev, InodesUse] ); check( |