Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Insert After can now create the line on your current cursor position, not just top/bottom of the note. #641

Merged
merged 3 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const NUMBER_REGEX = new RegExp(/^-?[0-9]*$/);

export const CREATE_IF_NOT_FOUND_TOP = "top";
export const CREATE_IF_NOT_FOUND_BOTTOM = "bottom";
export const CREATE_IF_NOT_FOUND_CURSOR = "cursor";

// == Format Syntax == //
export const DATE_REGEX = new RegExp(/{{DATE(\+-?[0-9]+)?}}/i);
Expand Down
93 changes: 36 additions & 57 deletions src/engine/CaptureChoiceEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,53 +30,49 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
app: App,
plugin: QuickAdd,
choice: ICaptureChoice,
private choiceExecutor: IChoiceExecutor
private choiceExecutor: IChoiceExecutor,
) {
super(app);
this.choice = choice;
this.plugin = plugin;
this.formatter = new CaptureChoiceFormatter(
app,
plugin,
choiceExecutor
);
this.formatter = new CaptureChoiceFormatter(app, plugin, choiceExecutor);
}

async run(): Promise<void> {
try {
const filePath = await this.getFormattedPathToCaptureTo(
this.choice.captureToActiveFile
this.choice.captureToActiveFile,
);
const content = this.getCaptureContent();

let getFileAndAddContentFn: typeof this.onFileExists;

if (await this.fileExists(filePath)) {
getFileAndAddContentFn = this.onFileExists.bind(
this
this,
) as typeof this.onFileExists;
} else if (this.choice?.createFileIfItDoesntExist?.enabled) {
getFileAndAddContentFn = this.onCreateFileIfItDoesntExist.bind(
this
this,
) as typeof this.onCreateFileIfItDoesntExist;
} else {
log.logWarning(
`The file ${filePath} does not exist and "Create file if it doesn't exist" is disabled.`
`The file ${filePath} does not exist and "Create file if it doesn't exist" is disabled.`,
);
return;
}

const { file, newFileContent, captureContent } =
await getFileAndAddContentFn(filePath, content);

if (this.choice.captureToActiveFile && !this.choice.prepend && !this.choice.insertAfter.enabled) {
if (
this.choice.captureToActiveFile &&
!this.choice.prepend &&
!this.choice.insertAfter.enabled
) {
// Parse Templater syntax in the capture content.
// If Templater isn't installed, it just returns the capture content.
const content = await templaterParseTemplate(
app,
captureContent,
file
);
const content = await templaterParseTemplate(app, captureContent, file);

appendToCurrentLine(content, this.app);
} else {
Expand All @@ -86,7 +82,7 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
if (this.choice.appendLink) {
const markdownLink = this.app.fileManager.generateMarkdownLink(
file,
""
"",
);

appendToCurrentLine(markdownLink, this.app);
Expand Down Expand Up @@ -127,14 +123,11 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
* if the capture path is invalid, or if the target folder is empty.
*/
private async getFormattedPathToCaptureTo(
shouldCaptureToActiveFile: boolean
shouldCaptureToActiveFile: boolean,
): Promise<string> {
if (shouldCaptureToActiveFile) {
const activeFile = this.app.workspace.getActiveFile();
invariant(
activeFile,
`Cannot capture to active file - no active file.`
);
invariant(activeFile, "Cannot capture to active file - no active file.");

return activeFile.path;
}
Expand All @@ -144,10 +137,7 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {

// Removing the trailing slash from the capture to path because otherwise isFolder will fail
// to get the folder.
const folderPath = formattedCaptureTo.replace(
/^\/$|\/\.md$|^\.md$/,
""
);
const folderPath = formattedCaptureTo.replace(/^\/$|\/\.md$|^\.md$/, "");
// Empty string means we suggest to capture anywhere in the vault.
const captureAnywhereInVault = folderPath === "";
const shouldCaptureToFolder =
Expand All @@ -168,29 +158,26 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {

private async selectFileInFolder(
folderPath: string,
captureAnywhereInVault: boolean
captureAnywhereInVault: boolean,
): Promise<string> {
const folderPathSlash =
folderPath.endsWith("/") || captureAnywhereInVault
? folderPath
: `${folderPath}/`;
const filesInFolder = getMarkdownFilesInFolder(folderPathSlash);

invariant(
filesInFolder.length > 0,
`Folder ${folderPathSlash} is empty.`
);
invariant(filesInFolder.length > 0, `Folder ${folderPathSlash} is empty.`);

const filePaths = filesInFolder.map((f) => f.path);
const targetFilePath = await InputSuggester.Suggest(
app,
filePaths.map((item) => item.replace(folderPathSlash, "")),
filePaths
filePaths,
);

invariant(
!!targetFilePath && targetFilePath.length > 0,
`No file selected for capture.`
"No file selected for capture.",
);

// Ensure user has selected a file in target folder. InputSuggester allows user to write
Expand All @@ -212,20 +199,20 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
const targetFilePath = await InputSuggester.Suggest(
app,
filePaths,
filePaths
filePaths,
);

invariant(
!!targetFilePath && targetFilePath.length > 0,
`No file selected for capture.`
"No file selected for capture.",
);

return await this.formatFilePath(targetFilePath);
}

private async onFileExists(
filePath: string,
content: string
content: string,
): Promise<{
file: TFile;
newFileContent: string;
Expand All @@ -245,7 +232,7 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
formatted,
this.choice,
fileContent,
file
file,
);

const secondReadFileContent: string = await this.app.vault.read(file);
Expand All @@ -255,14 +242,12 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
const res = merge(
secondReadFileContent,
fileContent,
formattedFileContent
formattedFileContent,
);
invariant(
!res.isSuccess,
() =>
`The file ${filePath} has been modified since the last read.` +
`\nQuickAdd could not merge the versions two without conflicts, and will not modify the file.` +
`\nThis is in order to prevent data loss.`
`The file ${filePath} has been modified since the last read.\nQuickAdd could not merge the versions two without conflicts, and will not modify the file.\nThis is in order to prevent data loss.`,
);

newFileContent = res.joinedResults() as string;
Expand All @@ -273,7 +258,7 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {

private async onCreateFileIfItDoesntExist(
filePath: string,
captureContent: string
captureContent: string,
): Promise<{
file: TFile;
newFileContent: string;
Expand All @@ -287,36 +272,30 @@ export class CaptureChoiceEngine extends QuickAddChoiceEngine {
this.app,
this.plugin,
this.choice.createFileIfItDoesntExist.template,
this.choiceExecutor
this.choiceExecutor,
);

fileContent = await singleTemplateEngine.run();
}

const file: TFile = await this.createFileWithInput(
filePath,
fileContent
);
const file: TFile = await this.createFileWithInput(filePath, fileContent);
await replaceTemplaterTemplatesInCreatedFile(this.app, file);

const updatedFileContent: string = await this.app.vault.cachedRead(
file
const updatedFileContent: string = await this.app.vault.cachedRead(file);
const newFileContent: string = await this.formatter.formatContentWithFile(
captureContent,
this.choice,
updatedFileContent,
file,
);
const newFileContent: string =
await this.formatter.formatContentWithFile(
captureContent,
this.choice,
updatedFileContent,
file
);

return { file, newFileContent, captureContent };
}

private async formatFilePath(captureTo: string) {
const formattedCaptureTo: string = await this.formatter.formatFileName(
captureTo,
this.choice.name
this.choice.name,
);

return this.normalizeMarkdownFilePath("", formattedCaptureTo);
Expand Down
Loading
Loading