Skip to content
This repository has been archived by the owner on Jun 4, 2022. It is now read-only.

Commit

Permalink
Dynamic classpath (#133)
Browse files Browse the repository at this point in the history
  • Loading branch information
anmonteiro committed Apr 18, 2017
1 parent ce341bc commit 67efbf0
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 27 deletions.
3 changes: 1 addition & 2 deletions .eslintrc
Expand Up @@ -13,11 +13,10 @@
"plugins" : ["flowtype", "import", "babel"],
"rules" : {
"linebreak-style": 0,
"no-duplicate-imports": 0,
"no-restricted-syntax": 0,
"no-unused-vars": ["error", { "args": "none" }],
"no-cond-assign": [2, "except-parens"],
"keyword-spacing": [2, {"before": true, "after": true}],
"array-bracket-spacing": 0,
"babel/array-bracket-spacing": 2,
"import/no-duplicates": 2,
"flowtype/boolean-style": 2,
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.md
Expand Up @@ -13,16 +13,18 @@ turn off pretty printing by binding `lumo.repl/*pprint-results*` to `false`.
([#127](https://github.com/anmonteiro/lumo/issues/127)).
- Interrupt printing at the REPL with `Ctrl+C` ([#107](https://github.com/anmonteiro/lumo/issues/107))
- Add missing Clojure repl special vars (*1, *2, *3, *e) ([#101](https://github.com/anmonteiro/lumo/issues/101))
- Make the classpath dynamic, add a new namespace `lumo.classpath` to interact
with the Lumo classpath ([#31](https://github.com/anmonteiro/lumo/issues/31)).

### Changes

- Print namespaced maps at the REPL.
- Do not print empty line if input is empty or whitespace only (make behavior
consistent with `clojure.main`).
- Invalidate cache when source file changes ([#54](https://github.com/anmonteiro/lumo/issues/54)).
- Upgrade ClojureScript to version 1.9.518.
- Upgrade ClojureScript to version 1.9.521.
- Upgrade Closure Compiler JS to version v20170409.
- Upgrade to Node.js version 7.9.0.
- Upgrade Node.js to version 7.9.0.

### Bug fixes

Expand Down
4 changes: 3 additions & 1 deletion scripts/aot-bundle-macros.bat
Expand Up @@ -11,7 +11,7 @@ echo "### Compiling Macro Namespaces"

mkdir lumo-cljs\out\macros-tmp || goto :error

echo (require 'lumo.build.api 'lumo.analyzer 'lumo.cljs-deps 'lumo.closure 'lumo.compiler 'lumo.io 'lumo.json 'lumo.util 'clojure.core.reducers 'clojure.zip 'clojure.data 'cljs.nodejs 'cljs.pprint 'cljs.test 'cljs.analyzer.api) (require-macros 'lumo.repl 'lumo.util 'clojure.template 'cljs.pprint 'cljs.support 'cljs.spec 'cljs.spec.impl.gen 'cljs.test 'cljs.reader 'cljs.env.macros 'cljs.analyzer.macros 'cljs.compiler.macros) | build\lumo.exe --quiet -c target -sdk lumo-cljs/out/macros-tmp || goto :error
echo (require 'lumo.build.api 'lumo.analyzer 'lumo.cljs-deps 'lumo.classpath 'lumo.closure 'lumo.compiler 'lumo.io 'lumo.json 'lumo.util 'clojure.core.reducers 'clojure.zip 'clojure.data 'cljs.nodejs 'cljs.pprint 'cljs.test 'cljs.analyzer.api) (require-macros 'lumo.repl 'lumo.util 'clojure.template 'cljs.pprint 'cljs.support 'cljs.spec 'cljs.spec.impl.gen 'cljs.test 'cljs.reader 'cljs.env.macros 'cljs.analyzer.macros 'cljs.compiler.macros) | build\lumo.exe --quiet -c target -sdk lumo-cljs/out/macros-tmp || goto :error

mv lumo-cljs\out\macros-tmp\clojure_SLASH_core_SLASH_reducers.js target\clojure\core\reducers.js || goto :error
mv lumo-cljs\out\macros-tmp\clojure_SLASH_core_SLASH_reducers.cache.json target\clojure\core\reducers.cache.json || goto :error
Expand All @@ -33,6 +33,8 @@ mv lumo-cljs\out\macros-tmp\lumo_SLASH_build_SLASH_api.js target\lumo\build\api.
mv lumo-cljs\out\macros-tmp\lumo_SLASH_build_SLASH_api.cache.json target\lumo\build\api.cache.json || goto :error
mv lumo-cljs\out\macros-tmp\lumo_SLASH_cljs_deps.js target\lumo\cljs_deps.js || goto :error
mv lumo-cljs\out\macros-tmp\lumo_SLASH_cljs_deps.cache.json target\lumo\cljs_deps.cache.json || goto :error
mv lumo-cljs\out\macros-tmp\lumo_SLASH_classpath.js target\lumo\classpath.js || goto :error
mv lumo-cljs\out\macros-tmp\lumo_SLASH_classpath.cache.json target\lumo\classpath.cache.json || goto :error
mv lumo-cljs\out\macros-tmp\lumo_SLASH_closure.js target\lumo\closure.js || goto :error
mv lumo-cljs\out\macros-tmp\lumo_SLASH_closure.cache.json target\lumo\closure.cache.json || goto :error
mv lumo-cljs\out\macros-tmp\lumo_SLASH_compiler.js target\lumo\compiler.js || goto :error
Expand Down
3 changes: 3 additions & 0 deletions scripts/aot-bundle-macros.sh
Expand Up @@ -17,6 +17,7 @@ $(pwd)/build/lumo --quiet -c target -sdk lumo-cljs/out/macros-tmp <<REPL_INPUT
(require 'lumo.build.api
'lumo.analyzer
'lumo.cljs-deps
'lumo.classpath
'lumo.closure
'lumo.compiler
'lumo.io
Expand Down Expand Up @@ -64,6 +65,8 @@ mv lumo-cljs/out/macros-tmp/lumo_SLASH_build_SLASH_api.js target/lumo/build/api.
mv lumo-cljs/out/macros-tmp/lumo_SLASH_build_SLASH_api.cache.json target/lumo/build/api.cache.json
mv lumo-cljs/out/macros-tmp/lumo_SLASH_cljs_deps.js target/lumo/cljs_deps.js
mv lumo-cljs/out/macros-tmp/lumo_SLASH_cljs_deps.cache.json target/lumo/cljs_deps.cache.json
mv lumo-cljs/out/macros-tmp/lumo_SLASH_classpath.js target/lumo/classpath.js
mv lumo-cljs/out/macros-tmp/lumo_SLASH_classpath.cache.json target/lumo/classpath.cache.json
mv lumo-cljs/out/macros-tmp/lumo_SLASH_closure.js target/lumo/closure.js
mv lumo-cljs/out/macros-tmp/lumo_SLASH_closure.cache.json target/lumo/closure.cache.json
mv lumo-cljs/out/macros-tmp/lumo_SLASH_compiler.js target/lumo/compiler.js
Expand Down
56 changes: 56 additions & 0 deletions src/cljs/bundled/lumo/classpath.cljs
@@ -0,0 +1,56 @@
(ns lumo.classpath
(:require [clojure.string :as string]))

(def fs (js/require "fs"))

(defn jar-file?
"Returns true if file is a normal file with a .jar or .JAR extension."
[f]
(and (try
(.. fs (statSync f) (isFile))
(catch :default _ false))
(or (.endsWith f ".jar")
(.endsWith f ".JAR"))))

(defn filenames-in-jar
"Returns a sequence of Strings naming the non-directory entries in
the JAR file."
[jar-file]
(let [zip (.load (js/$$LUMO_GLOBALS.JSZip.) (fs.readFileSync jar-file))]
(map #(. % -name)
(filter (fn [f]
(not (.-dir f)))
(js/Object.values zip.files)))))

(defn classpath
"Returns a sequence of the elements on the classpath."
[]
(seq (js/$$LUMO_GLOBALS.getSourcePaths)))

(defn- directory? [x]
(try
(.. fs (statSync x) (isDirectory))
(catch :default _ false)))

(defn classpath-directories
"Returns a sequence of the directories on the classpath."
[]
(filter directory? (classpath)))

;; TODO: clojure.java.classpath returns a JarFile seq. should we return a
;; JSZip.files entry?
(defn classpath-jarfiles
"Returns a sequence of the JAR files on the classpath."
[]
(filter jar-file? (classpath)))

(defn add!
"Add a directory, sequence of directories, JAR file or sequence of JAR to the Lumo classpath."
[path-or-paths]
(js/$$LUMO_GLOBALS.addSourcePaths (into-array (cond-> path-or-paths
(not (sequential? path-or-paths)) vector))))

(defn remove!
"Remove a directory or JAR file from the Lumo classpath."
[path]
(js/$$LUMO_GLOBALS.removeSourcePath path))
2 changes: 2 additions & 0 deletions src/cljs/snapshot/lumo/repl.cljs
Expand Up @@ -1007,6 +1007,7 @@
lumo.js-deps
lumo.repl
lumo.repl-resources
lumo.classpath
cognitect.transit
lazy-map.core
cljs.source-map
Expand Down Expand Up @@ -1091,6 +1092,7 @@
(map str (keys special-doc-map))
(map str (keys repl-special-doc-map))))])))

;; TODO: "str/" returns all cljs.core symbols
(defn ^:export get-completions
[line cb]
(let [js-matches (re-find #"js/(\S*)$" line)]
Expand Down
5 changes: 3 additions & 2 deletions src/js/__tests__/lumo-test.js
Expand Up @@ -132,6 +132,7 @@ describe('lumo', () => {

describe('readSource', () => {
const pathResolve = path.resolve;

beforeEach(() => {
jest.resetModules();
lumo = require('../lumo'); // eslint-disable-line global-require
Expand All @@ -145,7 +146,7 @@ describe('lumo', () => {
it('cycles through the source paths', () => {
const srcPaths = ['a', 'b', 'c'];
lumo.addSourcePaths(srcPaths);
const lumoPaths = ['', ...srcPaths];
const lumoPaths = [process.cwd(), ...srcPaths];

fs.readFileSync = jest.fn((filename: string) => {
throw new Error(`file doesn't exist: ${filename}`);
Expand Down Expand Up @@ -229,7 +230,7 @@ describe('lumo', () => {
it('cycles through the source paths', () => {
const srcPaths = ['a', 'b', 'c'];
lumo.addSourcePaths(srcPaths);
const lumoPaths = ['', ...srcPaths];
const lumoPaths = [process.cwd(), ...srcPaths];

fs.existsSync = jest.fn((_: string) => false);

Expand Down
6 changes: 4 additions & 2 deletions src/js/cljs.js
Expand Up @@ -152,7 +152,8 @@ function newDevelopmentContext(): vm$Context {
readSourceFromJar: lumo.readSourceFromJar,
eval: lumoEval,
addSourcePaths: lumo.addSourcePaths,
readSourcePaths: lumo.readSourcePaths,
getSourcePaths: lumo.getSourcePaths,
removeSourcePath: lumo.removeSourcePath,
},
global: undefined,
};
Expand Down Expand Up @@ -183,7 +184,8 @@ function newClojureScriptContext(): { [key: string]: mixed } {
readSourceFromJar: lumo.readSourceFromJar,
eval: lumoEval,
addSourcePaths: lumo.addSourcePaths,
readSourcePaths: lumo.readSourcePaths,
getSourcePaths: lumo.getSourcePaths,
removeSourcePath: lumo.removeSourcePath,
};

return global;
Expand Down
32 changes: 14 additions & 18 deletions src/js/lumo.js
Expand Up @@ -11,8 +11,7 @@ import JSZip from 'jszip';
import ArrayStream from './array-stream';
import * as util from './util';

// TODO: make this a set
const sourcePaths = [''];
const sourcePaths = new Set([process.cwd()]);

type SourceType = {|
source: string,
Expand Down Expand Up @@ -77,10 +76,7 @@ export function getGoogleClosureCompiler(): Function {

// TODO: cache JARs that we know have a given file / path
export function readSource(filename: string): ?SourceType {
const len = sourcePaths.length;
for (let i = 0; i < len; i += 1) {
const srcPath = sourcePaths[i];

for (const srcPath of sourcePaths.values()) {
try {
if (srcPath.endsWith('.jar')) {
const data = fs.readFileSync(srcPath);
Expand Down Expand Up @@ -124,7 +120,8 @@ export function writeCache(filename: string, source: string): ?Error {
}

export function loadUpstreamForeignLibs(): string[] {
return sourcePaths.reduce((ret: string[], srcPath: string) => {
const ret = [];
for (const srcPath of sourcePaths.values()) {
if (srcPath.endsWith('.jar')) {
try {
const data = fs.readFileSync(srcPath);
Expand All @@ -136,23 +133,19 @@ export function loadUpstreamForeignLibs(): string[] {
}
} catch (_) {} // eslint-disable-line no-empty
}
return ret;
}, []);
}
return ret;
}

export function resource(filename: string): ?ResourceType {
const len = sourcePaths.length;

if (isBundled(filename)) {
return {
type: 'bundled',
src: filename,
};
}

for (let i = 0; i < len; i += 1) {
const srcPath = sourcePaths[i];

for (const srcPath of sourcePaths.values()) {
if (srcPath.endsWith('.jar')) {
const data = fs.readFileSync(srcPath);
const zip = new JSZip().load(data);
Expand All @@ -179,17 +172,20 @@ export function resource(filename: string): ?ResourceType {
return null;
}

export function getSourcePaths(): string[] {
return [...sourcePaths];
}

export function addSourcePaths(srcPaths: string[]): void {
const expanded = srcPaths.map((srcPath: string) =>
// $FlowIssue
path.normalize(util.expandPath(srcPath)),
);

sourcePaths.push(...expanded);
expanded.forEach((p: string) => sourcePaths.add(p));
}

export function readSourcePaths(): string[] {
return [...sourcePaths];
export function removeSourcePath(srcPath: string): boolean {
return sourcePaths.delete(util.expandPath(srcPath));
}

export function readSourceFromJar({
Expand Down

0 comments on commit 67efbf0

Please sign in to comment.