mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-29 07:03:54 +00:00
Initial commit
This commit is contained in:
commit
dc9668c8d6
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
exa
|
||||||
|
*~
|
86
colours.rs
Normal file
86
colours.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
pub enum Colour {
|
||||||
|
Black = 30, Red = 31, Green = 32, Yellow = 33, Blue = 34, Purple = 35, Cyan = 36, White = 37,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Style {
|
||||||
|
Plain,
|
||||||
|
Foreground(Colour),
|
||||||
|
Style(StyleStruct),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StyleStruct {
|
||||||
|
foreground: Colour,
|
||||||
|
background: Option<Colour>,
|
||||||
|
bold: bool,
|
||||||
|
underline: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Style {
|
||||||
|
pub fn paint(&self, input: ~str) -> ~str {
|
||||||
|
match *self {
|
||||||
|
Plain => input,
|
||||||
|
Foreground(c) => c.paint(input),
|
||||||
|
Style(s) => match s {
|
||||||
|
StyleStruct { foreground, background, bold, underline } => {
|
||||||
|
let bg: ~str = match background {
|
||||||
|
Some(c) => format!("{};", c as int + 10),
|
||||||
|
None => ~"",
|
||||||
|
};
|
||||||
|
let bo: ~str = if bold { ~"1;" } else { ~"" };
|
||||||
|
let un: ~str = if underline { ~"4;" } else { ~"" };
|
||||||
|
format!("\x1B[{}{}{}{}m{}\x1B[0m", bo, un, bg, foreground as int, input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Style {
|
||||||
|
pub fn bold(&self) -> Style {
|
||||||
|
match *self {
|
||||||
|
Plain => Style(StyleStruct { foreground: White, background: None, bold: true, underline: false }),
|
||||||
|
Foreground(c) => Style(StyleStruct { foreground: c, background: None, bold: true, underline: false }),
|
||||||
|
Style(st) => Style(StyleStruct { foreground: st.foreground, background: st.background, bold: true, underline: false }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn underline(&self) -> Style {
|
||||||
|
match *self {
|
||||||
|
Plain => Style(StyleStruct { foreground: White, background: None, bold: false, underline: true }),
|
||||||
|
Foreground(c) => Style(StyleStruct { foreground: c, background: None, bold: false, underline: true }),
|
||||||
|
Style(st) => Style(StyleStruct { foreground: st.foreground, background: st.background, bold: false, underline: true }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on(&self, background: Colour) -> Style {
|
||||||
|
match *self {
|
||||||
|
Plain => Style(StyleStruct { foreground: White, background: Some(background), bold: false, underline: false }),
|
||||||
|
Foreground(c) => Style(StyleStruct { foreground: c, background: Some(background), bold: false, underline: false }),
|
||||||
|
Style(st) => Style(StyleStruct { foreground: st.foreground, background: Some(background), bold: false, underline: false }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Colour {
|
||||||
|
pub fn paint(&self, input: &str) -> ~str {
|
||||||
|
format!("\x1B[{}m{}\x1B[0m", *self as int, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn underline(&self) -> Style {
|
||||||
|
Style(StyleStruct { foreground: *self, background: None, bold: false, underline: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bold(&self) -> Style {
|
||||||
|
Style(StyleStruct { foreground: *self, background: None, bold: true, underline: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn normal(&self) -> Style {
|
||||||
|
Style(StyleStruct { foreground: *self, background: None, bold: false, underline: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on(&self, background: Colour) -> Style {
|
||||||
|
Style(StyleStruct { foreground: *self, background: Some(background), bold: false, underline: false })
|
||||||
|
}
|
||||||
|
}
|
86
exa.rs
Normal file
86
exa.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use std::io::fs;
|
||||||
|
use std::io;
|
||||||
|
use std::os;
|
||||||
|
|
||||||
|
use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan};
|
||||||
|
mod colours;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match os::args().as_slice() {
|
||||||
|
[] => unreachable!(),
|
||||||
|
[_] => { list(Path::new(".")) },
|
||||||
|
[_, ref p] => { list(Path::new(p.as_slice())) },
|
||||||
|
_ => { fail!("args?") },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list(path: Path) {
|
||||||
|
let mut files = match fs::readdir(&path) {
|
||||||
|
Ok(files) => files,
|
||||||
|
Err(e) => fail!("readdir: {}", e),
|
||||||
|
};
|
||||||
|
files.sort_by(|a, b| a.filename_str().cmp(&b.filename_str()));
|
||||||
|
for file in files.iter() {
|
||||||
|
let filename: &str = file.filename_str().unwrap();
|
||||||
|
|
||||||
|
// We have to use lstat here instad of file.stat(), as it
|
||||||
|
// doesn't follow symbolic links. Otherwise, the stat() call
|
||||||
|
// will fail if it encounters a link that's target is
|
||||||
|
// non-existent.
|
||||||
|
let stat: io::FileStat = match fs::lstat(file) {
|
||||||
|
Ok(stat) => stat,
|
||||||
|
Err(e) => fail!("Couldn't stat {}: {}", filename, e),
|
||||||
|
};
|
||||||
|
|
||||||
|
let colour = file_colour(&stat, filename);
|
||||||
|
|
||||||
|
println!("{} {}", perm_str(&stat), colour.paint(filename.to_owned()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_colour(stat: &io::FileStat, filename: &str) -> Style {
|
||||||
|
if stat.kind == io::TypeDirectory {
|
||||||
|
Blue.normal()
|
||||||
|
} else if stat.perm & io::UserExecute == io::UserExecute {
|
||||||
|
Green.normal()
|
||||||
|
} else if filename.ends_with("~") {
|
||||||
|
Black.bold()
|
||||||
|
} else {
|
||||||
|
Plain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn perm_str(stat: &io::FileStat) -> ~str {
|
||||||
|
let bits = stat.perm;
|
||||||
|
return format!("{}{}{}{}{}{}{}{}{}{}",
|
||||||
|
type_char(stat.kind),
|
||||||
|
bit(bits, io::UserRead, ~"r", Yellow.bold()),
|
||||||
|
bit(bits, io::UserWrite, ~"w", Red.bold()),
|
||||||
|
bit(bits, io::UserExecute, ~"x", Green.bold().underline()),
|
||||||
|
bit(bits, io::GroupRead, ~"r", Yellow.normal()),
|
||||||
|
bit(bits, io::GroupWrite, ~"w", Red.normal()),
|
||||||
|
bit(bits, io::GroupExecute, ~"x", Green.normal()),
|
||||||
|
bit(bits, io::OtherRead, ~"r", Yellow.normal()),
|
||||||
|
bit(bits, io::OtherWrite, ~"w", Red.normal()),
|
||||||
|
bit(bits, io::OtherExecute, ~"x", Green.normal()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bit(bits: u32, bit: u32, other: ~str, style: Style) -> ~str {
|
||||||
|
if bits & bit == bit {
|
||||||
|
style.paint(other)
|
||||||
|
} else {
|
||||||
|
Black.bold().paint(~"-")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_char(t: io::FileType) -> ~str {
|
||||||
|
return match t {
|
||||||
|
io::TypeFile => ~".",
|
||||||
|
io::TypeDirectory => Blue.paint("d"),
|
||||||
|
io::TypeNamedPipe => Yellow.paint("|"),
|
||||||
|
io::TypeBlockSpecial => Purple.paint("s"),
|
||||||
|
io::TypeSymlink => Cyan.paint("l"),
|
||||||
|
_ => ~"?",
|
||||||
|
}
|
||||||
|
}
|
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Loading…
Reference in New Issue
Block a user