summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2022-02-23 19:28:23 +0100
committerCanop <cano.petrole@gmail.com>2022-02-23 19:28:23 +0100
commit28124358e13c1d157735653b37c4cadbae931715 (patch)
tree3b339dc22bb3bcbe0691d63a8c941530b6439950
parent0bd7a7fa4f3dfd1a9f3ccdae38dcf7d553da3f1b (diff)
output all valid column names on bad argument
-rw-r--r--src/col.rs169
-rw-r--r--src/cols.rs10
2 files changed, 91 insertions, 88 deletions
diff --git a/src/col.rs b/src/col.rs
index f888cc8..7efa234 100644
--- a/src/col.rs
+++ b/src/col.rs
@@ -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(