I have a file that contains a number of functions (not dealing with HTML/CSS). Is there a way to import them into JXA so that I can use them in JXA?
from what I understood, do you want to Execute Script from a File?
https://wiki.keyboardmaestro.com/JavaScript_for_Automation?s[]=file
"The JXA script may be accessed as text in the Action, or from a file"
Thanks. But that does not answer my question. My question is how to import the functions in another file into the current working JXA script.
If you’re talking about using the file as a library you can just import it like any script library.
See, for example, https://github.com/JXA-Cookbook/JXA-Cookbook/wiki/Importing-Scripts
It may in practice be simpler to copy-paste your functions across, but it is possible to use the Function
/ eval
pattern (which has, to be honest, a deservedly sulphurous reputation).
I tend to do this rather than using the JXA Library mechanism (referenced in the previous post) which I find occasionally a bit fragile, and generally not able to cope with any cross-dependencies between the functions in the library (each has to be stand-alone).
Function/eval
:
// Evaluate a function f :: (() -> a)
// in the context of the JS libraries whose source
// filePaths are listed in fps :: [FilePath]
// usingLibs :: [FilePath] -> (() -> a) -> a
const usingLibs = fps =>
f => {
const gaps = fps.filter(fp => !doesFileExist(fp));
return 1 > gaps.length ? Function(
`"use strict";
${fps.map(readFile).join("\n\n")}
return (${f})();`
)() : `Library not found at: ${gaps.join("\n")}`;
};
For a fuller example:
Expand disclosure triangle to view JS Source
/* eslint-disable no-new-func */
(() => {
"use strict";
// main :: IO ()
const main = () => {
const inner = () =>
sj(
foldl(add)(0)(
ft(1)(10)
)
);
return inner();
};
// ----------------- LIBRARY IMPORT ------------------
// Evaluate a function f :: (() -> a)
// in the context of the JS libraries whose source
// filePaths are listed in fps :: [FilePath]
// Evaluate a function f :: (() -> a)
// in the context of the JS libraries whose source
// filePaths are listed in fps :: [FilePath]
// usingLibs :: [FilePath] -> (() -> a) -> a
const usingLibs = fps =>
f => {
const gaps = fps.filter(fp => !doesFileExist(fp));
return 1 > gaps.length ? Function(
`"use strict";
${fps.map(readFile).join("\n\n")}
return (${f})();`
)() : `Library not found at: ${gaps.join("\n")}`;
};
// doesFileExist :: FilePath -> IO Bool
const doesFileExist = strPath => {
const ref = Ref();
return $.NSFileManager.defaultManager
.fileExistsAtPathIsDirectory(
$(strPath)
.stringByStandardizingPath, ref
) && 1 !== ref[0];
};
// readFile :: FilePath -> IO String
const readFile = fp => {
const
e = $(),
ns = $.NSString.stringWithContentsOfFileEncodingError(
$(fp).stringByStandardizingPath,
$.NSUTF8StringEncoding,
e
);
return ObjC.unwrap(
ns.isNil() ? (
e.localizedDescription
) : ns
);
};
// ---------------------- MAIN -----------------------
// https://github.com/RobTrew/prelude-jxa
return usingLibs([
"~/prelude-jxa/jsPrelude.js",
"~/prelude-jxa/jxaSystemIO.js",
"~/jsParserCombinators/parserCombinators.js"
])(main);
})();