Merge pull request #14 from OlegLustenko/feature/regexp
feat(settings): Add ability to select by Regular Expression
This commit is contained in:
commit
0e5b34469b
112
main.ts
112
main.ts
|
@ -13,9 +13,13 @@ import { renameFilesInObsidian } from './src/services/file.service';
|
||||||
import { createPreviewElement } from './src/components/PreviewElement';
|
import { createPreviewElement } from './src/components/PreviewElement';
|
||||||
import {
|
import {
|
||||||
getObsidianFilesByFolderName,
|
getObsidianFilesByFolderName,
|
||||||
|
getObsidianFilesByRegExp,
|
||||||
getObsidianFilesWithTagName,
|
getObsidianFilesWithTagName,
|
||||||
} from './src/services/obsidian.service';
|
} from './src/services/obsidian.service';
|
||||||
import { renderPreviewFiles } from './src/components/RenderPreviewFiles';
|
import { renderPreviewFiles } from './src/components/RenderPreviewFiles';
|
||||||
|
import { createBackslash } from './src/components/RegExpBackslash';
|
||||||
|
import { RegExpFlag } from './src/constants/RegExpFlags';
|
||||||
|
import { RegExpFlagsSuggest } from './src/suggestions/RegExpFlagsSuggest';
|
||||||
|
|
||||||
interface BulkRenamePluginSettings {
|
interface BulkRenamePluginSettings {
|
||||||
folderName: string;
|
folderName: string;
|
||||||
|
@ -23,7 +27,11 @@ interface BulkRenamePluginSettings {
|
||||||
existingSymbol: string;
|
existingSymbol: string;
|
||||||
replacePattern: string;
|
replacePattern: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
viewType: 'tags' | 'folder';
|
regExpState: {
|
||||||
|
regExp: string;
|
||||||
|
flags: RegExpFlag[];
|
||||||
|
};
|
||||||
|
viewType: 'tags' | 'folder' | 'regexp';
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_SETTINGS: BulkRenamePluginSettings = {
|
const DEFAULT_SETTINGS: BulkRenamePluginSettings = {
|
||||||
|
@ -31,6 +39,10 @@ const DEFAULT_SETTINGS: BulkRenamePluginSettings = {
|
||||||
fileNames: [],
|
fileNames: [],
|
||||||
existingSymbol: '',
|
existingSymbol: '',
|
||||||
replacePattern: '',
|
replacePattern: '',
|
||||||
|
regExpState: {
|
||||||
|
regExp: '',
|
||||||
|
flags: [],
|
||||||
|
},
|
||||||
tags: [],
|
tags: [],
|
||||||
viewType: 'folder',
|
viewType: 'folder',
|
||||||
};
|
};
|
||||||
|
@ -38,10 +50,15 @@ const DEFAULT_SETTINGS: BulkRenamePluginSettings = {
|
||||||
const isViewTypeFolder = ({ settings }: BulkRenamePlugin) => {
|
const isViewTypeFolder = ({ settings }: BulkRenamePlugin) => {
|
||||||
return settings.viewType === 'folder';
|
return settings.viewType === 'folder';
|
||||||
};
|
};
|
||||||
|
|
||||||
const isViewTypeTags = ({ settings }: BulkRenamePlugin) => {
|
const isViewTypeTags = ({ settings }: BulkRenamePlugin) => {
|
||||||
return settings.viewType === 'tags';
|
return settings.viewType === 'tags';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isViewTypeRegExp = ({ settings }: BulkRenamePlugin) => {
|
||||||
|
return settings.viewType === 'regexp';
|
||||||
|
};
|
||||||
|
|
||||||
class BulkRenamePlugin extends Plugin {
|
class BulkRenamePlugin extends Plugin {
|
||||||
settings: BulkRenamePluginSettings;
|
settings: BulkRenamePluginSettings;
|
||||||
|
|
||||||
|
@ -97,6 +114,7 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
this.renderTabs();
|
this.renderTabs();
|
||||||
this.renderFileLocation();
|
this.renderFileLocation();
|
||||||
this.renderTagNames();
|
this.renderTagNames();
|
||||||
|
this.renderRegExpInput();
|
||||||
this.renderReplaceSymbol();
|
this.renderReplaceSymbol();
|
||||||
this.renderFilesAndPreview();
|
this.renderFilesAndPreview();
|
||||||
this.renderRenameFiles();
|
this.renderRenameFiles();
|
||||||
|
@ -127,6 +145,17 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
this.display();
|
this.display();
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.addButton((button) => {
|
||||||
|
button.setButtonText('Search by RegExp');
|
||||||
|
if (isViewTypeRegExp(this.plugin)) {
|
||||||
|
button.setCta();
|
||||||
|
}
|
||||||
|
button.onClick(async () => {
|
||||||
|
this.plugin.settings.viewType = 'regexp';
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
this.display();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +167,7 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
.setName('Folder location')
|
.setName('Folder location')
|
||||||
.setDesc('Find files within the folder')
|
.setDesc('Find files within the folder')
|
||||||
.addSearch((cb) => {
|
.addSearch((cb) => {
|
||||||
new FolderSuggest(this.app, cb.inputEl);
|
new FolderSuggest(this.app, cb.inputEl, this.plugin);
|
||||||
cb.setPlaceholder('Example: folder1/')
|
cb.setPlaceholder('Example: folder1/')
|
||||||
.setValue(this.plugin.settings.folderName)
|
.setValue(this.plugin.settings.folderName)
|
||||||
.onChange((newFolder) => {
|
.onChange((newFolder) => {
|
||||||
|
@ -157,11 +186,11 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
if (!isViewTypeTags(this.plugin)) {
|
if (!isViewTypeTags(this.plugin)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new Setting(this.containerEl)
|
new Setting(this.containerEl)
|
||||||
.setName('Tag names ')
|
.setName('Tag names ')
|
||||||
.setDesc('all files with the tags will be found')
|
.setDesc('all files with the tags will be found')
|
||||||
.addSearch((cb) => {
|
.addSearch((cb) => {
|
||||||
// @ts-ignore
|
|
||||||
cb.inputEl.addEventListener('keydown', (event) => {
|
cb.inputEl.addEventListener('keydown', (event) => {
|
||||||
if (event.key !== 'Enter') {
|
if (event.key !== 'Enter') {
|
||||||
return;
|
return;
|
||||||
|
@ -185,6 +214,68 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderRegExpInput() {
|
||||||
|
if (!isViewTypeRegExp(this.plugin)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const desc = document.createDocumentFragment();
|
||||||
|
desc.append(
|
||||||
|
desc.createEl('b', {
|
||||||
|
text: 'Reg exp will match file Operation System path',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(this.containerEl)
|
||||||
|
.setName('RegExp Search')
|
||||||
|
.setDesc(desc)
|
||||||
|
.addText((cb) => {
|
||||||
|
const backslash = createBackslash('/');
|
||||||
|
cb.inputEl.insertAdjacentElement('beforebegin', backslash);
|
||||||
|
// @ts-ignore
|
||||||
|
cb.inputEl.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key !== 'Enter') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = event.target as HTMLInputElement;
|
||||||
|
|
||||||
|
this.plugin.settings.regExpState.regExp = target.value;
|
||||||
|
this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
cb.setPlaceholder('Put your RegExp here')
|
||||||
|
.setValue(this.plugin.settings.regExpState.regExp)
|
||||||
|
.onChange((newFolder) => {
|
||||||
|
this.plugin.settings.regExpState.regExp = newFolder;
|
||||||
|
this.plugin.saveSettings();
|
||||||
|
this.getFilesByRegExp();
|
||||||
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
cb.inputEl.addClass('bulk_regexp');
|
||||||
|
cb.inputEl.onblur = this.reRenderPreview;
|
||||||
|
})
|
||||||
|
.addText((cb) => {
|
||||||
|
new RegExpFlagsSuggest(this.app, cb.inputEl, this.plugin);
|
||||||
|
const backslash = createBackslash('/');
|
||||||
|
cb.inputEl.insertAdjacentElement('beforebegin', backslash);
|
||||||
|
cb.inputEl.addEventListener('keydown', (event) => {
|
||||||
|
// @ts-ignore
|
||||||
|
event.stopPropagation();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
cb.setPlaceholder('flags here')
|
||||||
|
// .setDisabled(true)
|
||||||
|
.setValue(this.plugin.settings.regExpState.flags.join(''))
|
||||||
|
.onChange((flag: RegExpFlag) => {
|
||||||
|
this.plugin.saveSettings();
|
||||||
|
this.getFilesByRegExp();
|
||||||
|
this.reRenderPreview();
|
||||||
|
});
|
||||||
|
cb.inputEl.addClass('bulk_regexp_flags');
|
||||||
|
})
|
||||||
|
.controlEl.addClass('bulk_regexp_control');
|
||||||
|
}
|
||||||
|
|
||||||
renderReplaceSymbol() {
|
renderReplaceSymbol() {
|
||||||
const { settings } = this.plugin;
|
const { settings } = this.plugin;
|
||||||
|
|
||||||
|
@ -248,7 +339,7 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
renderRenameFiles() {
|
renderRenameFiles() {
|
||||||
const desc = document.createDocumentFragment();
|
const desc = document.createDocumentFragment();
|
||||||
desc.append(
|
desc.append(
|
||||||
'You are going to update all marked files and their directories',
|
'You are going to update all files from preview section',
|
||||||
desc.createEl('br'),
|
desc.createEl('br'),
|
||||||
desc.createEl('b', {
|
desc.createEl('b', {
|
||||||
text: 'Warning: ',
|
text: 'Warning: ',
|
||||||
|
@ -296,6 +387,12 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
this.getFilesByTags();
|
this.getFilesByTags();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isViewTypeRegExp(this.plugin)) {
|
||||||
|
this.getFilesByRegExp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.getFilesByFolder();
|
this.getFilesByFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +409,13 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
this.plugin,
|
this.plugin,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFilesByRegExp() {
|
||||||
|
this.plugin.settings.fileNames = getObsidianFilesByRegExp(
|
||||||
|
this.app,
|
||||||
|
this.plugin,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BulkRenamePlugin;
|
export default BulkRenamePlugin;
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
"version": "0.3.5",
|
"version": "0.3.5",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "^2.11.2"
|
"@popperjs/core": "^2.11.2",
|
||||||
|
"xregexp": "^5.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^28.1.8",
|
"@types/jest": "^28.1.8",
|
||||||
|
@ -855,6 +856,18 @@
|
||||||
"source-map": "^0.6.0"
|
"source-map": "^0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/runtime-corejs3": {
|
||||||
|
"version": "7.19.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz",
|
||||||
|
"integrity": "sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==",
|
||||||
|
"dependencies": {
|
||||||
|
"core-js-pure": "^3.25.1",
|
||||||
|
"regenerator-runtime": "^0.13.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.18.10",
|
"version": "7.18.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
|
||||||
|
@ -3367,6 +3380,16 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/core-js-pure": {
|
||||||
|
"version": "3.25.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.1.tgz",
|
||||||
|
"integrity": "sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/core-js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
|
@ -8421,6 +8444,11 @@
|
||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/regenerator-runtime": {
|
||||||
|
"version": "0.13.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||||
|
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||||
|
},
|
||||||
"node_modules/regex-not": {
|
"node_modules/regex-not": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
|
||||||
|
@ -10009,6 +10037,14 @@
|
||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/xregexp": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime-corejs3": "^7.16.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
@ -10669,6 +10705,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@babel/runtime-corejs3": {
|
||||||
|
"version": "7.19.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz",
|
||||||
|
"integrity": "sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==",
|
||||||
|
"requires": {
|
||||||
|
"core-js-pure": "^3.25.1",
|
||||||
|
"regenerator-runtime": "^0.13.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@babel/template": {
|
"@babel/template": {
|
||||||
"version": "7.18.10",
|
"version": "7.18.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
|
||||||
|
@ -12606,6 +12651,11 @@
|
||||||
"integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==",
|
"integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"core-js-pure": {
|
||||||
|
"version": "3.25.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.1.tgz",
|
||||||
|
"integrity": "sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A=="
|
||||||
|
},
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
|
@ -16376,6 +16426,11 @@
|
||||||
"source-map": "~0.6.1"
|
"source-map": "~0.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.13.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||||
|
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||||
|
},
|
||||||
"regex-not": {
|
"regex-not": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
|
||||||
|
@ -17596,6 +17651,14 @@
|
||||||
"signal-exit": "^3.0.7"
|
"signal-exit": "^3.0.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"xregexp": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime-corejs3": "^7.16.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"y18n": {
|
"y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "^2.11.2"
|
"@popperjs/core": "^2.11.2",
|
||||||
|
"xregexp": "^5.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^28.1.8",
|
"@types/jest": "^28.1.8",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export const createBackslash = (textContent = '/') => {
|
||||||
|
const previewLabel = window.document.createElement('div');
|
||||||
|
previewLabel.className = 'bulk_regexp_slash';
|
||||||
|
previewLabel.textContent = textContent;
|
||||||
|
return previewLabel;
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
export type RegExpFlag = 'g' | 'i' | 'm' | 'u' | 'y' | 'n' | 's' | 'x' | 'A';
|
||||||
|
|
||||||
|
export const REGEXP_FLAGS = [
|
||||||
|
'g',
|
||||||
|
'i',
|
||||||
|
'm',
|
||||||
|
'u',
|
||||||
|
'y',
|
||||||
|
'n',
|
||||||
|
's',
|
||||||
|
'x',
|
||||||
|
'A',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type RegExpFlags = typeof REGEXP_FLAGS;
|
|
@ -1,5 +1,6 @@
|
||||||
import { App, TFile } from 'obsidian';
|
import { App, TFile } from 'obsidian';
|
||||||
import BulkRenamePlugin from '../../main';
|
import BulkRenamePlugin from '../../main';
|
||||||
|
import XRegExp from 'xregexp';
|
||||||
|
|
||||||
export const getObsidianFilesByFolderName = (
|
export const getObsidianFilesByFolderName = (
|
||||||
app: App,
|
app: App,
|
||||||
|
@ -17,6 +18,27 @@ export const getObsidianFilesByFolderName = (
|
||||||
return filesSortedByName;
|
return filesSortedByName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getObsidianFilesByRegExp = (
|
||||||
|
app: App,
|
||||||
|
plugin: BulkRenamePlugin,
|
||||||
|
) => {
|
||||||
|
const { regExpState } = plugin.settings;
|
||||||
|
|
||||||
|
const regExp = XRegExp(regExpState.regExp, regExpState.flags.join(''));
|
||||||
|
|
||||||
|
const abstractFiles = app.vault.getAllLoadedFiles();
|
||||||
|
|
||||||
|
const matchedFileNames = abstractFiles.filter((file) => {
|
||||||
|
if (file instanceof TFile && XRegExp.match(file.path, regExp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}) as TFile[];
|
||||||
|
|
||||||
|
const filesSortedByName = sortFilesByName(matchedFileNames);
|
||||||
|
|
||||||
|
return filesSortedByName;
|
||||||
|
};
|
||||||
|
|
||||||
export const getObsidianFilesWithTagName = (
|
export const getObsidianFilesWithTagName = (
|
||||||
app: App,
|
app: App,
|
||||||
plugin: BulkRenamePlugin,
|
plugin: BulkRenamePlugin,
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes
|
||||||
|
|
||||||
|
import { TextInputSuggest } from './suggest';
|
||||||
|
import { REGEXP_FLAGS, RegExpFlag } from '../constants/RegExpFlags';
|
||||||
|
|
||||||
|
export class RegExpFlagsSuggest extends TextInputSuggest<RegExpFlag> {
|
||||||
|
// @ts-ignore TODO refactor types
|
||||||
|
getSuggestions() {
|
||||||
|
return REGEXP_FLAGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSuggestion = (flag: RegExpFlag, el: HTMLElement) => {
|
||||||
|
const { regExpState } = this.plugin.settings;
|
||||||
|
const hasFlag = regExpState.flags.includes(flag);
|
||||||
|
if (hasFlag) {
|
||||||
|
el.addClass('bulk-flag-selected');
|
||||||
|
} else {
|
||||||
|
el.removeClass('bulk-flag-selected');
|
||||||
|
}
|
||||||
|
el.setText(flag);
|
||||||
|
};
|
||||||
|
|
||||||
|
selectSuggestion = (flag: RegExpFlag, event: MouseEvent | KeyboardEvent) => {
|
||||||
|
const { regExpState } = this.plugin.settings;
|
||||||
|
const target = event.target as HTMLDivElement;
|
||||||
|
|
||||||
|
const hasFlag = regExpState.flags.includes(flag);
|
||||||
|
if (hasFlag) {
|
||||||
|
regExpState.flags = regExpState.flags.filter((existingFlag) => {
|
||||||
|
return existingFlag !== flag;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
regExpState.flags = [...regExpState.flags, flag];
|
||||||
|
}
|
||||||
|
target.classList.toggle('bulk-flag-selected');
|
||||||
|
this.inputEl.value = regExpState.flags.join('');
|
||||||
|
this.inputEl.trigger('input');
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { App, ISuggestOwner, Scope } from 'obsidian';
|
import { App, ISuggestOwner, Scope } from 'obsidian';
|
||||||
import { createPopper, Instance as PopperInstance } from '@popperjs/core';
|
import { createPopper, Instance as PopperInstance } from '@popperjs/core';
|
||||||
|
import BulkRenamePlugin from '../../main';
|
||||||
|
|
||||||
const wrapAround = (value: number, size: number): number => {
|
const wrapAround = (value: number, size: number): number => {
|
||||||
return ((value % size) + size) % size;
|
return ((value % size) + size) % size;
|
||||||
|
@ -104,6 +105,7 @@ class Suggest<T> {
|
||||||
|
|
||||||
export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
|
export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
|
||||||
protected app: App;
|
protected app: App;
|
||||||
|
protected plugin: BulkRenamePlugin;
|
||||||
protected inputEl: HTMLInputElement | HTMLTextAreaElement;
|
protected inputEl: HTMLInputElement | HTMLTextAreaElement;
|
||||||
|
|
||||||
private popper: PopperInstance;
|
private popper: PopperInstance;
|
||||||
|
@ -111,7 +113,12 @@ export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
|
||||||
private suggestEl: HTMLElement;
|
private suggestEl: HTMLElement;
|
||||||
private suggest: Suggest<T>;
|
private suggest: Suggest<T>;
|
||||||
|
|
||||||
constructor(app: App, inputEl: HTMLInputElement | HTMLTextAreaElement) {
|
constructor(
|
||||||
|
app: App,
|
||||||
|
inputEl: HTMLInputElement | HTMLTextAreaElement,
|
||||||
|
plugin: BulkRenamePlugin,
|
||||||
|
) {
|
||||||
|
this.plugin = plugin;
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.inputEl = inputEl;
|
this.inputEl = inputEl;
|
||||||
this.scope = new Scope();
|
this.scope = new Scope();
|
||||||
|
@ -191,7 +198,7 @@ export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
|
||||||
this.suggestEl.detach();
|
this.suggestEl.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract getSuggestions(inputStr: string): T[];
|
abstract getSuggestions(inputStr?: string): T[];
|
||||||
abstract renderSuggestion(item: T, el: HTMLElement): void;
|
abstract renderSuggestion(item: T, el: HTMLElement): void;
|
||||||
abstract selectSuggestion(item: T): void;
|
abstract selectSuggestion(item: T, evt: MouseEvent | KeyboardEvent): void;
|
||||||
}
|
}
|
||||||
|
|
26
styles.css
26
styles.css
|
@ -23,3 +23,29 @@
|
||||||
.bulk_preview_label {
|
.bulk_preview_label {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bulk_regexp_control {
|
||||||
|
border: 1px solid var(--background-modifier-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk_regexp_control > input {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk_regexp,
|
||||||
|
.bulk_regexp_flags {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk_regexp_flags {
|
||||||
|
caret-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk_regexp_slash {
|
||||||
|
font-size: 1.5em;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk-flag-selected {
|
||||||
|
background-color: lavender !important;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue