replace full path during replacement
This commit is contained in:
parent
2eef8f00b1
commit
3e30b9b546
|
@ -1,35 +0,0 @@
|
||||||
import { Notice } from 'obsidian';
|
|
||||||
|
|
||||||
export class TemplaterError extends Error {
|
|
||||||
constructor(msg: string, public console_msg?: string) {
|
|
||||||
super(msg);
|
|
||||||
this.name = this.constructor.name;
|
|
||||||
Error.captureStackTrace(this, this.constructor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function log_error(e: Error | TemplaterError): void {
|
|
||||||
const notice = new Notice('', 8000);
|
|
||||||
if (e instanceof TemplaterError && e.console_msg) {
|
|
||||||
// TODO: Find a better way for this
|
|
||||||
// @ts-ignore
|
|
||||||
notice.noticeEl.innerHTML = `<b>Templater Error</b>:<br/>${e.message}<br/>Check console for more information`;
|
|
||||||
console.error(`Templater Error:`, e.message, '\n', e.console_msg);
|
|
||||||
} else {
|
|
||||||
// @ts-ignore
|
|
||||||
notice.noticeEl.innerHTML = `<b>Templater Error</b>:<br/>${e.message}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function errorWrapperSync<T>(fn: () => T, msg: string): T {
|
|
||||||
try {
|
|
||||||
return fn();
|
|
||||||
} catch (e) {
|
|
||||||
log_error(new TemplaterError(msg, e.message));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum FileSuggestMode {
|
|
||||||
TemplateFiles,
|
|
||||||
ScriptFiles,
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
import {
|
|
||||||
App,
|
|
||||||
normalizePath,
|
|
||||||
TAbstractFile,
|
|
||||||
TFile,
|
|
||||||
TFolder,
|
|
||||||
Vault,
|
|
||||||
} from 'obsidian';
|
|
||||||
import { TemplaterError } from '../errors/errors';
|
|
||||||
|
|
||||||
export function resolveFolder(app: App, folder_str: string): TFolder {
|
|
||||||
folder_str = normalizePath(folder_str);
|
|
||||||
|
|
||||||
const folder = app.vault.getAbstractFileByPath(folder_str);
|
|
||||||
if (!folder) {
|
|
||||||
throw new TemplaterError(`Folder "${folder_str}" doesn't exist`);
|
|
||||||
}
|
|
||||||
if (!(folder instanceof TFolder)) {
|
|
||||||
throw new TemplaterError(`${folder_str} is a file, not a folder`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getFilesFromTheFolder(
|
|
||||||
app: App,
|
|
||||||
folder_str: string,
|
|
||||||
): Array<TFile> {
|
|
||||||
const folder = resolveFolder(app, folder_str);
|
|
||||||
|
|
||||||
const files: Array<TFile> = [];
|
|
||||||
Vault.recurseChildren(folder, (file: TAbstractFile) => {
|
|
||||||
if (file instanceof TFile) {
|
|
||||||
files.push(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
files.sort((a, b) => {
|
|
||||||
return a.basename.localeCompare(b.basename);
|
|
||||||
});
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
47
main.ts
47
main.ts
|
@ -1,13 +1,5 @@
|
||||||
import {
|
import { App, Plugin, PluginSettingTab, Setting, TFile } from 'obsidian';
|
||||||
App,
|
import { FolderSuggest } from './suggestions/folderSuggest';
|
||||||
FileManager,
|
|
||||||
Plugin,
|
|
||||||
PluginSettingTab,
|
|
||||||
Setting,
|
|
||||||
TAbstractFile,
|
|
||||||
TFile,
|
|
||||||
} from 'obsidian';
|
|
||||||
import { FolderSuggest } from './suggest/folderSuggest';
|
|
||||||
|
|
||||||
interface MyPluginSettings {
|
interface MyPluginSettings {
|
||||||
folderName: string;
|
folderName: string;
|
||||||
|
@ -95,6 +87,7 @@ class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFileLocation() {
|
renderFileLocation() {
|
||||||
const { settings } = this.plugin;
|
const { settings } = this.plugin;
|
||||||
new Setting(this.containerEl)
|
new Setting(this.containerEl)
|
||||||
|
@ -133,12 +126,14 @@ class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
text.setDisabled(true);
|
text.setDisabled(true);
|
||||||
const previewLabel = createPreviewElement();
|
const previewLabel = createPreviewElement();
|
||||||
text.inputEl.insertAdjacentElement('afterend', previewLabel);
|
text.inputEl.insertAdjacentElement('afterend', previewLabel);
|
||||||
|
text.inputEl.addClass('templater_cmd');
|
||||||
})
|
})
|
||||||
.addTextArea((text) => {
|
.addTextArea((text) => {
|
||||||
replacedPreviewTextArea = text.inputEl;
|
replacedPreviewTextArea = text.inputEl;
|
||||||
const value = getRenderedFileNamesReplaced(this.plugin);
|
const value = getRenderedFileNamesReplaced(this.plugin);
|
||||||
text.setValue(value);
|
text.setValue(value);
|
||||||
text.setDisabled(true);
|
text.setDisabled(true);
|
||||||
|
text.inputEl.addClass('templater_cmd');
|
||||||
})
|
})
|
||||||
.then((setting) => {
|
.then((setting) => {
|
||||||
syncScrolls(existingFilesTextArea, replacedPreviewTextArea, this.state);
|
syncScrolls(existingFilesTextArea, replacedPreviewTextArea, this.state);
|
||||||
|
@ -146,7 +141,6 @@ class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRenameFiles() {
|
renderRenameFiles() {
|
||||||
const { settings } = this.plugin;
|
|
||||||
new Setting(this.containerEl)
|
new Setting(this.containerEl)
|
||||||
.setName('Replace pattern')
|
.setName('Replace pattern')
|
||||||
.setDesc('Files in this folder will be available renamed.')
|
.setDesc('Files in this folder will be available renamed.')
|
||||||
|
@ -154,12 +148,19 @@ class BulkRenameSettingsTab extends PluginSettingTab {
|
||||||
button.setButtonText('Rename');
|
button.setButtonText('Rename');
|
||||||
button.onClick(() => {
|
button.onClick(() => {
|
||||||
const { replacePattern, existingSymbol } = this.plugin.settings;
|
const { replacePattern, existingSymbol } = this.plugin.settings;
|
||||||
const firstFile = this.plugin.settings.fileNames[0];
|
if (!replacePattern || !existingSymbol) {
|
||||||
console.log(firstFile);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.plugin.settings.fileNames.forEach((fileName) => {
|
||||||
|
this.app.fileManager.renameFile(
|
||||||
|
fileName,
|
||||||
|
replaceFilePath(this.plugin, fileName),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.addText((cb) => {});
|
.addText((cb) => {});
|
||||||
const fileManager = new FileManager();
|
|
||||||
this.plugin.settings.fileNames;
|
this.plugin.settings.fileNames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,24 +189,30 @@ const prepareFileNameString = (filesNames: TFile[]) => {
|
||||||
filesNames.forEach((fileName, index) => {
|
filesNames.forEach((fileName, index) => {
|
||||||
const isLast = index + 1 === filesNames.length;
|
const isLast = index + 1 === filesNames.length;
|
||||||
if (isLast) {
|
if (isLast) {
|
||||||
return (value += fileName.name);
|
return (value += fileName.path);
|
||||||
}
|
}
|
||||||
value += fileName.name + '\r\n';
|
value += fileName.path + '\r\n';
|
||||||
});
|
});
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRenderedFileNamesReplaced = (plugin: MyPlugin) => {
|
const getRenderedFileNamesReplaced = (plugin: MyPlugin) => {
|
||||||
const { fileNames, replacePattern, existingSymbol } = plugin.settings;
|
const { fileNames } = plugin.settings;
|
||||||
const newFiles = fileNames.map((file) => {
|
const newFiles = fileNames.map((file) => {
|
||||||
return {
|
return {
|
||||||
...file,
|
...file,
|
||||||
name: file.name.replaceAll(existingSymbol, replacePattern),
|
path: replaceFilePath(plugin, file),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return prepareFileNameString(newFiles);
|
return prepareFileNameString(newFiles);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const replaceFilePath = (plugin: MyPlugin, file: TFile) => {
|
||||||
|
const { replacePattern, existingSymbol } = plugin.settings;
|
||||||
|
|
||||||
|
return file.path.replaceAll(existingSymbol, replacePattern);
|
||||||
|
};
|
||||||
|
|
||||||
const createPreviewElement = () => {
|
const createPreviewElement = () => {
|
||||||
const previewLabel = window.document.createElement('span');
|
const previewLabel = window.document.createElement('span');
|
||||||
previewLabel.className = 'previewLabel';
|
previewLabel.className = 'previewLabel';
|
||||||
|
@ -220,14 +227,14 @@ const syncScrolls = (
|
||||||
state: State,
|
state: State,
|
||||||
) => {
|
) => {
|
||||||
existingFilesArea.addEventListener('scroll', (event) => {
|
existingFilesArea.addEventListener('scroll', (event) => {
|
||||||
const target = event.target;
|
const target = event.target as HTMLTextAreaElement;
|
||||||
if (target.scrollTop !== state.previewScroll) {
|
if (target.scrollTop !== state.previewScroll) {
|
||||||
previewArea.scrollTop = target.scrollTop;
|
previewArea.scrollTop = target.scrollTop;
|
||||||
state.previewScroll = target.scrollTop;
|
state.previewScroll = target.scrollTop;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
previewArea.addEventListener('scroll', (event) => {
|
previewArea.addEventListener('scroll', (event) => {
|
||||||
const target = event.target;
|
const target = event.target as HTMLTextAreaElement;
|
||||||
if (target.scrollTop !== state.filesScroll) {
|
if (target.scrollTop !== state.filesScroll) {
|
||||||
existingFilesArea.scrollTop = target.scrollTop;
|
existingFilesArea.scrollTop = target.scrollTop;
|
||||||
state.filesScroll = target.scrollTop;
|
state.filesScroll = target.scrollTop;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "obsidian-bulk-rename",
|
"name": "obsidian-bulk-rename",
|
||||||
"version": "1.0.0",
|
"version": "0.0.1",
|
||||||
"description": "Purpose of this plugin rename files based on pattern",
|
"description": "Purpose of this plugin rename files based on pattern",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes
|
|
||||||
|
|
||||||
import { App, TAbstractFile, TextAreaComponent, TFile } from 'obsidian';
|
|
||||||
import { TextInputSuggest } from './suggest';
|
|
||||||
import TemplaterPlugin from 'main';
|
|
||||||
import { errorWrapperSync } from '../errors/errors';
|
|
||||||
import { getFilesFromTheFolder } from '../files/files';
|
|
||||||
|
|
||||||
export class FileSuggest extends TextInputSuggest<TFile> {
|
|
||||||
constructor(
|
|
||||||
public app: App,
|
|
||||||
public inputEl: any,
|
|
||||||
private plugin: TemplaterPlugin,
|
|
||||||
) {
|
|
||||||
super(app, inputEl);
|
|
||||||
}
|
|
||||||
|
|
||||||
getFolder(): string {
|
|
||||||
return this.plugin.settings.mySetting;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_error_msg(): string {
|
|
||||||
return `Templates folder doesn't exist`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSuggestions(input_str: string): TFile[] {
|
|
||||||
const all_files = errorWrapperSync(
|
|
||||||
() => getFilesFromTheFolder(this.app, this.getFolder()),
|
|
||||||
this.get_error_msg(),
|
|
||||||
);
|
|
||||||
if (!all_files) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const files: TFile[] = [];
|
|
||||||
const lower_input_str = input_str.toLowerCase();
|
|
||||||
|
|
||||||
all_files.forEach((file: TAbstractFile) => {
|
|
||||||
if (
|
|
||||||
file instanceof TFile &&
|
|
||||||
file.extension === 'md' &&
|
|
||||||
file.path.toLowerCase().contains(lower_input_str)
|
|
||||||
) {
|
|
||||||
files.push(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSuggestion(file: TFile, el: HTMLElement): void {
|
|
||||||
el.setText(file.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectSuggestion(file: TFile): void {
|
|
||||||
this.inputEl.value = file.path;
|
|
||||||
this.inputEl.trigger('input');
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue