import std.array; import std.algorithm; import std.experimental.logger; import std.file; import std.stdio; import vibe.d; import app; import page; /** * Loads pages into memory and sets up a "watcher" to watch a directory for file changes. */ void initPages(T, string sortPred)(ref T[string] array, ref T*[] sortedRange, const string directory) { bool addPage(string path) { try { T newPage = new T(path); logf("Added %s", newPage.slug); array[newPage.slug] = 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()); } } } void sortThings() { sortedRange = sort!(sortPred)(array.values) .filter!(x => !x.isHidden) .map!"&a".array; logf("sorted: %s", sortedRange); } if (!existsFile(getWorkingDirectory() ~ directory)) { createDirectory(getWorkingDirectory() ~ directory); } scan(getWorkingDirectory() ~ directory); sortThings(); DirectoryWatcher watcher = watchDirectory(getWorkingDirectory() ~ directory, true); //auto watcher = FileWatch((getWorkingDirectory() ~ directory).toString(), 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()); log(newPage.slug); if (newPage.slug in array) { log("Slug not changed"); array[newPage.slug] = newPage; } else { log("Slug changed"); foreach(item; array) { if (item.name == change.path.toString()) { logf("Removed %s, which is the old slug of %s", newPage.slug, item.slug); array.remove(item.slug); } } } logf("%s modified: %s", typeid(T).stringof, newPage.slug); array[newPage.slug] = 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 { foreach(item; array.byValue) { logf(" - %s", item.name); if (item.name == change.path.toString()) { logf("Removed %s", item.slug); array.remove(item.slug); } } } catch(Exception e) {} break; default: break; } log("Current state:"); //sortedRange = sort!("a."~sortProp~" < b."~sortProp)(array.values); sortThings(); foreach (item; array) { logf("%s - %s", item.name, item.slug); } } } }