csvlens 0.15.1

Command line csv viewer
Documentation
use crate::errors::{CsvlensError, CsvlensResult};

/// Delimiter behaviour as specified in the command line
#[derive(Debug)]
pub enum Delimiter {
    /// Use the default delimiter (auto detect)
    Default,

    /// Comma delimiter
    Comma,

    /// Use tab as the delimiter
    Tab,

    /// Use the specified delimiter
    Character(u8),

    /// Auto-detect the delimiter
    Auto,
}

impl Delimiter {
    /// Create a Delimiter by parsing the command line argument for the delimiter
    pub fn from_arg(
        delimiter_arg: &Option<String>,
        tab_separation: bool,
        comma_separation: bool,
    ) -> CsvlensResult<Self> {
        if comma_separation {
            return Ok(Delimiter::Comma);
        }
        if tab_separation {
            return Ok(Delimiter::Tab);
        }

        if let Some(s) = delimiter_arg {
            if s == "auto" {
                return Ok(Delimiter::Auto);
            }
            if s == r"\t" {
                return Ok(Delimiter::Tab);
            }
            let mut chars = s.chars();
            let c = chars.next().ok_or_else(|| CsvlensError::DelimiterEmpty)?;
            if !c.is_ascii() {
                return Err(CsvlensError::DelimiterNotAscii(c));
            }
            if chars.next().is_some() {
                return Err(CsvlensError::DelimiterMultipleCharacters(s.clone()));
            }
            if c == 't' {
                // commonly occurrs when argument is specified like "-d \t" without quotes
                return Ok(Delimiter::Tab);
            }
            Ok(Delimiter::Character(c.try_into()?))
        } else {
            Ok(Delimiter::Default)
        }
    }
}

/// Sniff the delimiter from the file
pub fn sniff_delimiter(filename: &str) -> Option<u8> {
    let mut sniffer = qsv_sniffer::Sniffer::new();
    sniffer.sample_size(qsv_sniffer::SampleSize::Records(200));
    if let Ok(metadata) = sniffer.sniff_path(filename) {
        return Some(metadata.dialect.delimiter);
    }
    None
}