Difficulty Writing a Macro for a Simple Repetitive Task Using a Variable to Define the Number of Iterations


I know that this task involves the use of the repeat action but can't figure out how to implement it

Basically the task is simple:
1- type ↓ (arrow down) keystroke once → perform a series of 4 actions
2- type ↓ (arrow down) keystroke twice → perform a series of same 4 actions (same as above)

continue until the (number of times the keystroke ↓ is typed followed by series of actions) is equal to a variable called NoteCount minus 1 (Notecount-1) which I define and calculate at the beginning of my macro.

thank you for your time and patience !

Showing is always better than telling, and the first thing to do (if you want to convey a sufficiently concrete image to recruit some help or explanation) is to show an example document, and context, even if mocked up.

1 Like

My apologies for a poorly worded question. It's like I was expecting people to read my mind.

In another post, you very kindly created a script to count the number of headers in a markdown document.

The macro works perfectly. I now know how many headers there are in my Markdown document. Thanks to your scrip tthe number of headers is stored in the variable HeaderCount.

The objective is not to create a table of contents.

If I type [[/ in Bear Markdown a drop down list of all headers appears. There is no way to create a full table of contents in one keystroke.

To enter the first toc header as an active link, I must
1- type [[/
2- type Enter to paste the header link
3- type Enter again to enter a new line

To enter the second toc header as an active link, I must
1- type [[/
2- type ↓ (arrow down) once
2- type Enter to paste the header link
3- type Enter again to enter a new line

To enter the third toc header as an active link, I must
1- type [[/
2- type ↓ (arrow down) twice times
2- type Enter to paste the header link
3- type Enter again to enter a new line

Note: 3rd header : press down arrow twice.

and so on until I enter the HeaderCount number of Headers

thanks again very much

Thanks. Could you show us a sample TOC that would result from this ?

(There may be a more direct route, less UI-intensive route to defining and generating such a string)

1 Like

thanks again

by active link, I mean that if I click on the toc link, the document scrolls down to the header in question, something essential for long documents

in this case, all was done manually as per my previous post

Others will show you UI event routes, but I would personally tend to do this with an Execute JavaScript action.

(Again, you can capture the generated TOC string in a variable, and perhaps paste it into, or prepend it to, something else)

Something like this:

Prepend wikilink TOC for MD headings.kmmacros (22.2 KB)

JS Source
(() => {
    'use strict';

    // ------------- WIKI TOC FROM MARKDOWN --------------

    // Rob Trew @2020
    // Ver 0.02

    // main :: () -> IO String
    const main = () => {
            kmVar = Application(
                'Keyboard Maestro Engine'
            md = kmVar('mdText');

        return unlines(
                x => x.startsWith('#') ? (
                ) : []
        ) + '\n\n\n' + md;

    // ------------------- JS PRELUDE -------------------
    // https://github.com/RobTrew/prelude-jxa

    // lines :: String -> [String]
    const lines = s =>
        // A list of strings derived from a single
        // newline-delimited string.
        0 < s.length ? (
        ) : [];

    // list :: StringOrArrayLike b => b -> [a]
    const list = xs =>
        // xs itself, if it is an Array,
        // or an Array derived from xs.
        Array.isArray(xs) ? (
        ) : Array.from(xs || []);

    // tail :: [a] -> [a]
    const tail = xs =>
        // A new list consisting of all
        // items of xs except the first.
        'GeneratorFunction' !== xs.constructor
        .constructor.name ? (
            (ys => 0 < ys.length ? ys.slice(1) : [])(
        ) : (take(1)(xs), xs);

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = n =>
        // The first n elements of a list,
        // string of characters, or stream.
        xs => 'GeneratorFunction' !== xs
        .constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];

    // unlines :: [String] -> String
    const unlines = xs =>
        // A single string formed by the intercalation
        // of a list of strings with the newline character.

    // unwords :: [String] -> String
    const unwords = xs =>
        // A space-separated string derived
        // from a list of words.
        xs.join(' ');

    // words :: String -> [String]
    const words = s =>
        // List of space-delimited sub-strings.

    return main();
1 Like

I am extremely grateful for the time and energy you are putting into this problem

1- I changed the output to paste

2- when I create the links manually they are active. When I click on the links generated by the script they are not which is surprising considering it is javascript as in java.

Javascript is much too high level for me.

Perhaps a clue: this is Bear app Markdown. A link to a header looks like (for the first header title 1)

I can paste content generated from the script (with live links) into Bear here.

Screenshot 2020-10-05 at 21.17.47

Perhaps a direct paste from the action into Bear is a bit direct - are you pasting over the existing document ?

Doing that might duplicate part of the text, or break it up.

I would start with the Execute action option that places the output in the system clipboard, and then experiment with pasting into a fresh Bear document.

1 Like

you are a genius !
works very nicely. Exactly what I needed. thank you so much !!
Is it OK if I mention this post in the Bear forum with a link and all credit to you ?
It's simply that I think it's absolutely fantastic. Transforms Bear from a PIM for notes to a document manager.

1 Like