Here, FWIW, is a JavaScript for Automation version,
which can be used for moving DOWN (next blank line)
or moving UP (previous blank line).
(the directional option is set by editing the value of directionDown
at the top of the script to true
or false
)
To test in Script Editor.app
, set the language selector at top left to JavaScript
, and paste in all of the code (scrolling right down to the bottom) behind the disclosure triangle below:
Expand disclosure triangle to view JS Source
(() => {
"use strict";
// BIKE – Select next (or previous) empty line.
// Rob Trew @2022
// Ver 0.02
// JavaScript for Automation
// Test in Script Editor with language selector at
// top left set to JavaScript
// ---------------- DIRECTION OPTION -----------------
// To jump to PREVIOUS blank line,
// edit the value of `directionDown` to false.
const directionDown = true;
// main :: IO ()
// eslint-disable-next-line max-lines-per-function
const main = () => {
const
bike = Application("Bike"),
doc = bike.documents.at(0);
return doc.exists() ? (() => {
const
// IDs paired with names
rows = doc.rows.where({
visible: true
}),
idNames = zip(
rows.id()
)(
rows.name()
),
// Position of selected line
selectedID = doc.selectionRow.id(),
selnIndex = idNames.findIndex(
ab => selectedID === ab[0]
),
// Offset of first blank in remaining or
// preceding lines.
nextIndex = (
directionDown ? (
idNames.slice(1 + selnIndex)
) : (
idNames.slice(0, selnIndex)
.reverse()
)
)
.findIndex(ab => "" === ab[1]);
bike.activate();
// First following blank line selected (if any)
return -1 !== nextIndex ? (
doc.select({
at: rows.at(
directionDown ? (
selnIndex + (1 + nextIndex)
) : selnIndex - (1 + nextIndex)
)
}),
"Selected"
) : (
Object.assign(
Application.currentApplication(), {
includeStandardAdditions: true
}
).beep(),
`No more blank rows visible in ${doc.name()}`
);
})() : "No document open in Bike.";
};
// --------------------- GENERIC ---------------------
// https://github.com/RobTrew/prelude-jxa
// zip :: [a] -> [b] -> [(a, b)]
const zip = xs =>
// The paired members of xs and ys, up to
// the length of the shorter of the two lists.
ys => Array.from({
length: Math.min(xs.length, ys.length)
}, (_, i) => [xs[i], ys[i]]);
// MAIN ---
return main();
})();
If you use Keyboard Maestro, the pair of macros in this zip:
NextOrPreviousBikeEmptyLine.kmmacros.zip (2.6 KB)
initially assign the two directions to ⌥⌘Up Arrow
and ⌥⌘Down Arrow
respectively, but you can readily change to any other pair of keyboard bindings.