add suggestions for regExp flags, mark selected flags, make regExp field looks pretty

This commit is contained in:
Oleh Lustenko 2022-09-18 08:33:58 +03:00
parent 470dd8176d
commit 7ddd6525c6
6 changed files with 146 additions and 36 deletions

54
main.ts
View File

@ -17,6 +17,13 @@ import {
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 {
REGEXP_FLAGS,
RegExpFlag,
RegExpFlags,
} from './src/constants/RegExpFlags';
import { RegExpFlagsSuggest } from './src/suggestions/RegExpFlagsSuggest';
interface BulkRenamePluginSettings { interface BulkRenamePluginSettings {
folderName: string; folderName: string;
@ -25,6 +32,10 @@ interface BulkRenamePluginSettings {
replacePattern: string; replacePattern: string;
tags: string[]; tags: string[];
userRegExp: string; userRegExp: string;
regExpState: {
regExp: string;
flags: RegExpFlag[];
};
viewType: 'tags' | 'folder' | 'regexp'; viewType: 'tags' | 'folder' | 'regexp';
} }
@ -34,6 +45,10 @@ const DEFAULT_SETTINGS: BulkRenamePluginSettings = {
existingSymbol: '', existingSymbol: '',
replacePattern: '', replacePattern: '',
userRegExp: '', userRegExp: '',
regExpState: {
regExp: '',
flags: [],
},
tags: [], tags: [],
viewType: 'folder', viewType: 'folder',
}; };
@ -158,7 +173,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) => {
@ -212,7 +227,9 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
new Setting(this.containerEl) new Setting(this.containerEl)
.setName('RegExp') .setName('RegExp')
.setDesc('all files by titles will be found') .setDesc('all files by titles will be found')
.addSearch((cb) => { .addText((cb) => {
const backslash = createBackslash('/');
cb.inputEl.insertAdjacentElement('beforebegin', backslash);
// @ts-ignore // @ts-ignore
cb.inputEl.addEventListener('keydown', (event) => { cb.inputEl.addEventListener('keydown', (event) => {
if (event.key !== 'Enter') { if (event.key !== 'Enter') {
@ -220,21 +237,40 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
} }
const target = event.target as HTMLInputElement; const target = event.target as HTMLInputElement;
this.plugin.settings.userRegExp = target.value; this.plugin.settings.regExpState.regExp = target.value;
this.plugin.saveSettings(); this.plugin.saveSettings();
}); });
cb.setPlaceholder('Example: #tag, #tag2') cb.setPlaceholder('Put your RegExp here')
.setValue(this.plugin.settings.userRegExp) .setValue(this.plugin.settings.regExpState.regExp)
.onChange((newFolder) => { .onChange((newFolder) => {
this.plugin.settings.userRegExp = newFolder; this.plugin.settings.regExpState.regExp = newFolder;
this.plugin.saveSettings(); this.plugin.saveSettings();
this.getFilesByRegExp(); this.getFilesByRegExp();
}); });
// @ts-ignore // @ts-ignore
cb.containerEl.addClass('bulk_regexp'); cb.inputEl.addClass('bulk_regexp');
cb.inputEl.addClass('bulk_input');
cb.inputEl.onblur = this.reRenderPreview; 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();
});
cb.inputEl.addClass('bulk_regexp_flags');
})
.controlEl.addClass('bulk_regexp_control');
} }
renderReplaceSymbol() { renderReplaceSymbol() {

View File

@ -0,0 +1,6 @@
export const createBackslash = (textContent = '=> => => =>') => {
const previewLabel = window.document.createElement('div');
previewLabel.className = 'bulk_regexp_slash';
previewLabel.textContent = textContent;
return previewLabel;
};

View File

@ -0,0 +1,26 @@
export type RegExpFlag =
| 'g'
| 'm'
| 'i'
| 'x'
| 's'
| 'u'
| 'U'
| 'A'
| 'J'
| 'D';
export const REGEXP_FLAGS = [
'g',
'm',
'i',
'x',
's',
'u',
'U',
'A',
'J',
'D',
] as const;
export type RegExpFlags = typeof REGEXP_FLAGS;

View File

@ -0,0 +1,42 @@
// 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 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');
// this.settings.plugin.settings.regExpState.flags.push(file);
// this.inputEl.trigger('input');
// this.close();
};
}

View File

@ -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;
} }

View File

@ -24,35 +24,28 @@
margin-right: 15px; margin-right: 15px;
} }
.bulk_regexp { .bulk_regexp_control {
border: 1px solid var(--background-modifier-border);
}
.bulk_regexp_control > input {
border: none;
}
.bulk_regexp,
.bulk_regexp_flags {
width: 100%; width: 100%;
} }
.bulk_regexp > input { .bulk_regexp_flags {
color: green; caret-color: transparent;
padding: 0 28px 0 14px;
font-size: 20px;
font-weight: 700;
} }
.bulk_regexp:before { .bulk_regexp_slash {
content: '/'; font-size: 1.5em;
top: 2px; opacity: 0.5;
left: -15px;
} }
.bulk_regexp:after { .bulk-flag-selected {
content: '/'; background-color: lavender !important;
bottom: 5px;
right: -15px;
}
.bulk_regexp:before,
.bulk_regexp:after {
color: #000080;
font-size: 30px;
/*background-color: #cccccc;*/
display: block;
/*text-align: center;*/
position: absolute;
} }