Skip to content

Instantly share code, notes, and snippets.

@daveseah
Last active August 30, 2018 01:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daveseah/8d84050564c861d0f33649741c378ea9 to your computer and use it in GitHub Desktop.
Save daveseah/8d84050564c861d0f33649741c378ea9 to your computer and use it in GitHub Desktop.
Alfred 4 : Script to open a set of folders/objects (MacOS Automation Javascript/JXA)
/*////////////////////////// ALFRED OPEN FOLDERS \\\\\\\\\\\\\\\\\\\\\\\\\\\\*\
A script to accept an input query keyword, then open a set of folders/files
via the finder. I made this to quickly open folders and related files by
keyword. CMD-SPACE followed by cd km, fo example, opens my ~/KM folder and
launches a VSCODE project after speaking a custom prompt.
/// CONSTANTS ///////////////////////////////////////////////////////////////*/
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// long directory paths
const DESKTOP = `~/Desktop/`;
const DROPBOX = `${DESKTOP}/Dropbox`;
const KMBASE = `~/KM`;
const PROJECTS = `${DROPBOX}/@DAVE-PROJECTS`;
const PERSONAL = `${DROPBOX}/@DAVE-PERSONAL`;
const DSCOM = `${DROPBOX}/@DAVE-PERSONAL/@DavidSeahCom/`;
const VHOSTS = '~/Web/vhosts';
const BIZ = `${DROPBOX}/@DAVE-BUSINESS`;
// map keywords to "stuff to open"
// can be a directory path or a file
const ENTRIES = {
user : '~/',
me : '~/',
desk : DESKTOP,
drop : DROPBOX,
proj : PROJECTS,
dev : '~/Dev',
web : '~/Web',
dscom : `${DSCOM}`,
images : `${DSCOM}/httpdocs-synched/_wpcontent/images/18`,
km : [
`${KMBASE}`,
`${KMBASE}/km-ssg.code-workspace`,
// special string to override default speech prompt
'say: getting KM-SSG'
],
nc : [
'~/Dev/netcreate-2018/netcreate-2018.code-workspace',
'say: opening NetCreate',
],
ncwiki : [
'~/Dev/netcreate-2018-wiki/netcreate-wiki.code-workspace',
'say: opening NetCreate Wiki',
],
freelance : [
`${BIZ}/accounting/freelance2018.xlsx`,
'say: getting timesheet',
'flag: nofocus'
],
invoice : [
`${BIZ}/accounting/freelance2018-invoice.xlsx`,
'say: getting invoice',
'flag: nofocus'
]
} // end ENTRIES
/// MODULE LEVEL VARS /////////////////////////////////////////////////////////
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// m_app refers to this running script!
let m_app = Application.currentApplication();
m_app.includeStandardAdditions = true;
let m_say;
let m_finder = Application("Finder");
let m_focus = m_finder;
let m_flags = { nofocus : false };
/// ENTRY POINT ///////////////////////////////////////////////////////////////
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ alfred loads this script and expects there to be a run() function to call
with the 'query' received from the input.
The run() function should return data for the next linked item to use but
THIS script doesn't return anything useful since all the action happens
here
/*/ function run(argv) {
let query = argv[0].trim();
console.log(`contents of argv`,JSON.stringify(argv));
// does the query exist in our ENTRIES table?
// if not, throw up an alert window and exit
if (!ENTRIES.hasOwnProperty(query)) {
m_app.displayAlert(`I don't have a path alias for '${query}'`);
return query;
}
// if we got this far, we have a valid keyword
let entry = ENTRIES[query];
let opens = [];
// the opens[] array is loaded with string paths to open via Finder
// check for special case string 'say:' to override voice prompt
if (Array.isArray(entry)) for (entryItem of entry) {
if (DidProcessFlag(entryItem)) continue;
else opens.push(entryItem);
} else {
opens.push(entry);
}
// done processing, so use MacOS speech synthesis
m_app.say(m_say || `getting ${query}`);
// get an instance of the Finder, and tell it to open
// each path in opens[] array. the strings in opens[]
// have to be converted to the Path data structure.
opens.forEach((element)=>{
m_focus = m_finder.open(Path($(element).stringByStandardizingPath.js));
});
// tell the last opened path to activate in case it's behind anything
// not sure this is necessary
if ((!m_flags.nofocus)&&(m_focus)) m_focus.activate();
} // end function run()
/// SUPPORT FUNCTIONS /////////////////////////////////////////////////////////
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ DidProcessFlag() accepts a string, looking for keywords at the beginning
to set other global flags that affect how the workflow behaves.
Returns TRUE if it processed a flag, FALSE if there was no flag
/*/ function DidProcessFlag( entryItem ) {
if (entryItem.startsWith('say:')) {
m_say = entryItem.substring(4).trim();
return true;
}
if (entryItem.startsWith('flag:')) {
let flag = entryItem.substring(5).trim();
switch (flag) {
case 'nofocus' : m_flags.nofocus = true; break;
default:
m_app.displayAlert(`error processing flag:${flag}`)
}
return true;
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment