Skip to content
Permalink
Browse files

Merge branch 'glyphs' of https://github.com/asoderman/exa into asoder…

…man-glyphs

# Conflicts:
#	src/options/flags.rs
#	src/options/view.rs
#	src/output/grid.rs
  • Loading branch information...
ogham committed Jul 15, 2019
2 parents 9fcd7ad + f96a45f commit 9497b30b3322c52e9c8117a97abd6d96001dac65
Showing with 224 additions and 27 deletions.
  1. +2 −2 src/exa.rs
  2. +14 −0 src/info/filetype.rs
  3. +2 −1 src/options/flags.rs
  4. +20 −10 src/options/view.rs
  5. +23 −6 src/output/details.rs
  6. +10 −2 src/output/grid.rs
  7. +13 −3 src/output/grid_details.rs
  8. +120 −0 src/output/icons.rs
  9. +18 −2 src/output/lines.rs
  10. +2 −1 src/output/mod.rs
@@ -221,8 +221,8 @@ impl<'args, 'w, W: Write + 'w> Exa<'args, 'w, W> {
let View { ref mode, ref colours, ref style } = self.options.view;

match *mode {
Mode::Lines => {
let r = lines::Render { files, colours, style };
Mode::Lines(ref opts) => {
let r = lines::Render { files, colours, style, opts };
r.render(self.writer)
}

@@ -8,6 +8,7 @@ use ansi_term::Style;

use fs::File;
use output::file_name::FileColours;
use output::icons::FileIcon;


#[derive(Debug, Default, PartialEq)]
@@ -115,3 +116,16 @@ impl FileColours for FileExtensions {
})
}
}

impl FileIcon for FileExtensions {
fn icon_file(&self, file: &File) -> Option<char> {
use output::icons::Icons;

Some(match file {
f if self.is_music(f) || self.is_lossless(f) => Icons::Audio.value(),
f if self.is_image(f) => Icons::Image.value(),
f if self.is_video(f) => Icons::Video.value(),
_ => return None,
})
}
}
@@ -40,6 +40,7 @@ pub static BINARY: Arg = Arg { short: Some(b'b'), long: "binary", takes_
pub static BYTES: Arg = Arg { short: Some(b'B'), long: "bytes", takes_value: TakesValue::Forbidden };
pub static GROUP: Arg = Arg { short: Some(b'g'), long: "group", takes_value: TakesValue::Forbidden };
pub static HEADER: Arg = Arg { short: Some(b'h'), long: "header", takes_value: TakesValue::Forbidden };
pub static ICONS: Arg = Arg { short: None, long: "icons", takes_value: TakesValue::Forbidden };
pub static INODE: Arg = Arg { short: Some(b'i'), long: "inode", takes_value: TakesValue::Forbidden };
pub static LINKS: Arg = Arg { short: Some(b'H'), long: "links", takes_value: TakesValue::Forbidden };
pub static MODIFIED: Arg = Arg { short: Some(b'm'), long: "modified", takes_value: TakesValue::Forbidden };
@@ -66,7 +67,7 @@ pub static ALL_ARGS: Args = Args(&[
&ALL, &LIST_DIRS, &LEVEL, &REVERSE, &SORT, &DIRS_FIRST,
&IGNORE_GLOB, &GIT_IGNORE, &ONLY_DIRS,

&BINARY, &BYTES, &GROUP, &HEADER, &INODE, &LINKS, &MODIFIED, &CHANGED,
&BINARY, &BYTES, &GROUP, &HEADER, &ICONS, &INODE, &LINKS, &MODIFIED, &CHANGED,
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,

&GIT, &EXTENDED,
@@ -1,4 +1,4 @@
use output::{View, Mode, grid, details};
use output::{View, Mode, grid, details, lines};
use output::grid_details::{self, RowThreshold};
use output::table::{TimeTypes, Environment, SizeFormat, Columns, Options as TableOptions};
use output::time::TimeFormat;
@@ -41,6 +41,7 @@ impl Mode {
table: Some(TableOptions::deduce(matches, vars)?),
header: matches.has(&flags::HEADER)?,
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
icons: matches.has(&flags::ICONS)?,
})
}
};
@@ -52,14 +53,16 @@ impl Mode {
Err(Useless(&flags::ACROSS, true, &flags::ONE_LINE))
}
else {
Ok(Mode::Lines)
let lines = lines::Options { icons: matches.has(&flags::ICONS)? };
Ok(Mode::Lines(lines))
}
}
else if matches.has(&flags::TREE)? {
let details = details::Options {
table: None,
header: false,
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
icons: matches.has(&flags::ICONS)?,
};

Ok(Mode::Details(details))
@@ -68,11 +71,13 @@ impl Mode {
let grid = grid::Options {
across: matches.has(&flags::ACROSS)?,
console_width: width,
icons: matches.has(&flags::ICONS)?,
};

Ok(Mode::Grid(grid))
}
}

