Commit Graph

84 Commits

Author SHA1 Message Date
Benjamin Sago
45a807a14f Redo Git implementation to allow --git --recurse
This is all a big commit because it took a lot more work than I thought it would! The commit basically moves Git repositories from being per-directory to living for the whole life of the program. This allows for several directories in the same repository to be listed in the same invocation; before, it would try to rediscover the repository each time! This is why two of the tests “broke”: it suddenly started working with --recurse.

The Dir type does now not use Git at all; because a Dir doesn’t have a Git, then a File doesn’t have one either, so the Git cache gets passed to the render functions which will put them in the Table to render them.
2017-09-01 19:13:47 +01:00
Benjamin Sago
040dbb2414 Use a global Git cache
This commit adds a cache for Git repositories based on the path being queried.

Its only immediate effect is that when you query the same directory twice (such as /testcases/git /testcases/git), it won’t need to check that the second one is a Git directory the second time. So, a minuscule optimisation for something you’d never do anyway? Wrong! It’s going to let us combine multiple entries over the same repository later, letting us use --tree and --recurse, because now Git scanning is behind a factory.
2017-08-28 18:11:38 +01:00
Benjamin Sago
dd838c2dc1 Move Colours and LSColors to their own module
The ‘options’ module is allowed to depend on ‘style’, but ‘options::render’ is not.
2017-08-26 21:40:37 +01:00
Benjamin Sago
965bc9e37a Print the parsed options to the debug log
It adds a lot of lines to the output, so I’m not convinced it’s worth it, but…
2017-08-19 22:39:34 +01:00
Benjamin Sago
377260d88c Start logging at opportune moments
I want to be very careful when doing the “--git and --tree don’t work together” one to not search for more Git repositories than I should. Being able to log when a repository is looked up and also switch that functionality on and off would help with that.
2017-08-19 10:06:43 +01:00
Benjamin Sago
6740faa781 env vars should be referenced, not copied
Just because the type that gets used right now is Copy and Clone doesn’t mean that when we pass mock ones in for tests they’ll be those two as well. So we have to go through and add &s everywhere.
2017-08-13 11:14:58 +01:00
Benjamin Sago
da00e2fda2 Thread the row threshold through grid_details
No new features here, just some restructuring. Mode::GridDetails was nice and elegant with those two fields, but now there’s a grid-details-only option the elegance has gone out the window.
2017-08-12 22:49:16 +01:00
Benjamin Sago
a6ed42105d By lines, I meant details
Yeah, I forgot what I was meant to be doing half-way through.

This also adds the row_threshold field, which disables the view unless there will be more than the given number of rows. Getting the row count required upgrading term_grid to a version that has that function added.
2017-08-12 20:19:30 +01:00
Benjamin Sago
dbebd60c4e Extract var_os and use the mock to test
Some of the deduce functions used to just blatantly call std::env::var_os and not care, introducing global state into a module that was otherwise nice and functional and self-contained. (Well, almost. There’s still terminal width.)

Anyway, this made it hard to test, because we couldn’t test it fully with this global dependency in place. It *is* possible to work around this by actually setting the environment variables in the tests, but this way is more self-documenting.

With this in place, we can start to unit test things like deriving the view by passing in what the $COLUMNS environment variable should be, and that’s one of the first things checked.

src/options/mod.rs *almost* has all its tests moved to where they should be!
2017-08-10 17:54:28 +01:00
Benjamin Sago
b5bcf22612 Merge remote-tracking branch origin/option-pars-ng
This merges in exa’s own new options parser, which has the following features:

