use crate::position::Position;
use crate::security::safe_repeat;
use crate::utils::width_visible as line_width;
pub fn join_horizontal(pos: Position, strs: &[&str]) -> String {
if strs.is_empty() {
return String::new();
}
if strs.len() == 1 {
return strs[0].to_string();
}
let mut blocks: Vec<Vec<String>> = Vec::with_capacity(strs.len());
let mut max_widths: Vec<usize> = Vec::with_capacity(strs.len());
let mut max_height: usize = 0;
for s in strs {
let lines: Vec<String> = s.split('\n').map(|l| l.to_string()).collect();
if lines.len() > max_height {
max_height = lines.len();
}
let w = lines.iter().map(|l| line_width(l)).max().unwrap_or(0);
blocks.push(lines);
max_widths.push(w);
}
let v = pos.value();
for b in &mut blocks {
if b.len() >= max_height {
continue;
}
let need = max_height - b.len();
let mut extra = vec![String::new(); need];
if (v - 0.0).abs() < f64::EPSILON {
b.extend(extra);
} else if (v - 1.0).abs() < f64::EPSILON {
extra.append(b);
*b = extra;
} else {
let split = (need as f64 * v).round() as usize;
let top = need - split; let bottom = need - top;
let prepend = need - top;
let append = need - bottom;
let mut newv: Vec<String> = Vec::with_capacity(max_height);
newv.extend(std::iter::repeat_n(String::new(), prepend));
newv.append(b);
newv.extend(std::iter::repeat_n(String::new(), append));
*b = newv;
}
}
let mut out = String::new();
for i in 0..max_height {
for (j, block) in blocks.iter().enumerate() {
let line = if i < block.len() {
block[i].as_str()
} else {
""
};
out.push_str(line);
let pad = max_widths[j].saturating_sub(line_width(line));
if pad > 0 {
out.push_str(&safe_repeat(' ', pad));
}
}
if i < max_height - 1 {
out.push('\n');
}
}
out
}
pub fn join_vertical(pos: Position, strs: &[&str]) -> String {
if strs.is_empty() {
return String::new();
}
if strs.len() == 1 {
return strs[0].to_string();
}
let mut blocks: Vec<Vec<String>> = Vec::with_capacity(strs.len());
let mut max_width: usize = 0;
for s in strs {
let lines: Vec<String> = s.split('\n').map(|l| l.to_string()).collect();
let w = lines.iter().map(|l| line_width(l)).max().unwrap_or(0);
if w > max_width {
max_width = w;
}
blocks.push(lines);
}
let v = pos.value();
let mut out = String::new();
for (bi, block) in blocks.iter().enumerate() {
for (li, line) in block.iter().enumerate() {
let line = line.as_str();
let w = max_width.saturating_sub(line_width(line));
if (v - 0.0).abs() < f64::EPSILON {
out.push_str(line);
if w > 0 {
out.push_str(&safe_repeat(' ', w));
}
} else if (v - 1.0).abs() < f64::EPSILON {
if w > 0 {
out.push_str(&safe_repeat(' ', w));
}
out.push_str(line);
} else {
if w < 1 {
out.push_str(line);
} else {
let split = (w as f64 * v).round() as usize;
let right = w - split;
let left = w - right;
if left > 0 {
out.push_str(&safe_repeat(' ', left));
}
out.push_str(line);
if right > 0 {
out.push_str(&safe_repeat(' ', right));
}
}
}
if !(bi == blocks.len() - 1 && li == block.len() - 1) {
out.push('\n');
}
}
}
out
}