-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Support ls --dired #5280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Support ls --dired #5280
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
65559d4
Support ls --dired
sylvestre dd65685
stat-failed.sh: update of the test - we have a small difference
sylvestre a8c2b75
ls --dired: address some of the comments
sylvestre af4a91a
fix warnings
sylvestre 74f1890
use unwrap()
sylvestre 00290a0
Improve test
sylvestre ffedba1
Simplify test
sylvestre 48769c1
Remove a word from the spell ignore
sylvestre 2816df7
remove duplication of the spell ignore
sylvestre 15a78e0
Merge branch 'main' into perm
sylvestre 568fa33
rustfmt
sylvestre File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,178 @@ | ||
// 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 | ||
|
||
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, | ||
} | ||
|
||
/// 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>, | ||
pub just_printed_total: bool, | ||
} | ||
|
||
impl fmt::Display for BytePosition { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{} {}", self.start, self.end) | ||
} | ||
} | ||
|
||
// When --dired is used, all lines starts with 2 spaces | ||
static DIRED_TRAILING_OFFSET: usize = 2; | ||
|
||
/// Calculates the byte positions for DIRED | ||
pub fn calculate_dired_byte_positions( | ||
output_display_len: usize, | ||
dfn_len: usize, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Display File Name we should rename it (it is from ls.rs) |
||
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 start = output_display_len + offset_from_previous_line; | ||
let end = start + dfn_len; | ||
(start, end) | ||
} | ||
|
||
pub fn indent(out: &mut BufWriter<Stdout>) -> UResult<()> { | ||
write!(out, " ")?; | ||
Ok(()) | ||
} | ||
|
||
pub fn calculate_offset_and_push(dired: &mut DiredOutput, path_len: usize) { | ||
let offset = if dired.subdired_positions.is_empty() { | ||
DIRED_TRAILING_OFFSET | ||
} else { | ||
dired.subdired_positions[dired.subdired_positions.len() - 1].start + DIRED_TRAILING_OFFSET | ||
}; | ||
dired.subdired_positions.push(BytePosition { | ||
start: offset, | ||
end: path_len + offset, | ||
}); | ||
} | ||
|
||
/// 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.just_printed_total { | ||
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!(); | ||
} | ||
|
||
pub fn add_total(total_len: usize, dired: &mut DiredOutput) { | ||
dired.just_printed_total = true; | ||
dired.dired_positions.push(BytePosition { | ||
start: 0, | ||
// the 2 is from the trailing spaces | ||
// the 1 is from the line ending (\n) | ||
end: total_len + DIRED_TRAILING_OFFSET - 1, | ||
}); | ||
} | ||
|
||
/// 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(DIRED_TRAILING_OFFSET, |last_position| { | ||
last_position.start + DIRED_TRAILING_OFFSET | ||
}); | ||
let start = output_display_len + offset + DIRED_TRAILING_OFFSET; | ||
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 dired.just_printed_total { | ||
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 }, | ||
}; | ||
dired.just_printed_total = false; | ||
} | ||
} else { | ||
dired.dired_positions.push(BytePosition { start, end }); | ||
} | ||
} | ||
|
||
#[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 }]; | ||
let (start, end) = | ||
calculate_dired_byte_positions(output_display.len(), dfn.len(), &dired_positions); | ||
|
||
assert_eq!(start, 24); | ||
assert_eq!(end, 35); | ||
} | ||
|
||
#[test] | ||
fn test_dired_update_positions() { | ||
let mut dired = DiredOutput { | ||
dired_positions: vec![BytePosition { start: 5, end: 10 }], | ||
subdired_positions: vec![], | ||
just_printed_total: true, | ||
}; | ||
|
||
// 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) | ||
|
||
// 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); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm struggling with this field, it somehow doesn't fit to the other fields because it doesn't contain any data like the other fields. Though I don't know where it should be instead :|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i used to have it in BytePosition but terts didn't like it and suggested this place :)
However, I would not overthink this, this feature is probably not used much and won't get many updates