A subroutine which lists all the links (URLs) found in a given sample of plain text.
The list is formatted as as JSON array.
To count the links in the list, and get at individual items by index, see the Keyboard Maestro %JSONValue% token.
You can also work through the resulting list of URLs with a Keyboard Maestro For Each
action, using its JSON keys collection
option.
The subroutine, with a macro illustrating its use:
List of URLs found in a text Macros.kmmacros (8.6 KB)
Expand disclosure triangle to view JS source of subroutine
const
uw = ObjC.unwrap,
e = $(),
source = kmvar.local_Source_text,
maybeDetector = $.NSDataDetector
.dataDetectorWithTypesError(
$.NSTextCheckingTypeLink,
e
);
return maybeDetector.isNil()
? e.localizedDescription
: JSON.stringify(
uw(
maybeDetector
.matchesInStringOptionsRange(
$(source), 0,
$.NSMakeRange(0, source.length)
)
)
.map(
x => uw(x.URL.absoluteString)
),
null, 2
);
will produce the following from the text below:
Where the output text displayed is:
%Variable%local_LinkListJSON%
Number of links found: %JSONValue%local_LinkListJSON[0]%
First link: %JSONValue%local_LinkListJSON[1]%
Second link: %JSONValue%local_LinkListJSON[2]%
Third link: %JSONValue%local_LinkListJSON[3]%
BACKGROUND
In this thread on obtaining the first URL in the notes attached to a Things3 Todo,
Things 3 Get URL of notes - Questions & Suggestions - Keyboard Maestro Discourse
it would have been helpful to have a subroutine which extracted a list of any links found in the note text.
Instead, we ended up using a useful but slightly baroque regular expression, contributed in a Stack Overflow discussion.
javascript - What is a good regular expression to match a URL? - Stack Overflow
A useful rule of thumb is that if your regular expression is more than about
10 characters long (perhaps something simple like \r\n|\n|\r
) then
you are probably on the wrong track. Opinion varies on this, of course
see: Jeffrey Friedl's Blog » Source of the famous “Now you have two problems” quote
What we can safely say, however, is that regular expressions:
- Can't cope with recursive patterns (think of outlines, grammars), and
- are less readable than writable - worryingly time-consuming to debug and maintain.
On recent builds of macOS, the problem is largely solved for us by a very useful
Foundation library function (NSDataDetector dataDetectorWithTypes
)
which has an NSTextCheckingTypeLink
option, and does all the work for us –
building a list of the URLs in a given text.
We can wrap this in a Keyboard Maestro subroutine (as above, packaged with an example of its use) to make it easier to reach for.