Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion feature #403

Merged
merged 2 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions crates/shrs_core/src/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use thiserror::Error;

/// Trait to implement for shell history
pub trait History {
fn iter(&self) -> Box<dyn Iterator<Item = &String> + '_>;
/// Insert item into shell history
fn add(&mut self, cmd: String);
/// Remove all history entries
Expand Down Expand Up @@ -62,6 +63,10 @@ impl History for DefaultHistory {
fn get(&self, i: usize) -> Option<&String> {
self.hist.get(i)
}

fn iter(&self) -> Box<dyn Iterator<Item = &String> + '_> {
Box::new(self.hist.iter())
}
}

/// Store the history persistently in a file on disk
Expand Down Expand Up @@ -148,6 +153,10 @@ impl History for FileBackedHistory {
fn get(&self, i: usize) -> Option<&String> {
self.hist.get(i)
}

fn iter(&self) -> Box<dyn Iterator<Item = &String> + '_> {
Box::new(self.hist.iter())
}
}

fn parse_history_file(hist_file: PathBuf) -> Result<Vec<String>, FileBackedHistoryError> {
Expand Down
26 changes: 25 additions & 1 deletion crates/shrs_core/src/readline/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use ::crossterm::{
style::{Color, ContentStyle},
terminal::{disable_raw_mode, enable_raw_mode},
};
use clap::builder;
use shrs_utils::{
cursor_buffer::{CursorBuffer, Location},
styled_buf::StyledBuf,
Expand Down Expand Up @@ -112,7 +113,7 @@ impl LineState {
}

/// Get the contents of the prompt
fn get_full_command(&self) -> String {
pub fn get_full_command(&self) -> String {
let mut res: String = self.lines.clone();
let cur_line: String = self.cb.as_str().into();
res += cur_line.as_str();
Expand Down Expand Up @@ -173,6 +174,9 @@ pub struct Line {
#[builder(default = "String::new()")]
#[builder(setter(skip))]
normal_keys: String,

#[builder(default = "Box::new(DefaultSuggester)")]
suggester: Box<dyn Suggester>,
}

impl Default for Line {
Expand Down Expand Up @@ -255,6 +259,12 @@ impl Line {
},
);
}
} else {
// get search results from history and suggest the first result
if let Some(suggestion) = self.suggester.suggest(state) {
let trimmed_selection = suggestion[res.len()..].to_string();
styled_buf.push(trimmed_selection.as_str(), state.sh.theme.suggestion_style);
}
}

self.painter.paint(
Expand Down Expand Up @@ -387,6 +397,20 @@ impl Line {

return Ok(true);
},
// Insert suggestion when right arrow
Event::Key(KeyEvent {
code: KeyCode::Right,
modifiers: KeyModifiers::NONE,
..
}) => {
if let Some(suggestion) = self.suggester.suggest(state) {
state.line.cb.clear();
state
.line
.cb
.insert(Location::Cursor(), suggestion.as_str())?;
}
},

Event::Key(KeyEvent {
code: KeyCode::Enter,
Expand Down
2 changes: 2 additions & 0 deletions crates/shrs_core/src/readline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod line;
pub mod menu;
pub mod painter;
pub mod prompt;
pub mod suggester;
pub mod vi;

pub use buffer_history::{BufferHistory, DefaultBufferHistory};
Expand All @@ -31,4 +32,5 @@ pub use hooks::*;
pub use line::{Line, LineBuilder, LineBuilderError, LineMode, LineStateBundle, Readline};
pub use menu::{DefaultMenu, Menu};
pub use prompt::{DefaultPrompt, Prompt, *};
pub use suggester::{DefaultSuggester, Suggester};
pub use vi::*;
22 changes: 22 additions & 0 deletions crates/shrs_core/src/readline/suggester.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use super::line::LineStateBundle;

pub trait Suggester {
fn suggest(&self, line_ctx: &LineStateBundle) -> Option<String>;
}
pub struct DefaultSuggester;
impl Suggester for DefaultSuggester {
fn suggest(&self, line_ctx: &LineStateBundle) -> Option<String> {
let h = &line_ctx.ctx.history;
let res = line_ctx.line.get_full_command();
if res.is_empty() {
return None;
}

for s in h.iter() {
if s.starts_with(&res) {
return Some(s.to_owned());
}
}
None
}
}
2 changes: 2 additions & 0 deletions crates/shrs_core/src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub struct Theme {
pub err_style: ContentStyle,
pub selection_style: ContentStyle,
pub completion_style: ContentStyle,
pub suggestion_style: ContentStyle,
}

impl Default for Theme {
Expand All @@ -16,6 +17,7 @@ impl Default for Theme {
err_style: ContentStyle::new().red(),
selection_style: ContentStyle::new().white(),
completion_style: ContentStyle::new().red(),
suggestion_style: ContentStyle::new().dark_grey(),
}
}
}