Skip to content

Commit

Permalink
Added support for the VS Code Web version
Browse files Browse the repository at this point in the history
  • Loading branch information
mihai-vlc committed Jul 30, 2022
1 parent 7fe8972 commit 9ebd059
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 62 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
package-lock.json
tmp
*.vsix
dist
33 changes: 27 additions & 6 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,37 @@
"version": "0.2.0",
"configurations": [
{
"name": "Extension",
"name": "Run for native VS Code",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}"],
"stopOnEntry": false,
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
],
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/out/**/*.js"],
"skipFiles": ["<node_internals>/**", "**/node_modules/**", "**/resources/app/out/vs/**"],
"outFiles": [
"${workspaceRoot}/out/**/*.js"
],
"skipFiles": [
"<node_internals>/**",
"**/node_modules/**",
"**/resources/app/out/vs/**"
],
"preLaunchTask": "npm: watch"
},
{
"name": "Run Web Extension in VS Code",
"type": "extensionHost",
"debugWebWorkerHost": true,
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionDevelopmentKind=web"
],
"outFiles": [
"${workspaceFolder}/dist/web/**/*.js"
],
"preLaunchTask": "npm: watch-web"
}
]
}
}
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
"[javascript][typescript][typescriptreact][json][jsonc][yaml][markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
},
"editor.formatOnSave": true
}
11 changes: 10 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
"kind": "build",
"isDefault": true
}
},
{
"type": "npm",
"script": "watch-web",
"group": "build",
"isBackground": true,
"problemMatcher": [
"$ts-webpack-watch"
]
}
]
}
}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
# Path Autocomplete Change Log

#### 1.19.1

- Adds support for VS Code for Web

#### 1.19.1

- Fixes the extension loading on remote ssh #108

#### 1.19.0

- Updates the completion label to be consistent with insertText
- Fix: asar file is recogonized as directory
- Upgrade dependencies

#### 1.18.0

1. integrate some useful front end tools: eslint, prettier
2. optimize dotfiles, settings.json, launch.json
3. fix #100
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Provides path completion for visual studio code.
- it supports custom mappings via the `path-autocomplete.pathMappings` option
- it supports custom transformations to the inserted text via the `path-autocomplete.transformations`
- it supports windows paths with the `path-autocomplete.useBackslash`
- it supports VS Code for Web

## Installation

Expand Down
61 changes: 61 additions & 0 deletions build/web-extension.webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

//@ts-check
'use strict';

//@ts-check
/** @typedef {import('webpack').Configuration} WebpackConfig **/

const path = require('path');
const webpack = require('webpack');

