Răsfoiți Sursa

Initial commit

Ben S 11 ani în urmă
comite
dc9668c8d6
4 a modificat fișierele cu 174 adăugiri și 0 ștergeri
  1. 2 0
      .gitignore
  2. 86 0
      colours.rs
  3. 86 0
      exa.rs
  4. BIN
      screenshot.png

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+exa
+*~

+ 86 - 0
colours.rs

@@ -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 - 0
exa.rs

@@ -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