Repository: obsidian-tasks-group/obsidian-tasks (ts)

Issue:
Add ability to remove all or part of the global query
### ⚠️ Please check that this feature request hasn't been suggested before.

- [X] I searched previous [Ideas in Discussions](https://github.com/obsidian-tasks-group/obsidian-tasks/discussions/categories/ideas-any-new-feature-requests-go-in-issues-please?discussions_q=category%3A%22Ideas%3A+Any+New+Feature+Requests+go+in+Issues+please%22+-label%3A%22status%3A+released%22+-label%3Aduplicate+sort%3Atop) didn't find any similar feature requests.
- [X] I searched previous [Issues](https://github.com/obsidian-tasks-group/obsidian-tasks/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+enhancement%22+sort%3Acomments-desc) didn't find any similar feature requests.

### 🔖 Feature description

A task code block that removes the global query and/or global filter for special cases where the user wants to ignore those filters.

### ✔️ Solution

I have my global query set up to not search my Daily Notes directory for tasks, because I use a template that adds some daily tasks to each note that I don't always get done, and I don't go back and remove them. In my daily note template, I also have a task code block to show tasks that I have completed that day, and I want to show the tasks that I have completed from the daily note. But because my global query excludes the Daily Note directory, I have no way to query for those tasks.

In this scenario, I think it would be helpful to have a simple syntax in the tasks code block to remove the global filter and query.

\```tasks
remove global query
remove global filter
done today
\```

### ❓ Alternatives

A more complex, but alternative approach, would be to allow tasks code blocks to negate queries in the global query. I've only considered this temporarily, I don't think it's actually a viable approach, as it would be very difficult to match query lines against each other to determine if they negate each other.

### 📝 Additional Context

Global query for my use case:
```tasks
folder does not include 5. Templates
folder does not include Areas/Daily Notes
folder does not include 4. Archives
```

Task block for my daily note:
```tasks
done on 2023-06-27
short mode
```

Pull request:
feat: add `ignore global query` instruction
<!--- Provide a general summary of your changes in the Title above -->

# Description

Add `ignore global query` instruction to discard the Global Query in a given task block.

## Motivation and Context

Related to #2074 

## How has this been tested?

Unit test + smoke test 

Global Query = `tags include #test`
<img width="492" alt="Снимок экрана 2023-07-07 в 16 47 42" src="https://github.com/obsidian-tasks-group/obsidian-tasks/assets/93825870/e6e2f200-bb40-4731-bc1b-d7973bb3796a">

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

Changes visible to users:

- [x] **New feature** (prefix: `feat` - non-breaking change which adds functionality)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [x] My change requires a change to the documentation.
- [x] I have [updated the documentation](https://publish.obsidian.md/tasks-contributing/Documentation/About+Documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://publish.obsidian.md/tasks-contributing/Testing/About+Testing).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://publish.obsidian.md/tasks-contributing) and
[Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md).
Put an x in the boxes to confirm you agree.
-->

- [x] My contribution follow this project's [contributing guide](https://publish.obsidian.md/tasks-contributing)
- [x] I agree to follow this project's [Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md)


Patch:
diff --git a/docs/Queries/Global Query.md b/docs/Queries/Global Query.md
index 05816863..9255fdae 100644
--- a/docs/Queries/Global Query.md
+++ b/docs/Queries/Global Query.md
@@ -27,6 +27,22 @@ You can set a global query in the settings that Tasks will add to the start of a
 >     tags include work
 >     ```
 
+## Ignoring the global query
+
+If you need to ignore the Global Query in a given Tasks block you may add `ignore global query` instruction to any place of the block.
+
+For example, this allows you to have your task seaches ignore certain folders by default. And then in few searches, you can enable searching for tasks in those folders.
+
+> [!example]
+>
+> ```tasks
+> tags include work
+> ignore global query
+> ```
+
+> [!released]
+The `ignore global query` instruction was added in Tasks X.Y.Z.
+
 ## Examples
 
 Currently, any query that is allowed in a task block will also work as your Global Query. This feature is especially useful for applying [filters](Filters) or [layout options](Layout) by default for all your queries.
diff --git a/docs/Quick Reference.md b/docs/Quick Reference.md
index 158fb015..8bd44d2f 100644
--- a/docs/Quick Reference.md
+++ b/docs/Quick Reference.md
@@ -59,5 +59,6 @@ This table summarizes the filters and other options available inside a `tasks` b
 | `hide task count`                                                                                                                                                                                                                                                                               |                                             |                        |                        |                                                     |
 | `short mode`                                                                                                                                                                                                                                                                                    |                                             |                        |                        |                                                     |
 | **Other Instructions**                                                                                                                                                                                                                                                                          |                                             |                        |                        |                                                     |
+| `ignore global query`                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                     |
 | `explain`                                                                                                                                                                                                                                                                                       |                                             |                        |                        |                                                     |
 | `# comment`                                                                                                                                                                                                                                                                                     |                                             |                        |                        |                                                     |
diff --git a/src/Query/Query.ts b/src/Query/Query.ts
index 53a992a8..3e747864 100644
--- a/src/Query/Query.ts
+++ b/src/Query/Query.ts
@@ -21,11 +21,13 @@ export class Query implements IQuery {
     private _error: string | undefined = undefined;
     private _sorting: Sorter[] = [];
     private _grouping: Grouper[] = [];
+    private _ignoreGlobalQuery: boolean = false;
 
     private readonly hideOptionsRegexp =
         /^(hide|show) (task count|backlink|priority|created date|start date|scheduled date|done date|due date|recurrence rule|edit button|urgency|tags)/;
     private readonly shortModeRegexp = /^short/;
     private readonly explainQueryRegexp = /^explain/;
+    private readonly ignoreGlobalQueryRegexp = /^ignore global query/;
 
     private readonly limitRegexp = /^limit (groups )?(to )?(\d+)( tasks?)?/;
 
@@ -46,6 +48,9 @@ export class Query implements IQuery {
                     case this.explainQueryRegexp.test(line):
                         this._layoutOptions.explainQuery = true;
                         break;
+                    case this.ignoreGlobalQueryRegexp.test(line):
+                        this._ignoreGlobalQuery = true;
+                        break;
                     case this.limitRegexp.test(line):
                         this.parseLimit({ line });
                         break;
@@ -177,6 +182,10 @@ export class Query implements IQuery {
 Problem line: "${line}"`;
     }
 
+    public get ignoreGlobalQuery(): boolean {
+        return this._ignoreGlobalQuery;
+    }
+
     public applyQueryToTasks(tasks: Task[]): QueryResult {
         try {
             this.filters.forEach((filter) => {
diff --git a/src/lib/QueryRendererHelper.ts b/src/lib/QueryRendererHelper.ts
index 20975042..dc746c9e 100644
--- a/src/lib/QueryRendererHelper.ts
+++ b/src/lib/QueryRendererHelper.ts
@@ -29,13 +29,17 @@ export function explainResults(source: string): string {
         result += `Only tasks containing the global filter '${GlobalFilter.get()}'.\n\n`;
     }
 
-    const globalQuery: IQuery = new Query(getGlobalQuerySource());
+    const tasksBlockQuery = new Query({ source });
 
-    if (globalQuery.source.trim() !== '') {
-        result += `Explanation of the global query:\n\n${globalQuery.explainQuery()}\n`;
+    if (!tasksBlockQuery.ignoreGlobalQuery) {
+        const globalQuery: IQuery = new Query(getGlobalQuerySource());
+
+        if (globalQuery.source.trim() !== '') {
+            result += `Explanation of the global query:\n\n${globalQuery.explainQuery()}\n`;
+        }
     }
 
-    result += `Explanation of this Tasks code block query:\n\n${new Query({ source }).explainQuery()}`;
+    result += `Explanation of this Tasks code block query:\n\n${tasksBlockQuery.explainQuery()}`;
 
     return result;
 }
@@ -49,5 +53,12 @@ export function explainResults(source: string): string {
  * @returns {Query} The query to execute
  */
 export function getQueryForQueryRenderer(source: string): Query {
-    return new Query(getGlobalQuerySource()).append(new Query({ source }));
+    const globalQuery = new Query(getGlobalQuerySource());
+    const tasksBlockQuery = new Query({ source });
+
+    if (tasksBlockQuery.ignoreGlobalQuery) {
+        return tasksBlockQuery;
+    }
+
+    return globalQuery.append(tasksBlockQuery);
 }


Test patch:
diff --git a/tests/Query.test.ts b/tests/Query.test.ts
index b8104cb0..8d2c6afd 100644
--- a/tests/Query.test.ts
+++ b/tests/Query.test.ts
@@ -381,6 +381,7 @@ describe('Query parsing', () => {
             'hide tags',
             'hide task count',
             'hide urgency',
+            'ignore global query',
             'limit 42',
             'limit groups 31',
             'limit groups to 31 tasks',
diff --git a/tests/lib/QueryRendererHelper.test.ts b/tests/lib/QueryRendererHelper.test.ts
index 9832d477..81a57df6 100644
--- a/tests/lib/QueryRendererHelper.test.ts
+++ b/tests/lib/QueryRendererHelper.test.ts
@@ -72,6 +72,19 @@ description includes hello
 
 Explanation of this Tasks code block query:
 
+No filters supplied. All tasks will match the query.`;
+
+        expect(explainResults(query.source)).toEqual(expectedDisplayText);
+    });
+
+    it('should explain a task with global query set but ignored without the global query', () => {
+        updateSettings({ globalQuery: 'description includes hello' });
+
+        const source = 'ignore global query';
+        const query = new Query({ source });
+
+        const expectedDisplayText = `Explanation of this Tasks code block query:
+
 No filters supplied. All tasks will match the query.`;
 
         expect(explainResults(query.source)).toEqual(expectedDisplayText);
@@ -94,4 +107,11 @@ describe('query used for QueryRenderer', () => {
         updateSettings({ globalQuery: globalQuerySource });
         expect(getQueryForQueryRenderer(querySource).source).toEqual(`${globalQuerySource}\n${querySource}`);
     });
+
+    it('should ignore the global query if "ignore global query" is set', () => {
+        updateSettings({ globalQuery: 'path includes from_global_query' });
+        expect(getQueryForQueryRenderer('description includes from_block_query\nignore global query').source).toEqual(
+            'description includes from_block_query\nignore global query',
+        );
+    });
 });