tlc: Sprint 3 C9 — empty pattern inverts/clears marks

Previously mark_pattern("") and unmark_pattern("") were silent
no-ops (glob_match returned false for empty pattern). Now they
match MC's behavior:
  - mark_pattern(""): calls reverse_marks() (toggles every
    entry; from 0 marks → all entries marked, vice versa)
  - unmark_pattern(""): clears all marks

Tests (2 new in panel::tests):
  - mark_pattern_empty_inverts_marks (0→2→0 cycle)
  - unmark_pattern_empty_clears_all_marks

Total: 1276 passing (was 1274; +2 new).
This commit is contained in:
kellito
2026-07-05 18:10:55 +03:00
parent ab2d5de81d
commit 790e476d8e
@@ -424,8 +424,14 @@ impl Panel {
}
}
/// Mark entries matching `pattern` (Unix glob).
/// Mark entries matching `pattern` (Unix glob). An empty pattern
/// marks every regular entry (skipping `..`), matching MC's
/// "Select group" behavior with an empty expression.
pub fn mark_pattern(&mut self, pattern: &str) {
if pattern.is_empty() {
self.reverse_marks();
return;
}
for e in &self.entries {
if glob_match(pattern, &e.name) {
self.marked.insert(e.name.clone());
@@ -433,8 +439,14 @@ impl Panel {
}
}
/// Unmark entries matching `pattern` (Unix glob).
/// Unmark entries matching `pattern` (Unix glob). An empty
/// pattern clears every mark (matching MC's "Unselect group"
/// with an empty expression).
pub fn unmark_pattern(&mut self, pattern: &str) {
if pattern.is_empty() {
self.marked.clear();
return;
}
let to_remove: Vec<String> = self
.entries
.iter()
@@ -1238,6 +1250,40 @@ mod tests {
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn mark_pattern_empty_inverts_marks() {
let dir = std::env::temp_dir().join("tlc-panel-mark-empty-test");
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).unwrap();
fs::write(dir.join("a.txt"), b"x").unwrap();
fs::write(dir.join("b.txt"), b"x").unwrap();
let mut p = Panel::new(&dir, &empty_cfg()).unwrap();
// Empty pattern inverts: from 0 marks → all entries marked
// (skipping '..').
p.mark_pattern("");
assert_eq!(p.marked_count(), 2);
// Apply again: 2 marks → 0 marks.
p.mark_pattern("");
assert_eq!(p.marked_count(), 0);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn unmark_pattern_empty_clears_all_marks() {
let dir = std::env::temp_dir().join("tlc-panel-unmark-empty-test");
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).unwrap();
fs::write(dir.join("a.txt"), b"x").unwrap();
fs::write(dir.join("b.txt"), b"x").unwrap();
let mut p = Panel::new(&dir, &empty_cfg()).unwrap();
p.mark_pattern("*.txt");
assert_eq!(p.marked_count(), 2);
// Empty pattern clears every mark.
p.unmark_pattern("");
assert_eq!(p.marked_count(), 0);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn test_is_archive_extension_tar() {
assert_eq!(is_archive_extension("foo.tar"), Some("tar"));