“Copy, sort by length and paste” Macro

In my line of work I often need to find the longest line in some text.
For example to test if a business card design can accommodate the names supplied.

For this I use the macro below.

Keyboard Maestro 8.2.4 “Copy, sort by length and paste” Macro

Copy- sort by length and paste.kmmacros (2.9 KB)


Nice shell code for sort lines based on length :+1:t3:

Is there an advantage to creating the temporary file in this macro over doing this:

i.e. taking input from the system clipboard.

1 Like

No advantage. I just did not know how to get the clipboard in without writing the file first.
Thanks for the input.

1 Like

5 posts were split to a new topic: TIP: How to Use Standard In (stdin) in Shell Scripts

And I forgot to mention.
I have not made the shell code myself. Not that clever :slight_smile:
I found it here:

and if anyone wanted to include this kind of thing in an Applescript or Javascript context, we could paste a generic maximumBy function and then:


maximumBy(comparing(|length|), ¬
    paragraphs of (the clipboard))



For example:
Longest line in clipboard (Applescript).kmmacros (20.1 KB)

Longest line in clipboard (JS).kmmacros (19.5 KB)

Applescript source

on run
    maximumBy(comparing(|length|), |lines|(the clipboard))
end run

-- GENERIC FUNCTIONS ------------------------------------------------

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

-- comparing :: (a -> b) -> (a -> a -> Ordering)
on comparing(f)
        on |λ|(a, b)
            tell mReturn(f)
                set fa to |λ|(a)
                set fb to |λ|(b)
                if fa < fb then
                else if fa > fb then
                end if
            end tell
        end |λ|
    end script
end comparing

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

-- length :: [a] -> Int
on |length|(xs)
    length of xs
end |length|

-- lines :: String -> [String]
on |lines|(xs)
    paragraphs of xs
end |lines|

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

-- maximumBy :: (a -> a -> Ordering) -> [a] -> a
on maximumBy(f, xs)
    set cmp to mReturn(f)
    script max
        on |λ|(a, b)
            if a is missing value or cmp's |λ|(a, b) < 0 then
            end if
        end |λ|
    end script
    foldl(max, missing value, xs)
end maximumBy

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

Javascript source

(() => {

    const main = () =>

    // GENERIC FUNCTIONS ----------------------------------

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

    // comparing :: (a -> b) -> (a -> a -> Ordering)
    const comparing = f =>
        (x, y) => {
                a = f(x),
                b = f(y);
            return a < b ? -1 : (a > b ? 1 : 0);

    // length :: [a] -> Int
    const length = xs => xs.length;

    // lines :: String -> [String]
    const lines = s => s.split(/[\r\n]/);

    //  Ordering: (LT|EQ|GT):
    //  GT: 1 (or other positive n)
    //    EQ: 0
    //  LT: -1 (or other negative n)

    // maximumBy :: (a -> a -> Ordering) -> [a] -> a
    const maximumBy = (f, xs) =>
        0 < xs.length ? (
            .reduce((a, x) => 0 < f(x, a) ? x : a, xs[0])
        ) : undefined;

    // JXA ------------------------------------------------

    // standardSEAdditions :: () -> Application
    const standardSEAdditions = () =>
        Object.assign(Application('System Events'), {
            includeStandardAdditions: true

    // MAIN -----------------------------------------------
    return main();
1 Like

Here is an updated macro based on the input from @CJK and @peternlewis

Copy- sort by length and paste.kmmacros (2.2 KB)

And this one sort with the longest first in the list.
Actually more what I need.

Copy- sort by length and paste (longest first).kmmacros (2.2 KB)

1 Like

Hey Guys,

Here's one more for posterity.

I could have made it a bit faster, but I went for sheer simplicity.

It runs nearly instantly on 1,000 lines of text, and that's fast enough for me.

Copy and paste is left up to the user, so you may need to modify it a bit for your task.


Extract Longest Line from Text on the Clipboard.kmmacros (5.1 KB)

1 Like

A post was merged into an existing topic: Simplicity vs Complexity

A post was split to a new topic: Simplicity vs Complexity