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

Support task filtering #71

Merged
merged 4 commits into from
Mar 1, 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
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ Enabling this will tell iCal that it should periodically scan your vault for tas

The number of minutes between each scan to generate and save your calendar. Must be a number between 1 and 1,440 (24 hours).

### Only include tasks with certain tags?

Enabling this will unlock the [Only include tasks that contain these tags](README.md#only-include-tasks-that-contain-these-tags) setting.

### Only include tasks that contain these tags

You can enter one or more tags. Only tasks that contains one or more of these tasks will be included in your calendar. Multiple tags should be separated by a space.

### Exclude tasks with certain tags?

Enabling this will unlock the [Exclude tasks that contain these tags](README.md#exclude-tasks-that-contain-these-tags) setting.

### Exclude tasks that contain these tags

You can enter one or more tags. If a task contains any of these tags, then it will be excluded from your calendar. Multiple tags should be separated by a space.

If you have include tags and exclude tags, then exclude tags take priority.

### Save calendar to GitHub Gist

Saving to GitHub Gist means you will be given a URL that you can import into your calendar applications.
Expand Down
8 changes: 8 additions & 0 deletions src/Model/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export interface Settings {
oldTaskInDays: number;
howToProcessMultipleDates: string;
isDayPlannerPluginFormatEnabled: boolean;
isIncludeTasksWithTags: boolean;
includeTasksWithTags: string;
isExcludeTasksWithTags: boolean;
excludeTasksWithTags: string;
}

export const DEFAULT_SETTINGS: Settings = {
Expand All @@ -55,4 +59,8 @@ export const DEFAULT_SETTINGS: Settings = {
oldTaskInDays: 365,
howToProcessMultipleDates: HOW_TO_PROCESS_MULTIPLE_DATES.PreferDueDate,
isDayPlannerPluginFormatEnabled: false,
isIncludeTasksWithTags: false,
includeTasksWithTags: '#calendar',
isExcludeTasksWithTags: false,
excludeTasksWithTags: '#ignore',
};
59 changes: 59 additions & 0 deletions src/SettingTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,60 @@ export class SettingTab extends PluginSettingTab {
);
}

new Setting(containerEl)
.setName('Only include tasks with certain tags?')
.setDesc('Do you want your calendar to only include tasks that contain certain tags?')
.addToggle((toggle: ToggleComponent) =>
toggle
.setValue(settings.isIncludeTasksWithTags)
.onChange(async (value) => {
settings.isIncludeTasksWithTags = value;
this.display();
})
);

if (settings.isIncludeTasksWithTags) {
new Setting(containerEl)
.setName('Only include tasks that contain these tags')
.setDesc('Enter one or more tags. Separate multiple tags with a space. If one or more of these tags are found then the task will be included in your calendar.')
.addText((text) =>
text
.setValue(settings.includeTasksWithTags.toString())
.setPlaceholder(DEFAULT_SETTINGS.includeTasksWithTags)
.onChange(async (includeTasksWithTags) => {
includeTasksWithTags = this.cleanTags(includeTasksWithTags);
settings.includeTasksWithTags = includeTasksWithTags;
})
);
}

new Setting(containerEl)
.setName('Exclude tasks with certain tags?')
.setDesc('Do you want your calendar to exclude tasks that contain certain tags?')
.addToggle((toggle: ToggleComponent) =>
toggle
.setValue(settings.isExcludeTasksWithTags)
.onChange(async (value) => {
settings.isExcludeTasksWithTags = value;
this.display();
})
);

if (settings.isExcludeTasksWithTags) {
new Setting(containerEl)
.setName('Exclude tasks that contain these tags')
.setDesc('Enter one or more tags. Separate multiple tags with a space. If one or more of these tags are found then the task will be excluded from your calendar.')
.addText((text) =>
text
.setValue(settings.excludeTasksWithTags.toString())
.setPlaceholder(DEFAULT_SETTINGS.excludeTasksWithTags)
.onChange(async (excludeTasksWithTags) => {
excludeTasksWithTags = this.cleanTags(excludeTasksWithTags);
settings.excludeTasksWithTags = excludeTasksWithTags;
})
);
}

if (settings.isSaveToGistEnabled) {
containerEl.createEl('h1', { text: 'Save calendar to GitHub Gist' });

Expand Down Expand Up @@ -362,4 +416,9 @@ export class SettingTab extends PluginSettingTab {

throw new Error('GitHub Personal Access Token must start in "ghp_" for classic tokens or "github_pat_" for fine-grained tokens.');
}

// Replace multiple whitespace characters with a single space
cleanTags(value: string): string {
return value.replace(/\s+/g, ' ');
}
}
36 changes: 36 additions & 0 deletions src/SettingsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,42 @@ class SettingsManager {
this.settings.isDayPlannerPluginFormatEnabled = isDayPlannerPluginFormatEnabled;
this.saveSettings();
}

public get isIncludeTasksWithTags(): boolean {
return this.settings.isIncludeTasksWithTags;
}

public set isIncludeTasksWithTags(isIncludeTasksWithTags: boolean) {
this.settings.isIncludeTasksWithTags = isIncludeTasksWithTags;
this.saveSettings();
}

public get includeTasksWithTags(): string {
return this.settings.includeTasksWithTags;
}

public set includeTasksWithTags(includeTasksWithTags: string) {
this.settings.includeTasksWithTags = includeTasksWithTags;
this.saveSettings();
}

public get isExcludeTasksWithTags(): boolean {
return this.settings.isExcludeTasksWithTags;
}

public set isExcludeTasksWithTags(isExcludeTasksWithTags: boolean) {
this.settings.isExcludeTasksWithTags = isExcludeTasksWithTags;
this.saveSettings();
}

public get excludeTasksWithTags(): string {
return this.settings.excludeTasksWithTags;
}

public set excludeTasksWithTags(excludeTasksWithTags: string) {
this.settings.excludeTasksWithTags = excludeTasksWithTags;
this.saveSettings();
}
}

export let settings: SettingsManager = SettingsManager.settingsManager;
Expand Down
25 changes: 25 additions & 0 deletions src/TaskFinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@ export class TaskFinder {
}
}

// If the user wants to only include tasks with certain tags, filter them here
if (settings.isIncludeTasksWithTags) {
if (!this.hasTag(lineAndHeading.markdownLine, settings.includeTasksWithTags)) {
return null;
}
}

// If the user wants to exclude tasks with certain tags, filter them here
if (settings.isExcludeTasksWithTags) {
if (this.hasTag(lineAndHeading.markdownLine, settings.excludeTasksWithTags)) {
return null;
}
}

return createTaskFromLine(lineAndHeading.markdownLine, fileUri, dateOverride);
})
// Filter out the nulls
Expand All @@ -59,4 +73,15 @@ export class TaskFinder {

return timeRegExp.test(line);
}

// Does this line contain any of the tags provided?
hasTag(line: string, tags: string): boolean {
if (!tags.includes(' ')) {
// If tag inclusion/exclusion is enabled then this function will be called for every task that is discovered.
// This is a small optimisation so that if there is only one tag, then skip the split() and some() loop calls.
return line.includes(tags);
}

return tags.split(' ').some(tag => line.includes(tag));
}
}
Loading
Loading