mirror of
https://github.com/chenasraf/gi-gen-vscode-extension.git
synced 2026-05-17 17:58:04 +00:00
Initial commit
This commit is contained in:
5
.editorconfig
Normal file
5
.editorconfig
Normal file
@@ -0,0 +1,5 @@
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
24
.eslintrc.json
Normal file
24
.eslintrc.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/naming-convention": "warn",
|
||||
"@typescript-eslint/semi": "off",
|
||||
"curly": "warn",
|
||||
"eqeqeq": "warn",
|
||||
"no-throw-literal": "warn",
|
||||
"semi": "off"
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"out",
|
||||
"dist",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
out
|
||||
dist
|
||||
node_modules
|
||||
.vscode-test/
|
||||
*.vsix
|
||||
15
.prettierrc
Normal file
15
.prettierrc
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"trailingComma": "all",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.md",
|
||||
"options": {
|
||||
"printWidth": 100,
|
||||
"proseWrap": "always"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
34
.vscode/launch.json
vendored
Normal file
34
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// A launch configuration that compiles the extension and then opens it inside a new window
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "${defaultBuildTask}"
|
||||
},
|
||||
{
|
||||
"name": "Extension Tests",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/test/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "${defaultBuildTask}"
|
||||
}
|
||||
]
|
||||
}
|
||||
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.exclude": {
|
||||
"out": false // set this to true to hide the "out" folder with the compiled JS files
|
||||
},
|
||||
"search.exclude": {
|
||||
"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"
|
||||
}
|
||||
20
.vscode/tasks.json
vendored
Normal file
20
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
10
.vscodeignore
Normal file
10
.vscodeignore
Normal file
@@ -0,0 +1,10 @@
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
src/**
|
||||
.gitignore
|
||||
.yarnrc
|
||||
vsc-extension-quickstart.md
|
||||
**/tsconfig.json
|
||||
**/.eslintrc.json
|
||||
**/*.map
|
||||
**/*.ts
|
||||
5
CHANGELOG.md
Normal file
5
CHANGELOG.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Change Log
|
||||
|
||||
## [0.1.0] - 2022-25-05
|
||||
|
||||
- Initial release
|
||||
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# gi-gen README
|
||||
|
||||
This is the README for your extension "gi-gen". After writing up a brief description, we recommend
|
||||
including the following sections.
|
||||
|
||||
## Features
|
||||
|
||||
Create a gitignore file for your project automatically. Uses
|
||||
[https://github.com/chenasraf/gi_gen](gi_gen) to operate.
|
||||
|
||||
## Requirements
|
||||
|
||||
No requirements, the binary is downloaded on first run.
|
||||
|
||||
## Release Notes
|
||||
|
||||
Users appreciate release notes as you update your extension.
|
||||
|
||||
### 1.0.0
|
||||
|
||||
Initial release
|
||||
45
package.json
Normal file
45
package.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "gi-gen",
|
||||
"displayName": "GI Gen",
|
||||
"description": "Generates a .gitignore for your project",
|
||||
"version": "0.0.1",
|
||||
"engines": {
|
||||
"vscode": "^1.67.0"
|
||||
},
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onCommand:gi-gen.generate"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "gi-gen.generate",
|
||||
"title": "Generate .gitignore File"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "yarn run compile",
|
||||
"compile": "tsc -p ./",
|
||||
"watch": "tsc -watch -p ./",
|
||||
"pretest": "yarn run compile && yarn run lint",
|
||||
"lint": "eslint src --ext ts",
|
||||
"test": "node ./out/test/runTest.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/vscode": "^1.67.0",
|
||||
"@types/glob": "^7.2.0",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/node": "14.x",
|
||||
"@typescript-eslint/eslint-plugin": "^5.21.0",
|
||||
"@typescript-eslint/parser": "^5.21.0",
|
||||
"eslint": "^8.14.0",
|
||||
"glob": "^8.0.1",
|
||||
"mocha": "^9.2.2",
|
||||
"typescript": "^4.6.4",
|
||||
"@vscode/test-electron": "^2.1.3"
|
||||
}
|
||||
}
|
||||
127
src/extension.ts
Normal file
127
src/extension.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
// 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'
|
||||
import * as cp from 'child_process'
|
||||
import * as fs from 'fs/promises'
|
||||
import { F_OK } from 'constants'
|
||||
type OverwriteAnswer = 'Overwrite' | 'Append' | 'Skip'
|
||||
|
||||
// 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 "gi-gen" is now active!')
|
||||
console.log('Working Dir:', process.cwd())
|
||||
|
||||
// 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('gi-gen.generate', async () => {
|
||||
console.log('Start')
|
||||
|
||||
const langs = await getDetectedLanguages()
|
||||
|
||||
console.log('Detected:', langs)
|
||||
console.log('Open QuickPick')
|
||||
|
||||
const items = langs.map((l) => ({ label: l }))
|
||||
const selectedLangs =
|
||||
langs.length > 1
|
||||
? await vscode.window.showQuickPick(items, {
|
||||
canPickMany: true,
|
||||
placeHolder: 'Select language(s) to use in .gitignore output',
|
||||
})
|
||||
: items
|
||||
|
||||
const shouldClean =
|
||||
(
|
||||
await vscode.window.showQuickPick([{ label: 'Yes' }, { label: 'No' }], {
|
||||
placeHolder: 'Remove unused patterns from .gitignore output?',
|
||||
})
|
||||
)?.label === 'Yes'
|
||||
let overwriteAnswer: OverwriteAnswer = 'Overwrite'
|
||||
if (await pathExists(getWorkspaceDir()!.fsPath)) {
|
||||
overwriteAnswer = (await vscode.window.showQuickPick<{
|
||||
label: OverwriteAnswer
|
||||
}>([{ label: 'Overwrite' }, { label: 'Append' }, { label: 'Skip' }], {
|
||||
placeHolder: 'The file .gitignore already exists om the project, choose:',
|
||||
}))!.label
|
||||
}
|
||||
if (overwriteAnswer === 'Skip') {
|
||||
vscode.window.showInformationMessage('A .gitignore file already exists, skipped')
|
||||
return
|
||||
}
|
||||
|
||||
await runGiGen(
|
||||
selectedLangs!.map((i) => i.label),
|
||||
shouldClean,
|
||||
overwriteAnswer,
|
||||
).then(console.log.bind(console, 'Output:'))
|
||||
|
||||
vscode.window.showInformationMessage(
|
||||
'A .gitignore file was generated at the root of this project',
|
||||
)
|
||||
})
|
||||
|
||||
context.subscriptions.push(disposable)
|
||||
}
|
||||
|
||||
// this method is called when your extension is deactivated
|
||||
export function deactivate() {}
|
||||
|
||||
function runGiGen(
|
||||
languages: string[],
|
||||
cleanup: boolean,
|
||||
overwriteAnswer: OverwriteAnswer,
|
||||
): Promise<string> {
|
||||
const args: string[] = [
|
||||
languages.length ? '-l ' + languages.join(',') : '-d',
|
||||
cleanup ? '-c' : '-k',
|
||||
overwriteAnswer === 'Overwrite' ? '-w' : '-a',
|
||||
].filter(Boolean) as string[]
|
||||
|
||||
return shellExec('gi_gen', args)
|
||||
}
|
||||
|
||||
async function getDetectedLanguages(): Promise<string[]> {
|
||||
const res = await shellExec('gi_gen', ['-detect-languages'])
|
||||
return res.split('\n').filter(Boolean)
|
||||
}
|
||||
|
||||
function shellExec(cmd: string, args?: string[]): Promise<string> {
|
||||
const wd = getWorkspaceDir()
|
||||
const input = [cmd, ...(args ?? [])].join(' ')
|
||||
console.log('Executing', input, 'in', wd?.fsPath)
|
||||
return new Promise((resolve, reject) => {
|
||||
cp.exec(input, { cwd: wd!.fsPath }, (err, stdout, stderr) => {
|
||||
// console.log('stdout:', stdout)
|
||||
// console.log('stderr:', stderr)
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
if (stderr) {
|
||||
reject(stderr)
|
||||
return
|
||||
}
|
||||
resolve(stdout)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getWorkspaceDir() {
|
||||
return vscode.workspace.workspaceFolders?.[0].uri
|
||||
}
|
||||
|
||||
export async function pathExists(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(filePath, F_OK)
|
||||
return true
|
||||
} catch (e: any) {
|
||||
if (e.code === 'ENOENT') {
|
||||
return false
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
23
src/test/runTest.ts
Normal file
23
src/test/runTest.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import * as path from 'path';
|
||||
|
||||
import { runTests } from '@vscode/test-electron';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
// The folder containing the Extension Manifest package.json
|
||||
// Passed to `--extensionDevelopmentPath`
|
||||
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
|
||||
|
||||
// The path to test runner
|
||||
// Passed to --extensionTestsPath
|
||||
const extensionTestsPath = path.resolve(__dirname, './suite/index');
|
||||
|
||||
// Download VS Code, unzip it and run the integration test
|
||||
await runTests({ extensionDevelopmentPath, extensionTestsPath });
|
||||
} catch (err) {
|
||||
console.error('Failed to run tests');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
15
src/test/suite/extension.test.ts
Normal file
15
src/test/suite/extension.test.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import * as assert from 'assert';
|
||||
|
||||
// You can import and use all API from the 'vscode' module
|
||||
// as well as import your extension to test it
|
||||
import * as vscode from 'vscode';
|
||||
// import * as myExtension from '../../extension';
|
||||
|
||||
suite('Extension Test Suite', () => {
|
||||
vscode.window.showInformationMessage('Start all tests.');
|
||||
|
||||
test('Sample test', () => {
|
||||
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
|
||||
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
|
||||
});
|
||||
});
|
||||
38
src/test/suite/index.ts
Normal file
38
src/test/suite/index.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import * as path from 'path';
|
||||
import * as Mocha from 'mocha';
|
||||
import * as glob from 'glob';
|
||||
|
||||
export function run(): Promise<void> {
|
||||
// Create the mocha test
|
||||
const mocha = new Mocha({
|
||||
ui: 'tdd',
|
||||
color: true
|
||||
});
|
||||
|
||||
const testsRoot = path.resolve(__dirname, '..');
|
||||
|
||||
return new Promise((c, e) => {
|
||||
glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
|
||||
if (err) {
|
||||
return e(err);
|
||||
}
|
||||
|
||||
// Add files to the test suite
|
||||
files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
|
||||
|
||||
try {
|
||||
// Run the mocha test
|
||||
mocha.run(failures => {
|
||||
if (failures > 0) {
|
||||
e(new Error(`${failures} tests failed.`));
|
||||
} else {
|
||||
c();
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
e(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
17
tsconfig.json
Normal file
17
tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES2020",
|
||||
"outDir": "out",
|
||||
"lib": [
|
||||
"ES2020"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"strict": true /* enable all strict type-checking options */
|
||||
/* Additional Checks */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user