diff --git a/docs/Queries/Explaining Queries.md b/docs/Queries/Explaining Queries.md index b5177777ad..510582a3d8 100644 --- a/docs/Queries/Explaining Queries.md +++ b/docs/Queries/Explaining Queries.md @@ -43,16 +43,16 @@ the results begin with the following, on `2022-10-21`: ```text Explanation of this Tasks code block query: -starts after 2 years ago => - start date is after 2020-10-21 (Wednesday 21st October 2020) OR no start date + starts after 2 years ago => + start date is after 2020-10-21 (Wednesday 21st October 2020) OR no start date -scheduled after 1 week ago => - scheduled date is after 2022-10-14 (Friday 14th October 2022) + scheduled after 1 week ago => + scheduled date is after 2022-10-14 (Friday 14th October 2022) -due before tomorrow => - due date is before 2022-10-22 (Saturday 22nd October 2022) + due before tomorrow => + due date is before 2022-10-22 (Saturday 22nd October 2022) -No grouping instructions supplied. + No grouping instructions supplied. ``` @@ -80,10 +80,10 @@ the results begin with the following: ```text Explanation of this Tasks code block query: -path regex matches /^Root/Sub-Folder/Sample File\.md/i => - using regex: '^Root\/Sub-Folder\/Sample File\.md' with flag 'i' + path regex matches /^Root/Sub-Folder/Sample File\.md/i => + using regex: '^Root\/Sub-Folder\/Sample File\.md' with flag 'i' -No grouping instructions supplied. + No grouping instructions supplied. ``` @@ -105,14 +105,14 @@ the results begin with the following, on `2022-10-21`: ```text Explanation of this Tasks code block query: -not done + not done -(due before tomorrow) AND (is recurring) => - AND (All of): - due date is before 2022-10-22 (Saturday 22nd October 2022) - is recurring + (due before tomorrow) AND (is recurring) => + AND (All of): + due date is before 2022-10-22 (Saturday 22nd October 2022) + is recurring -No grouping instructions supplied. + No grouping instructions supplied. ``` @@ -142,21 +142,21 @@ the results begin with the following, on `2022-10-21`: ```text Explanation of this Tasks code block query: -( (description includes 1) AND (description includes 2) AND (description includes 3) ) OR ( (description includes 5) AND (description includes 6) AND (description includes 7) ) AND NOT (description includes 7) => - OR (At least one of): - AND (All of): - description includes 1 - description includes 2 - description includes 3 - AND (All of): + ( (description includes 1) AND (description includes 2) AND (description includes 3) ) OR ( (description includes 5) AND (description includes 6) AND (description includes 7) ) AND NOT (description includes 7) => + OR (At least one of): AND (All of): - description includes 5 - description includes 6 - description includes 7 - NOT: - description includes 7 - -No grouping instructions supplied. + description includes 1 + description includes 2 + description includes 3 + AND (All of): + AND (All of): + description includes 5 + description includes 6 + description includes 7 + NOT: + description includes 7 + + No grouping instructions supplied. ``` @@ -190,22 +190,22 @@ the results begin with the following, on `2022-10-21`: ```text Explanation of the global query: -heading includes tasks + heading includes tasks -No grouping instructions supplied. + No grouping instructions supplied. -At most 50 tasks. + At most 50 tasks. Explanation of this Tasks code block query: -not done + not done -due next week => - due date is between: - 2022-10-24 (Monday 24th October 2022) and - 2022-10-30 (Sunday 30th October 2022) inclusive + due next week => + due date is between: + 2022-10-24 (Monday 24th October 2022) and + 2022-10-30 (Sunday 30th October 2022) inclusive -No grouping instructions supplied. + No grouping instructions supplied. ``` @@ -234,17 +234,17 @@ the results begin with the following: ```text Explanation of this Tasks code block query: -path includes some/sample/file path.md + path includes some/sample/file path.md -root includes some/ + root includes some/ -folder includes some/sample/ + folder includes some/sample/ -filename includes file path.md + filename includes file path.md -description includes Some Cryptic String + description includes Some Cryptic String -No grouping instructions supplied. + No grouping instructions supplied. ``` diff --git a/docs/Queries/Line Continuations.md b/docs/Queries/Line Continuations.md index f4bf8844c8..7af5e8c447 100644 --- a/docs/Queries/Line Continuations.md +++ b/docs/Queries/Line Continuations.md @@ -31,12 +31,12 @@ explain ```text Explanation of this Tasks code block query: -(priority is highest) OR (priority is lowest) => - OR (At least one of): - priority is highest - priority is lowest + (priority is highest) OR (priority is lowest) => + OR (At least one of): + priority is highest + priority is lowest -No grouping instructions supplied. + No grouping instructions supplied. ``` @@ -74,9 +74,9 @@ explain ```text Explanation of this Tasks code block query: -description includes \ + description includes \ -No grouping instructions supplied. + No grouping instructions supplied. ``` diff --git a/docs/Queries/Regular Expressions.md b/docs/Queries/Regular Expressions.md index d0234df6bb..dc927055b1 100644 --- a/docs/Queries/Regular Expressions.md +++ b/docs/Queries/Regular Expressions.md @@ -95,10 +95,10 @@ path regex matches /^Root/Sub-Folder/Sample File\.md/i ```text Explanation of this Tasks code block query: -path regex matches /^Root/Sub-Folder/Sample File\.md/i => - using regex: '^Root\/Sub-Folder\/Sample File\.md' with flag 'i' + path regex matches /^Root/Sub-Folder/Sample File\.md/i => + using regex: '^Root\/Sub-Folder\/Sample File\.md' with flag 'i' -No grouping instructions supplied. + No grouping instructions supplied. ``` diff --git a/docs/Scripting/Placeholders.md b/docs/Scripting/Placeholders.md index ac44d588e0..f00c2f83c4 100644 --- a/docs/Scripting/Placeholders.md +++ b/docs/Scripting/Placeholders.md @@ -43,17 +43,17 @@ the results begin with the following, which demonstrates how each value inside ` ```text Explanation of this Tasks code block query: -path includes some/sample/file path.md + path includes some/sample/file path.md -root includes some/ + root includes some/ -folder includes some/sample/ + folder includes some/sample/ -filename includes file path.md + filename includes file path.md -description includes Some Cryptic String + description includes Some Cryptic String -No grouping instructions supplied. + No grouping instructions supplied. ``` diff --git a/src/Query/Explain/Explainer.ts b/src/Query/Explain/Explainer.ts index 7c71d49f85..076f02d831 100644 --- a/src/Query/Explain/Explainer.ts +++ b/src/Query/Explain/Explainer.ts @@ -2,6 +2,16 @@ import { getSettings } from '../../Config/Settings'; import type { Query } from '../Query'; export class Explainer { + private readonly indentation: string; + + /** + * Constructor. + * @param indentation - the indentation to use for the output. Defaults to 'not indented'. + */ + constructor(indentation: string = '') { + this.indentation = indentation; + } + /** * Generate a text description of the contents of a query. * @@ -40,12 +50,12 @@ export class Explainer { public explainFilters(query: Query) { const numberOfFilters = query.filters.length; if (numberOfFilters === 0) { - return 'No filters supplied. All tasks will match the query.\n'; + return this.indent('No filters supplied. All tasks will match the query.\n'); } return query.filters .map((filter) => { - return filter.explainFilterIndented(''); + return filter.explainFilterIndented(this.indentation); }) .join('\n'); } @@ -53,12 +63,12 @@ export class Explainer { public explainGroups(query: Query) { const numberOfGroups = query.grouping.length; if (numberOfGroups === 0) { - return 'No grouping instructions supplied.\n'; + return this.indent('No grouping instructions supplied.\n'); } let result = ''; for (let i = 0; i < numberOfGroups; i++) { - result += query.grouping[i].instruction + '\n'; + result += this.indentation + query.grouping[i].instruction + '\n'; } return result; } @@ -76,13 +86,13 @@ export class Explainer { if (query.limit !== undefined) { const result = getPluralisedText(query.limit) + '.\n'; - results.push(result); + results.push(this.indent(result)); } if (query.taskGroupLimit !== undefined) { const result = getPluralisedText(query.taskGroupLimit) + ' per group (if any "group by" options are supplied).\n'; - results.push(result); + results.push(this.indent(result)); } return results.join('\n'); } @@ -91,9 +101,14 @@ export class Explainer { let result = ''; const { debugSettings } = getSettings(); if (debugSettings.ignoreSortInstructions) { - result += - "NOTE: All sort instructions, including default sort order, are disabled, due to 'ignoreSortInstructions' setting.\n"; + result += this.indent( + "NOTE: All sort instructions, including default sort order, are disabled, due to 'ignoreSortInstructions' setting.\n", + ); } return result; } + + private indent(description: string) { + return this.indentation + description; + } } diff --git a/src/Query/Filter/Filter.ts b/src/Query/Filter/Filter.ts index c7b4c4aabc..2e90f43c3b 100644 --- a/src/Query/Filter/Filter.ts +++ b/src/Query/Filter/Filter.ts @@ -38,7 +38,7 @@ export class Filter { if (unindentedExplanation === this.instruction) { return `${indent}${this.instruction}\n`; } else { - return `${indent}${this.instruction} =>\n${explanation.asString(' ')}\n`; + return `${indent}${this.instruction} =>\n${explanation.asString(indent + ' ')}\n`; } } } diff --git a/src/lib/QueryRendererHelper.ts b/src/lib/QueryRendererHelper.ts index 1221f2d834..728aaecd84 100644 --- a/src/lib/QueryRendererHelper.ts +++ b/src/lib/QueryRendererHelper.ts @@ -1,6 +1,7 @@ import type { GlobalFilter } from '../Config/GlobalFilter'; import type { GlobalQuery } from '../Config/GlobalQuery'; import { Query } from '../Query/Query'; +import { Explainer } from '../Query/Explain/Explainer'; /** * @summary @@ -36,15 +37,17 @@ export function explainResults( result += `Only tasks containing the global filter '${globalFilter.get()}'.\n\n`; } + const explainer = new Explainer(' '); const tasksBlockQuery = new Query(source, path); if (!tasksBlockQuery.ignoreGlobalQuery) { if (globalQuery.hasInstructions()) { - result += `Explanation of the global query:\n\n${globalQuery.query(path).explainQuery()}\n`; + const globalQueryQuery = globalQuery.query(path); + result += `Explanation of the global query:\n\n${explainer.explainQuery(globalQueryQuery)}\n`; } } - result += `Explanation of this Tasks code block query:\n\n${tasksBlockQuery.explainQuery()}`; + result += `Explanation of this Tasks code block query:\n\n${explainer.explainQuery(tasksBlockQuery)}`; return result; } diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_boolean_combinations.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_boolean_combinations.approved.explanation.text index d31a329a18..9bda53ad41 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_boolean_combinations.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_boolean_combinations.approved.explanation.text @@ -1,10 +1,10 @@ Explanation of this Tasks code block query: -not done + not done -(due before tomorrow) AND (is recurring) => - AND (All of): - due date is before 2022-10-22 (Saturday 22nd October 2022) - is recurring + (due before tomorrow) AND (is recurring) => + AND (All of): + due date is before 2022-10-22 (Saturday 22nd October 2022) + is recurring -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_expands_dates.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_expands_dates.approved.explanation.text index 342edf6592..6d84d9fdf4 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_expands_dates.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_expands_dates.approved.explanation.text @@ -1,12 +1,12 @@ Explanation of this Tasks code block query: -starts after 2 years ago => - start date is after 2020-10-21 (Wednesday 21st October 2020) OR no start date + starts after 2 years ago => + start date is after 2020-10-21 (Wednesday 21st October 2020) OR no start date -scheduled after 1 week ago => - scheduled date is after 2022-10-14 (Friday 14th October 2022) + scheduled after 1 week ago => + scheduled date is after 2022-10-14 (Friday 14th October 2022) -due before tomorrow => - due date is before 2022-10-22 (Saturday 22nd October 2022) + due before tomorrow => + due date is before 2022-10-22 (Saturday 22nd October 2022) -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_explains_task_block_with_global_query_active.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_explains_task_block_with_global_query_active.approved.explanation.text index 7ce4475370..c8dea8db39 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_explains_task_block_with_global_query_active.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_explains_task_block_with_global_query_active.approved.explanation.text @@ -1,18 +1,18 @@ Explanation of the global query: -heading includes tasks + heading includes tasks -No grouping instructions supplied. + No grouping instructions supplied. -At most 50 tasks. + At most 50 tasks. Explanation of this Tasks code block query: -not done + not done -due next week => - due date is between: - 2022-10-24 (Monday 24th October 2022) and - 2022-10-30 (Sunday 30th October 2022) inclusive + due next week => + due date is between: + 2022-10-24 (Monday 24th October 2022) and + 2022-10-30 (Sunday 30th October 2022) inclusive -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_double_slash.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_double_slash.approved.explanation.text index 9ee57de7c3..75ba68a770 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_double_slash.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_double_slash.approved.explanation.text @@ -1,5 +1,5 @@ Explanation of this Tasks code block query: -description includes \ + description includes \ -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_single_slash.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_single_slash.approved.explanation.text index 89f6b187da..c45ca57736 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_single_slash.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_line_continuation_-_single_slash.approved.explanation.text @@ -1,8 +1,8 @@ Explanation of this Tasks code block query: -(priority is highest) OR (priority is lowest) => - OR (At least one of): - priority is highest - priority is lowest + (priority is highest) OR (priority is lowest) => + OR (At least one of): + priority is highest + priority is lowest -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_nested_boolean_combinations.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_nested_boolean_combinations.approved.explanation.text index 27b78b58c7..262203b3e9 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_nested_boolean_combinations.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_nested_boolean_combinations.approved.explanation.text @@ -1,17 +1,17 @@ Explanation of this Tasks code block query: -( (description includes 1) AND (description includes 2) AND (description includes 3) ) OR ( (description includes 5) AND (description includes 6) AND (description includes 7) ) AND NOT (description includes 7) => - OR (At least one of): - AND (All of): - description includes 1 - description includes 2 - description includes 3 - AND (All of): + ( (description includes 1) AND (description includes 2) AND (description includes 3) ) OR ( (description includes 5) AND (description includes 6) AND (description includes 7) ) AND NOT (description includes 7) => + OR (At least one of): AND (All of): - description includes 5 - description includes 6 - description includes 7 - NOT: - description includes 7 + description includes 1 + description includes 2 + description includes 3 + AND (All of): + AND (All of): + description includes 5 + description includes 6 + description includes 7 + NOT: + description includes 7 -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_placeholders.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_placeholders.approved.explanation.text index 17a4a87b73..2fbad4f5a9 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_placeholders.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_placeholders.approved.explanation.text @@ -1,13 +1,13 @@ Explanation of this Tasks code block query: -path includes some/sample/file path.md + path includes some/sample/file path.md -root includes some/ + root includes some/ -folder includes some/sample/ + folder includes some/sample/ -filename includes file path.md + filename includes file path.md -description includes Some Cryptic String + description includes Some Cryptic String -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/DocsSamplesForExplain.test.explain_regular_expression.approved.explanation.text b/tests/Query/Explain/DocsSamplesForExplain.test.explain_regular_expression.approved.explanation.text index c65bc56d30..18a64defa5 100644 --- a/tests/Query/Explain/DocsSamplesForExplain.test.explain_regular_expression.approved.explanation.text +++ b/tests/Query/Explain/DocsSamplesForExplain.test.explain_regular_expression.approved.explanation.text @@ -1,6 +1,6 @@ Explanation of this Tasks code block query: -path regex matches /^Root/Sub-Folder/Sample File\.md/i => - using regex: '^Root\/Sub-Folder\/Sample File\.md' with flag 'i' + path regex matches /^Root/Sub-Folder/Sample File\.md/i => + using regex: '^Root\/Sub-Folder\/Sample File\.md' with flag 'i' -No grouping instructions supplied. + No grouping instructions supplied. diff --git a/tests/Query/Explain/Explainer.test.ts b/tests/Query/Explain/Explainer.test.ts index 1c0dd17998..9cce2393f5 100644 --- a/tests/Query/Explain/Explainer.test.ts +++ b/tests/Query/Explain/Explainer.test.ts @@ -33,11 +33,7 @@ describe('explain errors', () => { }); describe('explain everything', () => { - it('all types of instruction', () => { - // Disable sort instructions - updateSettings({ debugSettings: new DebugSettings(true) }); - - const source = ` + const sampleOfAllInstructionTypes = ` not done (has start date) AND (description includes some) @@ -52,7 +48,12 @@ short mode limit 50 limit groups 3 `; - const query = new Query(source); + + it('all types of instruction - not indented', () => { + // Disable sort instructions + updateSettings({ debugSettings: new DebugSettings(true) }); + + const query = new Query(sampleOfAllInstructionTypes); expect(explainer.explainQuery(query)).toMatchInlineSnapshot(` "not done @@ -72,6 +73,32 @@ limit groups 3 " `); }); + + it('all types of instruction - indented', () => { + // Disable sort instructions + updateSettings({ debugSettings: new DebugSettings(true) }); + + const query = new Query(sampleOfAllInstructionTypes); + const indentedExplainer = new Explainer(' '); + expect(indentedExplainer.explainQuery(query)).toMatchInlineSnapshot(` + " not done + + (has start date) AND (description includes some) => + AND (All of): + has start date + description includes some + + group by priority reverse + group by happens + + At most 50 tasks. + + At most 3 tasks per group (if any "group by" options are supplied). + + NOTE: All sort instructions, including default sort order, are disabled, due to 'ignoreSortInstructions' setting. + " + `); + }); }); describe('explain filters', () => { diff --git a/tests/Query/Filter/Filter.test.ts b/tests/Query/Filter/Filter.test.ts index 1ba71007b7..0f8f120822 100644 --- a/tests/Query/Filter/Filter.test.ts +++ b/tests/Query/Filter/Filter.test.ts @@ -16,6 +16,30 @@ describe('Filter', () => { expect(filter.explanation.asString()).toEqual(line); expect(filter.filterFunction).not.toBeUndefined(); }); + + it('should create a Filter object with different explanation', () => { + const filter = new Filter( + // instruction differs from explanation + 'some sample instruction', + (_task: Task) => { + return true; + }, + new Explanation('some more detailed explanation of the filter'), + ); + + expect(filter.explainFilterIndented('')).toMatchInlineSnapshot(` + "some sample instruction => + some more detailed explanation of the filter + " + `); + + // Check that text is correctly indented: + expect(filter.explainFilterIndented(' ')).toMatchInlineSnapshot(` + " some sample instruction => + some more detailed explanation of the filter + " + `); + }); }); describe('FilterOrErrorMessage', () => { diff --git a/tests/lib/QueryRendererHelper.test.ts b/tests/lib/QueryRendererHelper.test.ts index f588faea69..04f952bdf4 100644 --- a/tests/lib/QueryRendererHelper.test.ts +++ b/tests/lib/QueryRendererHelper.test.ts @@ -16,9 +16,9 @@ describe('explain', () => { expect(explainResults(query.source, new GlobalFilter(), new GlobalQuery())).toMatchInlineSnapshot(` "Explanation of this Tasks code block query: - No filters supplied. All tasks will match the query. + No filters supplied. All tasks will match the query. - No grouping instructions supplied. + No grouping instructions supplied. " `); }); @@ -34,9 +34,9 @@ describe('explain', () => { Explanation of this Tasks code block query: - No filters supplied. All tasks will match the query. + No filters supplied. All tasks will match the query. - No grouping instructions supplied. + No grouping instructions supplied. " `); }); @@ -49,15 +49,15 @@ describe('explain', () => { expect(explainResults(query.source, new GlobalFilter(), globalQuery)).toMatchInlineSnapshot(` "Explanation of the global query: - description includes hello + description includes hello - No grouping instructions supplied. + No grouping instructions supplied. Explanation of this Tasks code block query: - No filters supplied. All tasks will match the query. + No filters supplied. All tasks will match the query. - No grouping instructions supplied. + No grouping instructions supplied. " `); }); @@ -74,15 +74,15 @@ describe('explain', () => { Explanation of the global query: - description includes hello + description includes hello - No grouping instructions supplied. + No grouping instructions supplied. Explanation of this Tasks code block query: - No filters supplied. All tasks will match the query. + No filters supplied. All tasks will match the query. - No grouping instructions supplied. + No grouping instructions supplied. " `); }); @@ -95,9 +95,9 @@ describe('explain', () => { expect(explainResults(query.source, new GlobalFilter(), globalQuery)).toMatchInlineSnapshot(` "Explanation of this Tasks code block query: - No filters supplied. All tasks will match the query. + No filters supplied. All tasks will match the query. - No grouping instructions supplied. + No grouping instructions supplied. " `); });