I am writing a small program that is supposed to list files in a directory. Similar to what 'ls' does but needed for something else.
I am running into a problem when printing the list of files to the screen.
All of the files are sorted into directories,executables,symlinks,etc and so have special ansi escape codes attatched.
The problem comes with the width formatting inside the {}.
┆ Library / ┆ prcomp / ┆.tmux.conf@
┆ Movies / ┆ quicklisp / ┆.viminfo
┆ Music / ┆.CFUserTextEncoding ┆.vimrc@
1 [Terminal Output]
/ = Directories , @ = symlinks
See the awkard spacing between .CFUserTextEncoding and .vimrc@ ?
The problem is that different formatting has different escape codes and variable length of the escape code itself
┆[47;30m Library [0m/ ┆[47;30m prcomp [0m/ ┆[1;3;4;36m.tmux.conf[0m@
┆[47;30m Movies [0m/ ┆[47;30m quicklisp [0m/ ┆[1;38;5;15m.viminfo[0m
┆[47;30m Music [0m/ ┆[1;38;5;15m.CFUserTextEncoding[0m ┆[1;3;4;36m.vimrc[0m@
2 [Raw Output]
,îÜ = Escape character
So whatever width it formats with is ignored since the terminal turns the escape characters into colors and the string appears 'trimmed' as expected. But this 'trimming' is causing the very formatting to cut short and the whole formatting looks messed up.
Everywhere where the formatting changes it is causing this formatting mess.
I've tried to workaround this by using a padding vector(vec![" "; space_count],join("")) but that is a whole different dominion of mess and this native formatter by far gave the most cleanest results.
Is there a way for go around the escape characters and align the text?
Edit:
A simple reproducible example:
use std::{env , fs, path::PathBuf};
use ansi_term::Colour;
use term_size;
fn main() {
println!("{esc}[2J{esc}[1;1H", esc = 27 as char); // clear
let term_cols = match term_size::dimensions() { Some((cols,_)) => cols, None => 0};
let mut files: Vec<PathBuf> = fs::read_dir(env::current_dir().unwrap())
.unwrap()
.filter_map(|file| Some(file.unwrap().path()))
.collect();
files.sort();
let max_columns = term_cols / 30 ;
let max_rows = (files.len() / max_columns) + 1;
for i in 0..max_rows {
for j in 0..max_columns {
let index = i+(max_rows*j);
if index >= files.len() { break; }
if files[index].is_dir() {
print!("|{:<1$}",format!("{}", Colour::Black.on(Colour::White)
.paint(files[index].file_name()
.unwrap()
.to_str()
.unwrap())), 25);
}
else if files[index].symlink_metadata().unwrap().file_type().is_symlink() {
print!("|{:<1$}", format!("{}",Colour::Cyan.bold()
.italic()
.underline()
.paint(files[index].file_name()
.unwrap()
.to_str()
.unwrap())), 25);
}
else {
print!("|{:<1$}", format!("{}", Colour::Fixed(15).bold()
.paint(files[index].file_name()
.unwrap()
.to_str()
.unwrap())), 25);
}
}
print!("\n");
}
}
Depends on
This is a simplified version of the code.