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

Code before:
                Some("auto") | _ => self.interactive_output,
            },
            paging_mode: match self.matches.value_of("paging") {
                Some("always") => PagingMode::Always,
                Some("never") => PagingMode::Never,
                Some("auto") | _ => if files.contains(&None) {
                    // If we are reading from stdin, only enable paging if we write to an
                    // interactive terminal and if we do not *read* from an interactive
                    // terminal.
                    if self.interactive_output && !atty::is(Stream::Stdin) {
                        PagingMode::QuitIfOneScreen
                    } else {
                        PagingMode::Never
                    }
                } else {
                    if self.interactive_output {
                        PagingMode::QuitIfOneScreen
                    } else {
                        PagingMode::Never
                    }
                },
            },
            term_width: Term::stdout().size().1 as usize,
            files,
            theme: self.matches.value_of("theme"),
            line_range: self.matches.value_of("line-range").map(LineRange::from),
        })
    }

    fn files(&self) -> Vec<Option<&str>> {
        self.matches
            .values_of("FILE")
            .map(|values| {
                values
                    .map(|filename| {
                        if filename == "-" {
                            None
                        } else {
                            Some(filename)
                        }
                    })
                    .collect()
            })
            .unwrap_or_else(|| vec![None]) // read from stdin (None) if no args are given
    }

    fn output_components(&self) -> Result<OutputComponents> {
        let matches = &self.matches;
        Ok(OutputComponents(if matches.is_present("number") {
            [OutputComponent::Numbers].iter().cloned().collect()
        } else {

Review comment (refactor):
If we change the signature of `LineRange::from`, as suggested above, we could use
``` rust
line_range: tranpose(self.matches.value_of("line-range").map(LineRange::from))
```
such that the parsing-error-messages would bubble up to the main function (and reported to the user).

Here, `transpose` is a little helper function that turns a "Option of Result" into a "Result of Option". It could be implemented like this:
```rust
fn transpose<T, E>(opt: Option<Result<T, E>>) -> Result<Option<T>, E> {
    opt.map_or(Ok(None), |res| res.map(Some))
}
```

This function is actually an experimental feature which means that we could soon replace this by a call to the standard-library `.transpose()`: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose

Code after:
                Some("never") => false,
                Some("auto") | _ => self.interactive_output,
            },
            paging_mode: match self.matches.value_of("paging") {
                Some("always") => PagingMode::Always,
                Some("never") => PagingMode::Never,
                Some("auto") | _ => if files.contains(&None) {
                    // If we are reading from stdin, only enable paging if we write to an
                    // interactive terminal and if we do not *read* from an interactive
                    // terminal.
                    if self.interactive_output && !atty::is(Stream::Stdin) {
                        PagingMode::QuitIfOneScreen
                    } else {
                        PagingMode::Never
                    }
                } else {
                    if self.interactive_output {
                        PagingMode::QuitIfOneScreen
                    } else {
                        PagingMode::Never
                    }
                },
            },
            term_width: Term::stdout().size().1 as usize,
            files,
            theme: self.matches.value_of("theme"),
            line_range: transpose(self.matches.value_of("line-range").map(LineRange::from))?,
        })
    }

    fn files(&self) -> Vec<Option<&str>> {
        self.matches
            .values_of("FILE")
            .map(|values| {
                values
                    .map(|filename| {
                        if filename == "-" {
                            None
                        } else {
                            Some(filename)
                        }
                    })
                    .collect()
            })
            .unwrap_or_else(|| vec![None]) // read from stdin (None) if no args are given
    }

    fn output_components(&self) -> Result<OutputComponents> {
        let matches = &self.matches;
        Ok(OutputComponents(if matches.is_present("number") {
            [OutputComponent::Numbers].iter().cloned().collect()