I want KM to write a list of numbers using variables with a padding of zeroes

I would like to put the sequence after a Prefix that would be the same with each changing number. For instance:
DepSecDef001
DepSecDef002
DepSecDef003
DepSecDef004
DepSecDef005

I guess I would also want to specify how many instances I want to wind up with in the list, too.

Thanks!

-jg

Hi Jimmy,

Here's something to get you started:

Write List of Padded Numbers.kmmacros (3.9 KB)
image

38%20PM
38%20PM

and, of course, there are also various approaches to doing this kind of thing with Execute Script actions in JavaScript or AppleScript:

Padded numeric suffixes.kmmacros (23.2 KB)

JS source

(() => {
    'use strict';

    const main = () => {
        const
            kmVar = Application(
                'Keyboard Maestro Engine'
            ).getvariable;
        const
            intFirst = parseInt(kmVar('firstIndex')),
            intLast = parseInt(kmVar('lastIndex')),
            strPrefix = kmVar('seriesPrefix'),
            intDigits = max(
                parseInt(kmVar('minDigitWidth')),
                intLast.toString().length
            );

        return unlines(
            map(x => strPrefix + justifyRight(
                    intDigits, '0', x.toString()
                ),
                enumFromTo(intFirst, intLast)
            )
        );
    };

    // GENERIC --------------------------------------------
    // https://github.com/RobTrew/prelude-jxa

    // enumFromTo :: (Int, Int) -> [Int]
    const enumFromTo = (m, n) =>
        Array.from({
            length: 1 + n - m
        }, (_, i) => m + i);

    // justifyRight :: Int -> Char -> String -> String
    const justifyRight = (n, cFiller, s) =>
        n > s.length ? (
            s.padStart(n, cFiller)
        ) : s;

    // map :: (a -> b) -> [a] -> [b]
    const map = (f, xs) =>
        (Array.isArray(xs) ? (
            xs
        ) : xs.split('')).map(f);

    // max :: Ord a => a -> a -> a
    const max = (a, b) => b > a ? b : a;

    // unlines :: [String] -> String
    const unlines = xs => xs.join('\n');

    // MAIN ---
    return main();
})();

Applescript source

on run
    tell application "Keyboard Maestro Engine"
        set intFirst to (getvariable "firstIndex") as integer
        set intLast to (getvariable "lastIndex") as integer
        set strPrefix to getvariable "seriesPrefix"
        set intDigits to my max((getvariable "minDigitWidth") as integer, ¬
            length of (intLast as string))
    end tell
    
    script series
        on |λ|(x)
            strPrefix & justifyRight(intDigits, "0", x as string)
        end |λ|
    end script
    unlines(map(series, enumFromTo(intFirst, intLast)))
end run


-- GENERIC --------------------------------------------
-- https://github.com/RobTrew/prelude-applescript

-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
    if m ≤ n then
        set lst to {}
        repeat with i from m to n
            set end of lst to i
        end repeat
        return lst
    else
        return {}
    end if
end enumFromTo

-- justifyRight :: Int -> Char -> String -> String
on justifyRight(n, cFiller, strText)
    if n > length of strText then
        text -n thru -1 of ((replicate(n, cFiller) as text) & strText)
    else
        strText
    end if
end justifyRight

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- max :: Ord a => a -> a -> a
on max(x, y)
    if x > y then
        x
    else
        y
    end if
end max

-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    if script is class of f then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary 
-- assembly of a target length
-- replicate :: Int -> a -> [a]
on replicate(n, a)
    set out to {}
    if n < 1 then return out
    set dbl to {a}
    
    repeat while (n > 1)
        if (n mod 2) > 0 then set out to out & dbl
        set n to (n div 2)
        set dbl to (dbl & dbl)
    end repeat
    return out & dbl
end replicate

-- unlines :: [String] -> String
on unlines(xs)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, linefeed}
    set str to xs as text
    set my text item delimiters to dlm
    str
end unlines

Thanks so much for this. It is by far the easier to understand and adjust and seems to work just fine.

1 Like

Thanks.

1 Like