mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-29 15:13:54 +00:00
Document the parsing decisions
Even though these can’t actually be viewed with `cargo doc` yet, they’re still good to have around.
This commit is contained in:
parent
5227f09f5b
commit
8d96be7f6a
@ -16,6 +16,7 @@ license = "MIT"
|
||||
[[bin]]
|
||||
name = "exa"
|
||||
path = "src/bin/main.rs"
|
||||
doc = false
|
||||
|
||||
[lib]
|
||||
name = "exa"
|
||||
|
@ -1,3 +1,69 @@
|
||||
//! Parsing command-line strings into exa options.
|
||||
//!
|
||||
//!
|
||||
//! ## Useless and overridden options
|
||||
//!
|
||||
//! Let’s say exa was invoked with just one argument: `exa --inode`. The
|
||||
//! `--inode` option is used in the details view, where it adds the inode
|
||||
//! column to the output. But because the details view is *only* activated with
|
||||
//! the `--long` argument, adding `--inode` without it would not have any
|
||||
//! effect.
|
||||
//!
|
||||
//! For a long time, exa’s philosophy was that the user should be warned
|
||||
//! whenever they could be mistaken like this. If you tell exa to display the
|
||||
//! inode, and it *doesn’t* display the inode, isn’t that more annoying than
|
||||
//! having it throw an error back at you?
|
||||
//!
|
||||
//! However, this doesn’t take into account *configuration*. Say a user wants
|
||||
//! to configure exa so that it lists inodes in the details view, but otherwise
|
||||
//! functions normally. A common way to do this for command-line programs is to
|
||||
//! define a shell alias that specifies the details they want to use every
|
||||
//! time. For the inode column, the alias would be:
|
||||
//!
|
||||
//! `alias exa="exa --inode"`
|
||||
//!
|
||||
//! Using this alias means that although the inode column will be shown in the
|
||||
//! details view, you’re now *only* allowed to use the details view, as any
|
||||
//! other view type will result in an error. Oops!
|
||||
//!
|
||||
//! Another example is when an option is specified twice, such as `exa
|
||||
//! --sort=Name --sort=size`. Did the user change their mind about sorting, and
|
||||
//! accidentally specify the option twice?
|
||||
//!
|
||||
//! Again, exa rejected this case, throwing an error back to the user instead
|
||||
//! of trying to guess how they want their output sorted. And again, this
|
||||
//! doesn’t take into account aliases being used to set defaults. A user who
|
||||
//! wants their files to be sorted case-insensitively may configure their shell
|
||||
//! with the following:
|
||||
//!
|
||||
//! `alias exa="exa --sort=Name"`
|
||||
//!
|
||||
//! Just like the earlier example, the user now can’t use any other sort order,
|
||||
//! because exa refuses to guess which one they meant. It’s *more* annoying to
|
||||
//! have to go back and edit the command than if there were no error.
|
||||
//!
|
||||
//! Fortunately, there’s a heuristic for telling which options came from an
|
||||
//! alias and which came from the actual command-line: aliased options are
|
||||
//! nearer the beginning of the options array, and command-line options are
|
||||
//! nearer the end. This means that after the options have been parsed, exa
|
||||
//! needs to traverse them *backwards* to find the last-most-specified one.
|
||||
//!
|
||||
//! For example, invoking exa with `exa --sort=size` when that alias is present
|
||||
//! would result in a full command-line of:
|
||||
//!
|
||||
//! `exa --sort=Name --sort=size`
|
||||
//!
|
||||
//! `--sort=size` should override `--sort=Name` because it’s closer to the end
|
||||
//! of the arguments array. In fact, because there’s no way to tell where the
|
||||
//! arguments came from -- it’s just a heuristic -- this will still work even
|
||||
//! if no aliases are being used!
|
||||
//!
|
||||
//! Finally, this isn’t just useful when options could override each other.
|
||||
//! Creating an alias `exal=”exa --long --inode --header”` then invoking `exal
|
||||
//! --grid --long` shouldn’t complain about `--long` being given twice when
|
||||
//! it’s clear what the user wants.
|
||||
|
||||
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use getopts;
|
||||
|
@ -1,3 +1,33 @@
|
||||
//! A general parser for command-line options.
|
||||
//!
|
||||
//! exa uses its own hand-rolled parser for command-line options. It supports
|
||||
//! the following syntax:
|
||||
//!
|
||||
//! - Long options: `--inode`, `--grid`
|
||||
//! - Long options with values: `--sort size`, `--level=4`
|
||||
//! - Short options: `-i`, `-G`
|
||||
//! - Short options with values: `-ssize`, `-L=4`
|
||||
//!
|
||||
//! These values can be mixed and matched: `exa -lssize --grid`. If you’ve used
|
||||
//! other command-line programs, then hopefully it’ll work much like them.
|
||||
//!
|
||||
//! Because exa already has its own files for the help text, shell completions,
|
||||
//! man page, and readme, so it can get away with having the options parser do
|
||||
//! very little: all it really needs to do is parse a slice of strings.
|
||||
//!
|
||||
//!
|
||||
//! ## UTF-8 and `OsStr`
|
||||
//!
|
||||
//! The parser uses `OsStr` as its string type. This is necessary for exa to
|
||||
//! list files that have invalid UTF-8 in their names: by treating file paths
|
||||
//! as bytes with no encoding, a file can be specified on the command-line and
|
||||
//! be looked up without having to be encoded into a `str` first.
|
||||
//!
|
||||
//! It also avoids the overhead of checking for invalid UTF-8 when parsing
|
||||
//! command-line options, as all the options and their values (such as
|
||||
//! `--sort size`) are guaranteed to just be 8-bit ASCII.
|
||||
|
||||
|
||||
#![allow(unused_variables, dead_code)]
|
||||
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
Loading…
Reference in New Issue
Block a user