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.
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.
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.
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!
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.
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.
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.
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.
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.
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.
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?
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.
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”
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.