import std.array; import std.algorithm; import std.experimental.logger; import std.file; import std.stdio; import std.traits; import vibe.d; import cache; import page; /** * Loads pages into memory and sets up a "watcher" to watch a directory for file changes. */ void initPages(T, C)(C *cache, const string directory) if (isImplicitlyConvertible!(T, Page)) { bool addPage(string path) { try { T newPage = new T(path); logf("Added %s", newPage.slug); cache.addItem(newPage); return true; } catch (page.ArticleParseException e) { logf("Could not parse %s: %s", path, e); return false; } catch (Exception e) { logf("Other exception while parsing %s: %s", path, e); return false; } } // Initial scan void scan(NativePath path, int level = 0) { logf("Scanning %s", path.toString()); foreach(file; iterateDirectory(path)) { if (file.isDirectory) { scan(path ~ file.name, level + 1); } else { addPage((path ~ file.name).toString()); } } } if (!existsFile(getWorkingDirectory() ~ directory)) { createDirectory(getWorkingDirectory() ~ directory); } scan(getWorkingDirectory() ~ directory); DirectoryWatcher watcher = watchDirectory(getWorkingDirectory() ~ directory, true); bool shouldStop = false; while (!shouldStop) { // Try to reduce changes to only one DirectoryChangeType per change DirectoryChange[] changes; shouldStop = !watcher.readChanges(changes); foreach(change; changes) { logf("=======[New changes]======"); string[] changeTypes = ["added", "removed", "modified"]; logf("Path: %s, type: %s", change.path.toString(), changeTypes[change.type]); if (endsWith(change.path.toString(), ".kate-swp")) continue; switch (change.type) with (DirectoryChangeType){ case added: try { addPage(change.path.toString()); } catch(Exception e) { warningf("Error while updating %s: %s", change.path.toString(), e.msg); } break; case modified: T newPage; try { newPage = new T(change.path.toString()); cache.changeItem(newPage); } catch(page.ArticleParseException e) { warningf("Could not parse %s", change.path.toString()); } catch (Exception e) { warningf("Error while updating %s: %s", change.path.toString(), e.msg); } break; case removed: try { cache.removeItemByName(change.path.toString()); } catch(Exception e) { logf("Error while trying to remove %s: %s", T.stringof, e.msg); } break; default: break; } } } }