tlc: Sprint 3 C10 — Find dialog pre-fills from cursor entry
Previously Find dialog always opened with the default placeholder
('*.rs'). Now open_find_dialog() inspects the active panel's
cursor entry and uses its name as the initial pattern — so
pressing M-? with cursor on 'main.rs' opens the dialog with
'main.rs' already in the input, ready for refinement (e.g.
'main.rs~' for backups, 'main*' for variants).
Implementation:
- find::FindDialog::new_with_pattern(start_dir, initial_pattern)
- panel::Panel::cursor_entry() -> Option<&Entry>
- widget::input::Input::set_text(s) mutable setter (the
existing .text() builder consumes self)
- dialog_ops::open_find_dialog() uses cursor entry name as
the initial pattern; skips '..' and falls back to default
when the panel is empty
Tests (2 new in find::tests):
- new_with_pattern_prefills_pattern_input
- new_with_pattern_empty_falls_back_to_default
Total: 1278 passing (was 1276; +2 new).
This commit is contained in:
@@ -354,10 +354,24 @@ impl FileManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Open the M-? Find dialog.
|
||||
/// Open the M-? Find dialog. The pattern input is pre-filled with
|
||||
/// the cursor entry's name (so searching for the selected file's
|
||||
/// pattern is the default); falls back to the default placeholder
|
||||
/// if the cursor is on `..` or the panel is empty.
|
||||
pub fn open_find_dialog(&mut self) -> Result<()> {
|
||||
let start = self.active_panel().path().to_path_buf();
|
||||
self.dialog = Some(DialogState::Find(Box::new(find::FindDialog::new(start))));
|
||||
let pattern = self
|
||||
.active_panel()
|
||||
.cursor_entry()
|
||||
.map(|e| e.name.clone())
|
||||
.filter(|n| n != "..")
|
||||
.unwrap_or_default();
|
||||
let dialog = if pattern.is_empty() {
|
||||
find::FindDialog::new(start)
|
||||
} else {
|
||||
find::FindDialog::new_with_pattern(start, &pattern)
|
||||
};
|
||||
self.dialog = Some(DialogState::Find(Box::new(dialog)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,8 @@ pub struct FindDialog {
|
||||
}
|
||||
|
||||
impl FindDialog {
|
||||
/// Create a new Find dialog rooted at `start_dir`.
|
||||
/// Create a new Find dialog rooted at `start_dir` with the default
|
||||
/// placeholder pattern ("*.rs").
|
||||
#[must_use]
|
||||
pub fn new(start_dir: PathBuf) -> Self {
|
||||
let pattern = Input::new().label("Find").placeholder("*.rs");
|
||||
@@ -147,6 +148,19 @@ impl FindDialog {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Find dialog rooted at `start_dir` with the
|
||||
/// pattern input pre-filled from the user's current selection
|
||||
/// (e.g. cursor filename). Empty `initial_pattern` falls back to
|
||||
/// the default placeholder.
|
||||
#[must_use]
|
||||
pub fn new_with_pattern(start_dir: PathBuf, initial_pattern: &str) -> Self {
|
||||
let mut dlg = Self::new(start_dir);
|
||||
if !initial_pattern.is_empty() {
|
||||
dlg.pattern.set_text(initial_pattern.to_string());
|
||||
}
|
||||
dlg
|
||||
}
|
||||
|
||||
/// Re-run the search against the current pattern and mode.
|
||||
/// Errors are stored in `last_error` rather than propagated, so
|
||||
/// the dialog stays interactive even when the user types an
|
||||
@@ -779,4 +793,18 @@ mod tests {
|
||||
.expect("render must not panic");
|
||||
let _ = fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_with_pattern_prefills_pattern_input() {
|
||||
let d = FindDialog::new_with_pattern(PathBuf::from("/tmp"), "foo.rs");
|
||||
assert_eq!(d.pattern.value(), "foo.rs");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_with_pattern_empty_falls_back_to_default() {
|
||||
let d = FindDialog::new_with_pattern(PathBuf::from("/tmp"), "");
|
||||
// Empty pattern leaves the input at the default placeholder
|
||||
// (".value()" returns empty when no text was set).
|
||||
assert_eq!(d.pattern.value(), "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +260,13 @@ impl Panel {
|
||||
&self.entries
|
||||
}
|
||||
|
||||
/// Entry under the cursor, or `None` if the cursor is past the
|
||||
/// end of the entry list.
|
||||
#[must_use]
|
||||
pub fn cursor_entry(&self) -> Option<&Entry> {
|
||||
self.entries.get(self.cursor)
|
||||
}
|
||||
|
||||
/// Current status message.
|
||||
#[must_use]
|
||||
pub fn message(&self) -> Option<&str> {
|
||||
|
||||
@@ -99,6 +99,13 @@ impl Input {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the current text (mutable setter, used to pre-fill the
|
||||
/// input after construction). Cursor moves to the end.
|
||||
pub fn set_text(&mut self, s: impl Into<String>) {
|
||||
self.text = s.into();
|
||||
self.cursor = self.text.chars().count();
|
||||
}
|
||||
|
||||
/// Mark the input as focused.
|
||||
#[must_use]
|
||||
pub fn focused(mut self) -> Self {
|
||||
|
||||
Reference in New Issue
Block a user