From 9908d8b924e1408ba29d305eab686e7e045893c6 Mon Sep 17 00:00:00 2001 From: Al0cam Date: Thu, 14 Nov 2024 17:20:32 +0100 Subject: [PATCH] Added rule matcher and implemented logic to move files if they fit a regex and use regex groups --- Utils/MovingUtil.ts | 1 + Utils/RuleMatcherUtil.ts | 94 ++++++++++++++++++++++++++++++++++++++++ main.ts | 69 ++++++++++++++++++++++++----- 3 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 Utils/RuleMatcherUtil.ts diff --git a/Utils/MovingUtil.ts b/Utils/MovingUtil.ts index fda164d..3a08103 100644 --- a/Utils/MovingUtil.ts +++ b/Utils/MovingUtil.ts @@ -1,3 +1,4 @@ +import { MovingRule } from "Models/MovingRule"; import { App, Notice, TFile, TFolder } from "obsidian"; diff --git a/Utils/RuleMatcherUtil.ts b/Utils/RuleMatcherUtil.ts new file mode 100644 index 0000000..1912d0e --- /dev/null +++ b/Utils/RuleMatcherUtil.ts @@ -0,0 +1,94 @@ +import { MovingRule } from "Models/MovingRule"; +import { TFile } from "obsidian"; + +class RuleMatcherUtil { + private static instance: RuleMatcherUtil; + + private constructor() {} + + public static getInstance(): RuleMatcherUtil { + if (!RuleMatcherUtil.instance) { + RuleMatcherUtil.instance = new RuleMatcherUtil(); + } + return RuleMatcherUtil.instance; + } + + /** + * Returns the first rule that matches the file + * If no rule matches, returns null + * + * @param file + * @param rules + * @returns MovingRule | null + */ + public getMatchingRule(file: TFile, rules: MovingRule[]): MovingRule | null { + for(let rule of rules) { + if(rule.regex == null || rule.regex == "") { + console.error("Rule does not have a regex: ", rule); + continue; + } else if(!this.isValidRegex(rule.regex)) { + console.error("Rule has an invalid regex: ", rule); + continue; + } + console.log("Checking if matches: ", file.name.match(rule.regex)); + console.log("Rule: ", rule); + if(file.name.match(rule.regex)) { + return rule; + } + } + return null; + } + + /** + * Returns the regex groups of the file that match the rule + * If no groups match, returns an empty array + * + * @param file + * @param rule + * @returns string[] + */ + public getGroupMatches(file: TFile, rule: MovingRule): RegExpMatchArray | null { + let matches = file.name.match(rule.regex); + return matches; + } + + /** + * Checks if the regex pattern is valid + * Meaning, syntax errors are caught, but not logical errors + * + * @param pattern + * @returns boolean + */ + private isValidRegex(pattern: string): boolean { + try { + new RegExp(pattern); + return true; + } catch (e) { + if (e instanceof SyntaxError) { + console.error(`Invalid regex pattern: ${e.message}`); + } + return false; + } + } + + // TODO: implement the distinction between named and unnamed groups + public constructFinalDesinationPath(rule: MovingRule, matches: RegExpMatchArray): string { + let folderPath = rule.folder; + return folderPath; + } + + private hasUnnamedGroups(pattern: string): boolean { + return /\(/.test(pattern); + } + + private getNamedGroups(pattern: string): RegExpMatchArray | null { + return pattern.match(/\(\?<\w+>/g); + } + + private getUnnamedGroups(pattern: string): RegExpMatchArray | null { + return pattern.match(/\(/g); + } +} + +const ruleMatcherUtil = RuleMatcherUtil.getInstance(); +export default ruleMatcherUtil; \ No newline at end of file diff --git a/main.ts b/main.ts index c31332c..7fce666 100644 --- a/main.ts +++ b/main.ts @@ -2,6 +2,7 @@ import { Plugin, TFile } from "obsidian"; import { AutoMoverSettings, DEFAULT_SETTINGS } from "Settings/Settings"; import { SettingsTab } from "Settings/SettingsTab"; import movingUtil from "Utils/MovingUtil"; +import ruleMatcherUtil from "Utils/RuleMatcherUtil"; export default class AutoMoverPlugin extends Plugin { settings: AutoMoverSettings; @@ -9,19 +10,43 @@ export default class AutoMoverPlugin extends Plugin { async onload() { console.log('loading plugin') movingUtil.init(this.app); - - // create file - // let newFile: TFile; - // if(this.app.vault.getAbstractFileByPath("Something.md") === null) { - // newFile = await this.app.vault.create("./Something.md", "This is a test file") - // } else { - // newFile = this.app.vault.getAbstractFileByPath("Something.md") as TFile; - // } - // delete file - // await this.app.vault.delete(this.app.vault.getAbstractFileByPath("amFolder/Something.md") as TFile); + /** + * Loading settings and creating the settings tab + */ this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); this.addSettingTab(new SettingsTab(this.app, this)); console.log(this.settings); + + // TODO: chec if there are any settings on when to apply the rules, + // because if you arent doing on open, save, close or create, then there is no point in checking for rules + if(this.checkIfMovingTriggersAreEnabled() && this.checkIfThereAreRulesToApply() && this.checkIfRulesAreValid()) { + if(this.settings.moveOnOpen) { + this.registerEvent(this.app.workspace.on("file-open", (file: TFile) => { + if(file == null || file.path == null) + return; + console.log("File opened: ", file.path); + // Question: what if there are multiple rules that apply to the same file? + // so far only the first one is applied and the rest are ignored + // i can live with that + + // TODO: what if the file is already in the correct folder? + // do nothing... + + // TODO: what if the folder which the file is supposed to be moved to does not exist? + // create the whole path to the folder and the folder itself + // having it do nothing would be conflicting with the idea to use regex groups in the first place + + let rule = ruleMatcherUtil.getMatchingRule(file, this.settings.movingRules); + if(rule != null) { + // TODO: Construct the folder path using the regex groups + let matches = ruleMatcherUtil.getGroupMatches(file, rule); + console.log("Matches: ", matches); + console.log("Moving file to: ", rule.folder); + // movingUtil.moveFile(file, rule.folder); + } + })); + } + } } async asyncloadSettings() { @@ -31,4 +56,28 @@ export default class AutoMoverPlugin extends Plugin { async onunload() { console.log('unloading plugin') } + + /** + * No point in doing anything if there is no trigger set which will cause you to move the files + * @returns boolean + */ + checkIfMovingTriggersAreEnabled(): boolean { + return this.settings.moveOnClose || this.settings.moveOnCreate || this.settings.moveOnOpen || this.settings.moveOnSave; + } + + /** + * If there are no rules to apply, then there is no point in checking for them + * @returns boolean + */ + checkIfThereAreRulesToApply(): boolean { + return this.settings.movingRules.length > 0; + } + + /** + * Superficail check if the rules are valid + * @returns boolean + */ + checkIfRulesAreValid(): boolean { + return this.settings.movingRules.every(rule => rule.regex !== '' && rule.folder !== ''); + } }