From 9b146acfbbfe7d0ab27360237281dcbcfd439461 Mon Sep 17 00:00:00 2001 From: Al0cam Date: Thu, 6 Feb 2025 21:20:58 +0100 Subject: [PATCH] updated errors and started work on building folders mentioned in regex string --- Settings/SettingsTab.ts | 20 +++++------ Utils/MovingUtil.ts | 65 +++++++++++++++++++++++++++------- Utils/RuleMatcherUtil.ts | 14 ++++---- main.ts | 76 +++++++++++++++++++++++++--------------- 4 files changed, 118 insertions(+), 57 deletions(-) diff --git a/Settings/SettingsTab.ts b/Settings/SettingsTab.ts index 5eddd76..58c6f24 100644 --- a/Settings/SettingsTab.ts +++ b/Settings/SettingsTab.ts @@ -11,7 +11,7 @@ export class SettingsTab extends PluginSettingTab{ } display(): void { - let { containerEl } = this; + const { containerEl } = this; // maybe not required containerEl.empty(); @@ -67,30 +67,30 @@ export class SettingsTab extends PluginSettingTab{ * instead of using the default .setting-item class I created a custom class to add other styling, * with the inclusion of the relevant styles from the .setting-item class */ - let movingRulesContainer = containerEl.createEl('div', {cls: 'moving_rules_container'}); - let header = movingRulesContainer.createEl('div', {cls: 'rule_header'}); + const movingRulesContainer = containerEl.createEl('div', {cls: 'moving_rules_container'}); + const header = movingRulesContainer.createEl('div', {cls: 'rule_header'}); header.createEl('h2', {text: 'Regex moving rules',}); - let addButton = header.createEl('button', {text: '+', cls: 'rule_button'}); + const addButton = header.createEl('button', {text: '+', cls: 'rule_button'}); addButton.addEventListener('click', () => { this.plugin.settings.movingRules.push(new MovingRule()); // this is used to rerender the settings tab this.display(); }); - let ruleList = movingRulesContainer.createEl('div'); + const ruleList = movingRulesContainer.createEl('div'); /** * Header of the rules */ - let ruleHeader = ruleList.createEl('div', {cls: 'rule margig_right'}); + const ruleHeader = ruleList.createEl('div', {cls: 'rule margig_right'}); ruleHeader.createEl('p', {text: "Regex", cls: 'rule_title'}); ruleHeader.createEl('p', {text: "Folder", cls: 'rule_title'}); /** * List of rules */ - for (let rule of this.plugin.settings.movingRules) { - let child = ruleList.createEl('div', {cls: 'rule'}); + for (const rule of this.plugin.settings.movingRules) { + const child = ruleList.createEl('div', {cls: 'rule'}); child.createEl('input', {value: rule.regex, cls: 'rule_input'}) .onchange = (e) => { rule.regex = (e.target as HTMLInputElement).value; @@ -103,11 +103,11 @@ export class SettingsTab extends PluginSettingTab{ this.plugin.settings.movingRules.map(r => r === rule ? rule : r); this.plugin.saveData(this.plugin.settings); }; - let deleteButton = child.createEl('button', {text: 'x', cls: 'rule_button rule_button_remove' }); + const deleteButton = child.createEl('button', {text: 'x', cls: 'rule_button rule_button_remove' }); deleteButton.addEventListener('click', () => { this.plugin.settings.movingRules = this.plugin.settings.movingRules.filter(r => r !== rule); this.display(); }); } } -} \ No newline at end of file +} diff --git a/Utils/MovingUtil.ts b/Utils/MovingUtil.ts index 3a08103..a49a840 100644 --- a/Utils/MovingUtil.ts +++ b/Utils/MovingUtil.ts @@ -1,7 +1,6 @@ import { MovingRule } from "Models/MovingRule"; import { App, Notice, TFile, TFolder } from "obsidian"; - class MovingUtil { private static instance: MovingUtil; private app: App; @@ -19,33 +18,75 @@ class MovingUtil { this.app = app; } + /** + * Checks if the path is a file + * + * @param path - Path to be checked + * @returns boolean + */ public isFile(path: string): boolean { - let something = this.app.vault.getAbstractFileByPath(path); - return this.app.vault.getAbstractFileByPath(path) instanceof TFile; + const file = this.app.vault.getAbstractFileByPath(path); + return file instanceof TFile; } + /** + * Checks if the path is a folder + * + * @param path - Path to be checked + * @returns boolean + */ public isFolder(path: string): boolean { return this.app.vault.getAbstractFileByPath(path) instanceof TFolder; } - + /** + * Moves the file to the destination path + * + * @param file - File to be moved + * @param newPath - Destination path + * @returns void + */ public moveFile(file: TFile, newPath: string): void { - if(this.isFolder(newPath)) { - this.app.vault.rename(file, newPath + "/" + file.name); + if (this.isFolder(newPath)) { + this.app.vault.rename(file, `${newPath}/${file.name}`); } else { - new Notice("Invalid destination path\n" + newPath + "is not a folder!", 5000); - console.error("Invalid destination path\n" + newPath + "is not a folder!"); + new Notice(`Invalid destination path\n${newPath} is not a folder!`, 5000); + console.error(`Invalid destination path\n${newPath} is not a folder!`); } } + /** + * Moves the file to the destination path + * + * @param folder - Folder to be moved + * @param newPath - Destination path + * @returns void + */ public moveFolder(folder: TFolder, newPath: string): void { - if(this.isFolder(newPath)) { - this.app.vault.rename(folder, newPath + "/" + folder.name); + if (this.isFolder(newPath)) { + this.app.vault.rename(folder, `${newPath}/${folder.name}`); } else { - new Notice("Invalid destination path\n" + newPath + "is not a folder!", 5000); - console.error("Invalid destination path\n" + newPath + "is not a folder!"); + new Notice(`Invalid destination path\n${newPath} is not a folder!`, 5000); + console.error(`Invalid destination path\n${newPath} is not a folder!`); } } + + /** + * Creates folder in destination path if it does not exist already + * + * @param path - Path of the folder to be created + * @returns Created folder or null if folder already exists + */ + public createFolder(path: string): TFolder | null { + if (!this.isFolder(path)) { + this.app.vault.createFolder(path).then((folder) => { + return folder; + }); + } + new Notice("Folder already exists", 5000); + console.error("Folder already exists"); + return null; + } } const movingUtil = MovingUtil.getInstance(); diff --git a/Utils/RuleMatcherUtil.ts b/Utils/RuleMatcherUtil.ts index 1912d0e..3bfc2f5 100644 --- a/Utils/RuleMatcherUtil.ts +++ b/Utils/RuleMatcherUtil.ts @@ -1,5 +1,5 @@ -import { MovingRule } from "Models/MovingRule"; -import { TFile } from "obsidian"; +import type { MovingRule } from "Models/MovingRule"; +import type { TFile } from "obsidian"; class RuleMatcherUtil { private static instance: RuleMatcherUtil; @@ -22,8 +22,8 @@ class RuleMatcherUtil { * @returns MovingRule | null */ public getMatchingRule(file: TFile, rules: MovingRule[]): MovingRule | null { - for(let rule of rules) { - if(rule.regex == null || rule.regex == "") { + for(const 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)) { @@ -48,7 +48,7 @@ class RuleMatcherUtil { * @returns string[] */ public getGroupMatches(file: TFile, rule: MovingRule): RegExpMatchArray | null { - let matches = file.name.match(rule.regex); + const matches = file.name.match(rule.regex); return matches; } @@ -73,7 +73,7 @@ class RuleMatcherUtil { // TODO: implement the distinction between named and unnamed groups public constructFinalDesinationPath(rule: MovingRule, matches: RegExpMatchArray): string { - let folderPath = rule.folder; + const folderPath = rule.folder; return folderPath; } @@ -91,4 +91,4 @@ class RuleMatcherUtil { } const ruleMatcherUtil = RuleMatcherUtil.getInstance(); -export default ruleMatcherUtil; \ No newline at end of file +export default ruleMatcherUtil; diff --git a/main.ts b/main.ts index 7fce666..bd8c1af 100644 --- a/main.ts +++ b/main.ts @@ -8,7 +8,7 @@ export default class AutoMoverPlugin extends Plugin { settings: AutoMoverSettings; async onload() { - console.log('loading plugin') + console.log("loading plugin"); movingUtil.init(this.app); /** * Loading settings and creating the settings tab @@ -17,34 +17,47 @@ export default class AutoMoverPlugin extends Plugin { this.addSettingTab(new SettingsTab(this.app, this)); console.log(this.settings); - // TODO: chec if there are any settings on when to apply the rules, + // Statement: check 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 + 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... + // Question: 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 + // 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); - } - })); + const rule = ruleMatcherUtil.getMatchingRule( + file, + this.settings.movingRules, + ); + + if (rule != null) { + // TODO: Construct the folder path using the regex groups + const matches = ruleMatcherUtil.getGroupMatches(file, rule); + console.log("Matches: ", matches); + console.log("Moving file to: ", rule.folder); + // movingUtil.moveFile(file, rule.folder); + } + }), + ); + } else { + // TODO: create event listener which happens on file save + // scratched feature + // maybe requires definition of new event and listener } } } @@ -54,7 +67,7 @@ export default class AutoMoverPlugin extends Plugin { } async onunload() { - console.log('unloading plugin') + console.log("unloading plugin"); } /** @@ -62,7 +75,12 @@ export default class AutoMoverPlugin extends Plugin { * @returns boolean */ checkIfMovingTriggersAreEnabled(): boolean { - return this.settings.moveOnClose || this.settings.moveOnCreate || this.settings.moveOnOpen || this.settings.moveOnSave; + return ( + this.settings.moveOnClose || + this.settings.moveOnCreate || + this.settings.moveOnOpen || + this.settings.moveOnSave + ); } /** @@ -78,6 +96,8 @@ export default class AutoMoverPlugin extends Plugin { * @returns boolean */ checkIfRulesAreValid(): boolean { - return this.settings.movingRules.every(rule => rule.regex !== '' && rule.folder !== ''); + return this.settings.movingRules.every( + (rule) => rule.regex !== "" && rule.folder !== "", + ); } }