use std::convert::TryInto;
use std::io::{BufWriter, Write};
use std::iter::FromIterator;
use crate::config::Config;
use crate::writeable::Writeable;
use crate::writer::WriteReceiver;
#[derive(Debug)]
pub struct Choice {
pub start: isize,
pub end: isize,
negative_index: bool,
reversed: bool,
}
impl Choice {
pub fn new(start: isize, end: isize) -> Self {
let negative_index = start < 0 || end < 0;
let reversed = end < start;
Choice {
start,
end,
negative_index,
reversed,
}
}
pub fn print_choice<W: Write>(
&self,
line: &String,
config: &Config,
handle: &mut BufWriter<W>,
) {
if config.opt.character_wise {
let line_chars = line[0..line.len() - 1].chars();
self.print_choice_generic(line_chars, config, handle);
} else {
let line_iter = config
.separator
.split(line)
.filter(|s| !s.is_empty() || config.opt.non_greedy);
self.print_choice_generic(line_iter, config, handle);
}
}
pub fn is_reverse_range(&self) -> bool {
self.reversed
}
pub fn has_negative_index(&self) -> bool {
self.negative_index
}
fn print_choice_generic<W, T, I>(&self, mut iter: I, config: &Config, handle: &mut BufWriter<W>)
where
W: Write,
T: Writeable + Copy,
I: Iterator<Item = T>,
{
if self.is_reverse_range() && !self.has_negative_index() {
self.print_choice_reverse(iter, config, handle);
} else if self.has_negative_index() {
self.print_choice_negative(iter, config, handle);
} else {
if self.start > 0 {
iter.nth((self.start - 1).try_into().unwrap());
}
let range = self.end.checked_sub(self.start).unwrap();
Choice::print_choice_loop_max_items(iter, config, handle, range);
}
}
fn print_choice_loop<W, T, I>(iter: I, config: &Config, handle: &mut BufWriter<W>)
where
W: Write,
T: Writeable + Copy,
I: Iterator<Item = T>,
{
Choice::print_choice_loop_max_items(iter, config, handle, isize::max_value());
}
fn print_choice_loop_max_items<W, T, I>(
iter: I,
config: &Config,
handle: &mut BufWriter<W>,
max_items: isize,
) where
W: Write,
T: Writeable + Copy,
I: Iterator<Item = T>,
{
let mut peek_iter = iter.peekable();
for i in 0..=max_items {
match peek_iter.next() {
Some(s) => {
handle.write_choice(s, config, peek_iter.peek().is_some() && i != max_items);
}
None => break,
};
}
}
fn print_choice_negative<W, T, I>(&self, iter: I, config: &Config, handle: &mut BufWriter<W>)
where
W: Write,
T: Writeable + Copy,
I: Iterator<Item = T>,
{
let vec = Vec::from_iter(iter);
let (start, end) = self.get_negative_start_end(&vec);
if end > start {
for word in vec[start..std::cmp::min(end, vec.len() - 1)].iter() {
handle.write_choice(*word, config, true);
}
handle.write_choice(vec[std::cmp::min(end, vec.len() - 1)], config, false);
} else if self.start < 0 {
for word in vec[end + 1..=std::cmp::min(start, vec.len() - 1)]
.iter()
.rev()
{
handle.write_choice(*word, config, true);
}
handle.write_choice(vec[end], config, false);
}
}
fn print_choice_reverse<W, T, I>(&self, mut iter: I, config: &Config, handle: &mut BufWriter<W>)
where
W: Write,
T: Writeable + Copy,
I: Iterator<Item = T>,
{
if self.end > 0 {