提交 49c1b8ea 编写于 作者: B Ben S

Use a more compact grid view

Now the grids are optimised so each column is only as wide as its longest file name. The method could do with some optimising, but at least it works.
上级 224849b0
......@@ -9,7 +9,7 @@ use std::io::FileType;
use std::io::fs;
use std::iter::AdditiveIterator;
use std::os;
use std::str::StrVector;
use std::cmp::max;
use column::Alignment::Left;
use column::Column;
......@@ -113,57 +113,90 @@ fn lines_view(files: Vec<File>) {
}
}
fn grid_view(across: bool, console_width: uint, files: Vec<File>) {
// Check if all the files can be displayed on one line, and do
// that if possible. The width has to take into account the
// two-space separator between file names for every file except
// the last one (because it's a separator)
let width = files.iter()
.map(|f| f.name.len() + 2)
.sum() - 2;
if width <= console_width {
let names: Vec<String> = files.iter()
.map(|f| f.file_name().to_string())
.collect();
println!("{}", names.connect(" "));
return;
}
fn fit_into_grid(across: bool, console_width: uint, files: &Vec<File>) -> Option<(uint, Vec<uint>)> {
// TODO: this function could almost certainly be optimised...
// surely not *all* of the numbers of lines are worth searching through!
// Instead of numbers of columns, try to find the fewest number of *lines*
// that the output will fit in.
for num_lines in range(1, files.len()) {
// The number of columns is the number of files divided by the number
// of lines, *rounded up*.
let mut num_columns = files.len() / num_lines;
if files.len() % num_lines != 0 {
num_columns += 1;
}
// Otherwise, contort them into a grid.
let max_column_length = files.iter().map(|f| f.file_name_width()).max().unwrap_or(0);
let num_columns = (console_width + 1) / (max_column_length + 1);
let count = files.len();
// Early abort: if there are so many columns that the width of the
// *column separators* is bigger than the width of the screen, then
// don't even try to tabulate it.
// This is actually a necessary check, because the width is stored as
// a uint, and making it go negative makes it huge instead, but it
// also serves as a speed-up.
if console_width < (num_columns - 1) * 2 {
continue;
}
let mut num_rows = count / num_columns;
if count % num_columns != 0 {
num_rows += 1;
}
// Remove the separator width from the available space.
let adjusted_width = console_width - (num_columns - 1) * 2;
for y in range(0, num_rows) {
for x in range(0, num_columns) {
let num = if across {
y * num_columns + x
// Find the width of each column by adding the lengths of the file
// names in that column up.
let mut column_widths = Vec::from_fn(num_columns, |_| 0u);
for (index, file) in files.iter().enumerate() {
let index = if across {
index % num_columns
}
else {
y + num_rows * x
index / num_lines
};
column_widths[index] = max(column_widths[index], file.name.len());
}
if num >= count {
continue;
}
// If they all fit in the terminal, combined, then success!
if column_widths.iter().map(|&x| x).sum() < adjusted_width {
return Some((num_lines, column_widths));
}
}
let ref file = files[num];
let styled_name = file.file_colour().paint(file.name.as_slice()).to_string();
if x == num_columns - 1 {
print!("{}", styled_name);
}
else {
print!("{}", Left.pad_string(&styled_name, max_column_length - file.name.len() + 1));
// If you get here you have really long file names.
return None;
}
fn grid_view(across: bool, console_width: uint, files: Vec<File>) {
if let Some((num_lines, widths)) = fit_into_grid(across, console_width, &files) {
for y in range(0, num_lines) {
for x in range(0, widths.len()) {
let num = if across {
y * widths.len() + x
}
else {
y + num_lines * x
};
// Show whitespace in the place of trailing files
if num >= files.len() {
continue;
}
let ref file = files[num];
let styled_name = file.file_colour().paint(file.name.as_slice()).to_string();
if x == widths.len() - 1 {
// The final column doesn't need to have trailing spaces
print!("{}", styled_name);
}
else {
assert!(widths[x] >= file.name.len());
print!("{}", Left.pad_string(&styled_name, widths[x] - file.name.len() + 2));
}
}
print!("\n");
}
print!("\n");
}
else {
// Drop down to lines view if the file names are too big for a grid
lines_view(files);
}
}
......@@ -201,10 +234,11 @@ fn details_view(options: &Options, columns: &Vec<Column>, files: Vec<File>) {
for (field_widths, row) in lengths.iter().zip(table.iter()) {
for (num, column) in columns.iter().enumerate() {
if num != 0 {
print!(" ");
print!(" "); // Separator
}
if num == columns.len() - 1 {
// The final column doesn't need to have trailing spaces
print!("{}", row[num]);
}
else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册