Skip to content

Commit

Permalink
v0.3.0 (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
chhoumann authored Jul 2, 2021
1 parent 0b3be0f commit e581766
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 33 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ Quickly add new pages or content to your vault.
You can also do a [manual installation](docs/ManualInstallation.md).

## What's new?
### 0.3.0
- Link suggestion in the input prompt now uses your Obsidian link settings by default.
- Add error handling for using ``{{MACRO}}`` to execute a macro that does not exist.
- Input prompt can now also suggest unresolved links.
- Capped input prompt at 50 suggestions for performance in larger vaults.
- You can now offset dates with ``{{DATE+3}}`` or ``{{DATE:<format>+3}}``. `+3` gives you the date in three days, while `+-3` gives you the date three days ago.
- Added a new API feature which allows you to execute choices from within user scripts. These keep the current variables for the execution, so you can 'transfer' variables.

### 0.2.14 - 0.2.16
- Add 'Insert at the end of section' feature to Captures.
- Revamped the Capture & Template format suggesters. They're now more like smart-autocompleters.
Expand Down
4 changes: 2 additions & 2 deletions docs/FormatSyntax.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## `format` syntax
| Template | Description |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{DATE}}` | Outputs the current date in `YYYY-MM-DD` format. |
| `{{DATE:<DATEFORMAT>}}` | Replace `<DATEFORMAT>` with a [Moment.js date format](https://momentjs.com/docs/#/displaying/format/). |
| `{{DATE}}` | Outputs the current date in `YYYY-MM-DD` format. You could write `{{DATE+3}}` to offset the date with 3 days. You can use `+-3` to offset with `-3` days. |
| `{{DATE:<DATEFORMAT>}}` | Replace `<DATEFORMAT>` with a [Moment.js date format](https://momentjs.com/docs/#/displaying/format/). You could write `{{DATE<DATEFORMAT>+3}}` to offset the date with 3 days. |
| `{{VDATE:<variable name>, <date format>}}` | You'll get prompted to enter a date and it'll be parsed to the given date format. You could write 'today' or 'in two weeks' and it'll give you the date for that. Works like variables, so you can use the date in multiple places. **REQUIRES THE NATURAL LANGUAGE DATES PLUGIN!** |
| `{{VALUE}}` or `{{NAME}}` | Interchangeable. Represents the value given in an input prompt. If text is selected in the current editor, it will be used as the value. |
| `{{VALUE:<variable name>` | You can now use variable names in values. They'll get saved and inserted just like values, but the difference is that you can have as many of them as you want. Use comma separation to get a suggester rather than a prompt. |
Expand Down
5 changes: 5 additions & 0 deletions docs/QuickAddAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ Returns an array of the selected items.

This function is asynchronous. You should ``await`` it.

### ``executeChoice(choiceName: string)``
Executes choice with the given name.

This function is asynchronous. You should ``await`` it.

## Utility module
### ``getClipboard()``
Returns the contents of your clipboard.
Expand Down
4 changes: 2 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"id": "quickadd",
"name": "QuickAdd",
"version": "0.2.16",
"minAppVersion": "0.12.00",
"version": "0.3.0",
"minAppVersion": "0.12.5",
"description": "Quickly add new pages or content to your vault.",
"author": "Christian B. B. Houmann",
"authorUrl": "https://bagerbach.com",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "quickadd",
"version": "0.2.16",
"version": "0.3.0",
"description": "Quickly add new pages or content to your vault.",
"main": "main.js",
"scripts": {
Expand Down Expand Up @@ -29,7 +29,7 @@
"babel-jest": "27.0.1",
"jest": "27.0.1",
"jest-environment-node": "27.0.1",
"obsidian": "^0.12.0",
"obsidian": "0.12.5",
"rollup": "^2.32.1",
"rollup-plugin-strip-code": "0.2.7",
"rollup-plugin-svelte": "^7.1.0",
Expand Down
1 change: 1 addition & 0 deletions src/IChoiceExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import type IChoice from "./types/choices/IChoice";

export interface IChoiceExecutor {
execute(choice: IChoice): Promise<void>;
variables: Map<string, string>;
}
2 changes: 1 addition & 1 deletion src/choiceExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type IMultiChoice from "./types/choices/IMultiChoice";
import ChoiceSuggester from "./gui/choiceSuggester";

export class ChoiceExecutor implements IChoiceExecutor {
private variables: Map<string, string> = new Map<string, string>();
public variables: Map<string, string> = new Map<string, string>();

constructor(private app: App, private plugin: QuickAdd) { }

Expand Down
6 changes: 4 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ export const FILE_NAME_FORMAT_SYNTAX: string[] = [
]

export const FILE_NUMBER_REGEX: RegExp = new RegExp(/([0-9]*)\.md$/);
export const DATE_REGEX: RegExp = new RegExp(/{{DATE(\+[0-9]*)?}}/);
export const DATE_REGEX_FORMATTED: RegExp = new RegExp(/{{DATE:([^}\n\r+]*)(\+[0-9]*)?}}/);
export const NUMBER_REGEX: RegExp = new RegExp(/^-?[0-9]*$/);

export const DATE_REGEX: RegExp = new RegExp(/{{DATE(\+-?[0-9]+)?}}/);
export const DATE_REGEX_FORMATTED: RegExp = new RegExp(/{{DATE:([^}\n\r+]*)(\+-?[0-9]+)?}}/);
export const NAME_VALUE_REGEX: RegExp = new RegExp(/{{NAME}}|{{VALUE}}/);
export const VARIABLE_REGEX: RegExp = new RegExp(/{{VALUE:([^\n\r}]*)}}/);
export const DATE_VARIABLE_REGEX: RegExp = new RegExp(/{{VDATE:([^\n\r},]*),\s*([^\n\r},]*)}}/);
Expand Down
3 changes: 2 additions & 1 deletion src/engine/MacroChoiceEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type {IWaitCommand} from "../types/macros/QuickCommands/IWaitCommand";

export class MacroChoiceEngine extends QuickAddChoiceEngine {
public choice: IMacroChoice;
public params = {app: this.app, quickAddApi: QuickAddApi.GetApi(this.app), variables: {}};
public params;
protected output: string;
protected macros: IMacro[];
protected choiceExecutor: IChoiceExecutor;
Expand All @@ -33,6 +33,7 @@ export class MacroChoiceEngine extends QuickAddChoiceEngine {
this.plugin = plugin;
this.macros = macros;
this.choiceExecutor = choiceExecutor;
this.params = {app: this.app, quickAddApi: QuickAddApi.GetApi(app, plugin, choiceExecutor), variables: {}};

variables?.forEach(((value, key) => {
this.params.variables[key] = value;
Expand Down
6 changes: 5 additions & 1 deletion src/engine/SingleMacroEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {MacroChoiceEngine} from "./MacroChoiceEngine";
import type QuickAdd from "../main";
import type {IChoiceExecutor} from "../IChoiceExecutor";
import {getUserScriptMemberAccess} from "../utility";
import {log} from "../logger/logManager";

export class SingleMacroEngine extends MacroChoiceEngine {
private memberAccess: string[];
Expand All @@ -15,7 +16,10 @@ export class SingleMacroEngine extends MacroChoiceEngine {
public async runAndGetOutput(macroName: string): Promise<string> {
const {basename, memberAccess} = getUserScriptMemberAccess(macroName);
const macro = this.macros.find(macro => macro.name === basename);
if (!macro) return;
if (!macro) {
log.logError(`macro '${macroName}' does not exist.`)
return;
}

if (memberAccess && memberAccess.length > 0) {
this.memberAccess = memberAccess;
Expand Down
1 change: 1 addition & 0 deletions src/formatters/completeFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class CompleteFormatter extends Formatter {

constructor(protected app: App, private plugin: QuickAdd, protected choiceExecutor: IChoiceExecutor) {
super();
this.variables = choiceExecutor.variables;
}

protected async format(input: string): Promise<string> {
Expand Down
22 changes: 16 additions & 6 deletions src/formatters/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {
DATE_VARIABLE_REGEX, LINEBREAK_REGEX,
LINK_TO_CURRENT_FILE_REGEX,
MACRO_REGEX,
NAME_VALUE_REGEX, TEMPLATE_REGEX,
NAME_VALUE_REGEX, NUMBER_REGEX, TEMPLATE_REGEX,
VARIABLE_REGEX
} from "../constants";
import {getDate} from "../utility";
import {match} from "assert";

export abstract class Formatter {
protected value: string;
Expand All @@ -20,17 +21,26 @@ export abstract class Formatter {

while (DATE_REGEX.test(output)) {
const dateMatch = DATE_REGEX.exec(output);
let offset: string = dateMatch[1]
if (offset)
offset = offset.replace('+', '');
let offset: number;

if (dateMatch[1]) {
const offsetString = dateMatch[1].replace('+', '').trim();
const offsetIsInt = NUMBER_REGEX.test(offsetString);
if (offsetIsInt) offset = parseInt(offsetString);
}
output = output.replace(DATE_REGEX, getDate({offset: offset}));
}

while (DATE_REGEX_FORMATTED.test(output)) {
const dateMatch = DATE_REGEX_FORMATTED.exec(output);
const format = dateMatch[1].replace('+', '');
const offset = parseInt(dateMatch[2]);
const format = dateMatch[1]
let offset: number;

if (dateMatch[2]) {
const offsetString = dateMatch[2].replace('+', '').trim();
const offsetIsInt = NUMBER_REGEX.test(offsetString);
if (offsetIsInt) offset = parseInt(offsetString);
}

output = output.replace(DATE_REGEX_FORMATTED, getDate({format, offset}));
}
Expand Down
55 changes: 48 additions & 7 deletions src/gui/silentFileAndTagSuggester.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {TextInputSuggest} from "./suggest";
import type {App} from "obsidian";
import type {App, TAbstractFile} from "obsidian";
import {TFile} from "obsidian";
import {FILE_LINK_REGEX, TAG_REGEX} from "../constants";

enum TagOrFile {
Expand All @@ -9,12 +10,15 @@ enum TagOrFile {
export class SilentFileAndTagSuggester extends TextInputSuggest<string> {
private lastInput: string = "";
private lastInputType: TagOrFile;
private fileNames: string[];
private files: TFile[];
private unresolvedLinkNames: string[];
private tags: string[];

constructor(public app: App, public inputEl: HTMLInputElement) {
super(app, inputEl);
this.fileNames = app.vault.getMarkdownFiles().map(f => f.basename);
this.files = app.vault.getMarkdownFiles();
this.unresolvedLinkNames = this.getUnresolvedLinkNames(app);

// @ts-ignore
this.tags = Object.keys(app.metadataCache.getTags());
}
Expand All @@ -38,10 +42,13 @@ export class SilentFileAndTagSuggester extends TextInputSuggest<string> {
const fileNameInput: string = fileLinkMatch[1];
this.lastInput = fileNameInput;
this.lastInputType = TagOrFile.File;
suggestions = this.fileNames.filter(filePath => filePath.toLowerCase().contains(fileNameInput.toLowerCase()));
suggestions = this.files
.filter(file => file.path.toLowerCase().contains(fileNameInput.toLowerCase()))
.map(file => file.path);
suggestions.push(...this.unresolvedLinkNames.filter(name => name.toLowerCase().contains(fileNameInput.toLowerCase())));
}

return suggestions;
return suggestions.slice(0, 50);
}

renderSuggestion(item: string, el: HTMLElement): void {
Expand All @@ -55,8 +62,14 @@ export class SilentFileAndTagSuggester extends TextInputSuggest<string> {
let insertedEndPosition: number = 0;

if (this.lastInputType === TagOrFile.File) {
this.inputEl.value = this.getNewInputValueForFileName(currentInputValue, item, cursorPosition, lastInputLength);
insertedEndPosition = cursorPosition - lastInputLength + item.length + 2;
const linkFile: TAbstractFile = this.app.vault.getAbstractFileByPath(item);

if (linkFile instanceof TFile) {
insertedEndPosition = this.makeLinkObsidianMethod(linkFile, currentInputValue, cursorPosition, lastInputLength);
} else {
insertedEndPosition = this.makeLinkManually(currentInputValue, item.replace(/.md$/, ''), cursorPosition, lastInputLength);
}

}

if (this.lastInputType === TagOrFile.Tag) {
Expand All @@ -69,11 +82,39 @@ export class SilentFileAndTagSuggester extends TextInputSuggest<string> {
this.inputEl.setSelectionRange(insertedEndPosition, insertedEndPosition);
}

private makeLinkObsidianMethod(linkFile: TFile, currentInputValue: string, cursorPosition: number, lastInputLength: number) {
const link = this.app.fileManager.generateMarkdownLink(linkFile, '');
this.inputEl.value = this.getNewInputValueForFileLink(currentInputValue, link, cursorPosition, lastInputLength);
return cursorPosition - lastInputLength + link.length + 2;
}

private makeLinkManually(currentInputValue: string, item: string, cursorPosition: number, lastInputLength: number) {
this.inputEl.value = this.getNewInputValueForFileName(currentInputValue, item, cursorPosition, lastInputLength);
return cursorPosition - lastInputLength + item.length + 2;
}

private getNewInputValueForFileLink(currentInputElValue: string, selectedItem: string, cursorPosition: number, lastInputLength: number): string {
return `${currentInputElValue.substr(0, cursorPosition - lastInputLength - 2)}${selectedItem}${currentInputElValue.substr(cursorPosition)}`;
}

private getNewInputValueForFileName(currentInputElValue: string, selectedItem: string, cursorPosition: number, lastInputLength: number): string {
return `${currentInputElValue.substr(0, cursorPosition - lastInputLength)}${selectedItem}]]${currentInputElValue.substr(cursorPosition)}`;
}

private getNewInputValueForTag(currentInputElValue: string, selectedItem: string, cursorPosition: number, lastInputLength: number) {
return `${currentInputElValue.substr(0, cursorPosition - lastInputLength - 1)}${selectedItem}${currentInputElValue.substr(cursorPosition)}`;
}

private getUnresolvedLinkNames(app: App): string[] {
const unresolvedLinks: Record<string, Record<string, number>> = app.metadataCache.unresolvedLinks;
const unresolvedLinkNames: Set<string> = new Set<string>();

for (const sourceFileName in unresolvedLinks) {
for (const unresolvedLink in unresolvedLinks[sourceFileName]) {
unresolvedLinkNames.add(unresolvedLink);
}
}

return Array.from(unresolvedLinkNames);
}
}
16 changes: 16 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ export default class QuickAdd extends Plugin {
}
}

public getChoice(choiceName: string): IChoice {
return this.settings.choices.find((choice) => this.getChoiceHelper(choiceName, choice));
}

private getChoiceHelper(targetChoiceName: string, currentChoice: IChoice) {
if (currentChoice.type === ChoiceType.Multi) {
let foundChoice: IChoice = (currentChoice as IMultiChoice).choices
.find((choice) => this.getChoiceHelper(targetChoiceName, choice));

if (foundChoice) return foundChoice;
}

if (currentChoice.name === targetChoiceName)
return currentChoice;
}

public removeCommandForChoice(choice: IChoice) {
deleteObsidianCommand(this.app, `quickadd:choice:${choice.id}`);
}
Expand Down
12 changes: 11 additions & 1 deletion src/quickAddApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@ import GenericYesNoPrompt from "./gui/GenericYesNoPrompt/GenericYesNoPrompt";
import GenericSuggester from "./gui/GenericSuggester/genericSuggester";
import type {App} from "obsidian";
import GenericCheckboxPrompt from "./gui/GenericCheckboxPrompt/genericCheckboxPrompt";
import type {IChoiceExecutor} from "./IChoiceExecutor";
import type QuickAdd from "./main";
import type IChoice from "./types/choices/IChoice";
import {log} from "./logger/logManager";

export class QuickAddApi {
public static GetApi(app: App) {
public static GetApi(app: App, plugin: QuickAdd, choiceExecutor: IChoiceExecutor) {
return {
inputPrompt: (header: string, placeholder?: string, value?: string) => {return this.inputPrompt(app, header, placeholder, value)},
yesNoPrompt: (header: string, text?: string) => {return this.yesNoPrompt(app, header, text)},
suggester: (displayItems: string[] | ((value: string, index?: number, arr?: string[]) => string[]), actualItems: string[]) => {return this.suggester(app, displayItems, actualItems)},
checkboxPrompt: (items: string[], selectedItems?: string[]) => {return this.checkboxPrompt(app, items, selectedItems)},
executeChoice: async (choiceName: string) => {
const choice: IChoice = plugin.getChoice(choiceName);
if (!choice) log.logError(`choice named '${choiceName}' not found`);

await choiceExecutor.execute(choice);
},
utility: {
getClipboard: async () => {return await navigator.clipboard.readText()},
setClipboard: async (text: string) => {return await navigator.clipboard.writeText(text)}
Expand Down
12 changes: 5 additions & 7 deletions src/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,15 @@ export function getNaturalLanguageDates(app: App) {
return app.plugins.plugins["nldates-obsidian"];
}

export function getDate(input?: {format?: string, offset?: number|string}) {
export function getDate(input?: {format?: string, offset?: number}) {
let duration;

if (input.offset) {
if(typeof input.offset === "string")
duration = window.moment.duration(input.offset);
else if (typeof input.offset === "number")
duration = window.moment.duration(input.offset, "days");
if (input.offset !== null && input.offset !== undefined && typeof input.offset === "number") {
duration = window.moment.duration(input.offset, "days");
}

return input.format ? window.moment().add(duration).format(input.format) : window.moment().add(duration).format("YYYY-MM-DD");
return input.format ? window.moment().add(duration).format(input.format)
: window.moment().add(duration).format("YYYY-MM-DD");
}

export function appendToCurrentLine(toAppend: string, app: App) {
Expand Down
3 changes: 2 additions & 1 deletion versions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"0.2.16": "0.12.4"
"0.2.16": "0.12.4",
"0.3.0": "0.12.5"
}

0 comments on commit e581766

Please sign in to comment.