Skip to content

Commit

Permalink
feat: Add tp.app module with autocompletions
Browse files Browse the repository at this point in the history
  • Loading branch information
Zachatoo committed Oct 22, 2024
1 parent 165c8fd commit f8e3f65
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 12 deletions.
5 changes: 5 additions & 0 deletions docs/documentation.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[tp.app]
name = "app"
description = "This module exposes the app instance. Prefer to use this over the global app instance."


[tp.config]
name = "config"
description = """This module exposes Templater's running configuration.
Expand Down
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Settings](./settings.md)
- [FAQ](./faq.md)
- [Internal Functions](./internal-functions/overview.md)
- [tp.app](./internal-functions/internal-modules/app-module.md)
- [tp.config](./internal-functions/internal-modules/config-module.md)
- [tp.date](./internal-functions/internal-modules/date-module.md)
- [tp.file](./internal-functions/internal-modules/file-module.md)
Expand Down
26 changes: 26 additions & 0 deletions docs/src/internal-functions/internal-modules/app-module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# App Module

{{ tp.app.description }}

This is mostly useful when writing scripts.

Refer to the Obsidian [developer documentation](https://docs.obsidian.md/Reference/TypeScript+API/App) for more information.

## Examples

```javascript
// Get all folders
<%
tp.app.vault.getAllLoadedFiles()
.filter(x => x instanceof tp.obsidian.TFolder)
.map(x => x.name)
%>

// Update frontmatter of existing file
<%*
const file = tp.file.find_tfile("path/to/file");
await tp.app.fileManager.processFrontMatter(file, (frontmatter) => {
frontmatter["key"] = "value";
});
%>
```
4 changes: 2 additions & 2 deletions docs/src/internal-functions/internal-modules/hooks-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ Function documentation is using a specific syntax. More information [here](../..
<%*
tp.hooks.on_all_templates_executed(async () => {
const file = tp.file.find_tfile(tp.file.path(true));
await app.fileManager.processFrontMatter(file, (frontmatter) => {
await tp.app.fileManager.processFrontMatter(file, (frontmatter) => {
frontmatter["key"] = "value";
});
});
%>
// Run a command from another plugin that modifies the current file, after Templater has updated the file
<%*
tp.hooks.on_all_templates_executed(() => {
app.commands.executeCommandById("obsidian-linter:lint-file");
tp.app.commands.executeCommandById("obsidian-linter:lint-file");
});
-%>
```
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Refer to the Obsidian API [declaration file](https://github.com/obsidianmd/obsid
```javascript
// Get all folders
<%
app.vault.getAllLoadedFiles()
tp.app.vault.getAllLoadedFiles()
.filter(x => x instanceof tp.obsidian.TFolder)
.map(x => x.name)
%>
Expand Down
1 change: 1 addition & 0 deletions docs/src/internal-functions/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

The different internal variables and functions offered by [Templater](https://github.com/SilentVoid13/Templater) are available under different **modules**, to sort them. The existing **internal modules** are:

- [App module](./internal-modules/app-module.md): `tp.app`
- [Config module](./internal-modules/config-module.md): `tp.config`
- [Date module](./internal-modules/date-module.md): `tp.date`
- [File module](./internal-modules/file-module.md): `tp.file`
Expand Down
1 change: 1 addition & 0 deletions src/core/functions/FunctionsGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class FunctionsGenerator implements IGenerateObject {

additional_functions(): Record<string, unknown> {
return {
app: this.plugin.app,
obsidian: obsidian_module,
};
}
Expand Down
11 changes: 6 additions & 5 deletions src/editor/Autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class Autocomplete extends EditorSuggest<TpSuggestDocumentation> {
//private in_command = false;
// https://regex101.com/r/ocmHzR/1
private tp_keyword_regex =
/tp\.(?<module>[a-z]*)?(?<fn_trigger>\.(?<fn>[a-z_]*)?)?$/;
/tp\.(?<module>[a-z]*)?(?<fn_trigger>\.(?<fn>[a-zA-Z_.]*)?)?$/;
private documentation: Documentation;
private latest_trigger_info: EditorSuggestTriggerInfo;
private module_name: ModuleName | string;
Expand Down Expand Up @@ -76,15 +76,16 @@ export class Autocomplete extends EditorSuggest<TpSuggestDocumentation> {
let suggestions: Array<TpSuggestDocumentation>;
if (this.module_name && this.function_trigger) {
suggestions = this.documentation.get_all_functions_documentation(
this.module_name as ModuleName
this.module_name as ModuleName,
this.function_name
) as TpFunctionDocumentation[];
} else {
suggestions = this.documentation.get_all_modules_documentation();
}
if (!suggestions) {
return [];
}
return suggestions.filter((s) => s.name.startsWith(context.query));
return suggestions.filter((s) => s.queryKey.startsWith(context.query));
}

renderSuggestion(value: TpSuggestDocumentation, el: HTMLElement): void {
Expand All @@ -108,7 +109,7 @@ export class Autocomplete extends EditorSuggest<TpSuggestDocumentation> {
return;
}
active_editor.editor.replaceRange(
value.name,
value.queryKey,
this.latest_trigger_info.start,
this.latest_trigger_info.end
);
Expand All @@ -119,7 +120,7 @@ export class Autocomplete extends EditorSuggest<TpSuggestDocumentation> {
// beginning of the word after completion,
// Not sure what's the cause of this bug.
const cursor_pos = this.latest_trigger_info.end;
cursor_pos.ch += value.name.length;
cursor_pos.ch += value.queryKey.length;
active_editor.editor.setCursor(cursor_pos);
}
}
Expand Down
77 changes: 73 additions & 4 deletions src/editor/TpDocumentation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import TemplaterPlugin from "main";
import { errorWrapperSync } from "utils/Error";
import { get_tfiles_from_folder } from "utils/Utils";
import { get_fn_params, get_tfiles_from_folder, is_object } from "utils/Utils";
import documentation from "../../docs/documentation.toml";

const module_names = [
"app",
"config",
"date",
"file",
Expand All @@ -29,6 +30,7 @@ export type TpDocumentation = {

export type TpModuleDocumentation = {
name: string;
queryKey: string;
description: string;
functions: {
[key: string]: TpFunctionDocumentation;
Expand All @@ -37,6 +39,7 @@ export type TpModuleDocumentation = {

export type TpFunctionDocumentation = {
name: string;
queryKey: string;
definition: string;
description: string;
example: string;
Expand Down Expand Up @@ -69,12 +72,22 @@ export class Documentation {
constructor(private plugin: TemplaterPlugin) {}

get_all_modules_documentation(): TpModuleDocumentation[] {
return Object.values(this.documentation.tp);
return Object.values(this.documentation.tp).map((mod) => {
mod.queryKey = mod.name;
return mod;
});
}

get_all_functions_documentation(
module_name: ModuleName
module_name: ModuleName,
function_name: string
): TpFunctionDocumentation[] | undefined {
if (module_name === "app") {
return this.get_app_functions_documentation(
this.plugin.app,
function_name
);
}
if (module_name === "user") {
if (
!this.plugin.settings ||
Expand All @@ -97,6 +110,7 @@ export class Documentation {
...processedFiles,
{
name: file.basename,
queryKey: file.basename,
definition: "",
description: "",
example: "",
Expand All @@ -109,7 +123,62 @@ export class Documentation {
if (!this.documentation.tp[module_name].functions) {
return;
}
return Object.values(this.documentation.tp[module_name].functions);
return Object.values(this.documentation.tp[module_name].functions).map(
(mod) => {
mod.queryKey = mod.name;
return mod;
}
);
}

private get_app_functions_documentation(
obj: unknown,
path: string
): TpFunctionDocumentation[] {
if (!is_object(obj)) {
return [];
}
const parts = path.split(".");
if (parts.length === 0) {
return [];
}

let currentObj = obj;
for (let index = 0; index < parts.length - 1; index++) {
const part = parts[index];
if (part in currentObj) {
if (!is_object(currentObj[part])) {
return [];
}
currentObj = currentObj[part];
}
}

const definitionPrefix = [
"tp",
"app",
...parts.slice(0, parts.length - 1),
].join(".");
const queryKeyPrefix = parts.slice(0, parts.length - 1).join(".");
const docs: TpFunctionDocumentation[] = [];
for (const key in currentObj) {
const definition = `${definitionPrefix}.${key}`;
const queryKey = queryKeyPrefix ? `${queryKeyPrefix}.${key}` : key;
docs.push({
name: key,
queryKey,
definition:
typeof currentObj[key] === "function"
? `${definition}(${get_fn_params(
currentObj[key] as (...args: unknown[]) => unknown
)})`
: definition,
description: "",
example: "",
});
}

return docs;
}

get_module_documentation(module_name: ModuleName): TpModuleDocumentation {
Expand Down
13 changes: 13 additions & 0 deletions src/utils/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,16 @@ export function get_folder_path_from_file_path(path: string) {
if (path_separator !== -1) return path.slice(0, path_separator);
return "";
}

export function is_object(obj: unknown): obj is Record<string, unknown> {
return obj !== null && typeof obj === "object";
}

export function get_fn_params(func: (...args: unknown[]) => unknown) {
const str = func.toString();
const len = str.indexOf("(");
return str
.substring(len + 1, str.indexOf(")"))
.replace(/ /g, "")
.split(",");
}

0 comments on commit f8e3f65

Please sign in to comment.