Repository: sharkdp/bat
File: src/less.rs (Rust)

Code before:
pub enum LessVersion {
    Less(usize),
    BusyBox,
}

pub fn retrieve_less_version(less_path: &dyn AsRef<OsStr>) -> Option<LessVersion> {
    let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?;

    let cmd = Command::new(resolved_path).arg("--version").output().ok()?;
    if cmd.status.success() {
        parse_less_version(&cmd.stdout)
    } else {
        parse_less_version(&cmd.stderr)
    }
}

fn parse_less_version(output: &[u8]) -> Option<LessVersion> {
    match std::str::from_utf8(output) {
        Ok(version) if version.starts_with("less ") => {
            let end = (&version[5..]).find(|c: char| !c.is_ascii_digit())? + 5;
            Some(LessVersion::Less(version[5..end].parse::<usize>().ok()?))
        }
        Ok(version) if version.contains("BusyBox ") => Some(LessVersion::BusyBox),
        _ => None,
    }
}

#[test]
fn test_parse_less_version_487() {
    let output = b"less 487 (GNU regular expressions)
Copyright (C) 1984-2016  Mark Nudelman

less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Homepage: http://www.greenwoodsoftware.com/less";

    assert_eq!(Some(LessVersion::Less(487)), parse_less_version(output));
}

#[test]
fn test_parse_less_version_529() {
    let output = b"less 529 (Spencer V8 regular expressions)
Copyright (C) 1984-2017  Mark Nudelman

less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Homepage: http://www.greenwoodsoftware.com/less";

    assert_eq!(Some(LessVersion::Less(529)), parse_less_version(output));

Review comment (refactor):
Bonus points if you move this out to a helper function so that the diff is minimized. Something like this:

```rust
fn parse_vanilla_less_version(output: &[u8]) -> Option<usize> { 
    let version = std::str::from_utf8(&output[5..]).ok()?;
    let end = version.find(|c: char| !c.is_ascii_digit())?;
    version[..end].parse::<usize>().ok()
}


Code after:
pub enum LessVersion {
    Less(usize),
    BusyBox,
}

pub fn retrieve_less_version(less_path: &dyn AsRef<OsStr>) -> Option<LessVersion> {
    let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?;

    let cmd = Command::new(resolved_path).arg("--version").output().ok()?;
    if cmd.status.success() {
        parse_less_version(&cmd.stdout)
    } else {
        parse_less_version_busybox(&cmd.stderr)
    }
}

fn parse_less_version(output: &[u8]) -> Option<LessVersion> {
    if !output.starts_with(b"less ") {
        return None;
    }

    let version = std::str::from_utf8(&output[5..]).ok()?;
    let end = version.find(|c: char| !c.is_ascii_digit())?;
    Some(LessVersion::Less(version[..end].parse::<usize>().ok()?))
}

fn parse_less_version_busybox(output: &[u8]) -> Option<LessVersion> {
    match std::str::from_utf8(output) {
        Ok(version) if version.contains("BusyBox ") => Some(LessVersion::BusyBox),
        _ => None,
    }
}

#[test]
fn test_parse_less_version_487() {
    let output = b"less 487 (GNU regular expressions)
Copyright (C) 1984-2016  Mark Nudelman

less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Homepage: http://www.greenwoodsoftware.com/less";

    assert_eq!(Some(LessVersion::Less(487)), parse_less_version(output));
}

#[test]
fn test_parse_less_version_529() {
    let output = b"less 529 (Spencer V8 regular expressions)
Copyright (C) 1984-2017  Mark Nudelman