Repository: cantino/mcfly (language: rust)

Issue:
Feature Request: Switch sort mode LAST RUN and RANK by using menu's interface
 It's more convenient to use hot key to switch to different mode if current history output doesn't provide suitable results


Discussion / hints:
Good suggestion, thanks @em2er 
I would like to work on this issue.
I have made the necessary changes, but I have a few questions.

I have decided to use F(1) for the keybinding, can use a different one if need be.
So the interface looks like:

```rust
    fn text(&self, interface: &Interface) -> &str {
        match *self {
            MenuMode::Normal => match interface.settings.key_scheme {
                KeyScheme::Emacs => {
                    "McFly | ESC - Exit | ⏎ - Run | TAB - Edit | **F1 - Switch** | F2 - Delete"
                }
                KeyScheme::Vim => {
                    if interface.in_vim_insert_mode {
                        "McFly (Ins) | ESC - Cmd  | ⏎ - Run | TAB - Edit | **F1 - Switch** | F2 - Delete"
                    } else {
                        "McFly (Cmd) | ESC - Exit | ⏎ - Run | TAB - Edit | **F1 - Switch** | F2 - Delete"
                    }
                }
            },
            MenuMode::ConfirmDelete => "Delete selected command from the history? (Y/N)",
        }
    }
```

Right now the command is called **Switch** (as a placeholder, only included the * to make it standout)
- What would be a more appropriate name? Change Sort? Result Sort? Other suggestions?

Also, after testing, I feel like there should be some type of feedback for the user to know which result sort they are currently using. 
- Any ideas of implementing said feedback?

Finally, when the user does switch to the different result sort, they have to enter a new key into the input to see the different results. I do not know if it is possible to instant refresh, if it is, I would be more than happy to try an implement it, but it may be out of scope of my knowledge of rust.
> What would be a more appropriate name? Change Sort? Result Sort? Other suggestions?  

According to current sort mode it can be like:
F1 - Sort by Rank
F1 - Sort by Time
Or maybe `F1 - Sort (Rank)` or `F1 - Sort (Time)`, so it visually changes when you press F1?

Fix patch:
diff --git a/src/interface.rs b/src/interface.rs
index 821026a0..364ccb75 100644
--- a/src/interface.rs
+++ b/src/interface.rs
@@ -4,8 +4,8 @@ use crate::history::History;
 use crate::fixed_length_grapheme_string::FixedLengthGraphemeString;
 use crate::history::Command;
 use crate::history_cleaner;
-use crate::settings::Settings;
 use crate::settings::{InterfaceView, KeyScheme};
+use crate::settings::{ResultSort, Settings};
 use chrono::{Duration, TimeZone, Utc};
 use humantime::format_duration;
 use std::io::{stdin, stdout, Write};
@@ -27,6 +27,7 @@ pub struct Interface<'a> {
     delete_requests: Vec<String>,
     menu_mode: MenuMode,
     in_vim_insert_mode: bool,
+    result_sort: ResultSort,
 }
 
 pub struct SelectionResult {
@@ -50,20 +51,33 @@ pub enum MenuMode {
 }
 
 impl MenuMode {
-    fn text(&self, interface: &Interface) -> &str {
+    fn text(&self, interface: &Interface) -> String {
+        let mut menu_text = String::from("McFly");
         match *self {
             MenuMode::Normal => match interface.settings.key_scheme {
-                KeyScheme::Emacs => "McFly | ESC - Exit | ⏎ - Run | TAB - Edit | F2 - Delete",
+                KeyScheme::Emacs => menu_text.push_str(" | ESC - Exit | "),
                 KeyScheme::Vim => {
                     if interface.in_vim_insert_mode {
-                        "McFly (Ins) | ESC - Cmd  | ⏎ - Run | TAB - Edit | F2 - Delete"
+                        menu_text.push_str(" (Ins) | ESC - Cmd | ");
                     } else {
-                        "McFly (Cmd) | ESC - Exit | ⏎ - Run | TAB - Edit | F2 - Delete"
+                        menu_text.push_str(" (Cmd) | ESC - Exit | ");
                     }
                 }
             },
-            MenuMode::ConfirmDelete => "Delete selected command from the history? (Y/N)",
+            MenuMode::ConfirmDelete => {
+                return String::from("Delete selected command from the history? (Y/N)")
+            }
+        }
+
+        menu_text.push_str("⏎ - Run | TAB - Edit | ");
+
+        match interface.result_sort {
+            ResultSort::Rank => menu_text.push_str("F1 - Sort (Time) | "),
+            ResultSort::LastRun => menu_text.push_str("F1 - Sort (Rank) | "),
         }
+
+        menu_text.push_str("F2 - Delete");
+        menu_text
     }
 
     fn bg(&self) -> String {
@@ -91,6 +105,7 @@ impl<'a> Interface<'a> {
             delete_requests: Vec::new(),
             menu_mode: MenuMode::Normal,
             in_vim_insert_mode: true,
+            result_sort: settings.result_sort.to_owned(),
         }
     }
 
@@ -381,10 +396,17 @@ impl<'a> Interface<'a> {
             &self.input.command,
             self.settings.results as i16,
             self.settings.fuzzy,
-            &self.settings.result_sort,
+            &self.result_sort,
         );
     }
 
+    fn switch_result_sort(&mut self) {
+        match self.result_sort {
+            ResultSort::Rank => self.result_sort = ResultSort::LastRun,
+            ResultSort::LastRun => self.result_sort = ResultSort::Rank,
+        }
+    }
+
     fn select(&mut self) {
         let stdin = stdin();
         let mut screen = AlternateScreen::from(stdout().into_raw_mode().unwrap());
@@ -497,6 +519,10 @@ impl<'a> Interface<'a> {
                 self.input.insert(c);
                 self.refresh_matches();
             }
+            Key::F(1) => {
+                self.switch_result_sort();
+                self.refresh_matches();
+            }
             Key::F(2) => {
                 if !self.matches.is_empty() {
                     if self.settings.delete_without_confirm {
@@ -553,6 +579,10 @@ impl<'a> Interface<'a> {
                     self.input.insert(c);
                     self.refresh_matches();
                 }
+                Key::F(1) => {
+                    self.switch_result_sort();
+                    self.refresh_matches();
+                }
                 Key::F(2) => {
                     if !self.matches.is_empty() {
                         if self.settings.delete_without_confirm {
@@ -621,6 +651,10 @@ impl<'a> Interface<'a> {
                 Key::Char(_c) => {
 
                 }
+                Key::F(1) => {
+                    self.switch_result_sort();
+                    self.refresh_matches();
+                },
                 Key::F(2) => {
                     if !self.matches.is_empty() {
                         if self.settings.delete_without_confirm {
diff --git a/src/settings.rs b/src/settings.rs
index 316af366..0dc4cacf 100644
--- a/src/settings.rs
+++ b/src/settings.rs
@@ -37,7 +37,7 @@ pub enum InterfaceView {
     Bottom,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub enum ResultSort {
     Rank,
     LastRun,


Test patch: