Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions src/uu/ptx/src/ptx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use std::cmp;
use std::cmp::PartialEq;
use std::collections::{BTreeSet, HashMap, HashSet};
use std::collections::{BTreeSet, HashSet};
use std::ffi::{OsStr, OsString};
use std::fmt::Write as FmtWrite;
use std::fs::File;
Expand Down Expand Up @@ -269,10 +269,10 @@ struct FileContent {
offset: usize,
}

type FileMap = HashMap<OsString, FileContent>;
type FileMap = Vec<(OsString, FileContent)>;

fn read_input(input_files: &[OsString]) -> std::io::Result<FileMap> {
let mut file_map: FileMap = HashMap::new();
let mut file_map: FileMap = FileMap::new();
let mut offset: usize = 0;
for filename in input_files {
let reader: BufReader<Box<dyn Read>> = BufReader::new(if filename == "-" {
Expand All @@ -287,14 +287,14 @@ fn read_input(input_files: &[OsString]) -> std::io::Result<FileMap> {
// Since we will be jumping around the line a lot, we dump the content into a Vec<char>, which can be indexed in constant time.
let chars_lines: Vec<Vec<char>> = lines.iter().map(|x| x.chars().collect()).collect();
let size = lines.len();
file_map.insert(
file_map.push((
filename.clone(),
FileContent {
lines,
chars_lines,
offset,
},
);
));
offset += size;
}
Ok(file_map)
Expand Down Expand Up @@ -751,8 +751,17 @@ fn write_traditional_output(
}

for word_ref in words {
let file_map_value: &FileContent = file_map
.get(&word_ref.filename)
// Since `ptx` accepts duplicate file arguments (e.g., `ptx file file`),
// simply looking up by filename is ambiguous.
// We use the `global_line_nr` (which is unique across the entire input stream)
// to identify which file covers this line.
let (_, file_map_value) = file_map
.iter()
.find(|(name, content)| {
name == &word_ref.filename
&& word_ref.global_line_nr >= content.offset
&& word_ref.global_line_nr < content.offset + content.lines.len()
})
.expect("Missing file in file map");
let FileContent {
ref lines,
Expand Down
8 changes: 8 additions & 0 deletions tests/by-util/test_ptx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,11 @@ fn test_unicode_truncation_alignment() {
.succeeds()
.stdout_only(" / bar\n föö/\n");
}

#[test]
fn test_duplicate_input_files() {
new_ucmd!()
.args(&["one_word", "one_word"])
.succeeds()
.stdout_is(" rust\n rust\n");
}
1 change: 1 addition & 0 deletions tests/fixtures/ptx/one_word
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rust
Loading