Skip to content

Commit

Permalink
added path suggestions when trying to open a file
Browse files Browse the repository at this point in the history
  • Loading branch information
curlpipe committed Oct 6, 2024
1 parent 7cb828e commit d0d1f52
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 3 deletions.
46 changes: 46 additions & 0 deletions kaolinite/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,52 @@ pub fn get_file_ext(path: &str) -> Option<String> {
.map(std::string::ToString::to_string)
}

/// Will get the current working directory
#[must_use]
#[cfg(not(tarpaulin_include))]
pub fn get_cwd() -> Option<String> {
Some(std::env::current_dir().ok()?.display().to_string())
}

/// Will list a directory
#[must_use]
#[cfg(not(tarpaulin_include))]
pub fn list_dir(path: &str) -> Option<Vec<String>> {
Some(
std::fs::read_dir(path)
.ok()?
.filter_map(std::result::Result::ok)
.filter_map(|e| e.path().to_str().map(std::string::ToString::to_string))
.collect(),
)
}

/// Get the parent directory
#[must_use]
#[cfg(not(tarpaulin_include))]
pub fn get_parent(path: &str) -> Option<String> {
Path::new(path).parent().map(|p| p.display().to_string())
}

/// Determine if something is a directory or a file
#[must_use]
#[cfg(not(tarpaulin_include))]
pub fn file_or_dir(path: &str) -> &str {
let path = Path::new(path);
let metadata = std::fs::metadata(path);
if let Ok(metadata) = metadata {
if metadata.is_file() {
"file"
} else if metadata.is_dir() {
"directory"
} else {
"neither"
}
} else {
"neither"
}
}

/// Determine the filetype from the extension
#[allow(clippy::too_many_lines)]
#[must_use]
Expand Down
70 changes: 68 additions & 2 deletions src/editor/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use crate::ui::{size, Feedback};
use crossterm::{
event::{read, Event as CEvent, KeyCode as KCode, KeyModifiers as KMod},
queue,
style::{Attribute, Print, SetAttribute, SetBackgroundColor as Bg, SetForegroundColor as Fg},
style::{
Attribute, Color, Print, SetAttribute, SetBackgroundColor as Bg, SetForegroundColor as Fg,
},
};
use kaolinite::utils::{width, Loc, Size};
use kaolinite::utils::{file_or_dir, get_cwd, get_parent, list_dir, width, Loc, Size};
use mlua::Lua;
use synoptic::{trim, Highlighter, TokOpt};

Expand Down Expand Up @@ -262,6 +264,70 @@ impl Editor {
Ok(input)
}

/// Prompt for selecting a file
pub fn path_prompt(&mut self) -> Result<String> {
let mut input = get_cwd().map(|s| s + "/").unwrap_or_default();
let mut done = false;
// Enter into a menu that asks for a prompt
while !done {
// Find the suggested file / folder
let parent = if input.ends_with('/') {
input.to_string()
} else {
get_parent(&input).unwrap_or_default()
};
let mut suggestion = list_dir(&parent)
.unwrap_or_default()
.iter()
.find(|p| p.starts_with(&input))
.map(std::string::ToString::to_string)
.unwrap_or(input.clone());
// Render prompt message
let h = size()?.h;
self.terminal.prepare_line(h)?;
self.terminal.show_cursor()?;
let suggestion_text = suggestion
.chars()
.skip(input.chars().count())
.collect::<String>();
let editor_fg = Fg(self.config.colors.borrow().editor_fg.to_color()?);
display!(
self,
"Path: ",
input.clone(),
Fg(Color::DarkGrey),
suggestion_text,
editor_fg
);
let tab_width = self.config.document.borrow_mut().tab_width;
self.terminal.goto(6 + width(&input, tab_width), h)?;
self.terminal.flush()?;
// Handle events
if let CEvent::Key(key) = read()? {
match (key.modifiers, key.code) {
// Exit the menu when the enter key is pressed
(KMod::NONE, KCode::Enter) => done = true,
// Remove from the input string if the user presses backspace
(KMod::NONE, KCode::Backspace) => {
input.pop();
}
// Add to the input string if the user presses a character
(KMod::NONE | KMod::SHIFT, KCode::Char(c)) => input.push(c),
// Autocomplete path
(KMod::NONE, KCode::Right | KCode::Tab) => {
if file_or_dir(&suggestion) == "directory" {
suggestion += "/";
}
input = suggestion;
}
_ => (),
}
}
}
// Return input string result
Ok(input)
}

/// Confirmation dialog
pub fn confirm(&mut self, msg: &str) -> Result<bool> {
let mut done = false;
Expand Down
2 changes: 1 addition & 1 deletion src/editor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl Editor {

/// Function to ask the user for a file to open
pub fn open_document(&mut self) -> Result<()> {
let path = self.prompt("File to open")?;
let path = self.path_prompt()?;
self.open(&path)?;
self.ptr = self.doc.len().saturating_sub(1);
Ok(())
Expand Down

0 comments on commit d0d1f52

Please sign in to comment.