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,
} from './src/services/obsidian.service';
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 {
folderName: string;
@ -25,6 +32,10 @@ interface BulkRenamePluginSettings {
replacePattern: string;
tags: string[];
userRegExp: string;
regExpState: {
regExp: string;
flags: RegExpFlag[];
};
viewType: 'tags' | 'folder' | 'regexp';
}
@ -34,6 +45,10 @@ const DEFAULT_SETTINGS: BulkRenamePluginSettings = {
existingSymbol: '',
replacePattern: '',
userRegExp: '',
regExpState: {
regExp: '',
flags: [],
},
tags: [],
viewType: 'folder',
};
@ -158,7 +173,7 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
.setName('Folder location')
.setDesc('Find files within the folder')
.addSearch((cb) => {
new FolderSuggest(this.app, cb.inputEl);
new FolderSuggest(this.app, cb.inputEl, this.plugin);
cb.setPlaceholder('Example: folder1/')
.setValue(this.plugin.settings.folderName)
.onChange((newFolder) => {
@ -212,7 +227,9 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
new Setting(this.containerEl)
.setName('RegExp')
.setDesc('all files by titles will be found')
.addSearch((cb) => {
.addText((cb) => {
const backslash = createBackslash('/');
cb.inputEl.insertAdjacentElement('beforebegin', backslash);
// @ts-ignore
cb.inputEl.addEventListener('keydown', (event) => {
if (event.key !== 'Enter') {
@ -220,21 +237,40 @@ export class BulkRenameSettingsTab extends PluginSettingTab {
}
const target = event.target as HTMLInputElement;
this.plugin.settings.userRegExp = target.value;
this.plugin.settings.regExpState.regExp = target.value;
this.plugin.saveSettings();
});
cb.setPlaceholder('Example: #tag, #tag2')
.setValue(this.plugin.settings.userRegExp)
cb.setPlaceholder('Put your RegExp here')
.setValue(this.plugin.settings.regExpState.regExp)
.onChange((newFolder) => {
this.plugin.settings.userRegExp = newFolder;
this.plugin.settings.regExpState.regExp = newFolder;
this.plugin.saveSettings();
this.getFilesByRegExp();
});
// @ts-ignore
cb.containerEl.addClass('bulk_regexp');
cb.inputEl.addClass('bulk_input');
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();
});
cb.inputEl.addClass('bulk_regexp_flags');
})
.controlEl.addClass('bulk_regexp_control');
}
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 { createPopper, Instance as PopperInstance } from '@popperjs/core';
import BulkRenamePlugin from '../../main';
const wrapAround = (value: number, size: number): number => {
return ((value % size) + size) % size;
@ -104,6 +105,7 @@ class Suggest<T> {
export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
protected app: App;
protected plugin: BulkRenamePlugin;
protected inputEl: HTMLInputElement | HTMLTextAreaElement;
private popper: PopperInstance;
@ -111,7 +113,12 @@ export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
private suggestEl: HTMLElement;
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.inputEl = inputEl;
this.scope = new Scope();
@ -191,7 +198,7 @@ export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
this.suggestEl.detach();
}
abstract getSuggestions(inputStr: string): T[];
abstract getSuggestions(inputStr?: string): T[];
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;
}
.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%;
}
.bulk_regexp > input {
color: green;
padding: 0 28px 0 14px;
font-size: 20px;
font-weight: 700;
.bulk_regexp_flags {
caret-color: transparent;
}
.bulk_regexp:before {
content: '/';
top: 2px;
left: -15px;
.bulk_regexp_slash {
font-size: 1.5em;
opacity: 0.5;
}
.bulk_regexp:after {
content: '/';
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;
.bulk-flag-selected {
background-color: lavender !important;
}