mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-12-28 10:40:48 +00:00
Merge branch 'asoderman-glyphs'
This commit is contained in:
commit
2e0e29da22
@ -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;
|
let View { ref mode, ref colours, ref style } = self.options.view;
|
||||||
|
|
||||||
match *mode {
|
match *mode {
|
||||||
Mode::Lines => {
|
Mode::Lines(ref opts) => {
|
||||||
let r = lines::Render { files, colours, style };
|
let r = lines::Render { files, colours, style, opts };
|
||||||
r.render(self.writer)
|
r.render(self.writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use ansi_term::Style;
|
|||||||
|
|
||||||
use fs::File;
|
use fs::File;
|
||||||
use output::file_name::FileColours;
|
use output::file_name::FileColours;
|
||||||
|
use output::icons::FileIcon;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq)]
|
#[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 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 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 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 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 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 };
|
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,
|
&ALL, &LIST_DIRS, &LEVEL, &REVERSE, &SORT, &DIRS_FIRST,
|
||||||
&IGNORE_GLOB, &GIT_IGNORE, &ONLY_DIRS,
|
&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,
|
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,
|
||||||
|
|
||||||
&GIT, &EXTENDED,
|
&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::grid_details::{self, RowThreshold};
|
||||||
use output::table::{TimeTypes, Environment, SizeFormat, Columns, Options as TableOptions};
|
use output::table::{TimeTypes, Environment, SizeFormat, Columns, Options as TableOptions};
|
||||||
use output::time::TimeFormat;
|
use output::time::TimeFormat;
|
||||||
@ -41,6 +41,7 @@ impl Mode {
|
|||||||
table: Some(TableOptions::deduce(matches, vars)?),
|
table: Some(TableOptions::deduce(matches, vars)?),
|
||||||
header: matches.has(&flags::HEADER)?,
|
header: matches.has(&flags::HEADER)?,
|
||||||
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
||||||
|
icons: matches.has(&flags::ICONS)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -52,7 +53,8 @@ impl Mode {
|
|||||||
Err(Useless(&flags::ACROSS, true, &flags::ONE_LINE))
|
Err(Useless(&flags::ACROSS, true, &flags::ONE_LINE))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Ok(Mode::Lines)
|
let lines = lines::Options { icons: matches.has(&flags::ICONS)? };
|
||||||
|
Ok(Mode::Lines(lines))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if matches.has(&flags::TREE)? {
|
else if matches.has(&flags::TREE)? {
|
||||||
@ -60,6 +62,7 @@ impl Mode {
|
|||||||
table: None,
|
table: None,
|
||||||
header: false,
|
header: false,
|
||||||
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
||||||
|
icons: matches.has(&flags::ICONS)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Mode::Details(details))
|
Ok(Mode::Details(details))
|
||||||
@ -68,11 +71,13 @@ impl Mode {
|
|||||||
let grid = grid::Options {
|
let grid = grid::Options {
|
||||||
across: matches.has(&flags::ACROSS)?,
|
across: matches.has(&flags::ACROSS)?,
|
||||||
console_width: width,
|
console_width: width,
|
||||||
|
icons: matches.has(&flags::ICONS)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Mode::Grid(grid))
|
Ok(Mode::Grid(grid))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the terminal width couldn’t be matched for some reason, such
|
// If the terminal width couldn’t be matched for some reason, such
|
||||||
// as the program’s stdout being connected to a file, then
|
// as the program’s stdout being connected to a file, then
|
||||||
// fallback to the lines view.
|
// fallback to the lines view.
|
||||||
@ -81,12 +86,14 @@ impl Mode {
|
|||||||
table: None,
|
table: None,
|
||||||
header: false,
|
header: false,
|
||||||
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
||||||
|
icons: matches.has(&flags::ICONS)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Mode::Details(details))
|
Ok(Mode::Details(details))
|
||||||
}
|
}
|
||||||
else {
|
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,
|
static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES, &flags::TIME_STYLE,
|
||||||
&flags::TIME, &flags::MODIFIED, &flags::CHANGED,
|
&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::HEADER, &flags::GROUP, &flags::INODE, &flags::GIT,
|
||||||
&flags::LINKS, &flags::BLOCKS, &flags::LONG, &flags::LEVEL,
|
&flags::LINKS, &flags::BLOCKS, &flags::LONG, &flags::LEVEL,
|
||||||
&flags::GRID, &flags::ACROSS, &flags::ONE_LINE ];
|
&flags::GRID, &flags::ACROSS, &flags::ONE_LINE ];
|
||||||
@ -563,19 +570,22 @@ mod test {
|
|||||||
mod views {
|
mod views {
|
||||||
use super::*;
|
use super::*;
|
||||||
use output::grid::Options as GridOptions;
|
use output::grid::Options as GridOptions;
|
||||||
|
use output::lines::Options as LineOptions;
|
||||||
|
|
||||||
// Default
|
// Default
|
||||||
test!(empty: Mode <- [], None; Both => like Ok(Mode::Grid(_)));
|
test!(empty: Mode <- [], None; Both => like Ok(Mode::Grid(_)));
|
||||||
|
|
||||||
// Grid views
|
// Grid views
|
||||||
test!(original_g: Mode <- ["-G"], None; Both => like Ok(Mode::Grid(GridOptions { across: false, 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: _ })));
|
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: _ })));
|
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: _ })));
|
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
|
// Lines views
|
||||||
test!(lines: Mode <- ["--oneline"], 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));
|
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
|
// Details views
|
||||||
test!(long: Mode <- ["--long"], None; Both => like Ok(Mode::Details(_)));
|
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::path::PathBuf;
|
||||||
use std::vec::IntoIter as VecIntoIter;
|
use std::vec::IntoIter as VecIntoIter;
|
||||||
|
|
||||||
use ansi_term::Style;
|
use ansi_term::{ANSIGenericString, Style};
|
||||||
|
|
||||||
use fs::{Dir, File};
|
use fs::{Dir, File};
|
||||||
use fs::dir_action::RecurseOptions;
|
use fs::dir_action::RecurseOptions;
|
||||||
@ -77,6 +77,7 @@ use output::cell::TextCell;
|
|||||||
use output::tree::{TreeTrunk, TreeParams, TreeDepth};
|
use output::tree::{TreeTrunk, TreeParams, TreeDepth};
|
||||||
use output::file_name::FileStyle;
|
use output::file_name::FileStyle;
|
||||||
use output::table::{Table, Options as TableOptions, Row as TableRow};
|
use output::table::{Table, Options as TableOptions, Row as TableRow};
|
||||||
|
use output::icons::painted_icon;
|
||||||
use scoped_threadpool::Pool;
|
use scoped_threadpool::Pool;
|
||||||
|
|
||||||
|
|
||||||
@ -105,6 +106,9 @@ pub struct Options {
|
|||||||
|
|
||||||
/// Whether to show each file's extended attributes.
|
/// Whether to show each file's extended attributes.
|
||||||
pub xattr: bool,
|
pub xattr: bool,
|
||||||
|
|
||||||
|
/// Enables --icons mode
|
||||||
|
pub icons: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +136,7 @@ struct Egg<'a> {
|
|||||||
errors: Vec<(IOError, Option<PathBuf>)>,
|
errors: Vec<(IOError, Option<PathBuf>)>,
|
||||||
dir: Option<Dir>,
|
dir: Option<Dir>,
|
||||||
file: &'a File<'a>,
|
file: &'a File<'a>,
|
||||||
|
icon: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsRef<File<'a>> for Egg<'a> {
|
impl<'a> AsRef<File<'a>> for Egg<'a> {
|
||||||
@ -194,7 +199,7 @@ impl<'a> Render<'a> {
|
|||||||
let table = table.as_ref();
|
let table = table.as_ref();
|
||||||
|
|
||||||
for file in src {
|
for file in src {
|
||||||
let file_eggs = file_eggs.clone();
|
let file_eggs = Arc::clone(&file_eggs);
|
||||||
|
|
||||||
scoped.execute(move || {
|
scoped.execute(move || {
|
||||||
let mut errors = Vec::new();
|
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);
|
file_eggs.lock().unwrap().push(egg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -271,12 +280,20 @@ impl<'a> Render<'a> {
|
|||||||
t.add_widths(row);
|
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 {
|
let row = Row {
|
||||||
tree: tree_params,
|
tree: tree_params,
|
||||||
cells: egg.table_row,
|
cells: egg.table_row,
|
||||||
name: self.style.for_file(&egg.file, self.colours)
|
name: name_cell,
|
||||||
.with_link_paths()
|
|
||||||
.paint().promote(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rows.push(row);
|
rows.push(row);
|
||||||
|
@ -5,12 +5,15 @@ use term_grid as tg;
|
|||||||
use fs::File;
|
use fs::File;
|
||||||
use style::Colours;
|
use style::Colours;
|
||||||
use output::file_name::FileStyle;
|
use output::file_name::FileStyle;
|
||||||
|
use output::icons::painted_icon;
|
||||||
|
use output::cell::DisplayWidth;
|
||||||
|
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
pub across: bool,
|
pub across: bool,
|
||||||
pub console_width: usize,
|
pub console_width: usize,
|
||||||
|
pub icons: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Options {
|
impl Options {
|
||||||
@ -38,11 +41,16 @@ impl<'a> Render<'a> {
|
|||||||
grid.reserve(self.files.len());
|
grid.reserve(self.files.len());
|
||||||
|
|
||||||
for file in &self.files {
|
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 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 {
|
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,
|
width: *width,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::io::{Write, Result as IOResult};
|
use std::io::{Write, Result as IOResult};
|
||||||
|
|
||||||
use ansi_term::ANSIStrings;
|
use ansi_term::{ANSIGenericString, ANSIStrings};
|
||||||
use term_grid as grid;
|
use term_grid as grid;
|
||||||
|
|
||||||
use fs::{Dir, File};
|
use fs::{Dir, File};
|
||||||
@ -17,7 +17,7 @@ use output::grid::Options as GridOptions;
|
|||||||
use output::file_name::FileStyle;
|
use output::file_name::FileStyle;
|
||||||
use output::table::{Table, Row as TableRow, Options as TableOptions};
|
use output::table::{Table, Row as TableRow, Options as TableOptions};
|
||||||
use output::tree::{TreeParams, TreeDepth};
|
use output::tree::{TreeParams, TreeDepth};
|
||||||
|
use output::icons::painted_icon;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
@ -135,7 +135,17 @@ impl<'a> Render<'a> {
|
|||||||
.collect::<Vec<TableRow>>();
|
.collect::<Vec<TableRow>>();
|
||||||
|
|
||||||
let file_names = self.files.iter()
|
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>>();
|
.collect::<Vec<TextCell>>();
|
||||||
|
|
||||||
let mut last_working_table = self.make_grid(1, options, git, &file_names, rows.clone(), &drender);
|
let mut last_working_table = self.make_grid(1, options, git, &file_names, rows.clone(), &drender);
|
||||||
|
120
src/output/icons.rs
Normal file
120
src/output/icons.rs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
use ansi_term::Style;
|
||||||
|
use fs::File;
|
||||||
|
use info::filetype::FileExtensions;
|
||||||
|
use output::file_name::FileStyle;
|
||||||
|
|
||||||
|
pub trait FileIcon {
|
||||||
|
fn icon_file(&self, file: &File) -> Option<char>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Icons {
|
||||||
|
Audio,
|
||||||
|
Image,
|
||||||
|
Video,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Icons {
|
||||||
|
pub fn value(&self) -> char {
|
||||||
|
match *self {
|
||||||
|
Icons::Audio => '\u{f001}',
|
||||||
|
Icons::Image => '\u{f1c5}',
|
||||||
|
Icons::Video => '\u{f03d}',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn painted_icon(file: &File, style: &FileStyle) -> String {
|
||||||
|
let file_icon = icon(&file).to_string();
|
||||||
|
let painted = style.exts
|
||||||
|
.colour_file(&file)
|
||||||
|
.map_or(file_icon.to_string(), |c| {
|
||||||
|
// Remove underline from icon
|
||||||
|
if c.is_underline {
|
||||||
|
match c.foreground {
|
||||||
|
Some(color) => Style::from(color).paint(file_icon).to_string(),
|
||||||
|
None => Style::default().paint(file_icon).to_string(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.paint(file_icon).to_string()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
format!("{} ", painted)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn icon(file: &File) -> char {
|
||||||
|
let extensions = Box::new(FileExtensions);
|
||||||
|
if file.is_directory() { '\u{f115}' }
|
||||||
|
else if let Some(icon) = extensions.icon_file(file) { icon }
|
||||||
|
else {
|
||||||
|
if let Some(ext) = file.ext.as_ref() {
|
||||||
|
match ext.as_str() {
|
||||||
|
"ai" => '\u{e7b4}',
|
||||||
|
"android" => '\u{e70e}',
|
||||||
|
"apple" => '\u{f179}',
|
||||||
|
"avro" => '\u{e60b}',
|
||||||
|
"c" => '\u{e61e}',
|
||||||
|
"clj" => '\u{e768}',
|
||||||
|
"coffee" => '\u{f0f4}',
|
||||||
|
"conf" => '\u{e615}',
|
||||||
|
"cpp" => '\u{e61d}',
|
||||||
|
"css" => '\u{e749}',
|
||||||
|
"d" => '\u{e7af}',
|
||||||
|
"dart" => '\u{e798}',
|
||||||
|
"db" => '\u{f1c0}',
|
||||||
|
"diff" => '\u{f440}',
|
||||||
|
"doc" => '\u{f1c2}',
|
||||||
|
"ebook" => '\u{e28b}',
|
||||||
|
"env" => '\u{f462}',
|
||||||
|
"epub" => '\u{e28a}',
|
||||||
|
"erl" => '\u{e7b1}',
|
||||||
|
"font" => '\u{f031}',
|
||||||
|
"gform" => '\u{f298}',
|
||||||
|
"git" => '\u{f1d3}',
|
||||||
|
"go" => '\u{e626}',
|
||||||
|
"hs" => '\u{e777}',
|
||||||
|
"html" => '\u{f13b}',
|
||||||
|
"iml" => '\u{e7b5}',
|
||||||
|
"java" => '\u{e204}',
|
||||||
|
"js" => '\u{e74e}',
|
||||||
|
"json" => '\u{e60b}',
|
||||||
|
"jsx" => '\u{e7ba}',
|
||||||
|
"less" => '\u{e758}',
|
||||||
|
"log" => '\u{f18d}',
|
||||||
|
"lua" => '\u{e620}',
|
||||||
|
"md" => '\u{f48a}',
|
||||||
|
"mustache" => '\u{e60f}',
|
||||||
|
"npmignore" => '\u{e71e}',
|
||||||
|
"pdf" => '\u{f1c1}',
|
||||||
|
"php" => '\u{e73d}',
|
||||||
|
"pl" => '\u{e769}',
|
||||||
|
"ppt" => '\u{f1c4}',
|
||||||
|
"psd" => '\u{e7b8}',
|
||||||
|
"py" => '\u{e606}',
|
||||||
|
"r" => '\u{f25d}',
|
||||||
|
"rb" => '\u{e21e}',
|
||||||
|
"rdb" => '\u{e76d}',
|
||||||
|
"rs" => '\u{e7a8}',
|
||||||
|
"rss" => '\u{f09e}',
|
||||||
|
"rubydoc" => '\u{e73b}',
|
||||||
|
"sass" => '\u{e603}',
|
||||||
|
"scala" => '\u{e737}',
|
||||||
|
"shell" => '\u{f489}',
|
||||||
|
"sqlite3" => '\u{e7c4}',
|
||||||
|
"styl" => '\u{e600}',
|
||||||
|
"tex" => '\u{e600}',
|
||||||
|
"ts" => '\u{e628}',
|
||||||
|
"twig" => '\u{e61c}',
|
||||||
|
"txt" => '\u{f15c}',
|
||||||
|
"video" => '\u{f03d}',
|
||||||
|
"vim" => '\u{e62b}',
|
||||||
|
"xls" => '\u{f1c3}',
|
||||||
|
"xml" => '\u{e619}',
|
||||||
|
"yml" => '\u{f481}',
|
||||||
|
"zip" => '\u{f410}',
|
||||||
|
_ => '\u{f15b}'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
'\u{f15b}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,40 @@
|
|||||||
use std::io::{Write, Result as IOResult};
|
use std::io::{Write, Result as IOResult};
|
||||||
|
|
||||||
use ansi_term::ANSIStrings;
|
use ansi_term::{ANSIStrings, ANSIGenericString};
|
||||||
|
|
||||||
use fs::File;
|
use fs::File;
|
||||||
use output::file_name::{FileName, FileStyle};
|
use output::file_name::{FileName, FileStyle};
|
||||||
use style::Colours;
|
use style::Colours;
|
||||||
|
use output::icons::painted_icon;
|
||||||
|
use output::cell::TextCell;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
|
pub struct Options {
|
||||||
|
pub icons: bool
|
||||||
|
}
|
||||||
|
|
||||||
/// The lines view literally just displays each file, line-by-line.
|
/// The lines view literally just displays each file, line-by-line.
|
||||||
pub struct Render<'a> {
|
pub struct Render<'a> {
|
||||||
pub files: Vec<File<'a>>,
|
pub files: Vec<File<'a>>,
|
||||||
pub colours: &'a Colours,
|
pub colours: &'a Colours,
|
||||||
pub style: &'a FileStyle,
|
pub style: &'a FileStyle,
|
||||||
|
pub opts: &'a Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Render<'a> {
|
impl<'a> Render<'a> {
|
||||||
pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
|
pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
|
||||||
for file in &self.files {
|
for file in &self.files {
|
||||||
let name_cell = self.render_file(file).paint();
|
let name_cell = self.render_file(file).paint();
|
||||||
writeln!(w, "{}", ANSIStrings(&name_cell))?;
|
if self.opts.icons {
|
||||||
|
// Create a TextCell for the icon then append the text to it
|
||||||
|
let mut cell = TextCell::default();
|
||||||
|
let icon = painted_icon(&file, self.style);
|
||||||
|
cell.push(ANSIGenericString::from(icon), 2);
|
||||||
|
cell.append(name_cell.promote());
|
||||||
|
writeln!(w, "{}", ANSIStrings(&cell))?;
|
||||||
|
} else {
|
||||||
|
writeln!(w, "{}", ANSIStrings(&name_cell))?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -8,6 +8,7 @@ pub mod details;
|
|||||||
pub mod file_name;
|
pub mod file_name;
|
||||||
pub mod grid_details;
|
pub mod grid_details;
|
||||||
pub mod grid;
|
pub mod grid;
|
||||||
|
pub mod icons;
|
||||||
pub mod lines;
|
pub mod lines;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
@ -34,5 +35,5 @@ pub enum Mode {
|
|||||||
Grid(grid::Options),
|
Grid(grid::Options),
|
||||||
Details(details::Options),
|
Details(details::Options),
|
||||||
GridDetails(grid_details::Options),
|
GridDetails(grid_details::Options),
|
||||||
Lines,
|
Lines(lines::Options),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user