@re-shell/cli
Version:
Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja
1,214 lines (1,213 loc) • 48.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.IDEConfigGenerator = void 0;
exports.generateIDEConfig = generateIDEConfig;
exports.detectProjectContext = detectProjectContext;
const events_1 = require("events");
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
class IDEConfigGenerator extends events_1.EventEmitter {
constructor(projectContext) {
super();
this.projectContext = projectContext;
}
async generate(config) {
this.emit('generation:start', config);
const result = {
success: false,
files: [],
errors: [],
warnings: []
};
try {
switch (config.editor) {
case 'vscode':
await this.generateVSCodeConfig(config, result);
break;
case 'intellij':
await this.generateIntelliJConfig(config, result);
break;
case 'vim':
await this.generateVimConfig(config, result);
break;
case 'sublime':
await this.generateSublimeConfig(config, result);
break;
case 'atom':
await this.generateAtomConfig(config, result);
break;
default:
result.errors?.push(`Unsupported editor: ${config.editor}`);
}
result.success = result.files.length > 0 && (!result.errors || result.errors.length === 0);
this.emit('generation:complete', result);
return result;
}
catch (error) {
result.errors?.push(error.message);
this.emit('generation:error', error);
return result;
}
}
async generateVSCodeConfig(config, result) {
const vscodeDir = path.join(this.projectContext.path, '.vscode');
await fs.ensureDir(vscodeDir);
// Settings
if (config.includeFormatting !== false) {
const settings = this.generateVSCodeSettings(config);
result.files.push({
path: path.join(vscodeDir, 'settings.json'),
content: JSON.stringify(settings, null, 2),
description: 'VSCode workspace settings'
});
}
// Extensions
if (config.includeRecommendedExtensions !== false) {
const extensions = this.generateVSCodeExtensions(config);
result.files.push({
path: path.join(vscodeDir, 'extensions.json'),
content: JSON.stringify(extensions, null, 2),
description: 'Recommended VSCode extensions'
});
}
// Launch configuration
if (config.includeDebugConfig !== false) {
const launch = this.generateVSCodeLaunch(config);
if (launch) {
result.files.push({
path: path.join(vscodeDir, 'launch.json'),
content: JSON.stringify(launch, null, 2),
description: 'VSCode debug configurations'
});
}
}
// Tasks
if (config.includeTasks !== false) {
const tasks = this.generateVSCodeTasks(config);
if (tasks) {
result.files.push({
path: path.join(vscodeDir, 'tasks.json'),
content: JSON.stringify(tasks, null, 2),
description: 'VSCode task configurations'
});
}
}
}
generateVSCodeSettings(config) {
const settings = {
// Editor settings
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.organizeImports": true
},
"editor.rulers": [80, 120],
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.trimAutoWhitespace": true,
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"files.eol": "\n",
// Search excludes
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/dist": true,
"**/build": true,
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/Thumbs.db": true
},
// File associations
"files.associations": {
"*.re-shell": "yaml",
".re-shellrc": "json"
}
};
// Language-specific settings
if (this.projectContext.hasTypeScript) {
Object.assign(settings, {
"typescript.updateImportsOnFileMove.enabled": "always",
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.quoteStyle": "single",
"typescript.format.semicolons": "insert",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
});
}
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
Object.assign(settings, {
"javascript.updateImportsOnFileMove.enabled": "always",
"javascript.preferences.importModuleSpecifier": "relative",
"javascript.preferences.quoteStyle": "single",
"javascript.format.semicolons": "insert",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
});
}
if (this.projectContext.hasESLint) {
Object.assign(settings, {
"eslint.enable": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"eslint.run": "onType",
"eslint.autoFixOnSave": true
});
}
if (this.projectContext.hasPrettier) {
Object.assign(settings, {
"prettier.singleQuote": true,
"prettier.trailingComma": "es5",
"prettier.tabWidth": 2,
"prettier.semi": true,
"prettier.printWidth": 100
});
}
if (this.projectContext.language === 'python') {
Object.assign(settings, {
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "88"],
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
});
}
if (this.projectContext.language === 'go') {
Object.assign(settings, {
"go.useLanguageServer": true,
"go.lintOnSave": "workspace",
"go.formatTool": "goimports",
"go.formatFlags": ["-local", "github.com/your-org"],
"[go]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
});
}
if (this.projectContext.language === 'java') {
Object.assign(settings, {
"java.configuration.updateBuildConfiguration": "automatic",
"java.format.settings.profile": "GoogleStyle",
"java.saveActions.organizeImports": true,
"[java]": {
"editor.defaultFormatter": "redhat.java"
}
});
}
if (this.projectContext.language === 'rust') {
Object.assign(settings, {
"rust-analyzer.cargo.watch.enable": true,
"rust-analyzer.checkOnSave.command": "clippy",
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true
}
});
}
// Merge custom settings
if (config.customSettings?.vscode) {
Object.assign(settings, config.customSettings.vscode);
}
return settings;
}
generateVSCodeExtensions(config) {
const recommendations = [
// General
"editorconfig.editorconfig",
"streetsidesoftware.code-spell-checker",
"wayou.vscode-todo-highlight",
"gruntfuggly.todo-tree",
"eamodio.gitlens",
"usernamehw.errorlens"
];
// Language-specific extensions
if (this.projectContext.hasTypeScript || this.projectContext.language === 'javascript') {
recommendations.push("dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "christian-kohler.path-intellisense", "formulahendry.auto-rename-tag", "steoates.autoimport", "wix.vscode-import-cost");
}
if (this.projectContext.hasTypeScript) {
recommendations.push("ms-vscode.vscode-typescript-next", "jpoissonnier.vscode-styled-components");
}
if (this.projectContext.framework === 'react') {
recommendations.push("dsznajder.es7-react-js-snippets", "burkeholland.simple-react-snippets", "jpoissonnier.vscode-styled-components");
}
if (this.projectContext.framework === 'vue') {
recommendations.push("octref.vetur", "johnsoncodehk.volar", "sdras.vue-vscode-snippets");
}
if (this.projectContext.framework === 'angular') {
recommendations.push("angular.ng-template", "johnpapa.angular2", "cyrilletuzi.angular-schematics");
}
if (this.projectContext.language === 'python') {
recommendations.push("ms-python.python", "ms-python.vscode-pylance", "ms-python.black-formatter", "charliermarsh.ruff");
}
if (this.projectContext.language === 'go') {
recommendations.push("golang.go");
}
if (this.projectContext.language === 'java') {
recommendations.push("redhat.java", "vscjava.vscode-java-debug", "vscjava.vscode-java-test", "vscjava.vscode-maven", "vscjava.vscode-spring-initializr");
}
if (this.projectContext.language === 'rust') {
recommendations.push("rust-lang.rust-analyzer", "bungcip.better-toml", "serayuzgur.crates");
}
if (this.projectContext.language === 'php') {
recommendations.push("bmewburn.vscode-intelephense-client", "neilbrayfield.php-docblocker", "wongjn.php-sniffer");
}
if (this.projectContext.language === 'ruby') {
recommendations.push("rebornix.ruby", "castwide.solargraph", "kaiwood.endwise");
}
if (this.projectContext.hasJest || this.projectContext.hasTesting) {
recommendations.push("orta.vscode-jest", "kavod-io.vscode-jest-test-adapter", "hbenl.vscode-test-explorer");
}
if (this.projectContext.gitEnabled) {
recommendations.push("mhutchie.git-graph", "donjayamanne.githistory");
}
return { recommendations };
}
generateVSCodeLaunch(config) {
const configurations = [];
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
// Node.js debugging
configurations.push({
type: "node",
request: "launch",
name: "Launch Program",
skipFiles: ["<node_internals>/**"],
program: "${workspaceFolder}/src/index.js",
preLaunchTask: "npm: build",
outFiles: ["${workspaceFolder}/dist/**/*.js"],
env: {
"NODE_ENV": "development"
}
});
// Jest debugging
if (this.projectContext.hasJest) {
configurations.push({
type: "node",
request: "launch",
name: "Jest: Current File",
program: "${workspaceFolder}/node_modules/.bin/jest",
args: [
"--runInBand",
"--no-coverage",
"${relativeFile}"
],
console: "integratedTerminal",
internalConsoleOptions: "neverOpen"
});
}
// NPM script debugging
configurations.push({
type: "node",
request: "launch",
name: "npm run dev",
runtimeExecutable: "npm",
runtimeArgs: ["run", "dev"],
skipFiles: ["<node_internals>/**"],
console: "integratedTerminal"
});
}
if (this.projectContext.language === 'python') {
configurations.push({
name: "Python: Current File",
type: "python",
request: "launch",
program: "${file}",
console: "integratedTerminal",
justMyCode: true
});
configurations.push({
name: "Python: Module",
type: "python",
request: "launch",
module: this.projectContext.name,
justMyCode: true
});
configurations.push({
name: "Python: Django",
type: "python",
request: "launch",
program: "${workspaceFolder}/manage.py",
args: ["runserver"],
django: true,
justMyCode: true
});
}
if (this.projectContext.language === 'go') {
configurations.push({
name: "Launch Package",
type: "go",
request: "launch",
mode: "auto",
program: "${fileDirname}"
});
configurations.push({
name: "Launch Test",
type: "go",
request: "launch",
mode: "test",
program: "${fileDirname}"
});
}
if (this.projectContext.language === 'java') {
configurations.push({
type: "java",
name: "Launch Current File",
request: "launch",
mainClass: "${file}"
});
configurations.push({
type: "java",
name: "Launch Application",
request: "launch",
mainClass: `com.example.${this.projectContext.name}.Application`,
projectName: this.projectContext.name
});
}
if (this.projectContext.language === 'rust') {
configurations.push({
type: "lldb",
request: "launch",
name: "Debug executable",
cargo: {
args: ["build", "--bin=${workspaceRootFolderName}", "--package=${workspaceRootFolderName}"],
filter: {
name: this.projectContext.name,
kind: "bin"
}
},
args: [],
cwd: "${workspaceFolder}"
});
configurations.push({
type: "lldb",
request: "launch",
name: "Debug unit tests",
cargo: {
args: ["test", "--no-run", "--bin=${workspaceRootFolderName}", "--package=${workspaceRootFolderName}"],
filter: {
name: this.projectContext.name,
kind: "bin"
}
},
args: [],
cwd: "${workspaceFolder}"
});
}
if (configurations.length === 0) {
return null;
}
return {
version: "0.2.0",
configurations
};
}
generateVSCodeTasks(config) {
const tasks = [];
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
// Build task
tasks.push({
label: "npm: build",
type: "npm",
script: "build",
group: {
kind: "build",
isDefault: true
},
problemMatcher: ["$tsc"],
presentation: {
reveal: "silent"
}
});
// Test task
tasks.push({
label: "npm: test",
type: "npm",
script: "test",
group: {
kind: "test",
isDefault: true
},
problemMatcher: [],
presentation: {
reveal: "always"
}
});
// Lint task
tasks.push({
label: "npm: lint",
type: "npm",
script: "lint",
problemMatcher: ["$eslint-stylish"],
presentation: {
reveal: "silent"
}
});
}
if (this.projectContext.language === 'python') {
tasks.push({
label: "pytest",
type: "shell",
command: "pytest",
args: ["-v"],
group: {
kind: "test",
isDefault: true
},
presentation: {
reveal: "always",
panel: "new"
}
});
tasks.push({
label: "pylint",
type: "shell",
command: "pylint",
args: ["${workspaceFolder}/${workspaceFolderBasename}"],
problemMatcher: [],
presentation: {
reveal: "always",
panel: "new"
}
});
}
if (this.projectContext.language === 'go') {
tasks.push({
label: "go: build",
type: "shell",
command: "go",
args: ["build", "-v", "./..."],
group: {
kind: "build",
isDefault: true
},
problemMatcher: ["$go"]
});
tasks.push({
label: "go: test",
type: "shell",
command: "go",
args: ["test", "-v", "./..."],
group: {
kind: "test",
isDefault: true
},
problemMatcher: ["$go"]
});
}
if (this.projectContext.language === 'rust') {
tasks.push({
label: "cargo build",
type: "cargo",
command: "build",
problemMatcher: ["$rustc"],
group: {
kind: "build",
isDefault: true
}
});
tasks.push({
label: "cargo test",
type: "cargo",
command: "test",
problemMatcher: ["$rustc"],
group: {
kind: "test",
isDefault: true
}
});
tasks.push({
label: "cargo check",
type: "cargo",
command: "check",
problemMatcher: ["$rustc"]
});
}
if (tasks.length === 0) {
return null;
}
return {
version: "2.0.0",
tasks
};
}
async generateIntelliJConfig(config, result) {
const ideaDir = path.join(this.projectContext.path, '.idea');
await fs.ensureDir(ideaDir);
// Project structure
const modules = this.generateIntelliJModules(config);
result.files.push({
path: path.join(ideaDir, 'modules.xml'),
content: modules,
description: 'IntelliJ project modules configuration'
});
// Code style
const codeStyle = this.generateIntelliJCodeStyle(config);
const codeStyleDir = path.join(ideaDir, 'codeStyles');
await fs.ensureDir(codeStyleDir);
result.files.push({
path: path.join(codeStyleDir, 'Project.xml'),
content: codeStyle,
description: 'IntelliJ code style settings'
});
result.files.push({
path: path.join(codeStyleDir, 'codeStyleConfig.xml'),
content: `<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>`,
description: 'IntelliJ code style configuration'
});
// Run configurations
if (config.includeDebugConfig !== false) {
const runConfigsDir = path.join(ideaDir, 'runConfigurations');
await fs.ensureDir(runConfigsDir);
const runConfigs = this.generateIntelliJRunConfigs(config);
for (const runConfig of runConfigs) {
result.files.push({
path: path.join(runConfigsDir, runConfig.filename),
content: runConfig.content,
description: runConfig.description
});
}
}
// VCS configuration
if (this.projectContext.gitEnabled) {
result.files.push({
path: path.join(ideaDir, 'vcs.xml'),
content: `<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>`,
description: 'IntelliJ VCS configuration'
});
}
}
generateIntelliJModules(config) {
return `<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/${this.projectContext.name}.iml" filepath="$PROJECT_DIR$/.idea/${this.projectContext.name}.iml" />
</modules>
</component>
</project>`;
}
generateIntelliJCodeStyle(config) {
const indent = " ";
return `<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value=" " />
<option name="RIGHT_MARGIN" value="120" />
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
<option name="SOFT_MARGINS" value="80,100" />
${this.projectContext.hasTypeScript || this.projectContext.language === 'javascript' ? `
<TypeScriptCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
</TypeScriptCodeStyleSettings>
<JavaScriptCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
</JavaScriptCodeStyleSettings>` : ''}
${this.projectContext.language === 'java' ? `
<JavaCodeStyleSettings>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="java" withSubpackages="true" static="false" />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="true" />
</value>
</option>
</JavaCodeStyleSettings>` : ''}
<codeStyleSettings language="TypeScript">
<option name="RIGHT_MARGIN" value="100" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="BLANK_LINES_AROUND_METHOD" value="1" />
<option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="1" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="RIGHT_MARGIN" value="100" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="BLANK_LINES_AROUND_METHOD" value="1" />
<option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="1" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>`;
}
generateIntelliJRunConfigs(config) {
const configs = [];
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
// npm scripts
configs.push({
filename: 'npm_dev.xml',
content: `<component name="ProjectRunConfigurationManager">
<configuration default="false" name="npm dev" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="dev" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>`,
description: 'npm dev script configuration'
});
configs.push({
filename: 'npm_test.xml',
content: `<component name="ProjectRunConfigurationManager">
<configuration default="false" name="npm test" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="test" />
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>`,
description: 'npm test script configuration'
});
configs.push({
filename: 'npm_build.xml',
content: `<component name="ProjectRunConfigurationManager">
<configuration default="false" name="npm build" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="build" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>`,
description: 'npm build script configuration'
});
}
if (this.projectContext.language === 'java') {
configs.push({
filename: 'Application.xml',
content: `<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Application" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.example.${this.projectContext.name}.Application" />
<module name="${this.projectContext.name}" />
<option name="VM_PARAMETERS" value="-Xmx512m -Xms256m" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>`,
description: 'Java application run configuration'
});
}
return configs;
}
async generateVimConfig(config, result) {
// .vimrc or init.vim
const vimConfig = this.generateVimConfiguration(config);
result.files.push({
path: path.join(this.projectContext.path, '.vimrc'),
content: vimConfig,
description: 'Vim configuration file'
});
// .editorconfig
const editorConfig = this.generateEditorConfig(config);
result.files.push({
path: path.join(this.projectContext.path, '.editorconfig'),
content: editorConfig,
description: 'EditorConfig for consistent coding styles'
});
// coc-settings.json for CoC.nvim
if (config.features?.some(f => f.name === 'coc' && f.enabled)) {
const cocSettings = this.generateCocSettings(config);
result.files.push({
path: path.join(this.projectContext.path, '.vim', 'coc-settings.json'),
content: JSON.stringify(cocSettings, null, 2),
description: 'CoC.nvim settings'
});
}
}
generateVimConfiguration(config) {
const lines = [
'" Re-Shell CLI generated Vim configuration',
'" Generated for project: ' + this.projectContext.name,
'',
'" Basic settings',
'set nocompatible',
'set encoding=utf-8',
'set fileencoding=utf-8',
'set fileencodings=utf-8',
'set ttyfast',
'',
'" Visual settings',
'syntax enable',
'set ruler',
'set number',
'set relativenumber',
'set cursorline',
'set colorcolumn=80,120',
'set showmatch',
'set list',
'set listchars=tab:→\\ ,trail:·,extends:»,precedes:«,nbsp:+',
'',
'" Indentation',
'set tabstop=2',
'set softtabstop=2',
'set shiftwidth=2',
'set expandtab',
'set autoindent',
'set smartindent',
'',
'" Search',
'set hlsearch',
'set incsearch',
'set ignorecase',
'set smartcase',
'',
'" File handling',
'set autoread',
'set autowrite',
'set nobackup',
'set noswapfile',
'set hidden',
'',
'" Completion',
'set wildmenu',
'set wildmode=list:longest,full',
'set wildignore+=*/node_modules/*,*/dist/*,*/build/*,*/.git/*',
''
];
// Language-specific settings
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
lines.push('" JavaScript/TypeScript settings', 'autocmd FileType javascript,typescript,typescriptreact,javascriptreact setlocal shiftwidth=2 tabstop=2 softtabstop=2', 'autocmd FileType json setlocal shiftwidth=2 tabstop=2 softtabstop=2', '');
}
if (this.projectContext.language === 'python') {
lines.push('" Python settings', 'autocmd FileType python setlocal shiftwidth=4 tabstop=4 softtabstop=4', 'autocmd FileType python setlocal textwidth=88', 'autocmd FileType python setlocal colorcolumn=88', 'let g:python_highlight_all = 1', '');
}
if (this.projectContext.language === 'go') {
lines.push('" Go settings', 'autocmd FileType go setlocal noexpandtab', 'autocmd FileType go setlocal shiftwidth=4 tabstop=4 softtabstop=4', 'autocmd BufWritePre *.go :silent! !gofmt -w %', '');
}
// Plugin recommendations
lines.push('" Plugin recommendations (requires plugin manager like vim-plug)', '" Plug \'tpope/vim-fugitive\' " Git integration', '" Plug \'airblade/vim-gitgutter\' " Git diff in gutter', '" Plug \'preservim/nerdtree\' " File explorer', '" Plug \'junegunn/fzf.vim\' " Fuzzy finder', '" Plug \'neoclide/coc.nvim\' " LSP support', '" Plug \'vim-airline/vim-airline\' " Status line', '" Plug \'morhetz/gruvbox\' " Color scheme', '');
// Language-specific plugins
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
lines.push('" JavaScript/TypeScript plugins', '" Plug \'pangloss/vim-javascript\'', '" Plug \'leafgarland/typescript-vim\'', '" Plug \'maxmellon/vim-jsx-pretty\'', '" Plug \'styled-components/vim-styled-components\'', '');
}
if (this.projectContext.language === 'python') {
lines.push('" Python plugins', '" Plug \'vim-python/python-syntax\'', '" Plug \'psf/black\', { \'branch\': \'stable\' }', '" Plug \'fisadev/vim-isort\'', '');
}
if (this.projectContext.language === 'go') {
lines.push('" Go plugins', '" Plug \'fatih/vim-go\', { \'do\': \':GoUpdateBinaries\' }', '');
}
// Key mappings
lines.push('" Key mappings', 'let mapleader = ","', 'nnoremap <leader>w :w<CR>', 'nnoremap <leader>q :q<CR>', 'nnoremap <leader>e :NERDTreeToggle<CR>', 'nnoremap <leader>f :Files<CR>', 'nnoremap <leader>b :Buffers<CR>', 'nnoremap <leader>g :GitGutterToggle<CR>', '', '" Clear search highlight', 'nnoremap <leader><space> :nohlsearch<CR>', '', '" Navigate between splits', 'nnoremap <C-h> <C-w>h', 'nnoremap <C-j> <C-w>j', 'nnoremap <C-k> <C-w>k', 'nnoremap <C-l> <C-w>l');
return lines.join('\n');
}
generateCocSettings(config) {
const settings = {
"suggest.enablePreview": true,
"suggest.enablePreselect": true,
"suggest.noselect": false,
"diagnostic.errorSign": "✗",
"diagnostic.warningSign": "⚠",
"diagnostic.infoSign": "ℹ",
"diagnostic.hintSign": "➤"
};
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
Object.assign(settings, {
"tsserver.enable": true,
"eslint.enable": true,
"eslint.autoFixOnSave": true,
"prettier.enable": true,
"prettier.formatOnSave": true
});
}
if (this.projectContext.language === 'python') {
Object.assign(settings, {
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.provider": "black",
"python.formatting.blackPath": "black",
"python.sortImports.path": "isort"
});
}
if (this.projectContext.language === 'go') {
Object.assign(settings, {
"go.goplsOptions": {
"completeUnimported": true,
"usePlaceholders": true
}
});
}
return settings;
}
async generateSublimeConfig(config, result) {
// Project file
const projectConfig = this.generateSublimeProject(config);
result.files.push({
path: path.join(this.projectContext.path, `${this.projectContext.name}.sublime-project`),
content: JSON.stringify(projectConfig, null, 2),
description: 'Sublime Text project configuration'
});
// Settings
const settings = this.generateSublimeSettings(config);
result.files.push({
path: path.join(this.projectContext.path, '.sublime', 'settings.json'),
content: JSON.stringify(settings, null, 2),
description: 'Sublime Text settings'
});
}
generateSublimeProject(config) {
const project = {
folders: [
{
path: ".",
folder_exclude_patterns: [
"node_modules",
"dist",
"build",
".git",
"__pycache__",
".pytest_cache"
],
file_exclude_patterns: [
"*.pyc",
"*.pyo",
".DS_Store",
"*.sublime-workspace"
]
}
],
settings: {
tab_size: 2,
translate_tabs_to_spaces: true,
trim_trailing_white_space_on_save: true,
ensure_newline_at_eof_on_save: true,
rulers: [80, 120]
}
};
// Build systems
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
project.build_systems = [
{
name: "npm test",
cmd: ["npm", "test"],
working_dir: "$project_path"
},
{
name: "npm build",
cmd: ["npm", "run", "build"],
working_dir: "$project_path"
}
];
}
return project;
}
generateSublimeSettings(config) {
return {
// Editor settings
font_size: 12,
line_numbers: true,
gutter: true,
margin: 4,
fold_buttons: true,
fade_fold_buttons: false,
// Indentation
tab_size: 2,
translate_tabs_to_spaces: true,
use_tab_stops: true,
detect_indentation: true,
auto_indent: true,
smart_indent: true,
// Visual
rulers: [80, 120],
draw_white_space: "all",
draw_indent_guides: true,
indent_guide_options: ["draw_active"],
// Behavior
trim_trailing_white_space_on_save: true,
ensure_newline_at_eof_on_save: true,
save_on_focus_lost: true,
// Search
show_definitions: true,
auto_complete: true,
auto_complete_delay: 50,
auto_complete_triggers: [
{
selector: "source.js",
characters: "."
}
]
};
}
async generateAtomConfig(config, result) {
const atomConfig = this.generateAtomConfiguration(config);
result.files.push({
path: path.join(this.projectContext.path, '.atom', 'config.cson'),
content: atomConfig,
description: 'Atom editor configuration'
});
}
generateAtomConfiguration(config) {
const lines = [
'"*":',
' core:',
' telemetryConsent: "no"',
' themes: [',
' "one-dark-ui"',
' "one-dark-syntax"',
' ]',
' editor:',
' fontSize: 14',
' showIndentGuide: true',
' showInvisibles: true',
' softTabs: true',
' tabLength: 2',
' tabType: "soft"',
' "exception-reporting":',
' userId: "re-shell-cli-user"',
' welcome:',
' showOnStartup: false'
];
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
lines.push(' "linter-eslint":', ' autofix:', ' fixOnSave: true', ' prettier:', ' formatOnSave: true', ' singleQuote: true', ' trailingComma: "es5"');
}
return lines.join('\n');
}
generateEditorConfig(config) {
const lines = [
'# EditorConfig is awesome: https://EditorConfig.org',
'# Generated by Re-Shell CLI',
'',
'# top-most EditorConfig file',
'root = true',
'',
'# Unix-style newlines with a newline ending every file',
'[*]',
'end_of_line = lf',
'insert_final_newline = true',
'trim_trailing_whitespace = true',
'charset = utf-8',
'',
'# Default indentation',
'indent_style = space',
'indent_size = 2',
''
];
// Language-specific settings
if (this.projectContext.language === 'javascript' || this.projectContext.hasTypeScript) {
lines.push('# JavaScript/TypeScript files', '[*.{js,jsx,ts,tsx,json}]', 'indent_size = 2', '');
}
if (this.projectContext.language === 'python') {
lines.push('# Python files', '[*.py]', 'indent_size = 4', 'max_line_length = 88', '');
}
if (this.projectContext.language === 'go') {
lines.push('# Go files', '[*.go]', 'indent_style = tab', 'indent_size = 4', '');
}
if (this.projectContext.language === 'java') {
lines.push('# Java files', '[*.java]', 'indent_size = 4', 'continuation_indent_size = 8', '');
}
lines.push('# Markdown files', '[*.md]', 'trim_trailing_whitespace = false', '', '# YAML files', '[*.{yml,yaml}]', 'indent_size = 2', '', '# Makefile', '[Makefile]', 'indent_style = tab');
return lines.join('\n');
}
async writeFiles(files) {
const written = [];
const errors = [];
for (const file of files) {
try {
await fs.ensureDir(path.dirname(file.path));
await fs.writeFile(file.path, file.content);
written.push(file.path);
this.emit('file:written', file.path);
}
catch (error) {
errors.push(`Failed to write ${file.path}: ${error.message}`);
this.emit('file:error', { path: file.path, error });
}
}
return { written, errors };
}
}
exports.IDEConfigGenerator = IDEConfigGenerator;
// Helper functions
async function generateIDEConfig(projectPath, editor, options = {}) {
// Auto-detect project context
const context = await detectProjectContext(projectPath);
const generator = new IDEConfigGenerator(context);
const config = {
editor,
...options
};
return generator.generate(config);
}
async function detectProjectContext(projectPath) {
const context = {
name: path.basename(projectPath),
path: projectPath
};
// Check for package.json
const packageJsonPath = path.join(projectPath, 'package.json');
if (await fs.pathExists(packageJsonPath)) {
try {
const packageJson = await fs.readJson(packageJsonPath);
context.name = packageJson.name || context.name;
// Detect TypeScript
if (packageJson.devDependencies?.typescript || packageJson.dependencies?.typescript) {
context.hasTypeScript = true;
}
// Detect ESLint
if (packageJson.devDependencies?.eslint || packageJson.dependencies?.eslint) {
context.hasESLint = true;
}
// Detect Prettier
if (packageJson.devDependencies?.prettier || packageJson.dependencies?.prettier) {
context.hasPrettier = true;
}
// Detect Jest
if (packageJson.devDependencies?.jest || packageJson.dependencies?.jest) {
context.hasJest = true;
context.hasTesting = true;
}
// Detect framework
if (packageJson.dependencies?.react || packageJson.dependencies?.['react-dom']) {
context.framework = 'react';
}
else if (packageJson.dependencies?.vue) {
context.framework = 'vue';
}
else if (packageJson.dependencies?.['@angular/core']) {
context.framework = 'angular';
}
context.language = 'javascript';
}
catch (error) {
// Invalid package.json
}
}
// Check for other language files
const files = await fs.readdir(projectPath);
if (files.some(f => f.endsWith('.py'))) {
context.language = 'python';
}
else if (files.some(f => f.endsWith('.go') || f === 'go.mod')) {
context.language = 'go';
}
else if (files.some(f => f.endsWith('.java'))) {
context.language = 'java';
}
else if (files.some(f => f.endsWith('.rs') || f === 'Cargo.toml')) {
context.language = 'rust';
}
else if (files.some(f => f.endsWith('.php'))) {
context.language = 'php';
}
else if (files.some(f => f.endsWith('.rb') || f === 'Gemfile')) {
context.language = 'ruby';
}
else if (files.some(f => f.endsWith('.cs') || f.endsWith('.csproj'))) {
context.language = 'dotnet';
}
// Check for git
if (await fs.pathExists(path.join(projectPath, '.git'))) {
context.gitEnabled = true;
}
// Detect package manager
if (await fs.pathExists(path.join(projectPath, 'pnpm-lock.yaml'))) {
context.packageManager = 'pnpm';
}
else if (await fs.pathExists(path.join(projectPath, 'yarn.lock'))) {
context.packageManager = 'yarn';
}
else if (await fs.pathExists(path.join(projectPath, 'package-lock.json'))) {
context.packageManager = 'npm';
}
else if (await fs.pathExists(path.join(projectPath, 'bun.lockb'))) {
context.packageManager = 'bun';
}
return context;
}