use crate::config::Config;
use crate::file_entry::{FileEntry, FileType};
use crate::sort::sort_default;
use colored::Colorize;
use unicode_width::UnicodeWidthStr;
pub fn format_short(mut entries: Vec<FileEntry>, config: &Config) {
sort_default(&mut entries);
let mut directories: Vec<FileEntry> = Vec::new();
let mut executables: Vec<FileEntry> = Vec::new();
let mut regular_files: Vec<FileEntry> = Vec::new();
for entry in entries {
match entry.get_file_type() {
FileType::Directory => directories.push(entry),
FileType::Executable => executables.push(entry),
FileType::RegularFile => regular_files.push(entry),
}
}
let column_spacing = config.display.column_spacing;
let max_rows = config.display.max_rows;
if max_rows > 0 {
format_with_max_rows(
directories,
executables,
regular_files,
max_rows,
column_spacing,
config,
);
} else {
format_single_column_per_type(
directories,
executables,
regular_files,
column_spacing,
config,
);
}
}
fn format_with_max_rows(
directories: Vec<FileEntry>,
executables: Vec<FileEntry>,
regular_files: Vec<FileEntry>,
max_rows: usize,
column_spacing: usize,
config: &Config,
) {
let dir_num_cols = if directories.is_empty() {
0
} else {
directories.len().div_ceil(max_rows)
};
let exec_num_cols = if executables.is_empty() {
0
} else {
executables.len().div_ceil(max_rows)
};
let file_num_cols = if regular_files.is_empty() {
0
} else {
regular_files.len().div_ceil(max_rows)
};
let dir_width = directories
.iter()
.map(|e| {
let filename = e.path.to_string_lossy();
UnicodeWidthStr::width(e.get_icon().as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref())
})
.max()
.unwrap_or(0);
let exec_width = executables
.iter()
.map(|e| {
let filename = e.path.to_string_lossy();
UnicodeWidthStr::width(e.get_icon().as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref())
})
.max()
.unwrap_or(0);
let file_width = regular_files
.iter()
.map(|e| {
let filename = e.path.to_string_lossy();
UnicodeWidthStr::width(e.get_icon().as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref())
})
.max()
.unwrap_or(0);
for row in 0..max_rows {
let mut line = String::new();
let mut has_any_content = false;
if dir_num_cols > 0 {
for col in 0..dir_num_cols {
let idx = col * max_rows + row;
if idx < directories.len() {
if col > 0 {
line.push_str(&" ".repeat(column_spacing));
}
let entry = &directories[idx];
let filename = entry.path.to_string_lossy();
let icon = entry.get_icon_custom(&config.icons);
let actual_width = UnicodeWidthStr::width(icon.as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref());
line.push_str(&format!(
"{} {}",
icon.color(entry.get_icon_color(&config.icons.colors)),
filename.color(entry.get_color(&config.colors)).bold()
));
if actual_width < dir_width {
line.push_str(&" ".repeat(dir_width - actual_width));
}
has_any_content = true;
} else if col == 0 {
line.push_str(&" ".repeat(dir_width));
} else {
line.push_str(&" ".repeat(column_spacing + dir_width));
}
}
if exec_num_cols > 0 || file_num_cols > 0 {
line.push_str(&" ".repeat(column_spacing));
}
}
if exec_num_cols > 0 {
for col in 0..exec_num_cols {
let idx = col * max_rows + row;
if idx < executables.len() {
if col > 0 {
line.push_str(&" ".repeat(column_spacing));
}
let entry = &executables[idx];
let filename = entry.path.to_string_lossy();
let icon = entry.get_icon_custom(&config.icons);
let actual_width = UnicodeWidthStr::width(icon.as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref());
line.push_str(&format!(
"{} {}",
icon.color(entry.get_icon_color(&config.icons.colors)),
filename.color(entry.get_color(&config.colors)).bold()
));
if actual_width < exec_width {
line.push_str(&" ".repeat(exec_width - actual_width));
}
has_any_content = true;
} else if col == 0 {
line.push_str(&" ".repeat(exec_width));
} else {
line.push_str(&" ".repeat(column_spacing + exec_width));
}
}
if file_num_cols > 0 {
line.push_str(&" ".repeat(column_spacing));
}
}
if file_num_cols > 0 {
for col in 0..file_num_cols {
let idx = col * max_rows + row;
if idx < regular_files.len() {
if col > 0 {
line.push_str(&" ".repeat(column_spacing));
}
let entry = ®ular_files[idx];
let filename = entry.path.to_string_lossy();
let icon = entry.get_icon_custom(&config.icons);
let actual_width = UnicodeWidthStr::width(icon.as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref());
line.push_str(&format!(
"{} {}",
icon.color(entry.get_icon_color(&config.icons.colors)),
filename.color(entry.get_color(&config.colors))
));
if col < file_num_cols - 1 && actual_width < file_width {
line.push_str(&" ".repeat(file_width - actual_width));
}
has_any_content = true;
}
}
}
if has_any_content {
println!("{}", line.trim_end());
}
}
}
fn format_single_column_per_type(
directories: Vec<FileEntry>,
executables: Vec<FileEntry>,
regular_files: Vec<FileEntry>,
column_spacing: usize,
config: &Config,
) {
let dir_width = directories
.iter()
.map(|e| {
let filename = e.path.to_string_lossy();
let icon = e.get_icon_custom(&config.icons);
UnicodeWidthStr::width(icon.as_str()) + 1 + UnicodeWidthStr::width(filename.as_ref())
})
.max()
.unwrap_or(0);
let exec_width = executables
.iter()
.map(|e| {
let filename = e.path.to_string_lossy();
let icon = e.get_icon_custom(&config.icons);
UnicodeWidthStr::width(icon.as_str()) + 1 + UnicodeWidthStr::width(filename.as_ref())
})
.max()
.unwrap_or(0);
let file_width = regular_files
.iter()
.map(|e| {
let filename = e.path.to_string_lossy();
let icon = e.get_icon_custom(&config.icons);
UnicodeWidthStr::width(icon.as_str()) + 1 + UnicodeWidthStr::width(filename.as_ref())
})
.max()
.unwrap_or(0);
let max_rows = *[directories.len(), executables.len(), regular_files.len()]
.iter()
.max()
.unwrap_or(&0);
for i in 0..max_rows {
let mut line = String::new();
if dir_width > 0 {
if i < directories.len() {
let entry = &directories[i];
let filename = entry.path.to_string_lossy();
let icon = entry.get_icon_custom(&config.icons);
let actual_width = UnicodeWidthStr::width(icon.as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref());
line.push_str(&format!(
"{} {}",
icon.color(entry.get_icon_color(&config.icons.colors)),
filename.color(entry.get_color(&config.colors)).bold()
));
if actual_width < dir_width {
line.push_str(&" ".repeat(dir_width - actual_width));
}
} else {
line.push_str(&" ".repeat(dir_width));
}
if exec_width > 0 || file_width > 0 {
line.push_str(&" ".repeat(column_spacing));
}
}
if exec_width > 0 {
if i < executables.len() {
let entry = &executables[i];
let filename = entry.path.to_string_lossy();
let icon = entry.get_icon_custom(&config.icons);
let actual_width = UnicodeWidthStr::width(icon.as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref());
line.push_str(&format!(
"{} {}",
icon.color(entry.get_icon_color(&config.icons.colors)),
filename.color(entry.get_color(&config.colors)).bold()
));
if actual_width < exec_width {
line.push_str(&" ".repeat(exec_width - actual_width));
}
} else {
line.push_str(&" ".repeat(exec_width));
}
if file_width > 0 {
line.push_str(&" ".repeat(column_spacing));
}
}
if i < regular_files.len() {
let entry = ®ular_files[i];
let filename = entry.path.to_string_lossy();
let icon = entry.get_icon_custom(&config.icons);
let actual_width = UnicodeWidthStr::width(icon.as_str())
+ 1
+ UnicodeWidthStr::width(filename.as_ref());
line.push_str(&format!(
"{} {}",
icon.color(entry.get_icon_color(&config.icons.colors)),
filename.color(entry.get_color(&config.colors))
));
if actual_width < file_width {
line.push_str(&" ".repeat(file_width - actual_width));
}
}
println!("{}", line.trim_end());
}
}