Currently the word count in status bar is always global for the entire document. I think it would make sense to scope the counts to the current focus branch.
I do all my work in a single Bike document – individual tasks and presentations are just bullets in a large hierarchy. The word count of the main document is meaningless to me, but when I focus into an item to work on some presentation it would be useful to know how many words it already has.
In the meanwhile, you could experiment with this script, which reports the combined word count of:
The selected line,
and all of its descendants.
Expand disclosure triangle to view JS source
(() => {
"use strict";
// Count of words in all descendants of the selected
// Bike row. (Including words in the row itself).
// The result is displayed in a dialog, and copied
// to the clipboard.
// Rob Trew @2023
// Ver 0.1
const title = "Words in selected row and its descendants";
// main :: IO ()
const main = () => {
ObjC.import("AppKit");
const doc = Application("Bike").documents.at(0);
return either(
alert(title)
)(
report => (
copyText(report),
alert(title)(report)
)
)(
doc.exists()
? (() => {
const
selnRow = doc.selectionRow,
rows = [
selnRow,
...selnRow.entireContents()
]
.flatMap(row => {
const s = row.name().trim();
return 0 < s.length
? [s]
: [];
}),
n = 0 < rows.length
? rows
.join("\n")
.split(/\s+/u)
.length
: 0;
return 0 < n
? Right(`${n} words in branch:\n\t"${rows[0]}"`)
: Left("No words in selected row and descendants.");
})()
: Left("No documents open in Bike.")
);
};
// ----------------------- JXA -----------------------
// alert :: String => String -> IO String
const alert = title =>
s => {
const sa = Object.assign(
Application("System Events"), {
includeStandardAdditions: true
});
return (
sa.activate(),
sa.displayDialog(s, {
withTitle: title,
buttons: ["OK"],
defaultButton: "OK"
}),
s
);
};
// copyText :: String -> IO String
const copyText = s => {
// ObjC.import("AppKit");
const pb = $.NSPasteboard.generalPasteboard;
return (
pb.clearContents,
pb.setStringForType(
$(s),
$.NSPasteboardTypeString
),
s
);
};
// --------------------- 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
});
// 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);
// MAIN ---
return main();
})();
To test in Script Editor, set the language selector at top left to JavaScript (rather than AppleScript)