forked from uutils/coreutils
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
493 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
// This file is part of the uutils coreutils package. | ||
// | ||
// For the full copyright and license information, please view the LICENSE | ||
// file that was distributed with this source code. | ||
// spell-checker:ignore dired subdired dired | ||
|
||
use crate::Config; | ||
use std::fmt; | ||
use std::io::{BufWriter, Stdout, Write}; | ||
use uucore::error::UResult; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct BytePosition { | ||
pub start: usize, | ||
pub end: usize, | ||
pub is_total: Option<bool>, | ||
} | ||
|
||
/// Represents the output structure for DIRED, containing positions for both DIRED and SUBDIRED. | ||
#[derive(Debug, Clone, Default)] | ||
pub struct DiredOutput { | ||
pub dired_positions: Vec<BytePosition>, | ||
pub subdired_positions: Vec<BytePosition>, | ||
} | ||
|
||
impl fmt::Display for BytePosition { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{} {}", self.start, self.end) | ||
} | ||
} | ||
|
||
/// Calculates the byte positions for DIRED | ||
pub fn calculate_dired_byte_positions( | ||
output_display_len: usize, | ||
dfn_len: usize, | ||
dired_positions: &[BytePosition], | ||
) -> (usize, usize) { | ||
let offset_from_previous_line = if let Some(last_position) = dired_positions.last() { | ||
last_position.end + 1 | ||
} else { | ||
0 | ||
}; | ||
let offset_trailing_spaces = 2; | ||
let start = output_display_len + offset_from_previous_line + offset_trailing_spaces; | ||
let end = start + dfn_len; | ||
(start, end) | ||
} | ||
|
||
pub fn dired_indent(config: &Config, out: &mut BufWriter<Stdout>) -> UResult<()> { | ||
if config.dired { | ||
write!(out, " ")?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub fn calculate_offset_and_push(dired: &mut DiredOutput, path_len: usize) { | ||
let offset = if dired.subdired_positions.is_empty() { | ||
2 | ||
} else { | ||
dired.subdired_positions[dired.subdired_positions.len() - 1].start + 2 | ||
}; | ||
dired.subdired_positions.push(BytePosition { | ||
start: offset, | ||
end: path_len + offset, | ||
is_total: None, | ||
}); | ||
} | ||
|
||
/// Prints the dired output based on the given configuration and dired structure. | ||
pub fn print_dired_output( | ||
config: &Config, | ||
dired: &DiredOutput, | ||
out: &mut BufWriter<Stdout>, | ||
) -> UResult<()> { | ||
out.flush()?; | ||
if config.recursive { | ||
print_positions("//SUBDIRED//", &dired.subdired_positions); | ||
} else if dired.dired_positions.last().map_or(false, |last_position| { | ||
!last_position.is_total.unwrap_or(false) | ||
}) { | ||
print_positions("//DIRED//", &dired.dired_positions); | ||
} | ||
println!("//DIRED-OPTIONS// --quoting-style={}", config.quoting_style); | ||
Ok(()) | ||
} | ||
|
||
/// Helper function to print positions with a given prefix. | ||
fn print_positions(prefix: &str, positions: &Vec<BytePosition>) { | ||
print!("{}", prefix); | ||
for c in positions { | ||
print!(" {}", c); | ||
} | ||
println!(); | ||
} | ||
|
||
/// Calculates byte positions and updates the dired structure. | ||
pub fn calculate_and_update_positions( | ||
output_display_len: usize, | ||
dfn_len: usize, | ||
dired: &mut DiredOutput, | ||
) { | ||
let offset = dired | ||
.dired_positions | ||
.last() | ||
.map_or(2, |last_position| last_position.start + 2); | ||
let start = output_display_len + offset + 2; | ||
let end = start + dfn_len; | ||
update_positions(start, end, dired, true); | ||
} | ||
|
||
/// Updates the dired positions based on the given start and end positions. | ||
/// update when it is the first element in the list (to manage "total X" | ||
/// insert when it isn't the about total | ||
pub fn update_positions(start: usize, end: usize, dired: &mut DiredOutput, adjust: bool) { | ||
if let Some(last_position) = dired.dired_positions.last() { | ||
if last_position.is_total.unwrap_or(false) { | ||
if let Some(last_position) = dired.dired_positions.last_mut() { | ||
*last_position = BytePosition { | ||
start: if adjust { | ||
start + last_position.end | ||
} else { | ||
start | ||
}, | ||
end: if adjust { end + last_position.end } else { end }, | ||
is_total: Some(false), | ||
}; | ||
} | ||
} else { | ||
dired.dired_positions.push(BytePosition { | ||
start, | ||
end, | ||
is_total: None, | ||
}); | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_calculate_dired_byte_positions() { | ||
let output_display = "sample_output".to_string(); | ||
let dfn = "sample_file".to_string(); | ||
let dired_positions = vec![BytePosition { | ||
start: 5, | ||
end: 10, | ||
is_total: None, | ||
}]; | ||
let (start, end) = calculate_dired_byte_positions(&output_display, &dfn, &dired_positions); | ||
assert_eq!(start, 26); | ||
assert_eq!(end, 37); | ||
} | ||
|
||
#[test] | ||
fn test_dired_update_positions() { | ||
let mut dired = DiredOutput { | ||
dired_positions: vec![BytePosition { | ||
start: 5, | ||
end: 10, | ||
is_total: Some(true), | ||
}], | ||
subdired_positions: vec![], | ||
}; | ||
|
||
// Test with adjust = true | ||
update_positions(15, 20, &mut dired, true); | ||
let last_position = dired.dired_positions.last().unwrap(); | ||
assert_eq!(last_position.start, 25); // 15 + 10 (end of the previous position) | ||
assert_eq!(last_position.end, 30); // 20 + 10 (end of the previous position) | ||
assert_eq!(last_position.is_total, Some(false)); | ||
|
||
// Test with adjust = false | ||
update_positions(30, 35, &mut dired, false); | ||
let last_position = dired.dired_positions.last().unwrap(); | ||
assert_eq!(last_position.start, 30); | ||
assert_eq!(last_position.end, 35); | ||
assert_eq!(last_position.is_total, None); | ||
} | ||
} |
Oops, something went wrong.