Hello,
is there a way to hide (partially or totally) notes related to tasks (globally or task by task)?
Thanks
Hello,
is there a way to hide (partially or totally) notes related to tasks (globally or task by task)?
Thanks
One route is an editor search:
e.g.
//@type!=note
Which you could name and keep as a saved search in the sidebar
(and clear, of course, with āEsc, or Editor > End Search
)
thanks a lot!
but I suspect that this cannot be done on a note by note basisā¦
second: is it possible to show only the first line of a longer note? like in workflowy or omni outlinerā¦
a disclosure triangle, a bullett point?
That would need a script which identifies the selected line, I think.
the first line of a longer note?
Are there multiline notes in TaskPaper ?
Or are we talking about primus inter pares ?
(The first in a sequence of notes should be definable)
If Iāve understood what youāre describing, then it may be worth experimenting with scripts like this, which:
note
, except for the first.(() => {
"use strict";
const TaskPaperContext = editor => {
const
followingNotes = editor.outline.evaluateItemPath(
"@type=note[0]/following-sibling::*",
editor.selection.startItem
);
return (
editor.forceHidden(
followingNotes,
true
),
`${followingNotes.length} notes hidden.`
);
};
// main :: IO ()
const main = () =>
Application("TaskPaper").documents.at(0)
.evaluate({
script: `${TaskPaperContext}`
});
return main();
})();
I wrote a script for this. See here:
thanks to allā¦ just to be clear to what I wish
could you give an example of how it works? My fault but I donāt understand it practically
(Good choice of poets)
Do you have Keyboard Maestro or FastScripts ?
(It might ā Iāll try to experiment at the weekend ā be possible to sketch a single key toggle between those three states, though it might be necessary to improvise a bit with the glyph meaning Ā«has notesĀ» tell me if thereās one that feels less noisy than āŖ etc)
I like these
Iāll experiment with those. (Not quite as clean-cut in their macOS text rendering as in the browser versions)
choose the better for you, please
What ergonomics are you aiming for here ?
For example:
task
(i.e. bulleted)?
your example is ok
task
(i.e. bulleted), ok butā¦Hereās a first sketch of the least ambitious version ā a global three-way toggle, independent of selection.
If you attach it to a keystroke with something like FastScripts or Keyboard Maestro you should find that it cycles the editor through three successive states:
@N
tag (I havenāt found the trick of making emoji characters work in this context). Then, on next use:@N
tag), and finally@N
tag.(() => {
"use strict";
// First sketch of a global three-way toggle:
// 1. Notes (terminal leaves) all hidden
// 2. First notes revealed
// 3. all notes shown
// --------------- TASKPAPER 3 CONTEXT ---------------
// eslint-disable-next-line max-lines-per-function
const TaskPaperContext = editor => {
// tp3Main :: () -> Either String Result
const tp3Main = () => {
const
outline = editor.outline,
paths = {
leavesHidden: "//*/..*",
firstLeaf: "//*/..*/*[0]"
},
xs = outline.items,
hiddenNotes = "data-N",
parents = outline.evaluateItemPath(
paths.leavesHidden
);
return Right(
"" === editor.itemPathFilter ? (
editor.itemPathFilter = paths.leavesHidden,
parents.forEach(
x => x.setAttribute(hiddenNotes, "")
),
"Leaves Hidden"
) : editor.itemPathFilter === paths.leavesHidden ? (
editor.itemPathFilter = paths.firstLeaf,
parents.forEach(
x => x.setAttribute(hiddenNotes, "")
),
"First leaves shown"
) : (
editor.itemPathFilter = "",
editor.setExpanded(xs),
parents.forEach(
x => x.removeAttribute(hiddenNotes)
),
"All visible"
)
);
};
// ---------- GENERICS FOR TP3 CONTEXT -----------
// Right :: b -> Either a b
const Right = x => ({
type: "Either",
Right: x
});
// ------------------ TP3 MAIN -------------------
return tp3Main();
};
// ------------------- JXA CONTEXT -------------------
// main :: () -> Either MessageString ResultString
const main = () => {
const
ds = Application("TaskPaper")
.documents;
return either(x => x)(x => x)(
bindLR(
ds.length > 0 ? (
Right(ds.at(0))
) : Left("No TP3 documents open")
)(
d => d.evaluate({
script: `${TaskPaperContext}`,
withOptions: {
glyph: "ā"
}
})
)
);
};
// --------------------- GENERIC ---------------------
// Left :: a -> Either a b
const Left = x => ({
type: "Either",
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: "Either",
Right: x
});
// bindLR (>>=) :: Either a ->
// (a -> Either b) -> Either b
const bindLR = m =>
mf => m.Left ? (
m
) : mf(m.Right);
// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = fl =>
// Application of the function fl to the
// contents of any Left value in e, or
// the application of fr to its Right value.
fr => e => e.Left ? (
fl(e.Left)
) : fr(e.Right);
// JXA MAIN ---
return main();
})();
For a week I have only my iPhoneā¦
no way to check it out, sorry
many thanks BTW!
Iām backā¦
actually I think, cycling through the three states you defined, your script hides all the leaf notes whether they are notes or tasks
Thatās right.
For the next iteration, we can start to introduce expressions like:
@type=note
@type!=note
into the path expressions, and define a subset of parents.
Perhaps, for a first test, we could edit the paths
record to something like:
paths = {
notesHidden: '//@type!=note union //@text=""',
// firstLeafNote: "//*/..*/@type=note[0]",
firstLeafNote: "//*/..*/@type=note[0] union @type!=note",
noteParents: "//@type=note/..*"
}
And the searches (node path) syntax at TaskPaper documentation: Searches may suggest further adjustments and refinements to you.
Here, to test, is a second version of the code, with the path adjustments above:
(() => {
"use strict";
// Third sketch of a global three-way toggle:
// 1. Notes (leaves with @type=note) all hidden
// 2. First notes revealed
// 3. all notes shown
// --------------- TASKPAPER 3 CONTEXT ---------------
// eslint-disable-next-line max-lines-per-function
const TaskPaperContext = editor => {
// tp3Main :: () -> Either String Result
const tp3Main = () => {
const
outline = editor.outline,
paths = {
notesHidden: '//@type!=note union //@text=""',
// firstLeafNote: "//*/..*/@type=note[0]",
firstLeafNote: "//*/..*/@type=note[0] union @type!=note",
noteParents: "//@type=note/..*"
},
xs = outline.items,
hiddenNotes = "data-N",
parents = outline.evaluateItemPath(
paths.notesHidden
),
noteParents = outline.evaluateItemPath(
paths.noteParents
);
return Right(
"" === editor.itemPathFilter ? (
editor.itemPathFilter = paths.notesHidden,
noteParents.forEach(
x => x.setAttribute(hiddenNotes, "")
),
"Leaves Hidden"
) : editor.itemPathFilter === paths.notesHidden ? (
editor.itemPathFilter = paths.firstLeafNote,
noteParents.forEach(
x => x.setAttribute(hiddenNotes, "")
),
"First leaves shown"
) : (
editor.itemPathFilter = "",
editor.setExpanded(xs),
parents.forEach(
x => x.removeAttribute(hiddenNotes)
),
"All visible"
)
);
};
// ---------- GENERICS FOR TP3 CONTEXT -----------
// Right :: b -> Either a b
const Right = x => ({
type: "Either",
Right: x
});
// ------------------ TP3 MAIN -------------------
return tp3Main();
};
// ------------------- JXA CONTEXT -------------------
// main :: () -> Either MessageString ResultString
const main = () => {
const
ds = Application("TaskPaper")
.documents;
return either(x => x)(x => x)(
bindLR(
ds.length > 0 ? (
Right(ds.at(0))
) : Left("No TP3 documents open")
)(
d => d.evaluate({
script: `${TaskPaperContext}`,
withOptions: {
glyph: "ā"
}
})
)
);
};
// --------------------- GENERIC ---------------------
// Left :: a -> Either a b
const Left = x => ({
type: "Either",
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: "Either",
Right: x
});
// bindLR (>>=) :: Either a ->
// (a -> Either b) -> Either b
const bindLR = m =>
mf => m.Left ? (
m
) : mf(m.Right);
// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = fl =>
// Application of the function fl to the
// contents of any Left value in e, or
// the application of fr to its Right value.
fr => e => e.Left ? (
fl(e.Left)
) : fr(e.Right);
// JXA MAIN ---
return main();
})();
it works, thanks!
One question: notes new lines are identified by a CR character?
My understanding is that a TaskPaper file is a tab-indented text file (UTF8) in which all lines are delimited by the Unix standard \n
(LF \n
linefeed, rather than CR \r
carriage return)
A note is just a line without special syntax (no trailing semicolon, and no leading bullet hyphen). A succession of note lines is delimited by \n
(LF) in the same way as any other succession of lines.