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

Add negative tags #952

Closed
wants to merge 9 commits into from
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
- RTL support https://github.com/st3v3nmw/obsidian-spaced-repetition/issues/335
- Fixed notes selection when all notes are reviewed. [`#548`](https://github.com/st3v3nmw/obsidian-spaced-repetition/issues/548)

- Added option for 'negative' review tags (i.e. `-#unread`). [@bitesizing](https://github.com/bitesizing)

#### [1.12.4](https://github.com/st3v3nmw/obsidian-spaced-repetition/compare/1.12.3...1.12.4)

- chore: fix package manager issue in CI [`#939`](https://github.com/st3v3nmw/obsidian-spaced-repetition/pull/939)
10 changes: 9 additions & 1 deletion docs/en/notes.md
Original file line number Diff line number Diff line change
@@ -7,7 +7,15 @@

## Getting started

Tag any notes that you'd like to review as `#review`. This default tag can be changed in the settings. (You can also use multiple tags)
Tag any notes that you'd like to review as `#review`.

## Tagging

Review tags can be changed in the settings. You can have multiple review tags.

Additionally, if you want to ignore tags, you can tag them with a '-' before the hashtag (e.g. `-#unread`). Notes with negative review tags will be ignored even if they also have positive review tags.

If a note has multiple review tags, it will be listed under the first relevant tag.

## New Notes

3 changes: 2 additions & 1 deletion src/lang/locale/en.ts
Original file line number Diff line number Diff line change
@@ -106,7 +106,8 @@ export default {
NOTES: "Notes",
REVIEW_PANE_ON_STARTUP: "Enable note review pane on startup",
TAGS_TO_REVIEW: "Tags to review",
TAGS_TO_REVIEW_DESC: "Enter tags separated by spaces or newlines i.e. #review #tag2 #tag3.",
TAGS_TO_REVIEW_DESC:
"Enter tags separated by spaces or newlines i.e. #review -#unread #paper. Notes with negative tags (i.e. -#unread) will be ignored even if a note also contains review tags.",
OPEN_RANDOM_NOTE: "Open a random note for review",
OPEN_RANDOM_NOTE_DESC: "When you turn this off, notes are ordered by importance (PageRank).",
AUTO_NEXT_NOTE: "Open next note automatically after a review",
50 changes: 31 additions & 19 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -380,6 +380,7 @@ export default class SRPlugin extends Plugin {

const notes: TFile[] = this.app.vault.getMarkdownFiles();
for (const noteFile of notes) {
// for each file in the vault...?
if (
this.data.settings.noteFoldersToIgnore.some((folder) =>
isEqualOrSubPath(noteFile.path, folder),
@@ -426,34 +427,47 @@ export default class SRPlugin extends Plugin {
fileCachedData.frontmatter || {};
const tags = getAllTags(fileCachedData) || [];

let shouldIgnore = true;
const matchedNoteTags = [];
// Compile list of negative and positive review tags
const tagsToReview = this.data.settings.tagsToReview.filter(
(tag) => !tag.startsWith("-"),
);
const negativeTagsToReview = this.data.settings.tagsToReview
.filter((tag) => tag.startsWith("-"))
.map((tag) => tag.slice(1));

for (const tagToReview of this.data.settings.tagsToReview) {
if (tags.some((tag) => tag === tagToReview || tag.startsWith(tagToReview + "/"))) {
if (!Object.prototype.hasOwnProperty.call(this.reviewDecks, tagToReview)) {
this.reviewDecks[tagToReview] = new ReviewDeck(tagToReview);
}
matchedNoteTags.push(tagToReview);
shouldIgnore = false;
break;
}
// Skip this item if any tags match a negative review tag
if (
negativeTagsToReview.some((negativeTag) => {
return tags.some(
(tag) => tag === negativeTag || tag.startsWith(negativeTag + "/"),
);
})
) {
continue;
}
if (shouldIgnore) {

// Add item to first matched review tag
const firstMatchedNoteTag = tagsToReview.find((reviewTag) =>
tags.some((tag) => tag === reviewTag || tag.startsWith(reviewTag + "/")),
);
if (firstMatchedNoteTag == undefined) {
continue;
}

// file has no scheduling information
// Create review deck if it doesn't exist
if (!Object.prototype.hasOwnProperty.call(this.reviewDecks, firstMatchedNoteTag)) {
this.reviewDecks[firstMatchedNoteTag] = new ReviewDeck(firstMatchedNoteTag);
}

// if file has no existing scheduling information, add it to its reviewDeck
if (
!(
Object.prototype.hasOwnProperty.call(frontmatter, "sr-due") &&
Object.prototype.hasOwnProperty.call(frontmatter, "sr-interval") &&
Object.prototype.hasOwnProperty.call(frontmatter, "sr-ease")
)
) {
for (const matchedNoteTag of matchedNoteTags) {
this.reviewDecks[matchedNoteTag].newNotes.push(noteFile);
}
this.reviewDecks[firstMatchedNoteTag].newNotes.push(noteFile);
continue;
}

@@ -470,9 +484,7 @@ export default class SRPlugin extends Plugin {
this.easeByPath.setEaseForPath(noteFile.path, ease);

// schedule the note
for (const matchedNoteTag of matchedNoteTags) {
this.reviewDecks[matchedNoteTag].scheduledNotes.push({ note: noteFile, dueUnix });
}
this.reviewDecks[firstMatchedNoteTag].scheduledNotes.push({ note: noteFile, dueUnix });
}

graph.rank(0.85, 0.000001, (node: string, rank: number) => {