// If the terminal width couldn’t be matched for some reason, such
// as the program’s stdout being connected to a file, then
// fallback to the lines view.
@@ -81,12 +86,14 @@ impl Mode {
table: None,
header: false,
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
icons: matches.has(&flags::ICONS)?,
};

Ok(Mode::Details(details))
}
else {
Ok(Mode::Lines)
let lines = lines::Options { icons: matches.has(&flags::ICONS)?, };
Ok(Mode::Lines(lines))
}
};

@@ -380,7 +387,7 @@ mod test {

static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES, &flags::TIME_STYLE,
&flags::TIME, &flags::MODIFIED, &flags::CHANGED,
&flags::CREATED, &flags::ACCESSED,
&flags::CREATED, &flags::ACCESSED, &flags::ICONS,
&flags::HEADER, &flags::GROUP, &flags::INODE, &flags::GIT,
&flags::LINKS, &flags::BLOCKS, &flags::LONG, &flags::LEVEL,
&flags::GRID, &flags::ACROSS, &flags::ONE_LINE ];
@@ -563,19 +570,22 @@ mod test {
mod views {
use super::*;
use output::grid::Options as GridOptions;
use output::lines::Options as LineOptions;

// Default
test!(empty: Mode <- [], None; Both => like Ok(Mode::Grid(_)));

// Grid views
test!(original_g: Mode <- ["-G"], None; Both => like Ok(Mode::Grid(GridOptions { across: false, console_width: _ })));
test!(grid: Mode <- ["--grid"], None; Both => like Ok(Mode::Grid(GridOptions { across: false, console_width: _ })));
test!(across: Mode <- ["--across"], None; Both => like Ok(Mode::Grid(GridOptions { across: true, console_width: _ })));
test!(gracross: Mode <- ["-xG"], None; Both => like Ok(Mode::Grid(GridOptions { across: true, console_width: _ })));
test!(original_g: Mode <- ["-G"], None; Both => like Ok(Mode::Grid(GridOptions { across: false, console_width: _, icons: _ })));
test!(grid: Mode <- ["--grid"], None; Both => like Ok(Mode::Grid(GridOptions { across: false, console_width: _, icons: _ })));
test!(across: Mode <- ["--across"], None; Both => like Ok(Mode::Grid(GridOptions { across: true, console_width: _, icons: _ })));
test!(gracross: Mode <- ["-xG"], None; Both => like Ok(Mode::Grid(GridOptions { across: true, console_width: _, icons: _ })));
test!(icons: Mode <- ["--icons"], None; Both => like Ok(Mode::Grid(GridOptions { across: _, console_width: _, icons: true})));

// Lines views
test!(lines: Mode <- ["--oneline"], None; Both => like Ok(Mode::Lines));
test!(prima: Mode <- ["-1"], None; Both => like Ok(Mode::Lines));
test!(lines: Mode <- ["--oneline"], None; Both => like Ok(Mode::Lines(LineOptions{ icons: _ })));
test!(prima: Mode <- ["-1"], None; Both => like Ok(Mode::Lines(LineOptions{ icons: _ })));
test!(line_icon: Mode <- ["-1", "--icons"], None; Both => like Ok(Mode::Lines(LineOptions { icons: true })));

// Details views
test!(long: Mode <- ["--long"], None; Both => like Ok(Mode::Details(_)));
@@ -64,7 +64,7 @@ use std::io::{Write, Error as IOError, Result as IOResult};
use std::path::PathBuf;
use std::vec::IntoIter as VecIntoIter;

use ansi_term::Style;
use ansi_term::{ANSIGenericString, Style};

use fs::{Dir, File};
use fs::dir_action::RecurseOptions;
@@ -77,6 +77,7 @@ use output::cell::TextCell;
use output::tree::{TreeTrunk, TreeParams, TreeDepth};
use output::file_name::FileStyle;
use output::table::{Table, Options as TableOptions, Row as TableRow};
use output::icons::painted_icon;
use scoped_threadpool::Pool;


@@ -105,6 +106,9 @@ pub struct Options {

/// Whether to show each file's extended attributes.
pub xattr: bool,

/// Enables --icons mode
pub icons: bool,
}


@@ -132,6 +136,7 @@ struct Egg<'a> {
errors: Vec<(IOError, Option<PathBuf>)>,
dir: Option<Dir>,
file: &'a File<'a>,
icon: Option<String>,
}

impl<'a> AsRef<File<'a>> for Egg<'a> {
@@ -194,7 +199,7 @@ impl<'a> Render<'a> {
let table = table.as_ref();

for file in src {
let file_eggs = file_eggs.clone();
let file_eggs = Arc::clone(&file_eggs);

scoped.execute(move || {
let mut errors = Vec::new();
@@ -255,7 +260,11 @@ impl<'a> Render<'a> {
}
};

let egg = Egg { table_row, xattrs, errors, dir, file };
let icon = if self.opts.icons {
Some(painted_icon(&file, &self.style))
} else { None };

let egg = Egg { table_row, xattrs, errors, dir, file, icon };
file_eggs.lock().unwrap().push(egg);
});
}
@@ -271,12 +280,20 @@ impl<'a> Render<'a> {
t.add_widths(row);
}

let mut name_cell = TextCell::default();
if let Some(icon) = egg.icon {
name_cell.push(ANSIGenericString::from(icon), 2)
}
name_cell.append(self.style.for_file(&egg.file, self.colours)
.with_link_paths()
.paint()
.promote());


let row = Row {
tree: tree_params,
cells: egg.table_row,
name: self.style.for_file(&egg.file, self.colours)
.with_link_paths()
.paint().promote(),
name: name_cell,
};

rows.push(row);
@@ -5,12 +5,15 @@ use term_grid as tg;
use fs::File;
use style::Colours;
use output::file_name::FileStyle;
use output::icons::painted_icon;
use output::cell::DisplayWidth;


#[derive(PartialEq, Debug, Copy, Clone)]
pub struct Options {
pub across: bool,
pub console_width: usize,
pub icons: bool,
}

impl Options {
@@ -38,11 +41,16 @@ impl<'a> Render<'a> {
grid.reserve(self.files.len());

for file in &self.files {
let icon = if self.opts.icons { Some(painted_icon(&file, &self.style)) } else { None };
let filename = self.style.for_file(file, self.colours).paint();
let width = filename.width();
let width = if self.opts.icons {
DisplayWidth::from(2) + filename.width()
} else {
filename.width()
};

grid.add(tg::Cell {
contents: filename.strings().to_string(),
contents: format!("{icon}{filename}", icon=&icon.unwrap_or("".to_string()), filename=filename.strings().to_string()),
width: *width,
});
}
@@ -2,7 +2,7 @@

use std::io::{Write, Result as IOResult};

use ansi_term::ANSIStrings;
use ansi_term::{ANSIGenericString, ANSIStrings};
use term_grid as grid;

use fs::{Dir, File};
@@ -17,7 +17,7 @@ use output::grid::Options as GridOptions;
use output::file_name::FileStyle;
use output::table::{Table, Row as TableRow, Options as TableOptions};
use output::tree::{TreeParams, TreeDepth};

use output::icons::painted_icon;

#[derive(Debug)]
pub struct Options {
@@ -135,7 +135,17 @@ impl<'a> Render<'a> {
.collect::<Vec<TableRow>>();

let file_names = self.files.iter()
.map(|file| self.style.for_file(file, self.colours).paint().promote())
.map(|file| {
if self.details.icons {
let mut icon_cell = TextCell::default();
icon_cell.push(ANSIGenericString::from(painted_icon(&file, &self.style)), 2);
let file_cell = self.style.for_file(file, self.colours).paint().promote();
icon_cell.append(file_cell);
icon_cell
} else {
self.style.for_file(file, self.colours).paint().promote()
}
})
.collect::<Vec<TextCell>>();

let mut last_working_table = self.make_grid(1, options, git, &file_names, rows.clone(), &drender);

0 comments on commit 9497b30

Please sign in to comment.
You can’t perform that action at this time.