module.exports = /** @type WebpackConfig */ {
context: path.dirname(__dirname),
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
target: 'webworker', // extensions run in a webworker context
entry: {
extension: './src/extension.ts',
},
resolve: {
mainFields: ['module', 'main'],
extensions: ['.ts', '.js'], // support ts-files and js-files
alias: {},
fallback: {
assert: require.resolve('assert'),
path: require.resolve('path-browserify'),
},
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
},
],
},
],
},
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser',
}),
],
externals: {
vscode: 'commonjs vscode', // ignored because it doesn't exist
},
performance: {
hints: false,
},
output: {
filename: '[name].js',
path: path.join(__dirname, '../out/web'),
libraryTarget: 'commonjs',
},
devtool: 'nosources-source-map',
};
34 changes: 21 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "path-autocomplete",
"displayName": "Path Autocomplete",
"description": "Provides path completion for visual studio code.",
"version": "1.19.1",
"description": "Provides path completion for visual studio code and VS Code for Web.",
"version": "1.20.0",
"publisher": "ionutvmi",
"icon": "icon.png",
"repository": {
Expand All @@ -14,7 +14,7 @@
"email": "[email protected]"
},
"engines": {
"vscode": "^1.64.0"
"vscode": "^1.69.0"
},
"keywords": [
"path",
Expand All @@ -30,26 +30,34 @@
"*"
],
"main": "./out/src/extension",
"browser": "./out/web/extension.js",
"scripts": {
"vscode:prepublish": "npm run compile",
"vscode:prepublish": "npm run compile && npm run compile-web",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"type-check": "tsc -p ./tsconfig.json --noEmit",
"lint": "eslint -c .eslintrc.js --ext .ts"
"lint": "eslint -c .eslintrc.js --ext .ts",
"compile-web": "webpack --config ./build/web-extension.webpack.config.js",
"watch-web": "webpack --watch --config ./build/web-extension.webpack.config.js"
},
"dependencies": {
"minimatch": "5.0.1"
},
"devDependencies": {
"@types/minimatch": "^3.0.5",
"@types/node": "^17.0.21",
"@types/vscode": "^1.64.0",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"eslint": "^8.10.0",
"eslint-config-prettier": "^8.5.0",
"@types/minimatch": "3.0.5",
"@types/node": "18.6.2",
"@types/vscode": "1.69.0",
"@typescript-eslint/eslint-plugin": "5.31.0",
"@typescript-eslint/parser": "5.31.0",
"eslint": "8.20.0",
"eslint-config-prettier": "8.5.0",
"path-browserify": "1.0.1",
"prettier": "2.5.1",
"typescript": "^4.6.2"
"process": "0.11.10",
"ts-loader": "9.3.1",
"typescript": "4.7.4",
"webpack": "5.74.0",
"webpack-cli": "4.10.0"
},
"contributes": {
"configuration": {
Expand Down
6 changes: 2 additions & 4 deletions src/features/FileInfo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { basename } from 'path';
import fs from 'fs';

export type FileType = 'dir' | 'file';

export class FileInfo {
Expand All @@ -13,10 +11,10 @@ export class FileInfo {
*
* @throws Error if the path is invalid or you don't have permissions to it
*/
constructor(path: string, type?: FileType) {
constructor(path: string, type: FileType) {
this.name = basename(path);
this.path = path;
this.type = type ?? (fs.statSync(path).isDirectory() ? 'dir' : 'file');
this.type = type;
}

get isDirectory() {
Expand Down
45 changes: 15 additions & 30 deletions src/features/FsUtils.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,23 @@
import fs from 'fs';
import fsAsync from 'fs/promises';
import vs from 'vscode';

export function pathExists(localPath: string) {
return fsAsync
.access(localPath, fs.constants.F_OK)
.then(() => true)
.catch(() => false);
export async function pathExists(localPath: string): Promise<boolean> {
try {
await vs.workspace.fs.stat(vs.Uri.file(localPath));
return true;
} catch (e) {
return false;
}
}

const originalFs = getFsModule();

export async function isDirectory(filePath: string): Promise<boolean> {
return new Promise((resolve, reject) => {
originalFs.stat(filePath, (err, statInfo) => {
if (err) {
reject(err);
return;
}

resolve(statInfo.isDirectory());
});
});
}

function getFsModule() {
try {
// throws an error if module is not found (remote ssh environment)
require.resolve("original-fs");

// using original-fs rather than fs to deal with .asar file
// ref: https://github.com/microsoft/vscode/issues/143393#issuecomment-1047518447
return require('original-fs') as typeof fs;
const stat = await vs.workspace.fs.stat(vs.Uri.file(filePath));
return stat.type === vs.FileType.Directory;
} catch (e) {
console.log("original-fs not found, falling back to the default fs module");
return fs;
return false;
}
}

export async function readDirectory(filePath: string) {
return vs.workspace.fs.readDirectory(vs.Uri.file(filePath));
}
13 changes: 6 additions & 7 deletions src/features/PathAutocompleteProvider.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import fsAsync from 'fs/promises';
import path from 'path';

import vs from 'vscode';
import minimatch from 'minimatch';
import { FileInfo } from './FileInfo';
import PathConfiguration from './PathConfiguration';
import { isDirectory, pathExists } from './FsUtils';
import { isDirectory, pathExists, readDirectory } from './FsUtils';

interface MappingItem {
currentDir: string;
Expand Down Expand Up @@ -185,13 +184,13 @@ export class PathAutocomplete implements vs.CompletionItemProvider {
*/
async getFolderItems(foldersPath: string[]): Promise<FileInfo[]> {
const getFileInfoPromises = foldersPath.map(async (folderPath) => {
const filenames = await fsAsync.readdir(folderPath);
const fileTuples = await readDirectory(folderPath);
return Promise.all(
filenames.map(async (filename) => {
const filePath = path.join(folderPath, filename);
fileTuples.map(async (fileTuple) => {
const filePath = path.join(folderPath, fileTuple[0]);
try {
const fileType = (await isDirectory(filePath)) ? 'dir' : 'file';
return new FileInfo(filePath, fileType);
const isDir = fileTuple[1] === vs.FileType.Directory;
return new FileInfo(filePath, isDir ? 'dir' : 'file');
} catch (err) {
// silently ignore permissions errors
console.error(err);
Expand Down

0 comments on commit 9ebd059

Please sign in to comment.