summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsushi-shi <47691267+sushi-shi@users.noreply.github.com>2022-02-25 19:44:37 +0300
committerGitHub <noreply@github.com>2022-02-25 11:44:37 -0500
commit7c6bb9ca1b3d7fb61a4cfc5c997ae0e247bd5acc (patch)
treebccb3bd1be460eea8b49d002ecd3c1fc12b1fcab /src
parent5451fd9865f2a75d623992a072eb639ea20e688f (diff)
Add reversed autocompletion (#145)
Diffstat (limited to 'src')
-rw-r--r--src/ui/views/tui_textfield.rs92
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,