Skip to content

Commit 17d4e4f

Browse files
authored
Merge pull request #6399 from tertsdiepraam/more-mem-usage
`more`: reduce memory usage a bit
2 parents 843c0c2 + c1f82b1 commit 17d4e4f

File tree

1 file changed

+41
-65
lines changed

1 file changed

+41
-65
lines changed

src/uu/more/src/more.rs

Lines changed: 41 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
9898
println!("{panic_info}");
9999
}));
100100

101-
let matches = match uu_app().try_get_matches_from(args) {
102-
Ok(m) => m,
103-
Err(e) => return Err(e.into()),
104-
};
101+
let matches = uu_app().try_get_matches_from(args)?;
105102

106103
let mut options = Options::from(&matches);
107104

@@ -308,12 +305,12 @@ fn more(
308305
rows = number;
309306
}
310307

311-
let lines = break_buff(buff, usize::from(cols));
308+
let lines = break_buff(buff, cols as usize);
312309

313310
let mut pager = Pager::new(rows, lines, next_file, options);
314311

315-
if options.pattern.is_some() {
316-
match search_pattern_in_file(&pager.lines, &options.pattern) {
312+
if let Some(pat) = options.pattern.as_ref() {
313+
match search_pattern_in_file(&pager.lines, pat) {
317314
Some(number) => pager.upper_mark = number,
318315
None => {
319316
execute!(stdout, terminal::Clear(terminal::ClearType::CurrentLine))?;
@@ -446,8 +443,8 @@ struct Pager<'a> {
446443
// The current line at the top of the screen
447444
upper_mark: usize,
448445
// The number of rows that fit on the screen
449-
content_rows: u16,
450-
lines: Vec<String>,
446+
content_rows: usize,
447+
lines: Vec<&'a str>,
451448
next_file: Option<&'a str>,
452449
line_count: usize,
453450
silent: bool,
@@ -456,11 +453,11 @@ struct Pager<'a> {
456453
}
457454

458455
impl<'a> Pager<'a> {
459-
fn new(rows: u16, lines: Vec<String>, next_file: Option<&'a str>, options: &Options) -> Self {
456+
fn new(rows: u16, lines: Vec<&'a str>, next_file: Option<&'a str>, options: &Options) -> Self {
460457
let line_count = lines.len();
461458
Self {
462459
upper_mark: options.from_line,
463-
content_rows: rows.saturating_sub(1),
460+
content_rows: rows.saturating_sub(1) as usize,
464461
lines,
465462
next_file,
466463
line_count,
@@ -472,30 +469,25 @@ impl<'a> Pager<'a> {
472469

473470
fn should_close(&mut self) -> bool {
474471
self.upper_mark
475-
.saturating_add(self.content_rows.into())
472+
.saturating_add(self.content_rows)
476473
.ge(&self.line_count)
477474
}
478475

479476
fn page_down(&mut self) {
480477
// If the next page down position __after redraw__ is greater than the total line count,
481478
// the upper mark must not grow past top of the screen at the end of the open file.
482-
if self
483-
.upper_mark
484-
.saturating_add(self.content_rows as usize * 2)
485-
.ge(&self.line_count)
486-
{
487-
self.upper_mark = self.line_count - self.content_rows as usize;
479+
if self.upper_mark.saturating_add(self.content_rows * 2) >= self.line_count {
480+
self.upper_mark = self.line_count - self.content_rows;
488481
return;
489482
}
490483

491-
self.upper_mark = self.upper_mark.saturating_add(self.content_rows.into());
484+
self.upper_mark = self.upper_mark.saturating_add(self.content_rows);
492485
}
493486

494487
fn page_up(&mut self) {
495-
let content_row_usize: usize = self.content_rows.into();
496488
self.upper_mark = self
497489
.upper_mark
498-
.saturating_sub(content_row_usize.saturating_add(self.line_squeezed));
490+
.saturating_sub(self.content_rows.saturating_add(self.line_squeezed));
499491

500492
if self.squeeze {
501493
let iter = self.lines.iter().take(self.upper_mark).rev();
@@ -520,15 +512,15 @@ impl<'a> Pager<'a> {
520512
// TODO: Deal with column size changes.
521513
fn page_resize(&mut self, _: u16, row: u16, option_line: Option<u16>) {
522514
if option_line.is_none() {
523-
self.content_rows = row.saturating_sub(1);
515+
self.content_rows = row.saturating_sub(1) as usize;
524516
};
525517
}
526518

527519
fn draw(&mut self, stdout: &mut std::io::Stdout, wrong_key: Option<char>) {
528520
self.draw_lines(stdout);
529521
let lower_mark = self
530522
.line_count
531-
.min(self.upper_mark.saturating_add(self.content_rows.into()));
523+
.min(self.upper_mark.saturating_add(self.content_rows));
532524
self.draw_prompt(stdout, lower_mark, wrong_key);
533525
stdout.flush().unwrap();
534526
}
@@ -541,7 +533,7 @@ impl<'a> Pager<'a> {
541533
let mut displayed_lines = Vec::new();
542534
let mut iter = self.lines.iter().skip(self.upper_mark);
543535

544-
while displayed_lines.len() < self.content_rows as usize {
536+
while displayed_lines.len() < self.content_rows {
545537
match iter.next() {
546538
Some(line) => {
547539
if self.squeeze {
@@ -608,13 +600,12 @@ impl<'a> Pager<'a> {
608600
}
609601
}
610602

611-
fn search_pattern_in_file(lines: &[String], pattern: &Option<String>) -> Option<usize> {
612-
let pattern = pattern.clone().unwrap_or_default();
603+
fn search_pattern_in_file(lines: &[&str], pattern: &str) -> Option<usize> {
613604
if lines.is_empty() || pattern.is_empty() {
614605
return None;
615606
}
616607
for (line_number, line) in lines.iter().enumerate() {
617-
if line.contains(pattern.as_str()) {
608+
if line.contains(pattern) {
618609
return Some(line_number);
619610
}
620611
}
@@ -630,20 +621,22 @@ fn paging_add_back_message(options: &Options, stdout: &mut std::io::Stdout) -> U
630621
}
631622

632623
// Break the lines on the cols of the terminal
633-
fn break_buff(buff: &str, cols: usize) -> Vec<String> {
634-
let mut lines = Vec::with_capacity(buff.lines().count());
624+
fn break_buff(buff: &str, cols: usize) -> Vec<&str> {
625+
// We _could_ do a precise with_capacity here, but that would require scanning the
626+
// whole buffer. Just guess a value instead.
627+
let mut lines = Vec::with_capacity(2048);
635628

636629
for l in buff.lines() {
637630
lines.append(&mut break_line(l, cols));
638631
}
639632
lines
640633
}
641634

642-
fn break_line(line: &str, cols: usize) -> Vec<String> {
635+
fn break_line(line: &str, cols: usize) -> Vec<&str> {
643636
let width = UnicodeWidthStr::width(line);
644637
let mut lines = Vec::new();
645638
if width < cols {
646-
lines.push(line.to_string());
639+
lines.push(line);
647640
return lines;
648641
}
649642

@@ -655,14 +648,14 @@ fn break_line(line: &str, cols: usize) -> Vec<String> {
655648
total_width += width;
656649

657650
if total_width > cols {
658-
lines.push(line[last_index..index].to_string());
651+
lines.push(&line[last_index..index]);
659652
last_index = index;
660653
total_width = width;
661654
}
662655
}
663656

664657
if last_index != line.len() {
665-
lines.push(line[last_index..].to_string());
658+
lines.push(&line[last_index..]);
666659
}
667660
lines
668661
}
@@ -721,49 +714,32 @@ mod tests {
721714
#[test]
722715
fn test_search_pattern_empty_lines() {
723716
let lines = vec![];
724-
let pattern = Some(String::from("pattern"));
725-
assert_eq!(None, search_pattern_in_file(&lines, &pattern));
717+
let pattern = "pattern";
718+
assert_eq!(None, search_pattern_in_file(&lines, pattern));
726719
}
727720

728721
#[test]
729722
fn test_search_pattern_empty_pattern() {
730-
let lines = vec![String::from("line1"), String::from("line2")];
731-
let pattern = None;
732-
assert_eq!(None, search_pattern_in_file(&lines, &pattern));
723+
let lines = vec!["line1", "line2"];
724+
let pattern = "";
725+
assert_eq!(None, search_pattern_in_file(&lines, pattern));
733726
}
734727

735728
#[test]
736729
fn test_search_pattern_found_pattern() {
737-
let lines = vec![
738-
String::from("line1"),
739-
String::from("line2"),
740-
String::from("pattern"),
741-
];
742-
let lines2 = vec![
743-
String::from("line1"),
744-
String::from("line2"),
745-
String::from("pattern"),
746-
String::from("pattern2"),
747-
];
748-
let lines3 = vec![
749-
String::from("line1"),
750-
String::from("line2"),
751-
String::from("other_pattern"),
752-
];
753-
let pattern = Some(String::from("pattern"));
754-
assert_eq!(2, search_pattern_in_file(&lines, &pattern).unwrap());
755-
assert_eq!(2, search_pattern_in_file(&lines2, &pattern).unwrap());
756-
assert_eq!(2, search_pattern_in_file(&lines3, &pattern).unwrap());
730+
let lines = vec!["line1", "line2", "pattern"];
731+
let lines2 = vec!["line1", "line2", "pattern", "pattern2"];
732+
let lines3 = vec!["line1", "line2", "other_pattern"];
733+
let pattern = "pattern";
734+
assert_eq!(2, search_pattern_in_file(&lines, pattern).unwrap());
735+
assert_eq!(2, search_pattern_in_file(&lines2, pattern).unwrap());
736+
assert_eq!(2, search_pattern_in_file(&lines3, pattern).unwrap());
757737
}
758738

759739
#[test]
760740
fn test_search_pattern_not_found_pattern() {
761-
let lines = vec![
762-
String::from("line1"),
763-
String::from("line2"),
764-
String::from("something"),
765-
];
766-
let pattern = Some(String::from("pattern"));
767-
assert_eq!(None, search_pattern_in_file(&lines, &pattern));
741+
let lines = vec!["line1", "line2", "something"];
742+
let pattern = "pattern";
743+
assert_eq!(None, search_pattern_in_file(&lines, pattern));
768744
}
769745
}

0 commit comments

Comments
 (0)