Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "--list-languages" command line argument #79

Merged
merged 15 commits into from
May 8, 2018
Merged

Add "--list-languages" command line argument #79

merged 15 commits into from
May 8, 2018

Conversation

connorkuehl
Copy link
Contributor

Closes #69

$ ./target/debug/bat.exe Cargo.toml --list-languages
ASP                              | asa
HTML (ASP)                       | asp
ActionScript                     | as
AppleScript                      | applescript, script editor
Batch File                       | bat, cmd
NAnt Build File                  | build
C#                               | cs, csx
C++                              | cpp, cc, cp, cxx, c++, C, h, hh, hpp, hxx, h++, inl, ipp
C                                | c, h
--snipped--

src/main.rs Outdated

for lang in languages {
print!("{:width$} | ", lang.name, width = longest);
for i in 0..lang.file_extensions.len() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a more idiomatic way to list elements separated by a comma (except the last) than an indexed for-loop? I guess after using range loops and not having to deal with indices for so long I feel quite spoiled.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should be able to use lang.file_extensions.join(", ").

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That worked. Thank you!

Copy link
Owner

@sharkdp sharkdp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thank you very much work working on this!

src/main.rs Outdated
.arg(
Arg::with_name("list languages")
.long("list-languages")
.takes_value(false)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think false is the default value, so .takes_value can be removed here.

src/main.rs Outdated
@@ -437,6 +437,12 @@ fn run() -> Result<()> {
.default_value("auto")
.help("When to use the pager"),
)
.arg(
Arg::with_name("list languages")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if we use list-languages here, just like the .long(..) name.

src/main.rs Outdated
@@ -486,6 +492,31 @@ fn run() -> Result<()> {
)
})?;

if let Some(_) = app_matches.values_of("list languages") {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use if app_matches.is_present("list-languages").

src/main.rs Outdated

let longest = match languages.iter()
.map(|s| s.name.len())
.max() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use languages.iter().....max().unwrap_or(32) here instead of the match statement.

src/main.rs Outdated
};

for lang in languages {
print!("{:width$} | ", lang.name, width = longest);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Didn't know this was possible.

src/main.rs Outdated

for lang in languages {
print!("{:width$} | ", lang.name, width = longest);
for i in 0..lang.file_extensions.len() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should be able to use lang.file_extensions.join(", ").

@sharkdp
Copy link
Owner

sharkdp commented May 7, 2018

Maybe we should also restrict the length of the file extensions?

Ruby                             | rb, Appfile, Appraisals, Berksfile, Brewfile, capfile, cgi, Cheffile, config.ru, Deliverfile, Fastfile, fcgi, Gemfile, gemspec, Guardfile, irbrc, jbuilder, podspec, prawn, rabl, rake, Rakefile, Rantfile, rbx, rjs, ruby.rail, Scanfile, simplecov, Snapfile, thor, Thorfile, Vagrantfile

😮

@connorkuehl
Copy link
Contributor Author

Yes, we should limit the size of the extensions column. I had no idea some languages could have so many extensions lol.

I implemented simple line-wrapping for it. I'm still trying to learn more Rust, so if it is unnecessarily complex I would love some feedback to trim it down. I tried brainstorming a cool and simple iterator solution to this problem but didn't get too far.

Here's what it looks like:

--snipped--
reStructuredText                 | rst, rest
Ruby                             | rb, Appfile, Appraisals, Berksfile, Brewfile, capfile, cgi,
                                 | Cheffile, config.ru, Deliverfile, Fastfile, fcgi, Gemfile,
                                 | gemspec, Guardfile, irbrc, jbuilder, podspec, prawn, rabl,
                                 | rake, Rakefile, Rantfile, rbx, rjs, ruby.rail, Scanfile,
                                 | simplecov, Snapfile, thor, Thorfile, Vagrantfile
Cargo Build Results              |
Rust                             | rs
SQL                              | sql, ddl, dml
--snipped--

src/main.rs Outdated
print!("{:width$}{}", lang.name, separator, width = longest);

// Line-wrapping for the possible file extension overflow.
let desired_width = 48;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this could be desired_width = term_width - longest - padding?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should I get the term_width? I looked around and I'm not seeing a function I can call to get that value.

I notice it's set with a literal 90 in run(); should I just create a constant and apply it to both places?

Copy link
Owner

@sharkdp sharkdp May 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term_width is computed/retrieved in printer.rs. We should probably move that to the run function and store it in the Options struct.

@sharkdp
Copy link
Owner

sharkdp commented May 8, 2018

That looks great, thank you very much!

Could you please try to resolve the merge conflicts? If you need help with that, let me know.

I implemented simple line-wrapping for it. I'm still trying to learn more Rust, so if it is unnecessarily complex I would love some feedback to trim it down. I tried brainstorming a cool and simple iterator solution to this problem but didn't get too far.

Your iterative version is completely fine, however... 😄

If you want to use this as an exercise to write iterator-based code, you would probably have to look at fold, because you need some way to store the state (e.g. num_chars) while iterating.

One option to do this could be to fold the list of extensions (["aa", "bb", .. "zz"]) into a list of lists ([["aa", "bb", "cc"], ["dd", "ee", "ff"], ...]). You could then call .join(", ") on the inner lists (via map) and call .join("\n ") (with the appropriate number of spaces) on the outer list.

I'm pretty sure the functional/iterator-based version will not be completely superior in terms of elegance, but it's worth a try (and a good exercise) 😄

@sharkdp sharkdp added this to the 0.3 milestone May 8, 2018
@sharkdp
Copy link
Owner

sharkdp commented May 8, 2018

We should probably also filter out Languages without any extensions. These are typically syntax definitions which are included by others, e.g. "Regular Expressions (Python)"

@sharkdp
Copy link
Owner

sharkdp commented May 8, 2018

Actually, we should probably just hide the ones that have hidden == true (https://docs.rs/syntect/2.0.1/syntect/parsing/syntax_definition/struct.SyntaxDefinition.html)

src/main.rs Outdated
print!("{:width$}{}", lang.name, separator, width = longest);

// Line-wrapping for the possible file extension overflow.
let desired_width = options.term_width - longest;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have to subtract separator.length() as well?

src/printer.rs Outdated
@@ -18,8 +17,7 @@ pub struct Printer<'a> {

impl<'a> Printer<'a> {
pub fn new(handle: &'a mut Write, options: &'a Options) -> Self {
let (_, term_width) = Term::stdout().size();
let term_width = term_width as usize;
let term_width = options.term_width;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just replace all the usages of term_width with options.term_width then

src/main.rs Outdated
let mut extension = lang.file_extensions.iter().peekable();
while let Some(word) = extension.next() {
// If we can't fit this word in, then create a line break and align it in.
if word.len() + num_chars >= desired_width {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to check for word.len() + 2 + num_chars >= .. here due to the ", " part which is possibly appended?

src/printer.rs Outdated
@@ -30,7 +26,7 @@ impl<'a> Printer<'a> {
Printer {
handle,
colors,
term_width,
term_width: options.term_width,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think term_width can be removed from Printer if it is already included in options.

Copy link
Owner

@sharkdp sharkdp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much!

@connorkuehl
Copy link
Contributor Author

Thanks for putting up with me! I appreciate it, I learned a lot.

src/main.rs Outdated
print!("\n{:width$}{}", "", separator, width = longest);
}

num_chars += word.len();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this also needs to be num_chars += word.len() + comma_separator.len();. But I can also change this, if you want.

connorkuehl and others added 14 commits May 8, 2018 22:06
* removes redundant `.takes_value(false)`.
* changes Arg name to "list-languages" to be consistent with long-form.
* replaces unnecessary match statement with is_present().
* replaces unnecessary match statement on iter and uses unwrap_or()
instead.
* replaces for-loop with a call to join().
* Adds separator.length() to calculation for desired width.
* Replaces use of term_width with options.term_width.
* Adds the comma and space separator to calculation for line-wrapping.
@sharkdp sharkdp merged commit f7af537 into sharkdp:master May 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants