Skip to content

Commit

Permalink
feature: ✨ 功能完成
Browse files Browse the repository at this point in the history
    - 完成基本功能
  • Loading branch information
YoRolling committed Dec 6, 2018
1 parent 1059a9c commit 3f0ab4d
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 43 deletions.
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 @@
"out": true // set this to false to include "out" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off"
"typescript.tsc.autoDetect": "off",
"typescript.tsdk": "node_modules/typescript/lib"
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "exclude-it",
"displayName": "Exclude It",
"description": "exclude files or folders with right click ",
"version": "0.0.1",
"version": "1.0.0",
"engines": {
"vscode": "^1.29.0"
},
Expand All @@ -17,11 +17,11 @@
"commands": [
{
"command": "extension.excludeWs",
"title": "exclude it as workspace"
"title": "Exclude: workspace"
},
{
"command": "extension.excludeglobal",
"title": "exclude it as global"
"title": "Exclude: global"
}
],
"menus": {
Expand Down
163 changes: 124 additions & 39 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,154 @@
'use strict';
"use strict";
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
const Path = require('path');
const fs = require('fs');
import * as vscode from "vscode";
import * as utils from "./utils/utils";
import { isNullOrUndefined } from "util";
const rootPath = vscode.workspace.rootPath;

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "exclude-it" is now active!');

// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand(
'extension.excludeWs',
() => {
// The code you place here will be executed every time your command is executed

// Display a message box to the user
vscode.window.showInformationMessage('Hello World!');
"extension.excludeWs",
(uri: vscode.Uri) => {
globMatch(uri, false);
}
);
// excludeglobal
context.subscriptions.push(disposable);
context.subscriptions.push(registerGlobal());
context.subscriptions.push(registerGlobal(context));
}

function registerGlobal() {
function registerGlobal(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand(
'extension.excludeglobal',
"extension.excludeglobal",
(uri: vscode.Uri) => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
const parseMeta = parseFilePath(uri.path);
vscode.window.showInformationMessage(JSON.stringify(uri));
globMatch(uri, true);
}
);
return disposable;
}

/**
* show file glob quick pick to decide which `glob` will be add to exluded
* @author YoRolling
* @param filePath
* @since 1.0.0
* @param {string[]} items
* @returns
*/
function parseFilePath(filePath: String): Promise<{} | Error> {
return new Promise((res, rej) => {
fs.exists(filePath, (error: Error, stat) => {
if (error) {
rej(error);
return;
}
const extname = Path.extname(filePath);
const basename = Path.basename(filePath);
const dirname = Path.dirname(filePath);
res({
path: filePath,
extname,
basename,
dirname
});
});
function shouldShowPicker(items: string[]) {
return vscode.window.showQuickPick(items, {
canPickMany: true
});
}
// this method is called when your extension is deactivated
export function deactivate() {}

/**
* flush config to settings.json
* @author YoRolling
* @since 1.0.0
* @param {string} key
* @param {*} values
* @returns
*/
function flushConf(key: string, values: string[], global: boolean) {
if (isNullOrUndefined(key)) {
vscode.window.showErrorMessage(`E1000001: Internal error`);
return;
}
if (isNullOrUndefined(values)) {
vscode.window.showErrorMessage(`E1000002: Internal error`);
return;
}
const config = vscode.workspace.getConfiguration("files");
let clude: any = config.get("exclude");
if (!clude) {
clude = {};
}
try {
Array.from(new Set(values)).filter((v) => v !== '*' ).forEach((glob: string) => {
clude[glob] = true;
});

config.update("exclude", clude, global).then(() => {
vscode.window.showInformationMessage("♡ You got it!");
});
} catch (error) {

}
}

/**
*
*
* @param {vscode.Uri} uri
* @param {boolean} [isGlobal=true]
*/
async function globMatch(uri: vscode.Uri, isGlobal = true) {
try {
const fileMeta = <utils.Meta>(
await utils.parseFilePath(uri.path, rootPath)
);
const isFile = await utils.isFile(uri.path);
const isFolder = await utils.isFolder(uri.path);
let result: string[] | undefined;
let glob: string[] = [];
if (isFile) {

Object.keys(fileMeta).forEach(key => {
let r = undefined;
switch (key) {
case "path":
break;
case "extname":
r = fileMeta[key] ? `**/*${fileMeta[key]}` : undefined ;
break;
case "basename":
r = fileMeta[key];
break;
case "dirname":
r = fileMeta[key]
? `${fileMeta[key] + "/"}*.*`
: undefined;
break;
}
if (r) {
glob.push(r);
}
});
if(fileMeta["dirname"]) {
if(fileMeta["extname"]) {
glob.push(
`${ fileMeta["dirname"]}/*${fileMeta["extname"]}`
);
}
} else {
if(fileMeta["extname"]) {
glob.push(
`*${fileMeta["extname"]}`
);
}
}

if (fileMeta["basename"]) {
glob.push(`**/${fileMeta["basename"]}`);
if ( fileMeta['dirname'] ) {
glob.push(`${fileMeta['dirname']}/${fileMeta["basename"]}`);
}
}
result = await shouldShowPicker(glob);
} else if (isFolder) {
result = [`${fileMeta.basename}`];
}
if (result) {
flushConf("files.exclude", result, isGlobal);
}
} catch (error) {
vscode.window.showErrorMessage(error.message || error);
}
}
126 changes: 126 additions & 0 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Stats, lstat, access } from "fs";
import { isNullOrUndefined } from "util";

import * as path from 'path';

/**
*  检测文件或者目录是否存在
* @author YoRolling
* @export
* @param {string} _path
* @returns {(Promise<boolean | Error>)}
* @version 0.0.1
*/
export function exist(_path: string): Promise<boolean | Error> {
if (isUnavail(_path)) {
return Promise.reject(new Error(`${_path} should has a falsy value`));
}
return new Promise((res, rej) => {
access(_path, (error: Error) => {
if (isNullOrUndefined(error)) {
res(true);
} else {
rej(error);
}
});
});
}

/**
* 检测传入路径是否合法
* @author YoRolling
* @param {string} _path file path or folder's
* @returns {boolean}
*/
function isUnavail(_path: string): boolean {
return isNullOrUndefined(_path) || _path === '';
}

/**
* get stats for _path
* @author YoRolling`
* @export
* @param {string} _path
* @returns {(Promise<Stats | Error >)}
*/
export async function lsStat(_path: string): Promise<Stats | Error> {
if (isUnavail(_path)) {
return Promise.reject(false);
}
try {
await exist(_path);
return new Promise<Stats | Error>((res, rej) => {
lstat(_path, (error: Error, stats: Stats) => {
if (!isNullOrUndefined(error)) {
rej(error);
} else {
res(stats);
}
});
});
} catch (error) {
return Promise.reject(error);
}
}

/**
* @author YoRolling
* @version 0.1.1
* @export
* @param {string} _path
* @returns {(Promise<boolean | Error>)}
*/
export async function isFile(_path: string): Promise<boolean> {
if (isUnavail(_path)) {
return false;
}
try {
const stats = <Stats>await lsStat(_path);
return stats.isFile();
} catch (error) {
return false;
}
}


export async function isFolder(_path: string): Promise<boolean> {
if (isUnavail(_path)) {
return false;
}
try {
const stats = <Stats>await lsStat(_path);
return stats.isDirectory();
} catch (error) {
return false;
}
}
/**
* @author YoRolling
* @param filePath
*/
export async function parseFilePath(filePath: string,rootPath = ''): Promise<Meta | Error> {
if (isUnavail(filePath)) {
return Promise.reject(new Error(`${filePath} should have a fasly value`));
}
try {
await exist(filePath);
const extname = path.extname(filePath);
const basename = path.basename(filePath);
const dirname = path.relative(rootPath, path.dirname(filePath) );
return {
path: filePath,
extname,
basename,
dirname
};
} catch (error) {
return Promise.reject(error);
}
}

export interface Meta {
path: string;
extname: string;
basename: string;
dirname: string;
}

0 comments on commit 3f0ab4d

Please sign in to comment.