Action
Search with one of services listed in a draft
Search on-line for :
- the selected phrase, or
- the text of the line containing the cursor.
Displays:
- a menu of online search services, and
- a text field for adjusting or replacing the search term.
The menu items are defined by any Markdown-formatted links in a draft whose UUID
should be specified at the top of the script step.
The idea is to facilitate edits and additions to the list of services, by taking it:
- out of the script step code,
- and into a draft.
It would also be possible, by:
- duplicating the action, and
- making a copy with a different UUID at the top of the script step
to use more than one such action, each using a different list of services, contained in a different draft.
( Note: the UUID of a draft can be obtained though the information icon at top left > Copy Link to Draft )
Sample of a possible draft contents for use with this action, adapted from the Search Field Mega Action
by @jmreeks:
[Amazon](https://amazon.com/s?ie=UTF8&index=blended&keywords=)
[App Store](itms-apps://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?media=software&term=)
[DuckDuckGo](https://duckduckgo.com/?q=)
[Google](https://google.com/search?q=)
[Google Images](https://google.com/search?tbm=isch&q=)
[Google Translate](https://translate.google.com/#auto/en/)
[IMDB](https://www.imdb.com/find?q=)
[iTunes](itms:/search?term=)
[Rotten Tomatoes](https://www.rottentomatoes.com/search/?search=)
[Twitter](https://twitter.com/search?q=)
[Wikipedia](https://en.wikipedia.org/wiki/Special:Search?search=)
[Wolfram Alpha](https://www.wolframalpha.com/input/?i=)
[YouTube](https://www.youtube.com/results?search_query=)
Steps
-
script
(() => { 'use strict'; /* UUID of a draft containing MD links with named search expressions up to the '=' sign. e.g. [DuckDuckGo](https://duckduckgo.com/?q=) */ // SERVICES EITHER FROM MARKDOWN LINKS IN A DRAFT, // (specified by its uuid) const uuidLinksDraft = '9A15F571-0871-4DF7-A1F3-2E5464F197A3'; // OR IF DRAFT NOT FOUND BY THAT UUID, THEN FROM THESE DEFAULTS: const fallbackDefaults = ` [Amazon](https://amazon.com/s?ie=UTF8&index=blended&keywords=) [App Store](itms-apps://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?media=software&term=) [DuckDuckGo](https://duckduckgo.com/?q=) [Google](https://google.com/search?q=) [Google Images](https://google.com/search?tbm=isch&q=) [Google Translate](https://translate.google.com/#auto/en/) [IMDB](https://www.imdb.com/find?q=) [iTunes](itms:/search?term=) [Rotten Tomatoes](https://www.rottentomatoes.com/search/?search=) [Twitter](https://twitter.com/search?q=) [Wikipedia](https://en.wikipedia.org/wiki/Special:Search?search=) [Wolfram Alpha](https://www.wolframalpha.com/input/?i=) [YouTube](https://www.youtube.com/results?search_query=)`; const main = () => { const d = Draft.find(uuidLinksDraft), lrResult = bindLR( bindLR( // LIST OF SERVICES EITHER FROM DRAFT // WITH GIVEN UUID OR FROM DEFAULTS ABOVE Right( d !== undefined ? [ 'List found in draft:\n' + uuidLinksDraft, d.content ] : [ 'No draft found by uuid:\n' + uuidLinksDraft + '\n(using default service list)', fallbackDefaults ] ), ([sourceName, strLinks]) => Right([ sourceName, new Map( regexMatches( /\[(.*)\]\((.*)\)/g, strLinks ) .map(x => [x[1], x[2]]) ) ]) ), ([sourceName, serviceMap]) => { const e = editor; return bindLR( textAndMenuChoiceLR( true, 'Search with chosen service', sourceName, 'Term:', // SELECTION OR CURRENT LINE e.getSelectedText().trim() || e.getTextInRange( ...e.getSelectedLineRange() ), [...serviceMap.keys()] ), dct => { const maybeURL = serviceMap .get(dct.choice); return maybeURL !== undefined ? ( Right( app.openURL( maybeURL + encodeURIComponent( dct.text ) ) ) ) : Left( 'Service not found: ' + dct.choice ); } ); } ); const strLeft = lrResult.Left; return strLeft && strLeft.includes('uuid') ? ( alert(strLeft) ) : console.log(lrResult.Left || lrResult.Right) }; // A CONFIRMED TEXT, AND AN ITEM CHOSEN FROM A MENU // textAndMenuChoiceLR :: Bool -> String -> String -> // String -> String -> [String] -> // Either String { text: String, choice :: String } const textAndMenuChoiceLR = ( withCancelButton, title, msg, strLabel, strText, items) => { const p = items.reduce( (a, item) => (a.addButton(item), a), Object.assign( Prompt.create(), { title: title, message: msg, isCancellable: withCancelButton } ) ); return ( p.addTextField('txt', strLabel, strText), items.length > 0 ? ( p.show() ? Right({ text: p.fieldValues.txt, choice: p.buttonPressed }) : Left('Cancel') ) : Left('Empty menu') ); }; // GENERIC FUNCTIONS --- // Left :: a -> Either a b const Left = x => ({ type: 'Either', Left: x }); // Right :: b -> Either a b const Right = x => ({ type: 'Either', Right: x }); // bindLR (>>=) :: Either a -> (a -> Either b) -> Either b const bindLR = (m, mf) => m.Right !== undefined ? ( mf(m.Right) ) : m; // regexMatches :: String -> String -> [[String]] const regexMatches = (strRgx, strHay) => { const rgx = new RegExp(strRgx, 'g'); let m = rgx.exec(strHay), xs = []; while (m)(xs.push(m), m = rgx.exec(strHay)); return xs; }; // MAIN --- return main(); })();
Options
-
After Success Default Notification Error Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.