Initial more implementation

This commit is contained in:
Martin Kysel 2016-08-17 20:41:34 +01:00
parent ae0e1c4768
commit 7d77b9720d
6 changed files with 140 additions and 0 deletions

1
.gitignore vendored
View file

@ -6,5 +6,6 @@ target/
*~
.*.swp
.*.swo
.idea
Cargo.lock
lib*.a

View file

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

View file

@ -66,6 +66,7 @@ PROGS := \
ls \
mkdir \
mktemp \
more \
nl \
nproc \
od \

18
src/more/Cargo.toml Normal file
View file

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

5
src/more/main.rs Normal file
View file

@ -0,0 +1,5 @@
extern crate uu_more;
fn main() {
std::process::exit(uu_more::uumain(std::env::args().collect()));
}

113
src/more/more.rs Normal file
View file

@ -0,0 +1,113 @@
#![crate_name = "uu_more"]
/*
* This file is part of the uutils coreutils package.
*
* (c) Jordy Dickinson <jordy.dickinson@gmail.com>
*
* 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<String>) -> 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!("");
}