diff options
author | sushi-shi <47691267+sushi-shi@users.noreply.github.com> | 2022-02-25 19:44:37 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-25 11:44:37 -0500 |
commit | 7c6bb9ca1b3d7fb61a4cfc5c997ae0e247bd5acc (patch) | |
tree | bccb3bd1be460eea8b49d002ecd3c1fc12b1fcab /src | |
parent | 5451fd9865f2a75d623992a072eb639ea20e688f (diff) |
Add reversed autocompletion (#145)
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/views/tui_textfield.rs | 92 |
1 files changed, 54 insertions, 38 deletions
diff --git a/src/ui/views/tui_textfield.rs b/src/ui/views/tui_textfield.rs index 544aede..b2372d4 100644 --- a/src/ui/views/tui_textfield.rs +++ b/src/ui/views/tui_textfield.rs @@ -211,44 +211,18 @@ impl<'a> TuiTextField<'a> { let _ = terminal.hide_cursor(); return None; } - Key::Char('\t') => { - // If we are in the middle of a word, move to the end of it, - // so we don't split it with autocompletion. - move_to_the_end(&mut line_buffer); - - if completion_tracker.is_none() { - if let Some((pos, mut candidates)) = - get_candidates(&completer, &mut line_buffer) - { - candidates.sort_by(|x, y| { - x.display() - .partial_cmp(y.display()) - .unwrap_or(std::cmp::Ordering::Less) - }); - let ct = CompletionTracker::new( - pos, - candidates, - String::from(line_buffer.as_str()), - ); - completion_tracker = Some(ct); - } - } - - if let Some(ref mut s) = completion_tracker { - if !s.candidates.is_empty() { - let candidate = &s.candidates[s.index]; - - completer.update( - &mut line_buffer, - s.pos, - candidate.display(), - ); - - s.index = (s.index + 1) % s.candidates.len(); - } - } - false - } + Key::Char('\t') => autocomplete( + &mut line_buffer, + &mut completion_tracker, + &completer, + false, + ), + Key::BackTab => autocomplete( + &mut line_buffer, + &mut completion_tracker, + &completer, + true, + ), // Current `completion_tracker` should be droped // only if we moved to another word @@ -322,6 +296,48 @@ impl<'a> TuiTextField<'a> { } } +fn autocomplete( + line_buffer: &mut LineBuffer, + completion_tracker: &mut Option<CompletionTracker>, + completer: &FilenameCompleter, + reversed: bool, +) -> bool { + // If we are in the middle of a word, move to the end of it, + // so we don't split it with autocompletion. + move_to_the_end(line_buffer); + + if let Some(ref mut ct) = completion_tracker { + ct.index = if reversed { + ct.index.checked_sub(1).unwrap_or(ct.candidates.len() - 1) + } else { + (ct.index + 1) % ct.candidates.len() + }; + + let candidate = &ct.candidates[ct.index]; + completer.update(line_buffer, ct.pos, candidate.display()); + } else if let Some((pos, mut candidates)) = get_candidates(completer, line_buffer) { + if !candidates.is_empty() { + candidates.sort_by(|x, y| { + x.display() + .partial_cmp(y.display()) + .unwrap_or(std::cmp::Ordering::Less) + }); + + let first_idx = if reversed { candidates.len() - 1 } else { 0 }; + let first = candidates[first_idx].display().to_string(); + + let mut ct = + CompletionTracker::new(pos, candidates, String::from(line_buffer.as_str())); + ct.index = first_idx; + + *completion_tracker = Some(ct); + completer.update(line_buffer, pos, &first); + } + } + + false +} + fn moved_to_another_word<F, Any>(line_buffer: &mut LineBuffer, action: F) -> bool where F: FnOnce(&mut LineBuffer) -> Any, |