Skip to content

Commit

Permalink
Added error collection on startup, fixed html parent folder creation
Browse files Browse the repository at this point in the history
  • Loading branch information
Linus-Mussmaecher committed Jun 10, 2024
1 parent 5a2306a commit 2071609
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 51 deletions.
43 changes: 23 additions & 20 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,36 @@ impl App {
/// - Loading a config file
/// - Indexing notes from the given path
/// - Creating an initial select screen and empty display stack
pub fn new(args: crate::Arguments) -> Self {
/// Also returns all errors that happened during creation that did not prevent the creation.
pub fn new(args: crate::Arguments) -> (Self, Vec<error::RucolaError>) {
// Create all configs
let (styles, builder, manager, tracker, stats_show) =
files::load_configurations(args).unwrap();

// Index all files in path
let index = std::rc::Rc::new(std::cell::RefCell::new(data::NoteIndex::new(
tracker,
builder.clone(),
)));
let (index, errors) = data::NoteIndex::new(tracker, builder.clone());

let index = std::rc::Rc::new(std::cell::RefCell::new(index));

// Initialize app state
Self {
select: ui::screen::SelectScreen::new(
index.clone(),
manager.clone(),
builder.clone(),
styles.clone(),
stats_show,
),
display: None,
display_stack: Vec::new(),
index,
styles,
manager,
builder,
}
(
Self {
select: ui::screen::SelectScreen::new(
index.clone(),
manager.clone(),
builder.clone(),
styles.clone(),
stats_show,
),
display: None,
display_stack: Vec::new(),
index,
styles,
manager,
builder,
},
errors,
)
}

/// Reads the top of the display stack, creates a new display screen from it and sets that as the currently active display screen.
Expand Down
2 changes: 1 addition & 1 deletion src/data/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ mod tests {
let config = files::Config::default();
let tracker = files::FileTracker::new(&config);
let builder = files::HtmlBuilder::new(&config);
let index = data::NoteIndex::new(tracker, builder);
let index = data::NoteIndex::new(tracker, builder).0;

assert_eq!(index.inner.len(), 11);

Expand Down
54 changes: 38 additions & 16 deletions src/data/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ pub type NoteIndexContainer = std::rc::Rc<std::cell::RefCell<NoteIndex>>;
/// Contains an indexed and hashed list of notes
pub struct NoteIndex {
/// The wrapped HashMap, available only in the data module.
/// TODO: This should not be pub
pub inner: HashMap<String, Note>,
pub(super) inner: HashMap<String, Note>,

/// === Config ===
/// The file tracker that sends file events and watches the structure of the vault of this index.
tracker: files::FileTracker,
/// The HtmlBuilder this index uses to create its HTML files.
Expand All @@ -24,28 +24,50 @@ impl NoteIndex {
/// - The key will be the file name, without the file extension, in lowercase and with spaces replaced by dashes
/// - The value will be an instance of Note containing metadata of the file.
///
/// All files that lead to IO errors when loading are ignored.
pub fn new(tracker: files::FileTracker, builder: files::HtmlBuilder) -> Self {
/// All IO errors that happeded during the creation or the (potential) HTML conversion are returned alongside.
pub fn new(
tracker: files::FileTracker,
builder: files::HtmlBuilder,
) -> (Self, Vec<error::RucolaError>) {
// create an error struct
let mut errors = vec![];
// collect all the notes from the vault folder
let inner = tracker
.get_walker() // Check only OKs
.flatten()
// Convert tiles to notes and skip errors
.flat_map(|entry| Note::from_path(entry.path()))
.filter(|entry| entry.metadata().is_ok_and(|md| md.is_file()))
.flat_map(|entry| match Note::from_path(entry.path()) {
Ok(note) => Some(note),
Err(e) => {
errors.push(e.into());
None
}
})
// Extract name and convert to id
.map(|note| (super::name_to_id(&note.name), note))
// Collect into hash map
.collect::<HashMap<_, _>>();

// create all htmls
for (_id, note) in inner.iter() {
let _todo = builder.create_html(note, false);
}
Self {
inner,
tracker,
builder,
}
// create htmls and save errors
errors.extend(
inner
.iter()
.map(|(_id, note)| builder.create_html(&note, false))
.flat_map(|res| match res {
Ok(_) => None,
Err(e) => Some(e),
}),
);

(
Self {
inner,
tracker,
builder,
},
errors,
)
}

/// Wrapper of the HashMap::get() Function
Expand Down Expand Up @@ -187,7 +209,7 @@ mod tests {
let config = files::Config::default();
let tracker = files::FileTracker::new(&config);
let builder = files::HtmlBuilder::new(&config);
let index = NoteIndex::new(tracker, builder);
let index = NoteIndex::new(tracker, builder).0;

assert_eq!(index.inner.len(), 11);

Expand All @@ -211,7 +233,7 @@ mod tests {
let config = files::Config::default();
let tracker = files::FileTracker::new(&config);
let builder = files::HtmlBuilder::new(&config);
let index = NoteIndex::new(tracker, builder);
let index = NoteIndex::new(tracker, builder).0;

assert_eq!(index.inner.len(), 11);

Expand Down
2 changes: 1 addition & 1 deletion src/data/note_statistics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ mod tests {
let config = files::Config::default();
let tracker = files::FileTracker::new(&config);
let builder = files::HtmlBuilder::new(&config);
let index = data::NoteIndex::new(tracker, builder);
let index = data::NoteIndex::new(tracker, builder).0;

assert_eq!(index.inner.len(), 11);

Expand Down
9 changes: 3 additions & 6 deletions src/files/file_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ impl FileManager {
let index_b = index.borrow_mut();
// Retrieve the old version from the table
let note = index_b
.inner
.get(id)
.ok_or_else(|| error::RucolaError::NoteNoteFound(id.to_owned()))?;

Expand Down Expand Up @@ -94,7 +93,6 @@ impl FileManager {
let index_b = index.borrow_mut();
// Retrieve the old version from the table
let note = index_b
.inner
.get(id)
.ok_or_else(|| error::RucolaError::NoteNoteFound(id.to_owned()))?;

Expand Down Expand Up @@ -151,7 +149,6 @@ impl FileManager {

// Extract old note from the index.
let note = index
.inner
.get(old_id)
.ok_or_else(|| error::RucolaError::NoteNoteFound(old_id.to_owned()))?;

Expand All @@ -174,7 +171,7 @@ impl FileManager {
// search for references to the old id.
.blinks_vec(old_id)
.iter()
.filter_map(|(id, _)| index.inner.get(id))
.filter_map(|(id, _)| index.get(id))
{
// open the file once to read its old content
let old_content = std::fs::read_to_string(&other_note.path)?;
Expand Down Expand Up @@ -203,11 +200,11 @@ impl FileManager {
index: &mut data::NoteIndexContainer,
id: &str,
) -> Result<(), error::RucolaError> {
let table = &mut index.borrow_mut().inner;
// Follow its path and delete it
fs::remove_file(path::Path::new(
// get the note
&table
&index
.borrow_mut()
.get(id)
.ok_or_else(|| error::RucolaError::NoteNoteFound(id.to_owned()))?
.path,
Expand Down
15 changes: 12 additions & 3 deletions src/files/html_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,18 @@ impl HtmlBuilder {

let tar_path = self.id_to_path(&data::name_to_id(&note.name));

fs::create_dir_all(&tar_path)?;

let mut tar_file = std::fs::File::create(tar_path.clone())?;
let mut tar_file = match fs::File::create(&tar_path) {
// file could be created -> all good
Ok(file) => file,
Err(_) => {
// something went wrong -> try to create the file path
if let Some(parent) = tar_path.parent() {
fs::create_dir_all(parent)?;
}
// try again, this time returning error if it doesn't work
fs::File::create(&tar_path)?
}
};

writeln!(tar_file, "<title>{}</title>", note.name)?;
self.add_preamble(&mut tar_file, contains_math)?;
Expand Down
8 changes: 4 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ fn main() -> Result<(), error::RucolaError> {
// draw loading screen
draw_loading_screen(&mut terminal)?;

// Displayed error
let mut current_error: Option<error::RucolaError> = None;

// Create the app state
let mut app = app::App::new(args);
let (mut app, errors) = app::App::new(args);

// Displayed error
let mut current_error: Option<error::RucolaError> = errors.into_iter().last();

// Main loop
'main: loop {
Expand Down

0 comments on commit 2071609

Please sign in to comment.