Skip to content

Commit c7d62f4

Browse files
authored
Add option to use regex on file path instead of folder templates
Merge pull request #974 from harmtemolder/master refs: #471
2 parents 78d9484 + 4ba5ee9 commit c7d62f4

File tree

3 files changed

+228
-18
lines changed

3 files changed

+228
-18
lines changed

docs/src/settings.md

+44-13
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,58 @@
11
# Settings
22

3-
You can set a `Template folder location` to tell [Templater](https://github.com/SilentVoid13/Templater) to only check this folder for templates.
3+
## General Settings
44

5-
You can set a timeout for your system commands with the `Timeout` option. A system command that takes longer than what you defined will be canceled and considered as a failure.
5+
- `Template folder location`: Files in this folder will be available as templates.
6+
- `Syntax Highlighting on Desktop` adds syntax highlighting for [Templater](https://github.com/SilentVoid13/Templater) commands in edit mode.
7+
- `Syntax Highlighting on Mobile` adds syntax highlighting for [Templater](https://github.com/SilentVoid13/Templater) commands in edit mode on mobile. Use with caution: this may break live preview on mobile platforms."
8+
- `Automatic jump to cursor` automatically triggers `tp.file.cursor` after inserting a template. You can also set a hotkey to manually trigger `tp.file.cursor`.
9+
- `Trigger Templater on new file creation`: [Templater](https://github.com/SilentVoid13/Templater) will listen for the new file creation event, and, if it matches a rule you've set, replace every command it finds in the new file's content. This makes [Templater](https://github.com/SilentVoid13/Templater) compatible with other plugins like the Daily note core plugin, Calendar plugin, Review plugin, Note refactor plugin, etc.
10+
- Make sure to set up rules under either Folder Templates or File Regex Template below.
11+
- **Warning:** This can be dangerous if you create new files with unknown / unsafe content on creation. Make sure that every new file's content is safe on creation."
12+
- `Show icon in sidebar`: Show [Templater](https://github.com/SilentVoid13/Templater) icon in sidebar ribbon, allowing you to quickly use templates anywhere.
613

7-
You can set [Templater](https://github.com/SilentVoid13/Templater) to be triggered on new file creation. It will listen for the new file creation event and replace every command it finds in the new file's content.
14+
## Template Hotkeys
815

9-
This makes Templater compatible with other plugins like the Daily note core plugin, Calendar plugin, Review plugin, Note refactor plugin, ...
16+
Template Hotkeys allows you to bind a template to a hotkey.
1017

11-
## Security Warning
18+
## Folder Templates
1219

13-
It can be dangerous if you create new files with unknown / unsafe content on creation. Make sure that every new file's content is safe on creation.
20+
**Note**: This setting is hidden by default. To view it first enable the `Trigger Template on new file creation` setting. And since it's mutually exclusive with File Regex Templates, enabling one will disable the other.
1421

15-
## Folder Templates
22+
You can specify a template that will automatically be used on a selected folder and children using the `Folder Templates` functionality. The deepest match will be used, so the order of the rules is irrelevant.
23+
24+
Add a rule for "`/`" if you need a catch-all.
25+
26+
## File Regex Templates
27+
28+
**Note**: This setting is hidden by default. To view it first enable the `Trigger Template on new file creation` setting. And since it's mutually exclusive with Folder Templates, enabling one will disable the other.
29+
30+
You can specify regex declarations that a new file's path will be tested against. If a regex matches, the associated template will automatically be used. Rules are tested top-to-bottom, and the first match will be used.
31+
32+
End with a rule for "`.*`" if you need a catch-all.
33+
34+
Use a tool like [Regex101](https://regex101.com/) to verify your regexes.
35+
36+
## Startup Templates
37+
38+
Startup Templates are templates that will get executed once when Templater starts.
39+
40+
These templates won't output anything.
41+
42+
This can be useful to set up templates adding hooks to obsidian events for example.
43+
44+
## User Script Functions
45+
46+
All JavaScript files in this folder will be loaded as CommonJS modules, to import custom [user functions](./user-functions/overview.md).
1647

17-
You can specify a template that will automatically be used on a selected folder and children using the `Folder Templates` functionality.
48+
The folder needs to be accessible from the vault.
1849

19-
**Note**: This setting is hidden by default. To view it first enable the `Trigger Template on new file creation` setting.
50+
Check the [documentation](./user-functions/script-user-functions.md) for more information.
2051

21-
## System Commands
52+
## User System Command Functions
2253

23-
You can enable system commands. This allows you to create [user functions](./user-functions/overview.md) linked to system commands.
54+
Allows you to create [user functions](./user-functions/overview.md) linked to system commands.
2455

25-
### Arbitrary system commands
56+
Check the [documentation](./user-functions/system-user-functions.md) for more information.
2657

27-
It can be dangerous to execute arbitrary system commands from untrusted sources. Only run system commands that you understand, from trusted sources.
58+
**Warning:** It can be dangerous to execute arbitrary system commands from untrusted sources. Only run system commands that you understand, from trusted sources.

src/core/Templater.ts

+31
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,17 @@ export class Templater {
443443
} while (folder);
444444
}
445445

446+
get_new_file_template_for_file(file: TFile): string | undefined {
447+
const match = this.plugin.settings.file_templates.find((e) => {
448+
const eRegex = new RegExp(e.regex);
449+
return eRegex.test(file.path);
450+
});
451+
452+
if (match && match.template) {
453+
return match.template;
454+
}
455+
}
456+
446457
static async on_file_creation(
447458
templater: Templater,
448459
file: TAbstractFile
@@ -488,6 +499,26 @@ export class Templater {
488499
return;
489500
}
490501
await templater.write_template_to_file(template_file, file);
502+
} else if (
503+
file.stat.size == 0 &&
504+
templater.plugin.settings.enable_file_templates
505+
) {
506+
const file_template_match =
507+
templater.get_new_file_template_for_file(file);
508+
if (!file_template_match) {
509+
return;
510+
}
511+
const template_file: TFile = await errorWrapper(
512+
async (): Promise<TFile> => {
513+
return resolve_tfile(file_template_match);
514+
},
515+
`Couldn't find template ${file_template_match}`
516+
);
517+
// errorWrapper failed
518+
if (template_file == null) {
519+
return;
520+
}
521+
await templater.write_template_to_file(template_file, file);
491522
} else {
492523
if (file.stat.size <= 100000) {
493524
//https://github.com/SilentVoid13/Templater/issues/873

src/settings/Settings.ts

+153-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ export interface FolderTemplate {
1111
template: string;
1212
}
1313

14+
export interface FileTemplate {
15+
regex: string;
16+
template: string;
17+
}
18+
1419
export const DEFAULT_SETTINGS: Settings = {
1520
command_timeout: 5,
1621
templates_folder: "",
@@ -22,6 +27,8 @@ export const DEFAULT_SETTINGS: Settings = {
2227
user_scripts_folder: "",
2328
enable_folder_templates: true,
2429
folder_templates: [{ folder: "", template: "" }],
30+
enable_file_templates: false,
31+
file_templates: [{ regex: ".*", template: "" }],
2532
syntax_highlighting: true,
2633
syntax_highlighting_mobile: false,
2734
enabled_templates_hotkeys: [""],
@@ -39,6 +46,8 @@ export interface Settings {
3946
user_scripts_folder: string;
4047
enable_folder_templates: boolean;
4148
folder_templates: Array<FolderTemplate>;
49+
enable_file_templates: boolean;
50+
file_templates: Array<FileTemplate>;
4251
syntax_highlighting: boolean;
4352
syntax_highlighting_mobile: boolean;
4453
enabled_templates_hotkeys: Array<string>;
@@ -60,6 +69,7 @@ export class TemplaterSettingTab extends PluginSettingTab {
6069
this.add_trigger_on_new_file_creation_setting();
6170
if (this.plugin.settings.trigger_on_file_creation) {
6271
this.add_folder_templates_setting();
72+
this.add_file_templates_setting();
6373
}
6474
this.add_templates_hotkeys_setting();
6575
this.add_startup_templates_setting();
@@ -174,9 +184,12 @@ export class TemplaterSettingTab extends PluginSettingTab {
174184
add_trigger_on_new_file_creation_setting(): void {
175185
const desc = document.createDocumentFragment();
176186
desc.append(
177-
"Templater will listen for the new file creation event, and replace every command it finds in the new file's content.",
187+
"Templater will listen for the new file creation event, and, if it matches a rule you've set, replace every command it finds in the new file's content. ",
188+
"This makes Templater compatible with other plugins like the Daily note core plugin, Calendar plugin, Review plugin, Note refactor plugin, etc. ",
189+
desc.createEl("br"),
190+
desc.createEl("br"),
191+
"Make sure to set up rules under either Folder Templates or File Regex Template below.",
178192
desc.createEl("br"),
179-
"This makes Templater compatible with other plugins like the Daily note core plugin, Calendar plugin, Review plugin, Note refactor plugin, ...",
180193
desc.createEl("br"),
181194
desc.createEl("b", {
182195
text: "Warning: ",
@@ -343,7 +356,7 @@ export class TemplaterSettingTab extends PluginSettingTab {
343356

344357
const descUseNewFileTemplate = document.createDocumentFragment();
345358
descUseNewFileTemplate.append(
346-
"When enabled Templater will make use of the folder templates defined below."
359+
"When enabled, Templater will make use of the folder templates defined below. This option is mutually exclusive with File Regex Templates below, so enabling one will disable the other."
347360
);
348361

349362
new Setting(this.containerEl)
@@ -352,9 +365,12 @@ export class TemplaterSettingTab extends PluginSettingTab {
352365
.addToggle((toggle) => {
353366
toggle
354367
.setValue(this.plugin.settings.enable_folder_templates)
355-
.onChange((use_new_file_templates) => {
368+
.onChange((use_new_folder_templates) => {
356369
this.plugin.settings.enable_folder_templates =
357-
use_new_file_templates;
370+
use_new_folder_templates;
371+
if (use_new_folder_templates) {
372+
this.plugin.settings.enable_file_templates = false;
373+
}
358374
this.plugin.save_settings();
359375
// Force refresh
360376
this.display();
@@ -469,6 +485,138 @@ export class TemplaterSettingTab extends PluginSettingTab {
469485
});
470486
}
471487

488+
add_file_templates_setting(): void {
489+
this.containerEl.createEl("h2", { text: "File Regex Templates" });
490+
491+
const descHeading = document.createDocumentFragment();
492+
descHeading.append(
493+
"File Regex Templates are triggered when a new ",
494+
descHeading.createEl("strong", { text: "empty" }),
495+
" file is created that matches one of them. Templater will fill the empty file with the specified template."
496+
);
497+
498+
new Setting(this.containerEl).setDesc(descHeading);
499+
500+
const descUseNewFileTemplate = document.createDocumentFragment();
501+
descUseNewFileTemplate.append(
502+
"When enabled, Templater will make use of the file regex templates defined below. This option is mutually exclusive with Folder Templates above, so enabling one will disable the other."
503+
);
504+
505+
new Setting(this.containerEl)
506+
.setName("Enable File Regex Templates")
507+
.setDesc(descUseNewFileTemplate)
508+
.addToggle((toggle) => {
509+
toggle
510+
.setValue(this.plugin.settings.enable_file_templates)
511+
.onChange((use_new_file_templates) => {
512+
this.plugin.settings.enable_file_templates =
513+
use_new_file_templates;
514+
if (use_new_file_templates) {
515+
this.plugin.settings.enable_folder_templates =
516+
false;
517+
}
518+
this.plugin.save_settings();
519+
// Force refresh
520+
this.display();
521+
});
522+
});
523+
524+
if (!this.plugin.settings.enable_file_templates) {
525+
return;
526+
}
527+
528+
new Setting(this.containerEl)
529+
.setName("Add New")
530+
.setDesc(
531+
"Add new file regex. The first match from the top is used, so the order of the rules is important. Use `.*` as a final catch-all, if you need it."
532+
)
533+
.addButton((button: ButtonComponent) => {
534+
button
535+
.setTooltip("Add additional file regex")
536+
.setButtonText("+")
537+
.setCta()
538+
.onClick(() => {
539+
this.plugin.settings.file_templates.push({
540+
regex: "",
541+
template: "",
542+
});
543+
this.plugin.save_settings();
544+
this.display();
545+
});
546+
});
547+
548+
this.plugin.settings.file_templates.forEach((file_template, index) => {
549+
const s = new Setting(this.containerEl)
550+
.addText((cb) => {
551+
cb.setPlaceholder("File Regex")
552+
.setValue(file_template.regex)
553+
.onChange((new_regex) => {
554+
this.plugin.settings.file_templates[index].regex =
555+
new_regex;
556+
this.plugin.save_settings();
557+
});
558+
// @ts-ignore
559+
cb.inputEl.addClass("templater_search");
560+
})
561+
.addSearch((cb) => {
562+
new FileSuggest(
563+
cb.inputEl,
564+
this.plugin,
565+
FileSuggestMode.TemplateFiles
566+
);
567+
cb.setPlaceholder("Template")
568+
.setValue(file_template.template)
569+
.onChange((new_template) => {
570+
this.plugin.settings.file_templates[
571+
index
572+
].template = new_template;
573+
this.plugin.save_settings();
574+
});
575+
// @ts-ignore
576+
cb.containerEl.addClass("templater_search");
577+
})
578+
.addExtraButton((cb) => {
579+
cb.setIcon("up-chevron-glyph")
580+
.setTooltip("Move up")
581+
.onClick(() => {
582+
arraymove(
583+
this.plugin.settings.file_templates,
584+
index,
585+
index - 1
586+
);
587+
this.plugin.save_settings();
588+
this.display();
589+
});
590+
})
591+
.addExtraButton((cb) => {
592+
cb.setIcon("down-chevron-glyph")
593+
.setTooltip("Move down")
594+
.onClick(() => {
595+
arraymove(
596+
this.plugin.settings.file_templates,
597+
index,
598+
index + 1
599+
);
600+
this.plugin.save_settings();
601+
this.display();
602+
});
603+
})
604+
.addExtraButton((cb) => {
605+
cb.setIcon("cross")
606+
.setTooltip("Delete")
607+
.onClick(() => {
608+
this.plugin.settings.file_templates.splice(
609+
index,
610+
1
611+
);
612+
this.plugin.save_settings();
613+
this.display();
614+
});
615+
});
616+
s.infoEl.remove();
617+
});
618+
}
619+
472620
add_startup_templates_setting(): void {
473621
new Setting(this.containerEl).setName("Startup templates").setHeading();
474622

0 commit comments

Comments
 (0)