diff --git a/extension.js b/extension.js index 8345e6b..5e9bbde 100644 --- a/extension.js +++ b/extension.js @@ -1,6 +1,7 @@ const vscode = require('vscode'); const fs = require('fs'); const path = require('path'); +const { findParentModules } = require('./find-parent-modules'); const { findChildPackages } = require('./find-child-packages'); const { showError } = require('./utils'); @@ -16,6 +17,7 @@ exports.activate = context => { const useLastFolder = preferences.get('useLastFolder', false); const nodeModulesPath = preferences.get('path', nodeModules); + const searchParentModules = preferences.get('searchParentModules', true); const searchPath = (workspaceName, workspaceRoot, folderPath) => { // Path to node_modules in this workspace folder @@ -30,7 +32,7 @@ exports.activate = context => { const folderFullPath = path.join(workspaceRoot, folderPath); // Read folder, built quick pick with files/folder (and shortcuts) - fs.readdir(folderFullPath, (readErr, files) => { + fs.readdir(folderFullPath, async (readErr, files) => { if (readErr) { if (folderPath === nodeModulesPath) { return showError('No node_modules folder in this workspace.'); @@ -39,14 +41,29 @@ exports.activate = context => { return showError(`Unable to open folder ${folderPath}`); } - if (folderPath !== nodeModulesPath) { - files.push(''); - files.push(workspaceNodeModules); - files.push('..'); + const isParentFolder = folderPath.includes('..'); + const options = files; + + // If searching in root node_modules, also include modules from parent folders, that are outside of the workspace + if (folderPath === nodeModulesPath) { + if (searchParentModules) { + const parentModules = await findParentModules(workspaceRoot, nodeModulesPath); + options.push(...parentModules); + } + } else { + // Otherwise, show option to move back to root + options.push(''); + options.push(workspaceNodeModules); + + // If current folder is not outside of the workspace, also add option to move a step back + if (!isParentFolder) { + options.push('..'); + } } - vscode.window.showQuickPick(files, { - placeHolder: path.join(workspaceName, folderPath) + + vscode.window.showQuickPick(options, { + placeHolder: path.format({ dir: workspaceName, base: folderPath}) }) .then(selected => { // node_modules shortcut selected diff --git a/find-parent-modules.js b/find-parent-modules.js new file mode 100644 index 0000000..7b56f71 --- /dev/null +++ b/find-parent-modules.js @@ -0,0 +1,36 @@ +const fs = require('fs'); +const path = require('path').posix; +const util = require('util'); + +const fsExists = util.promisify(fs.exists); +const fsReaddir = util.promisify(fs.readdir); + +// Looks for node_modules in parent folders of the workspace recursively. +// Returns a list of paths relative to workspaceRoot/nodeModulesPath +const findParentModules = async (workspaceRoot, nodeModulesPath) => { + const absoluteRootNodeModules = path.join('/', nodeModulesPath); + + const find = async dir => { + const ret = []; + if (await fsExists(dir)) { + const getFilePath = file => + path.relative(path.join(workspaceRoot, nodeModulesPath), path.join(dir, file)); + + const dirFiles = await fsReaddir(dir); + ret.push(...dirFiles.map(getFilePath)); + } + + if (dir !== absoluteRootNodeModules) { + const parent = path.join(dir, '..', '..', nodeModulesPath); + ret.push(...(await find(parent))); + } + + return ret; + }; + + return find(path.join(workspaceRoot, '..', nodeModulesPath)); +}; + +module.exports = { + findParentModules +}; diff --git a/package.json b/package.json index 6fe8d63..e0b9843 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,11 @@ "type": "string", "default": "node_modules", "description": "Relative path to node_modules folder." + }, + "search-node-modules.searchParentModules": { + "type": "boolean", + "default": true, + "description": "Include modules from parent folders in search results." } } }