提交 268b7d52 编写于 作者: B Benjamin Sago

Rename Columns to table::Options

The views have been renamed to be the Optionses of their module; now the options for the Table — Columns — has followed suit.

This works out, because the table module depended on everything in the columns module. It opens the door for other only-table-specific things to be included.

The casualty was that by making it non-Clone and non-PartialEq, a bunch of other #[derive]-d types had to have their derivions removed too.
上级 d27812f8
......@@ -23,7 +23,7 @@ pub use self::view::{View, Mode};
/// These **options** represent a parsed, error-checked versions of the
/// user’s command-line options.
#[derive(PartialEq, Debug, Clone)]
#[derive(Debug)]
pub struct Options {
/// The action to perform when encountering a directory rather than a
......@@ -124,8 +124,8 @@ impl Options {
/// results will end up being displayed.
pub fn should_scan_for_git(&self) -> bool {
match self.view.mode {
Mode::Details(details::Options { columns: Some(cols), .. }) |
Mode::GridDetails(_, details::Options { columns: Some(cols), .. }) => cols.should_scan_for_git(),
Mode::Details(details::Options { columns: Some(ref cols), .. }) |
Mode::GridDetails(_, details::Options { columns: Some(ref cols), .. }) => cols.should_scan_for_git(),
_ => false,
}
}
......@@ -201,13 +201,13 @@ mod test {
#[test]
fn long_across() {
let opts = Options::getopts(&[ "--long", "--across" ]);
assert_eq!(opts, Err(Misfire::Useless("across", true, "long")))
assert_eq!(opts.unwrap_err(), Misfire::Useless("across", true, "long"))
}
#[test]
fn oneline_across() {
let opts = Options::getopts(&[ "--oneline", "--across" ]);
assert_eq!(opts, Err(Misfire::Useless("across", true, "oneline")))
assert_eq!(opts.unwrap_err(), Misfire::Useless("across", true, "oneline"))
}
#[test]
......
......@@ -4,14 +4,14 @@ use getopts;
use output::Colours;
use output::{grid, details};
use output::column::{Columns, TimeTypes, SizeFormat};
use output::table::{TimeTypes, SizeFormat, Options as TableOptions};
use output::file_name::Classify;
use options::Misfire;
use fs::feature::xattr;
/// The **view** contains all information about how to format output.
#[derive(PartialEq, Debug, Clone)]
#[derive(Debug)]
pub struct View {
pub mode: Mode,
pub colours: Colours,
......@@ -31,7 +31,7 @@ impl View {
/// The **mode** is the “type” of output.
#[derive(PartialEq, Debug, Clone)]
#[derive(Debug)]
pub enum Mode {
Grid(grid::Options),
Details(details::Options),
......@@ -54,7 +54,7 @@ impl Mode {
}
else {
Ok(details::Options {
columns: Some(Columns::deduce(matches)?),
columns: Some(TableOptions::deduce(matches)?),
header: matches.opt_present("header"),
xattr: xattr::ENABLED && matches.opt_present("extended"),
})
......@@ -194,9 +194,9 @@ impl TerminalWidth {
}
impl Columns {
fn deduce(matches: &getopts::Matches) -> Result<Columns, Misfire> {
Ok(Columns {
impl TableOptions {
fn deduce(matches: &getopts::Matches) -> Result<Self, Misfire> {
Ok(TableOptions {
size_format: SizeFormat::deduce(matches)?,
time_types: TimeTypes::deduce(matches)?,
inode: matches.opt_present("inode"),
......
use fs::Dir;
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum Column {
Permissions,
FileSize(SizeFormat),
Timestamp(TimeType),
Blocks,
User,
Group,
HardLinks,
Inode,
GitStatus,
}
/// Each column can pick its own **Alignment**. Usually, numbers are
/// right-aligned, and text is left-aligned.
#[derive(Copy, Clone)]
pub enum Alignment {
Left, Right,
}
impl Column {
/// Get the alignment this column should use.
pub fn alignment(&self) -> Alignment {
match *self {
Column::FileSize(_)
| Column::HardLinks
| Column::Inode
| Column::Blocks
| Column::GitStatus => Alignment::Right,
_ => Alignment::Left,
}
}
/// Get the text that should be printed at the top, when the user elects
/// to have a header row printed.
pub fn header(&self) -> &'static str {
match *self {
Column::Permissions => "Permissions",
Column::FileSize(_) => "Size",
Column::Timestamp(t) => t.header(),
Column::Blocks => "Blocks",
Column::User => "User",
Column::Group => "Group",
Column::HardLinks => "Links",
Column::Inode => "inode",
Column::GitStatus => "Git",
}
}
}
#[derive(PartialEq, Copy, Clone, Debug, Default)]
pub struct Columns {
pub size_format: SizeFormat,
pub time_types: TimeTypes,
pub inode: bool,
pub links: bool,
pub blocks: bool,
pub group: bool,
pub git: bool
}
impl Columns {
pub fn should_scan_for_git(&self) -> bool {
self.git
}
pub fn for_dir(&self, dir: Option<&Dir>) -> Vec<Column> {
let mut columns = vec![];
if self.inode {
columns.push(Column::Inode);
}
columns.push(Column::Permissions);
if self.links {
columns.push(Column::HardLinks);
}
columns.push(Column::FileSize(self.size_format));
if self.blocks {
columns.push(Column::Blocks);
}
columns.push(Column::User);
if self.group {
columns.push(Column::Group);
}
if self.time_types.modified {
columns.push(Column::Timestamp(TimeType::Modified));
}
if self.time_types.created {
columns.push(Column::Timestamp(TimeType::Created));
}
if self.time_types.accessed {
columns.push(Column::Timestamp(TimeType::Accessed));
}
if cfg!(feature="git") {
if let Some(d) = dir {
if self.should_scan_for_git() && d.has_git_repo() {
columns.push(Column::GitStatus);
}
}
}
columns
}
}
/// Formatting options for file sizes.
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum SizeFormat {
/// Format the file size using **decimal** prefixes, such as “kilo”,
/// “mega”, or “giga”.
DecimalBytes,
/// Format the file size using **binary** prefixes, such as “kibi”,
/// “mebi”, or “gibi”.
BinaryBytes,
/// Do no formatting and just display the size as a number of bytes.
JustBytes,
}
impl Default for SizeFormat {
fn default() -> SizeFormat {
SizeFormat::DecimalBytes
}
}
/// The types of a file’s time fields. These three fields are standard
/// across most (all?) operating systems.
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum TimeType {
/// The file’s accessed time (`st_atime`).
Accessed,
/// The file’s modified time (`st_mtime`).
Modified,
/// The file’s creation time (`st_ctime`).
Created,
}
impl TimeType {
/// Returns the text to use for a column’s heading in the columns output.
pub fn header(&self) -> &'static str {
match *self {
TimeType::Accessed => "Date Accessed",
TimeType::Modified => "Date Modified",
TimeType::Created => "Date Created",
}
}
}
/// Fields for which of a file’s time fields should be displayed in the
/// columns output.
///
/// There should always be at least one of these--there's no way to disable
/// the time columns entirely (yet).
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct TimeTypes {
pub accessed: bool,
pub modified: bool,
pub created: bool,
}
impl Default for TimeTypes {
/// By default, display just the ‘modified’ time. This is the most
/// common option, which is why it has this shorthand.
fn default() -> TimeTypes {
TimeTypes { accessed: false, modified: true, created: false }
}
}
......@@ -68,11 +68,10 @@ use fs::{Dir, File};
use fs::feature::xattr::{Attribute, FileAttributes};
use options::{FileFilter, RecurseOptions};
use output::colours::Colours;
use output::column::Columns;
use output::cell::TextCell;
use output::tree::{TreeTrunk, TreeParams, TreeDepth};
use output::file_name::{FileName, LinkStyle, Classify};
use output::table::{Table, Environment, Row as TableRow};
use output::table::{Table, Environment, Options as TableOptions, Row as TableRow};
/// With the **Details** view, the output gets formatted into columns, with
......@@ -86,13 +85,14 @@ use output::table::{Table, Environment, Row as TableRow};
///
/// Almost all the heavy lifting is done in a Table object, which handles the
/// columns for each row.
#[derive(PartialEq, Debug, Clone, Default)]
#[derive(Debug)]
pub struct Options {
/// A Columns object that says which columns should be included in the
/// output in the general case. Directories themselves can pick which
/// columns are *added* to this list, such as the Git column.
pub columns: Option<Columns>,
/// Options specific to drawing a table.
///
/// Directories themselves can pick which columns are *added* to this
/// list, such as the Git column.
pub columns: Option<TableOptions>,
/// Whether to show a header line or not.
pub header: bool,
......@@ -139,7 +139,7 @@ impl<'a> Render<'a> {
pub fn render<W: Write>(self, w: &mut W) -> IOResult<()> {
let mut rows = Vec::new();
if let Some(columns) = self.opts.columns {
if let Some(ref columns) = self.opts.columns {
let env = Environment::load_all();
let colz = columns.for_dir(self.dir);
let mut table = Table::new(&colz, &self.colours, &env);
......
......@@ -8,12 +8,11 @@ use fs::feature::xattr::FileAttributes;
use options::FileFilter;
use output::cell::TextCell;
use output::column::Column;
use output::colours::Colours;
use output::details::{Options as DetailsOptions, Row as DetailsRow, Render as DetailsRender};
use output::grid::Options as GridOptions;
use output::file_name::{FileName, LinkStyle, Classify};
use output::table::{Table, Environment, Row as TableRow};
use output::table::{Table, Column, Environment, Row as TableRow};
use output::tree::{TreeParams, TreeDepth};
......@@ -43,7 +42,7 @@ impl<'a> Render<'a> {
pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
let columns_for_dir = match self.details.columns {
Some(cols) => cols.for_dir(self.dir),
Some(ref cols) => cols.for_dir(self.dir),
None => Vec::new(),
};
......
......@@ -2,12 +2,12 @@ pub use self::cell::{TextCell, TextCellContents, DisplayWidth};
pub use self::colours::Colours;
pub use self::escape::escape;
pub mod column;
pub mod details;
pub mod file_name;
pub mod grid_details;
pub mod grid;
pub mod lines;
pub mod table;
pub mod time;
mod cell;
......@@ -15,4 +15,3 @@ mod colours;
mod escape;
mod render;
mod tree;
mod table;
use fs::fields as f;
use output::column::SizeFormat;
use output::cell::{TextCell, DisplayWidth};
use output::colours::Colours;
use output::table::SizeFormat;
use locale;
......@@ -68,8 +68,8 @@ impl f::DeviceIDs {
#[cfg(test)]
pub mod test {
use output::colours::Colours;
use output::column::SizeFormat;
use output::cell::{TextCell, DisplayWidth};
use output::table::SizeFormat;
use fs::fields as f;
use locale;
......
......@@ -11,10 +11,205 @@ use users::UsersCache;
use output::cell::TextCell;
use output::colours::Colours;
use output::column::{Alignment, Column};
use output::time::TimeFormat;
use fs::{File, fields as f};
use fs::{File, Dir, fields as f};
/// Options for displaying a table.
#[derive(Debug)]
pub struct Options {
pub size_format: SizeFormat,
pub time_types: TimeTypes,
pub inode: bool,
pub links: bool,
pub blocks: bool,
pub group: bool,
pub git: bool
}
impl Options {
pub fn should_scan_for_git(&self) -> bool {
self.git
}
pub fn for_dir(&self, dir: Option<&Dir>) -> Vec<Column> {
let mut columns = vec![];
if self.inode {
columns.push(Column::Inode);
}
columns.push(Column::Permissions);
if self.links {
columns.push(Column::HardLinks);
}
columns.push(Column::FileSize(self.size_format));
if self.blocks {
columns.push(Column::Blocks);
}
columns.push(Column::User);
if self.group {
columns.push(Column::Group);
}
if self.time_types.modified {
columns.push(Column::Timestamp(TimeType::Modified));
}
if self.time_types.created {
columns.push(Column::Timestamp(TimeType::Created));
}
if self.time_types.accessed {
columns.push(Column::Timestamp(TimeType::Accessed));
}
if cfg!(feature="git") {
if let Some(d) = dir {
if self.should_scan_for_git() && d.has_git_repo() {
columns.push(Column::GitStatus);
}
}
}
columns
}
}
/// A table contains these.
#[derive(Debug)]
pub enum Column {
Permissions,
FileSize(SizeFormat),
Timestamp(TimeType),
Blocks,
User,
Group,
HardLinks,
Inode,
GitStatus,
}
/// Each column can pick its own **Alignment**. Usually, numbers are
/// right-aligned, and text is left-aligned.
#[derive(Copy, Clone)]
pub enum Alignment {
Left, Right,
}
impl Column {
/// Get the alignment this column should use.
pub fn alignment(&self) -> Alignment {
match *self {
Column::FileSize(_)
| Column::HardLinks
| Column::Inode
| Column::Blocks
| Column::GitStatus => Alignment::Right,
_ => Alignment::Left,
}
}
/// Get the text that should be printed at the top, when the user elects
/// to have a header row printed.
pub fn header(&self) -> &'static str {
match *self {
Column::Permissions => "Permissions",
Column::FileSize(_) => "Size",
Column::Timestamp(t) => t.header(),
Column::Blocks => "Blocks",
Column::User => "User",
Column::Group => "Group",
Column::HardLinks => "Links",
Column::Inode => "inode",
Column::GitStatus => "Git",
}
}
}
/// Formatting options for file sizes.
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum SizeFormat {
/// Format the file size using **decimal** prefixes, such as “kilo”,
/// “mega”, or “giga”.
DecimalBytes,
/// Format the file size using **binary** prefixes, such as “kibi”,
/// “mebi”, or “gibi”.
BinaryBytes,
/// Do no formatting and just display the size as a number of bytes.
JustBytes,
}
impl Default for SizeFormat {
fn default() -> SizeFormat {
SizeFormat::DecimalBytes
}
}
/// The types of a file’s time fields. These three fields are standard
/// across most (all?) operating systems.
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum TimeType {
/// The file’s accessed time (`st_atime`).
Accessed,
/// The file’s modified time (`st_mtime`).
Modified,
/// The file’s creation time (`st_ctime`).
Created,
}
impl TimeType {
/// Returns the text to use for a column’s heading in the columns output.
pub fn header(&self) -> &'static str {
match *self {
TimeType::Accessed => "Date Accessed",
TimeType::Modified => "Date Modified",
TimeType::Created => "Date Created",
}
}
}
/// Fields for which of a file’s time fields should be displayed in the
/// columns output.
///
/// There should always be at least one of these--there's no way to disable
/// the time columns entirely (yet).
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct TimeTypes {
pub accessed: bool,
pub modified: bool,
pub created: bool,
}
impl Default for TimeTypes {
/// By default, display just the ‘modified’ time. This is the most
/// common option, which is why it has this shorthand.
fn default() -> TimeTypes {
TimeTypes { accessed: false, modified: true, created: false }
}
}
/// The **environment** struct contains any data that could change between
......@@ -121,7 +316,7 @@ impl<'a, 'f> Table<'a> {
}
fn display(&self, file: &File, column: &Column, xattrs: bool) -> TextCell {
use output::column::TimeType::*;
use output::table::TimeType::*;
match *column {
Column::Permissions => self.permissions_plus(file, xattrs).render(&self.colours),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册