diff --git a/.gitignore b/.gitignore index c08be9d2b..07a32c65b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,6 @@ target/ *~ .*.swp .*.swo +.idea Cargo.lock lib*.a diff --git a/Cargo.toml b/Cargo.toml index 426f08b45..3ce10523b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,6 +63,7 @@ generic = [ "ls", "mkdir", "mktemp", + "more", "nl", "nproc", "od", @@ -144,6 +145,7 @@ mkdir = { optional=true, path="src/mkdir" } mkfifo = { optional=true, path="src/mkfifo" } mknod = { optional=true, path="src/mknod" } mktemp = { optional=true, path="src/mktemp" } +more = { optional=true, path="src/more" } mv = { optional=true, path="src/mv" } nice = { optional=true, path="src/nice" } nl = { optional=true, path="src/nl" } diff --git a/Makefile b/Makefile index 98c34f4b7..73004a18e 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,7 @@ PROGS := \ ls \ mkdir \ mktemp \ + more \ nl \ nproc \ od \ diff --git a/src/more/Cargo.toml b/src/more/Cargo.toml new file mode 100644 index 000000000..88e88d39c --- /dev/null +++ b/src/more/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "more" +version = "0.0.1" +authors = [] + +[lib] +name = "uu_more" +path = "more.rs" + +[dependencies] +getopts = "*" +libc = "*" +nix = "*" +uucore = { path="../uucore" } + +[[bin]] +name = "more" +path = "main.rs" diff --git a/src/more/main.rs b/src/more/main.rs new file mode 100644 index 000000000..b67081dd0 --- /dev/null +++ b/src/more/main.rs @@ -0,0 +1,5 @@ +extern crate uu_more; + +fn main() { + std::process::exit(uu_more::uumain(std::env::args().collect())); +} diff --git a/src/more/more.rs b/src/more/more.rs new file mode 100644 index 000000000..bae650abd --- /dev/null +++ b/src/more/more.rs @@ -0,0 +1,113 @@ +#![crate_name = "uu_more"] + +/* + * This file is part of the uutils coreutils package. + * + * (c) Jordy Dickinson + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +extern crate getopts; + +#[macro_use] +extern crate uucore; + +use getopts::Options; +use std::io::{stdout, stdin, stderr, Write, Read, Result}; +use std::fs::File; + +extern crate nix; +use nix::sys::termios; + +#[derive(Clone, Eq, PartialEq)] +pub enum Mode { + More, + Help, + Version, +} + +static NAME: &'static str = "more"; +static VERSION: &'static str = env!("CARGO_PKG_VERSION"); + +pub fn uumain(args: Vec) -> i32 { + let mut opts = Options::new(); + + opts.optflag("h", "help", "display this help and exit"); + opts.optflag("v", "version", "output version information and exit"); + + let matches = match opts.parse(&args[1..]) { + Ok(m) => m, + Err(e) => { + show_error!("{}", e); + panic!() + }, + }; + let usage = opts.usage("more TARGET."); + let mode = if matches.opt_present("version") { + Mode::Version + } else if matches.opt_present("help") { + Mode::Help + } else { + Mode::More + }; + + match mode { + Mode::More => more(matches), + Mode::Help => help(&usage), + Mode::Version => version(), + } + + 0 +} + +fn version() { + println!("{} {}", NAME, VERSION); +} + +fn help(usage: &str) { + let msg = format!("{0} {1}\n\n\ + Usage: {0} TARGET\n \ + \n\ + {2}", NAME, VERSION, usage); + println!("{}", msg); +} + +fn more(matches: getopts::Matches) { + let mut files = matches.free; + let mut f = File::open(files.first().unwrap()).unwrap(); + let mut buffer = [0; 1024]; + + let saved_term = termios::tcgetattr(0).unwrap(); + let mut term = saved_term; + // Unset canonical mode, so we get characters immediately + term.c_lflag.remove(termios::ICANON); + // Disable local echo + term.c_lflag.remove(termios::ECHO); + termios::tcsetattr(0, termios::TCSADRAIN, &term).unwrap(); + + let mut end = false; + while let Ok(sz) = f.read(&mut buffer) { + if sz == 0 { break; } + stdout().write(&buffer[0..sz]).unwrap(); + for byte in std::io::stdin().bytes() { + let byte = byte.unwrap(); + match byte { + b' ' => break, + b'q' | 27 => { + end = true; + break; + }, + _ => () + } + } + + if end { break;} + } + + term.c_lflag.insert(termios::ICANON); + term.c_lflag.insert(termios::ECHO); + termios::tcsetattr(0, termios::TCSADRAIN, &term).unwrap(); + println!(""); +}