mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 13:37:48 +00:00
relpath, tee, split, unexpand: fix build
This commit is contained in:
parent
8d889fc5c9
commit
cc854698d7
4 changed files with 62 additions and 63 deletions
|
@ -64,14 +64,13 @@ pub fn uumain(args: Vec<String>) -> isize {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut suffix_pos = 0;
|
let mut suffix_pos = 0;
|
||||||
absfrom.components()
|
for (f, t) in absfrom.components().zip(absto.components()) {
|
||||||
.zip(absto.components())
|
if f == t {
|
||||||
.take_while(
|
suffix_pos += 1;
|
||||||
|&(f, t)| if f == t {
|
} else {
|
||||||
suffix_pos += 1; true
|
break;
|
||||||
} else {
|
}
|
||||||
false
|
}
|
||||||
}).last();
|
|
||||||
|
|
||||||
let mut result = Path::new("");
|
let mut result = Path::new("");
|
||||||
absfrom.components().skip(suffix_pos).map(|_| result.push("..")).last();
|
absfrom.components().skip(suffix_pos).map(|_| result.push("..")).last();
|
||||||
|
|
|
@ -111,7 +111,7 @@ pub fn uumain(args: Vec<String>) -> isize {
|
||||||
struct Settings {
|
struct Settings {
|
||||||
prefix: String,
|
prefix: String,
|
||||||
numeric_suffix: bool,
|
numeric_suffix: bool,
|
||||||
suffix_length: uint,
|
suffix_length: usize,
|
||||||
input: String,
|
input: String,
|
||||||
strategy: String,
|
strategy: String,
|
||||||
strategy_param: String,
|
strategy_param: String,
|
||||||
|
@ -124,30 +124,29 @@ struct SplitControl {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Splitter {
|
trait Splitter {
|
||||||
// Factory pattern
|
|
||||||
fn new(_hint: Option<Self>, &Settings) -> Box<Splitter>;
|
|
||||||
|
|
||||||
// Consume the current_line and return the consumed string
|
// Consume the current_line and return the consumed string
|
||||||
fn consume(&mut self, &mut SplitControl) -> String;
|
fn consume(&mut self, &mut SplitControl) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LineSplitter {
|
struct LineSplitter {
|
||||||
saved_lines_to_write: uint,
|
saved_lines_to_write: usize,
|
||||||
lines_to_write: uint,
|
lines_to_write: usize,
|
||||||
}
|
}
|
||||||
|
impl LineSplitter {
|
||||||
impl Splitter for LineSplitter {
|
fn new(settings: &Settings) -> Box<Splitter> {
|
||||||
fn new(_: Option<LineSplitter>, settings: &Settings) -> Box<Splitter> {
|
|
||||||
let n = match settings.strategy_param.as_slice().parse() {
|
let n = match settings.strategy_param.as_slice().parse() {
|
||||||
Some(a) => a,
|
Some(a) => a,
|
||||||
_ => crash!(1, "invalid number of lines")
|
_ => crash!(1, "invalid number of lines")
|
||||||
};
|
};
|
||||||
box LineSplitter {
|
Box::new(LineSplitter {
|
||||||
saved_lines_to_write: n,
|
saved_lines_to_write: n,
|
||||||
lines_to_write: n,
|
lines_to_write: n,
|
||||||
} as Box<Splitter>
|
}) as Box<Splitter>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Splitter for LineSplitter {
|
||||||
fn consume(&mut self, control: &mut SplitControl) -> String {
|
fn consume(&mut self, control: &mut SplitControl) -> String {
|
||||||
self.lines_to_write -= 1;
|
self.lines_to_write -= 1;
|
||||||
if self.lines_to_write == 0 {
|
if self.lines_to_write == 0 {
|
||||||
|
@ -159,42 +158,44 @@ impl Splitter for LineSplitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ByteSplitter {
|
struct ByteSplitter {
|
||||||
saved_bytes_to_write: uint,
|
saved_bytes_to_write: usize,
|
||||||
bytes_to_write: uint,
|
bytes_to_write: usize,
|
||||||
break_on_line_end: bool,
|
break_on_line_end: bool,
|
||||||
require_whole_line: bool,
|
require_whole_line: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Splitter for ByteSplitter {
|
impl ByteSplitter {
|
||||||
fn new(_: Option<ByteSplitter>, settings: &Settings) -> Box<Splitter> {
|
fn new(settings: &Settings) -> Box<Splitter> {
|
||||||
let mut strategy_param : Vec<char> = settings.strategy_param.chars().collect();
|
let mut strategy_param : Vec<char> = settings.strategy_param.chars().collect();
|
||||||
let suffix = strategy_param.pop().unwrap();
|
let suffix = strategy_param.pop().unwrap();
|
||||||
let multiplier = match suffix {
|
let multiplier = match suffix {
|
||||||
'0'...'9' => 1u,
|
'0'...'9' => 1us,
|
||||||
'b' => 512u,
|
'b' => 512us,
|
||||||
'k' => 1024u,
|
'k' => 1024us,
|
||||||
'm' => 1024u * 1024u,
|
'm' => 1024us * 1024us,
|
||||||
_ => crash!(1, "invalid number of bytes")
|
_ => crash!(1, "invalid number of bytes")
|
||||||
};
|
};
|
||||||
let n = if suffix.is_alphabetic() {
|
let n = if suffix.is_alphabetic() {
|
||||||
match strategy_param.as_slice().iter().map(|c| *c).collect::<String>().as_slice().parse::<uint>() {
|
match strategy_param.as_slice().iter().map(|c| *c).collect::<String>().as_slice().parse::<usize>() {
|
||||||
Some(a) => a,
|
Some(a) => a,
|
||||||
_ => crash!(1, "invalid number of bytes")
|
_ => crash!(1, "invalid number of bytes")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match settings.strategy_param.as_slice().parse::<uint>() {
|
match settings.strategy_param.as_slice().parse::<usize>() {
|
||||||
Some(a) => a,
|
Some(a) => a,
|
||||||
_ => crash!(1, "invalid number of bytes")
|
_ => crash!(1, "invalid number of bytes")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
box ByteSplitter {
|
Box::new(ByteSplitter {
|
||||||
saved_bytes_to_write: n * multiplier,
|
saved_bytes_to_write: n * multiplier,
|
||||||
bytes_to_write: n * multiplier,
|
bytes_to_write: n * multiplier,
|
||||||
break_on_line_end: if settings.strategy == "b" { false } else { true },
|
break_on_line_end: if settings.strategy == "b" { false } else { true },
|
||||||
require_whole_line: false,
|
require_whole_line: false,
|
||||||
} as Box<Splitter>
|
}) as Box<Splitter>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Splitter for ByteSplitter {
|
||||||
fn consume(&mut self, control: &mut SplitControl) -> String {
|
fn consume(&mut self, control: &mut SplitControl) -> String {
|
||||||
let line = control.current_line.clone();
|
let line = control.current_line.clone();
|
||||||
let n = std::cmp::min(line.as_slice().chars().count(), self.bytes_to_write);
|
let n = std::cmp::min(line.as_slice().chars().count(), self.bytes_to_write);
|
||||||
|
@ -217,13 +218,13 @@ impl Splitter for ByteSplitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// (1, 3) -> "aab"
|
// (1, 3) -> "aab"
|
||||||
fn str_prefix(i: uint, width: uint) -> String {
|
fn str_prefix(i: usize, width: usize) -> String {
|
||||||
let mut c = "".to_string();
|
let mut c = "".to_string();
|
||||||
let mut n = i;
|
let mut n = i;
|
||||||
let mut w = width;
|
let mut w = width;
|
||||||
while w > 0 {
|
while w > 0 {
|
||||||
w -= 1;
|
w -= 1;
|
||||||
let div = Int::pow(26 as uint, w);
|
let div = Int::pow(26 as usize, w);
|
||||||
let r = n / div;
|
let r = n / div;
|
||||||
n -= r * div;
|
n -= r * div;
|
||||||
c.push(char::from_u32((r as u32) + 97).unwrap());
|
c.push(char::from_u32((r as u32) + 97).unwrap());
|
||||||
|
@ -232,13 +233,13 @@ fn str_prefix(i: uint, width: uint) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
// (1, 3) -> "001"
|
// (1, 3) -> "001"
|
||||||
fn num_prefix(i: uint, width: uint) -> String {
|
fn num_prefix(i: usize, width: usize) -> String {
|
||||||
let mut c = "".to_string();
|
let mut c = "".to_string();
|
||||||
let mut n = i;
|
let mut n = i;
|
||||||
let mut w = width;
|
let mut w = width;
|
||||||
while w > 0 {
|
while w > 0 {
|
||||||
w -= 1;
|
w -= 1;
|
||||||
let div = Int::pow(10 as uint, w);
|
let div = Int::pow(10 as usize, w);
|
||||||
let r = n / div;
|
let r = n / div;
|
||||||
n -= r * div;
|
n -= r * div;
|
||||||
c.push(char::from_digit(r, 10).unwrap());
|
c.push(char::from_digit(r, 10).unwrap());
|
||||||
|
@ -246,23 +247,23 @@ fn num_prefix(i: uint, width: uint) -> String {
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split(settings: &Settings) -> int {
|
fn split(settings: &Settings) -> isize {
|
||||||
let mut reader = io::BufferedReader::new(
|
let mut reader = io::BufferedReader::new(
|
||||||
if settings.input.as_slice() == "-" {
|
if settings.input.as_slice() == "-" {
|
||||||
box io::stdio::stdin_raw() as Box<Reader>
|
Box::new(io::stdio::stdin_raw()) as Box<Reader>
|
||||||
} else {
|
} else {
|
||||||
let r = match io::File::open(&Path::new(settings.input.clone())) {
|
let r = match io::File::open(&Path::new(settings.input.clone())) {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(_) => crash!(1, "cannot open '{}' for reading: No such file or directory", settings.input)
|
Err(_) => crash!(1, "cannot open '{}' for reading: No such file or directory", settings.input)
|
||||||
};
|
};
|
||||||
box r as Box<Reader>
|
Box::new(r) as Box<Reader>
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut splitter: Box<Splitter> =
|
let mut splitter: Box<Splitter> =
|
||||||
match settings.strategy.as_slice() {
|
match settings.strategy.as_slice() {
|
||||||
"l" => Splitter::new(None::<LineSplitter>, settings),
|
"l" => LineSplitter::new(settings),
|
||||||
"b" | "C" => Splitter::new(None::<ByteSplitter>, settings),
|
"b" | "C" => ByteSplitter::new(settings),
|
||||||
a @ _ => crash!(1, "strategy {} not supported", a)
|
a @ _ => crash!(1, "strategy {} not supported", a)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -271,7 +272,7 @@ fn split(settings: &Settings) -> int {
|
||||||
request_new_file: true, // Request new file
|
request_new_file: true, // Request new file
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut writer = io::BufferedWriter::new(box io::stdio::stdout_raw() as Box<Writer>);
|
let mut writer = io::BufferedWriter::new(Box::new(io::stdio::stdout_raw()) as Box<Writer>);
|
||||||
let mut fileno = 0;
|
let mut fileno = 0;
|
||||||
loop {
|
loop {
|
||||||
if control.current_line.as_slice().chars().count() == 0 {
|
if control.current_line.as_slice().chars().count() == 0 {
|
||||||
|
@ -293,7 +294,7 @@ fn split(settings: &Settings) -> int {
|
||||||
crash_if_err!(1, writer.flush());
|
crash_if_err!(1, writer.flush());
|
||||||
}
|
}
|
||||||
fileno += 1;
|
fileno += 1;
|
||||||
writer = io::BufferedWriter::new(box io::File::open_mode(&Path::new(filename.as_slice()), io::Open, io::Write) as Box<Writer>);
|
writer = io::BufferedWriter::new(Box::new(io::File::open_mode(&Path::new(filename.as_slice()), io::Open, io::Write)) as Box<Writer>);
|
||||||
control.request_new_file = false;
|
control.request_new_file = false;
|
||||||
if settings.verbose {
|
if settings.verbose {
|
||||||
println!("creating file '{}'", filename);
|
println!("creating file '{}'", filename);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![crate_name = "tee"]
|
#![crate_name = "tee"]
|
||||||
#![feature(phase)]
|
|
||||||
/*
|
/*
|
||||||
* This file is part of the uutils coreutils package.
|
* This file is part of the uutils coreutils package.
|
||||||
*
|
*
|
||||||
|
@ -66,7 +65,7 @@ fn options(args: &[String]) -> Result<Options, ()> {
|
||||||
append: m.opt_present("append"),
|
append: m.opt_present("append"),
|
||||||
ignore_interrupts: m.opt_present("ignore-interrupts"),
|
ignore_interrupts: m.opt_present("ignore-interrupts"),
|
||||||
print_and_exit: to_print,
|
print_and_exit: to_print,
|
||||||
files: box names.iter().map(|name| Path::new(name.clone())).collect()
|
files: Box::new(names.iter().map(|name| Path::new(name.clone())).collect())
|
||||||
})
|
})
|
||||||
}).map_err(|message| warn(message.as_slice()))
|
}).map_err(|message| warn(message.as_slice()))
|
||||||
}
|
}
|
||||||
|
@ -81,7 +80,7 @@ fn exec(options: Options) -> Result<(), ()> {
|
||||||
fn tee(options: Options) -> Result<(), ()> {
|
fn tee(options: Options) -> Result<(), ()> {
|
||||||
let writers = options.files.iter().map(|path| open(path, options.append)).collect();
|
let writers = options.files.iter().map(|path| open(path, options.append)).collect();
|
||||||
let output = &mut MultiWriter::new(writers);
|
let output = &mut MultiWriter::new(writers);
|
||||||
let input = &mut NamedReader { inner: box stdin() as Box<Reader> };
|
let input = &mut NamedReader { inner: Box::new(stdin()) as Box<Reader> };
|
||||||
if copy(input, output).is_err() || output.flush().is_err() {
|
if copy(input, output).is_err() || output.flush().is_err() {
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,15 +90,15 @@ fn tee(options: Options) -> Result<(), ()> {
|
||||||
|
|
||||||
fn open(path: &Path, append: bool) -> Box<Writer+'static> {
|
fn open(path: &Path, append: bool) -> Box<Writer+'static> {
|
||||||
let inner = if *path == Path::new("-") {
|
let inner = if *path == Path::new("-") {
|
||||||
box stdout() as Box<Writer>
|
Box::new(stdout()) as Box<Writer>
|
||||||
} else {
|
} else {
|
||||||
let mode = if append { Append } else { Truncate };
|
let mode = if append { Append } else { Truncate };
|
||||||
match File::open_mode(path, mode, Write) {
|
match File::open_mode(path, mode, Write) {
|
||||||
Ok(file) => box file as Box<Writer>,
|
Ok(file) => Box::new(file) as Box<Writer>,
|
||||||
Err(_) => box NullWriter as Box<Writer>
|
Err(_) => Box::new(NullWriter) as Box<Writer>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
box NamedWriter { inner: inner, path: box path.clone() } as Box<Writer>
|
Box::new(NamedWriter { inner: inner, path: Box::new(path.clone()) }) as Box<Writer>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NamedWriter {
|
struct NamedWriter {
|
||||||
|
@ -112,7 +111,7 @@ impl Writer for NamedWriter {
|
||||||
with_path(&*self.path.clone(), || {
|
with_path(&*self.path.clone(), || {
|
||||||
let val = self.inner.write(buf);
|
let val = self.inner.write(buf);
|
||||||
if val.is_err() {
|
if val.is_err() {
|
||||||
self.inner = box NullWriter as Box<Writer>;
|
self.inner = Box::new(NullWriter) as Box<Writer>;
|
||||||
}
|
}
|
||||||
val
|
val
|
||||||
})
|
})
|
||||||
|
@ -122,7 +121,7 @@ impl Writer for NamedWriter {
|
||||||
with_path(&*self.path.clone(), || {
|
with_path(&*self.path.clone(), || {
|
||||||
let val = self.inner.flush();
|
let val = self.inner.flush();
|
||||||
if val.is_err() {
|
if val.is_err() {
|
||||||
self.inner = box NullWriter as Box<Writer>;
|
self.inner = Box::new(NullWriter) as Box<Writer>;
|
||||||
}
|
}
|
||||||
val
|
val
|
||||||
})
|
})
|
||||||
|
@ -134,14 +133,14 @@ struct NamedReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reader for NamedReader {
|
impl Reader for NamedReader {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
|
||||||
with_path(&Path::new("stdin"), || {
|
with_path(&Path::new("stdin"), || {
|
||||||
self.inner.read(buf)
|
self.inner.read(buf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_path<F, T>(path: &Path, cb: F) -> IoResult<T> where F: Fn() -> IoResult<T> {
|
fn with_path<F, T>(path: &Path, mut cb: F) -> IoResult<T> where F: FnMut() -> IoResult<T> {
|
||||||
match cb() {
|
match cb() {
|
||||||
Err(f) => { warn(format!("{}: {}", path.display(), f.to_string()).as_slice()); Err(f) }
|
Err(f) => { warn(format!("{}: {}", path.display(), f.to_string()).as_slice()); Err(f) }
|
||||||
okay => okay
|
okay => okay
|
||||||
|
|
|
@ -21,9 +21,9 @@ mod util;
|
||||||
static NAME: &'static str = "unexpand";
|
static NAME: &'static str = "unexpand";
|
||||||
static VERSION: &'static str = "0.0.1";
|
static VERSION: &'static str = "0.0.1";
|
||||||
|
|
||||||
static DEFAULT_TABSTOP: uint = 8;
|
static DEFAULT_TABSTOP: usize = 8;
|
||||||
|
|
||||||
fn tabstops_parse(s: String) -> Vec<uint> {
|
fn tabstops_parse(s: String) -> Vec<usize> {
|
||||||
let words = s.as_slice().split(',').collect::<Vec<&str>>();
|
let words = s.as_slice().split(',').collect::<Vec<&str>>();
|
||||||
|
|
||||||
let nums = words.into_iter()
|
let nums = words.into_iter()
|
||||||
|
@ -31,7 +31,7 @@ fn tabstops_parse(s: String) -> Vec<uint> {
|
||||||
.unwrap_or_else(
|
.unwrap_or_else(
|
||||||
|| crash!(1, "{}\n", "tab size contains invalid character(s)"))
|
|| crash!(1, "{}\n", "tab size contains invalid character(s)"))
|
||||||
)
|
)
|
||||||
.collect::<Vec<uint>>();
|
.collect::<Vec<usize>>();
|
||||||
|
|
||||||
if nums.iter().any(|&n| n == 0) {
|
if nums.iter().any(|&n| n == 0) {
|
||||||
crash!(1, "{}\n", "tab size cannot be 0");
|
crash!(1, "{}\n", "tab size cannot be 0");
|
||||||
|
@ -47,7 +47,7 @@ fn tabstops_parse(s: String) -> Vec<uint> {
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
files: Vec<String>,
|
files: Vec<String>,
|
||||||
tabstops: Vec<uint>,
|
tabstops: Vec<usize>,
|
||||||
aflag: bool
|
aflag: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,24 +108,24 @@ pub fn uumain(args: Vec<String>) -> isize {
|
||||||
fn open(path: String) -> io::BufferedReader<Box<Reader+'static>> {
|
fn open(path: String) -> io::BufferedReader<Box<Reader+'static>> {
|
||||||
let mut file_buf;
|
let mut file_buf;
|
||||||
if path.as_slice() == "-" {
|
if path.as_slice() == "-" {
|
||||||
io::BufferedReader::new(box io::stdio::stdin_raw() as Box<Reader>)
|
io::BufferedReader::new(Box::new(io::stdio::stdin_raw()) as Box<Reader>)
|
||||||
} else {
|
} else {
|
||||||
file_buf = match io::File::open(&Path::new(path.as_slice())) {
|
file_buf = match io::File::open(&Path::new(path.as_slice())) {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
_ => crash!(1, "{}: {}\n", path, "No such file or directory")
|
_ => crash!(1, "{}: {}\n", path, "No such file or directory")
|
||||||
};
|
};
|
||||||
io::BufferedReader::new(box file_buf as Box<Reader>)
|
io::BufferedReader::new(Box::new(file_buf) as Box<Reader>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_tabstop(tabstops: &[uint], col: uint) -> bool {
|
fn is_tabstop(tabstops: &[usize], col: usize) -> bool {
|
||||||
match tabstops {
|
match tabstops {
|
||||||
[tabstop] => col % tabstop == 0,
|
[tabstop] => col % tabstop == 0,
|
||||||
tabstops => tabstops.binary_search(|&e| e.cmp(&col)).found().is_some()
|
tabstops => tabstops.binary_search_by(|&e| e.cmp(&col)).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_next_stop(tabstops: &[uint], col: uint) -> Option<uint> {
|
fn to_next_stop(tabstops: &[usize], col: usize) -> Option<usize> {
|
||||||
match tabstops {
|
match tabstops {
|
||||||
[tabstop] => Some(tabstop - col % tabstop),
|
[tabstop] => Some(tabstop - col % tabstop),
|
||||||
tabstops => tabstops.iter().skip_while(|&t| *t <= col).next()
|
tabstops => tabstops.iter().skip_while(|&t| *t <= col).next()
|
||||||
|
@ -134,7 +134,7 @@ fn to_next_stop(tabstops: &[uint], col: uint) -> Option<uint> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unexpandspan(mut output: &mut io::LineBufferedWriter<io::stdio::StdWriter>,
|
fn unexpandspan(mut output: &mut io::LineBufferedWriter<io::stdio::StdWriter>,
|
||||||
tabstops: &[uint], nspaces: uint, col: uint, init: bool) {
|
tabstops: &[usize], nspaces: usize, col: usize, init: bool) {
|
||||||
let mut cur = col - nspaces;
|
let mut cur = col - nspaces;
|
||||||
if nspaces > 1 || init {
|
if nspaces > 1 || init {
|
||||||
loop {
|
loop {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue