Skip to content

Commit

Permalink
feat: create new empty doc with ' o'
Browse files Browse the repository at this point in the history
  • Loading branch information
justinpombrio committed Dec 1, 2024
1 parent 62cfc4a commit e9a50d4
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 14 deletions.
3 changes: 3 additions & 0 deletions scripts/init.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ fn file_selection_keymap(dir, open_dir) {
fn open_file_menu(dir) {
let keymap = file_selection_keymap(dir, |dir| open_file_menu(dir));
keymap.bind_key_for_regular_candidates("enter", "OpenFile", |path| s::open_doc(path));
keymap.bind_key_for_custom_candidate("enter", "NewFile",
|name| s::new_doc(s::join_path(dir, name))
);
let menu = s::make_menu("open_file_menu", `Open file in ${dir}/`);
s::set_menu_keymap(menu, keymap);
s::set_menu_is_candidate_menu(menu, true);
Expand Down
2 changes: 2 additions & 0 deletions src/keymap/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,13 @@ impl MenuSelection {
.first()
.map(|c| c.display_str() == self.input)
.unwrap_or(false);
let has_regular_candidates = !self.filtered_candidates.is_empty();
if let Some(candidate) = &self.custom_candidate {
self.filtered_candidates.insert(0, candidate.to_owned());
}

self.index = if self.custom_candidate.is_some()
&& has_regular_candidates
&& (is_exact_match || !self.default_to_custom_candidate)
{
1
Expand Down
49 changes: 38 additions & 11 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,37 +308,63 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {
fs_util::path_to_string(&cwd)
}

pub fn new_doc(&mut self, path: &str) -> Result<(), SynlessError> {
use std::path::PathBuf;

let path_buf = PathBuf::from(path);
if path_buf.exists() {
return Err(error!(
FileSystem,
"File already exists: {}",
path_buf.display()
));
}
let language_name = self.language_name_from_file_extension(&path_buf)?;
let doc_name = DocName::File(path_buf);
self.engine.add_empty_doc(&doc_name, &language_name)?;
self.engine.set_visible_doc(&doc_name)
}

pub fn open_doc(&mut self, path: &str) -> Result<(), SynlessError> {
use std::fs::read_to_string;
use std::path::PathBuf;

let source = read_to_string(path)
.map_err(|err| error!(FileSystem, "Failed to read file at '{path}' ({err})"))?;
let path_buf = PathBuf::from(path);
let ext = path_buf
let language_name = self.language_name_from_file_extension(&path_buf)?;
let doc_name = DocName::File(path_buf);
self.engine
.load_doc_from_source(doc_name.clone(), &language_name, &source)?;
self.engine.set_visible_doc(&doc_name)
}

fn language_name_from_file_extension(
&self,
path: &std::path::Path,
) -> Result<String, SynlessError> {
let extension = path
.extension()
.ok_or_else(|| {
error!(
Doc,
"Can't open file at '{path}' because it doesn't have an extension"
"Can't determine language of '{}' because it doesn't have an extension",
path.display()
)
})?
.to_str()
.ok_or_else(|| {
error!(
Doc,
"Can't open file at '{path}' because its extension is not valid Unicode"
"Can't determine language of '{}' because its extension is not valid Unicode",
path.display()
)
})?;
let language_name = self
Ok(self
.engine
.lookup_file_extension(&format!(".{ext}"))
.ok_or_else(|| error!(Doc, "No language registered for extension '{ext}'"))?
.to_owned();
let doc_name = DocName::File(path_buf);
self.engine
.load_doc_from_source(doc_name.clone(), &language_name, &source)?;
self.engine.set_visible_doc(&doc_name)
.lookup_file_extension(&format!(".{extension}"))
.ok_or_else(|| error!(Doc, "No language registered for extension '{extension}'"))?
.to_owned())
}

pub fn doc_switching_candidates(&self) -> Result<Vec<rhai::Dynamic>, SynlessError> {
Expand Down Expand Up @@ -780,6 +806,7 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {

// Doc management
register!(module, rt.current_dir()?);
register!(module, rt.new_doc(path: &str)?);
register!(module, rt.open_doc(path: &str)?);
register!(module, rt.doc_switching_candidates()?);
register!(module, rt.switch_to_doc(path: &str)?);
Expand Down
21 changes: 18 additions & 3 deletions src/util/fs_util.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
use crate::util::{error, SynlessError};
use std::path::Path;
use std::path::{Path, PathBuf};

pub fn path_to_string(path: &Path) -> Result<String, SynlessError> {
path.canonicalize()
.map_err(|_| error!(FileSystem, "Invalid path: {}", path.display()))?
let mut path_buf = PathBuf::from(path);
let mut suffixes = Vec::new();
while !path_buf.exists() {
if let Some(suffix) = path_buf.file_name() {
suffixes.push(suffix.to_owned());
path_buf.pop();
} else {
return Err(error!(FileSystem, "Path is confusing: {}", path.display()));
}
}
let mut canonical_path = path_buf
.canonicalize()
.map_err(|_| error!(FileSystem, "Invalid path: {}", path.display()))?;
while let Some(suffix) = suffixes.pop() {
canonical_path.push(suffix);
}
canonical_path
.to_str()
.map(|s| s.to_owned())
.ok_or_else(|| {
Expand Down

0 comments on commit e9a50d4

Please sign in to comment.