- You can specify an option twice and it’ll use the second one, making aliases usable for defaults (fixes #144)
- Lets arguments be specified more than once (fixes #125)

Strict mode is not done yet; I just wanted to merge this in because it’s been a while, and there’s work that needs to be done on master so I don’t want them drifting apart any further.

It’s likely that you’ll find cases where multiple arguments doesn’t work or where the wrong value is being used. There aren’t tests for *everything* yet, and it still uses global environment variables.

# Conflicts:
#	src/options/view.rs
2017-08-05 21:34:57 +01:00
PJB3005
f249c8528b Use term_size crate to fetch terminal size.
Should be cross-platform, one step closer to Windows support.
2017-08-05 08:09:26 +02:00
Benjamin Sago
2d1f462bfa Switch to the new options parser
This commit removes the dependency on the ‘getopts’ crate entirely, and re-writes all its uses to use the new options parser instead.

As expected there are casualties galore:

- We now need to collect the options into a vector at the start, so we can use references to them, knowing they’ll be stored *somewhere*.
- Because OsString isn’t Display, its Debug impl gets used instead. (This is hopefully temporary)
- Options that take values (such as ‘sort’ or ‘time-style’) now parse those values with ‘to_string_lossy’. The ‘lossy’ part means “I’m at a loss for what to do here”
- Error messages got a lot worse, but “--tree --all --all” is now a special case of error rather than just another Misfire::Useless.
- Some tests had to be re-written to deal with the fact that the parser works with references.
- ParseError loses its lifetime and owns its contents, to avoid having to attach <'a> to Misfire.
- The parser now takes an iterator instead of a slice.
- OsStrings can’t be ‘match’ patterns, so the code devolves to using long Eq chains instead.
- Make a change to the xtest that assumed an input argument with invalid UTF-8 in was always an error to stderr, when that now in fact works!
- Fix a bug in Vagrant where ‘exa’ and ‘rexa’ didn’t properly escape filenames with spaces in.
2017-07-26 17:48:18 +01:00
Benjamin Sago
5b1966d261 Move filter and dir_action from options to fs
This commit moves the definitions of Filter and DirAction from the options module to the fs module, but leaves the parts that actually have to do with option parsing alone.

Now, the options module shouldn’t define any types that get used elsewhere in the program: it only adds functionality to types that already exist.
2017-07-24 08:34:50 +01:00
Benjamin Sago
0d613652a7 Replace FileName::new with a factory
The new FileStyles value will contain all the fields necessary to “style” a file’s name. Right now this is only the Classify field, but there can be more later. The benefit of this is that when we add more, we won’t need to update all the places where file names are displayed.
2017-07-08 12:11:11 +01:00
Benjamin Sago
fc60838ff3 Extract table from details and grid_details
This commit extracts the common table element from the details and grid_details modules, and makes it its own reusable thing.

- A Table no longer holds the values it’s rendering; it just holds a continually-updated version of the maximum widths for each column. This means that all of the resulting values that turn into Rows — which here are either files, or file eggs — need to be stored *somewhere*, and that somewhere is a secondary vector that gets passed around and modified alongside the Table.
- Likewise, all the mutable methods that were on Table that added a Row now *return* the row that would have been added, hoping that the row does get stored somewhere. (It does, don’t worry.)
- Because rendering with mock users is tested in the user-field-rendering module, we don’t need to bother threading different types of U through the Environment, so now it’s just been specialised to UsersCache.
- Accidentally speed up printing a table by not buffering its entire output first when not necessary.
2017-07-02 01:02:17 +01:00
Benjamin Sago
31148eda7b Match up fields with parameter names
The arguments passed to File’s constructor were different from the field names used — these might as well both be the same.

Also, move ext and filename to be File methods to save an import, and add tests.

Also also, by passing a PathBuf in to the constructor directly, we can save one (possibly two) instance/s where we pass in a reference to something we were going to lose ownership of anyway, only to have it basically cloned.
2017-06-29 13:07:45 +01:00
Benjamin Sago
30f74b08b4 Always look up metadata
We can do this because the only File::new invocation that already has metadata is already in the file module, so it doesn’t need its own constructor.
2017-06-29 12:24:04 +01:00
Benjamin Sago
dd8bff083f Override the names of . and ..
There was a problem when displaying . and .. in directory listings: their names would normalise to actual names! So instead of literally seeing `.`, you’d see the current directory’s name, inserted in sort order into the list of results. Obviously this is not what we want.

In unrelated news, putting `.` and `..` into the list of paths read from a directory just takes up more heap space for something that’s basically constant.

We can solve both these problems at once by moving the DotFilter to the files iterator in Dir, rather than at the Dir’s creation. Having the iterator know whether it should display `.` and `..` means it can emit those files first, and because it knows what those files really represent, it can override their file names to actually be those sequences of dots.

This is not a perfect solution: the main casualty is that a File can now be constructed with a name, some metadata, both, or neither. This is currently handled with a bunch of Options, and returns IOResult even without doing any IO operations.

But at least all the tests pass!
2017-06-28 18:41:31 +01:00
Benjamin Sago
20793ce7f4 Implement . and .. by inserting them maually
I originally thought that the entries . and .. were in *every* directory entry, and exa was already doing something to filter it out. And then... I could find no such code! Turns out, if we want those entries present, we have to insert them ourselves.

This was harder than expected. Because the file filter doesn’t have access to the parent directory path, it can’t “filter” the files vector by inserting the files at the beginning.

Instead, we do it at the iterator level. A directory can be scanned in three different ways depending on what sort of dotfiles, if any, are wanted. At this point, we already have access to the parent directory’s path, so we can just insert them manually. The enum got moved to the dir module because it’s used most there.
2017-06-27 01:13:50 +01:00
Benjamin Sago
65d94636d7 Remove filter and dir_action from Details
These two fields were originally needed to determine how to recurse when using tree view.

However, as there was no distinction between the “options parsed from the command-line” Details and the “values needed to render a table” Details, these had to be threaded through the options parser as a special-case to end up in the right struct.

No more! Because there are separate structs for options and rendering, we can just add them in later.
2017-06-26 08:28:32 +01:00
Benjamin Sago
14144e2ad3 Create Render structs from views
Instead of having render methods on the types that are now called Options, create new Render structs (one per view) and execute them. This means that it’s easier to extract methods from them — some of them are pretty long.

Also, remove the GridDetails struct, which got consumed by Mode (mostly)

By introducing another indirection between the structs that command-line options get parsed into and the structs that get rendered, it should be easier to refactor that horrible function in view.rs.
2017-06-26 00:53:48 +01:00
Benjamin Sago
84b01f2064 Fix bug where colours were incorrectly applied
exa assumed that the COLUMNS environment variable being present always meant that the output was to a terminal, so it should use colours. But because this variable can be overridden, colours were being incorrectly set!

The ‘fix’ is to stop trying to be clever while only calculating the terminal width once, and instead just stick it in a lazy_static so it’s usable everywhere.
2017-06-25 14:51:44 +01:00
Benjamin Sago
aea0035f94 Move Colour and Classify to the View
All four view types — lines, grid, details, and grid-details — held their own colours and classify flags.

This didn’t make any sense for the grid-details view, which had to pick which one to use: the values were in there twice.

It also gave the Table in the details view access to more information than it really should have had.

Now, those two flags are returned separately from the view “mode”, which is the new term for one of those four things.
2017-06-24 22:39:15 +01:00
Benjamin Sago
de60b95850 Don’t core dump when given invalid UTF-8 arguments
By parsing OsStrings rather than Strings, it’s the getopts crate that’s doing the UTF-8 checking rather than us, so if one of them isn’t valid, it’ll just fail to parse rather than crash exa.

Also, save a few allocations here and there.
2017-05-19 00:08:13 +01:00
Benjamin Sago
2f79b4db03 Start using new shorthand object field syntax 2017-05-18 22:43:32 +01:00
Kevin Ballard
15e08338d8 Remove lazy_static crate
It's not being used anymore.
2017-05-17 22:48:11 -07:00
Benjamin Sago
56d4d4c156 Also escape characters in links and headings
Doing this meant that the escaping functionality got used in three places, so it was extracted into a generalised function in its own module.

This is slighly slower for the case where escaped characters are displayed in the same colour as the displayable characters, which happens when listing a directory’s name when recursing. Optimise this, yeah?
2017-05-01 21:54:53 +01:00
Benjamin Sago
3087565c01 Merge pull request #154 from neosilky/clippy-fixes
Fix some issues indicated by clippy
2017-04-11 08:18:55 +01:00
Laurent Arnoud
8b61a3a0f2
Exit with a non-zero status on error
With `ls` from Debian coreutils 8.26-2

```
ls /bad/path
echo $? # => 2
```

Reproduced same behaviour with exa

Fix https://github.com/ogham/exa/issues/135
2017-04-01 00:10:49 +02:00
Daniel Lockyer
da3061d1b3 Replace use of .iter() with reference 2017-03-31 17:08:11 +01:00
Benjamin Sago
3bce55f569 Run Untry over the entire source tree 2017-03-26 17:35:50 +01:00
Ben S
95596297a9 Basic glob ignoring
See #97 and recently #130 too.

This allows the user to pass in options such as "--ignore '*.pyc'" to not list any files ending in '.pyc' in the output. It uses the Rust glob crate and currently does a simple split on pipe, without any escaping, so it’s not really *complete*, but is at least something.
2016-10-30 14:43:33 +00:00
Ben S
a6712994c5 Make the views non-Copy
This has to be done for when ignore patterns get introduced and have to be stored in a Vec.
2016-10-30 14:31:25 +00:00
Ben S
dcc17b1d15 This lint flag started to cause all kinds of fuss 2016-10-29 19:52:21 +01:00
Ben S
a7e3456b0d Only engage the view when there are files to show
This changes the way that views are used to display the actual lists of files. It used to pass empty vectors to the view methods, which most of the time would not print anything because there are no files to list — except when there’s a header row which gets printed for no files.

By not calling the view method at all when there’s nothing to print, exa won’t ever print extra things in the view unless it needs to for a file.

This fixes #106 “Don’t print the header if the result set is empty”
2016-10-29 19:07:43 +01:00
Gemmarx
8d25719b6b Change to put error messages into stderr 2016-07-31 04:12:03 +09:00
Benjamin Sago
110a1c716b Convert exa into a library
This commit removes the 'main' function present in main.rs, renames it to exa.rs, and puts the 'main' function in its own binary. This, I think, makes it more clear how the program works and where the main entry point is.

Librarification also means that we can start testing as a whole. Two tests have been added that test everything, passing in raw command-line arguments then comparing against the binary coloured text that gets produced.

Casualties include having to specifically mark some code blocks in documentation as 'tests', as rustdoc kept on trying to execute my ANSI art.
2016-04-19 07:48:41 +01:00
Ben S
6457f4b577 Rename exa.rs to main.rs 2015-01-23 19:36:01 +00:00
Ben S
0e473bf37b Upgrade to latest Rust, and move options code 2015-01-23 19:27:06 +00:00
Benjamin Sago
95388e6e90 Fix header-printing logic 2015-01-13 00:35:44 +01:00
Benjamin Sago
728e7dd976 Forbid certain argument combinations 2015-01-13 00:31:30 +01:00
Benjamin Sago
3d59a48efe Make option parsing unit-testable 2015-01-12 22:47:05 +01:00
Benjamin Sago
23e5d3ce8d Allow for different types of failure 2015-01-12 22:14:27 +01:00
Benjamin Sago
3f08836c3f Move viewing code to its own module 2015-01-12 21:08:42 +01:00
Benjamin Sago
9729679f05 Main code tidy-ups 2015-01-12 20:48:07 +01:00
Benjamin Sago
d93bca8779 Make some options fields private 2015-01-12 19:44:39 +01:00
Benjamin Sago
1c5409e253 Upgrade to Rust alpha
- uint -> usize
- getopts Cargo library
- replace feature gates with unstable APIs
2015-01-12 01:31:24 +01:00
Ben S
d400231de5 Upgrade to latest Rust
Also, remove dependency on the Regex library by replacing the one place it was used with standard code that should hopefully be faster anyway.
2015-01-05 14:41:43 +00:00
Ben S
ba36d4f7f0 Library and Rust upgrades 2015-01-04 13:56:07 +00:00
Ben S
24628f97be Use number_prefix crate for number prefixes 2014-12-18 07:00:31 +00:00