pro-cpp-cli-core 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/index.js +85 -73
- package/package.json +7 -16
package/README.md
CHANGED
|
@@ -56,6 +56,12 @@ Now `cl.exe` is recognized, and `procpp` can build your code!
|
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
59
|
+
🧐 Why this package?
|
|
60
|
+
|
|
61
|
+
Tired of configuring CMake and tasks.json for days just to test a simple C++ idea? pro-cpp-cli brings modern Web Development DX (like Vite/Nodemon) to the C++ world. Zero configuration. Native C++20 Modules support. Just write code.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
59
65
|
🐞 Debugging
|
|
60
66
|
|
|
61
67
|
Just press F5! Our `init` command sets up a "Bulletproof" debugger configuration that won't conflict with the watcher.
|
package/index.js
CHANGED
|
@@ -1,21 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* PRO C++ CLI Core (
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* PRO C++ CLI Core (V1.0.7)
|
|
5
|
+
* - Added Environment Check (cl.exe validation)
|
|
6
|
+
* - Added Versioning (-v, --version)
|
|
7
|
+
* - Improved 'init' template for 100% success rate
|
|
8
|
+
* - Native ANSI Colors & Performance Tracking
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
const { execSync, spawn } = require('child_process');
|
|
10
12
|
const fs = require('fs');
|
|
11
13
|
const path = require('path');
|
|
14
|
+
const { performance } = require('perf_hooks');
|
|
12
15
|
|
|
13
|
-
const
|
|
16
|
+
const packageJson = require('./package.json');
|
|
17
|
+
const [,, command] = process.argv;
|
|
14
18
|
let currentAppProcess = null;
|
|
15
19
|
let watchTimeout = null;
|
|
16
20
|
|
|
17
21
|
const BUILD_DIR = path.join(process.cwd(), '.build');
|
|
18
22
|
|
|
23
|
+
const colors = {
|
|
24
|
+
reset: "\x1b[0m",
|
|
25
|
+
cyan: "\x1b[36m",
|
|
26
|
+
green: "\x1b[32m",
|
|
27
|
+
yellow: "\x1b[33m",
|
|
28
|
+
red: "\x1b[31m",
|
|
29
|
+
gray: "\x1b[90m",
|
|
30
|
+
bold: "\x1b[1m"
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// --- UTILS ---
|
|
34
|
+
|
|
35
|
+
function checkEnv() {
|
|
36
|
+
try {
|
|
37
|
+
execSync('cl.exe', { stdio: 'ignore' });
|
|
38
|
+
return true;
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.error(`\n${colors.red}${colors.bold}❌ MSVC Compiler (cl.exe) NOT FOUND!${colors.reset}`);
|
|
41
|
+
console.log(`${colors.yellow}💡 Fix: Please use "Developer PowerShell for VS 2022" or "Developer Command Prompt".${colors.reset}\n`);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
19
46
|
function runSyncCommand(cmd) {
|
|
20
47
|
try {
|
|
21
48
|
execSync(cmd, { stdio: 'inherit' });
|
|
@@ -26,34 +53,26 @@ function runSyncCommand(cmd) {
|
|
|
26
53
|
}
|
|
27
54
|
|
|
28
55
|
function cleanupOldBuilds() {
|
|
29
|
-
// 1. Clean .build folder
|
|
30
56
|
if (fs.existsSync(BUILD_DIR)) {
|
|
31
57
|
const files = fs.readdirSync(BUILD_DIR);
|
|
32
58
|
files.forEach(file => {
|
|
33
|
-
if (
|
|
59
|
+
if (['.obj', '.pdb', '.ilk', '.ifc'].some(ext => file.endsWith(ext)) || file.startsWith('app_build_')) {
|
|
34
60
|
try { fs.unlinkSync(path.join(BUILD_DIR, file)); } catch (err) {}
|
|
35
61
|
}
|
|
36
62
|
});
|
|
37
63
|
}
|
|
38
|
-
// 2. Clean root folder (just in case)
|
|
39
|
-
const rootFiles = fs.readdirSync(process.cwd());
|
|
40
|
-
rootFiles.forEach(file => {
|
|
41
|
-
if (file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk') || file.endsWith('.ifc') || (file.startsWith('app_build_') && file.endsWith('.exe'))) {
|
|
42
|
-
try { fs.unlinkSync(path.join(process.cwd(), file)); } catch (err) {}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
64
|
}
|
|
46
65
|
|
|
47
66
|
function getSortedCppFiles() {
|
|
48
67
|
const fileList = [];
|
|
49
|
-
|
|
50
68
|
function scanDir(dir) {
|
|
69
|
+
if (!fs.existsSync(dir)) return;
|
|
51
70
|
const files = fs.readdirSync(dir);
|
|
52
71
|
for (const file of files) {
|
|
53
72
|
const filePath = path.join(dir, file);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (file !== 'node_modules' && file !== '.vscode' && file !== '.build') {
|
|
73
|
+
const stat = fs.statSync(filePath);
|
|
74
|
+
if (stat.isDirectory()) {
|
|
75
|
+
if (file !== 'node_modules' && file !== '.vscode' && file !== '.build' && !file.startsWith('.')) {
|
|
57
76
|
scanDir(filePath);
|
|
58
77
|
}
|
|
59
78
|
} else if (filePath.endsWith('.cpp') || filePath.endsWith('.ixx')) {
|
|
@@ -63,11 +82,12 @@ function getSortedCppFiles() {
|
|
|
63
82
|
}
|
|
64
83
|
scanDir(process.cwd());
|
|
65
84
|
|
|
85
|
+
if (fileList.length === 0) return null;
|
|
86
|
+
|
|
66
87
|
const fileData = fileList.map(file => {
|
|
67
88
|
const content = fs.readFileSync(file, 'utf8');
|
|
68
89
|
const exportsMatch = content.match(/export\s+module\s+([a-zA-Z0-9_]+)\s*;/);
|
|
69
90
|
const importsMatches = [...content.matchAll(/import\s+([a-zA-Z0-9_]+)\s*;/g)].map(m => m[1]);
|
|
70
|
-
|
|
71
91
|
return { file, exports: exportsMatch ? exportsMatch[1] : null, imports: importsMatches };
|
|
72
92
|
});
|
|
73
93
|
|
|
@@ -79,12 +99,10 @@ function getSortedCppFiles() {
|
|
|
79
99
|
if (visited.has(node.file)) return;
|
|
80
100
|
if (processing.has(node.file)) return;
|
|
81
101
|
processing.add(node.file);
|
|
82
|
-
|
|
83
102
|
node.imports.forEach(imp => {
|
|
84
103
|
const dep = fileData.find(f => f.exports === imp);
|
|
85
104
|
if (dep) visit(dep);
|
|
86
105
|
});
|
|
87
|
-
|
|
88
106
|
processing.delete(node.file);
|
|
89
107
|
visited.add(node.file);
|
|
90
108
|
sortedFiles.push(`"${node.file}"`);
|
|
@@ -94,68 +112,52 @@ function getSortedCppFiles() {
|
|
|
94
112
|
return sortedFiles.join(' ');
|
|
95
113
|
}
|
|
96
114
|
|
|
115
|
+
// --- COMMANDS ---
|
|
116
|
+
|
|
97
117
|
function initProject() {
|
|
98
|
-
console.log(
|
|
118
|
+
console.log(`${colors.cyan}${colors.bold}🚀 Initializing PRO C++ Project...${colors.reset}`);
|
|
99
119
|
const vscodeDir = path.join(process.cwd(), '.vscode');
|
|
100
120
|
if (!fs.existsSync(vscodeDir)) fs.mkdirSync(vscodeDir);
|
|
101
121
|
|
|
102
|
-
|
|
103
|
-
const tasksContent = {
|
|
122
|
+
const tasks = {
|
|
104
123
|
"version": "2.0.0",
|
|
105
124
|
"tasks": [{
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"command": "
|
|
109
|
-
"
|
|
110
|
-
"problemMatcher": ["$msCompile"],
|
|
111
|
-
"group": "build"
|
|
125
|
+
"label": "PRO-CPP-BUILD",
|
|
126
|
+
"type": "shell",
|
|
127
|
+
"command": "procpp run",
|
|
128
|
+
"group": { "kind": "build", "isDefault": true }
|
|
112
129
|
}]
|
|
113
130
|
};
|
|
114
|
-
fs.writeFileSync(path.join(vscodeDir, 'tasks.json'), JSON.stringify(
|
|
131
|
+
fs.writeFileSync(path.join(vscodeDir, 'tasks.json'), JSON.stringify(tasks, null, 4));
|
|
115
132
|
|
|
116
|
-
|
|
117
|
-
const propertiesContent = {
|
|
133
|
+
const props = {
|
|
118
134
|
"configurations": [{
|
|
119
135
|
"name": "Win32",
|
|
120
136
|
"includePath": ["${workspaceFolder}/**"],
|
|
121
137
|
"compilerPath": "cl.exe",
|
|
122
|
-
"cStandard": "c17",
|
|
123
138
|
"cppStandard": "c++20",
|
|
124
139
|
"intelliSenseMode": "windows-msvc-x64",
|
|
125
|
-
"compilerArgs": [
|
|
126
|
-
"/std:c++20",
|
|
127
|
-
"/experimental:module",
|
|
128
|
-
"/ifcSearchDir", // Указываем IDE, где искать .ifc файлы!
|
|
129
|
-
"${workspaceFolder}/.build"
|
|
130
|
-
]
|
|
140
|
+
"compilerArgs": ["/std:c++20", "/experimental:module", "/ifcSearchDir", "${workspaceFolder}/.build"]
|
|
131
141
|
}],
|
|
132
142
|
"version": 4
|
|
133
143
|
};
|
|
134
|
-
fs.writeFileSync(path.join(vscodeDir, 'c_cpp_properties.json'), JSON.stringify(
|
|
135
|
-
|
|
136
|
-
// 3. settings.json (Hide .build folder from UI)
|
|
137
|
-
const settingsContent = {
|
|
138
|
-
"files.exclude": {
|
|
139
|
-
".build": true,
|
|
140
|
-
"**/.build": true
|
|
141
|
-
},
|
|
142
|
-
"C_Cpp.errorSquiggles": "disabled"
|
|
143
|
-
};
|
|
144
|
-
fs.writeFileSync(path.join(vscodeDir, 'settings.json'), JSON.stringify(settingsContent, null, 4));
|
|
144
|
+
fs.writeFileSync(path.join(vscodeDir, 'c_cpp_properties.json'), JSON.stringify(props, null, 4));
|
|
145
145
|
|
|
146
|
-
// 4. main.cpp template
|
|
147
146
|
const mainCppPath = path.join(process.cwd(), 'main.cpp');
|
|
148
147
|
if (!fs.existsSync(mainCppPath)) {
|
|
149
|
-
|
|
148
|
+
// Using standard include for max compatibility in template
|
|
149
|
+
fs.writeFileSync(mainCppPath, `#include <iostream>\n\nint main() {\n std::cout << "🚀 PRO C++ is running!" << std::endl;\n return 0;\n}`);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
console.log(
|
|
152
|
+
console.log(`${colors.green}✅ Ready! Use 'procpp watch' to start developing.${colors.reset}`);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
function buildAndRun() {
|
|
156
|
+
if (!checkEnv()) return;
|
|
157
|
+
|
|
156
158
|
const cppFiles = getSortedCppFiles();
|
|
157
159
|
if (!cppFiles) {
|
|
158
|
-
console.error(
|
|
160
|
+
console.error(`${colors.red}❌ Error: No .cpp or .ixx files found!${colors.reset}`);
|
|
159
161
|
return;
|
|
160
162
|
}
|
|
161
163
|
|
|
@@ -164,55 +166,65 @@ function buildAndRun() {
|
|
|
164
166
|
if (!fs.existsSync(BUILD_DIR)) fs.mkdirSync(BUILD_DIR);
|
|
165
167
|
|
|
166
168
|
const outputExeName = `app_build_${Date.now()}.exe`;
|
|
169
|
+
console.log(`\n${colors.cyan}🔨 Compiling...${colors.reset}`);
|
|
167
170
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// Компилируем чисто, без странных флагов
|
|
171
|
-
const compileCmd = `cl.exe /std:c++20 /nologo /EHsc ${cppFiles} /Fe"${outputExeName}"`;
|
|
171
|
+
const startTime = performance.now();
|
|
172
|
+
const compileCmd = `cl.exe /std:c++20 /nologo /EHsc /Zi ${cppFiles} /Fe"${outputExeName}"`;
|
|
172
173
|
|
|
173
174
|
if (runSyncCommand(compileCmd)) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
} catch(e) {}
|
|
175
|
+
const buildTime = ((performance.now() - startTime) / 1000).toFixed(2);
|
|
176
|
+
|
|
177
|
+
// Move artifacts to .build
|
|
178
|
+
fs.readdirSync(process.cwd()).forEach(file => {
|
|
179
|
+
if (['.obj', '.ifc', '.pdb', '.ilk'].some(ext => file.endsWith(ext)) || file === outputExeName) {
|
|
180
|
+
try { fs.renameSync(path.join(process.cwd(), file), path.join(BUILD_DIR, file)); } catch(e) {}
|
|
181
181
|
}
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
-
console.log(
|
|
184
|
+
console.log(`${colors.green}${colors.bold}⚡ [Success] Compiled in ${buildTime}s${colors.reset}`);
|
|
185
|
+
console.log(`${colors.yellow}🟢 RUNNING -> ${outputExeName}${colors.reset}\n` + `${colors.gray}${"-".repeat(40)}${colors.reset}`);
|
|
185
186
|
|
|
186
|
-
// Запускаем из папки .build
|
|
187
187
|
currentAppProcess = spawn(`.\\.build\\${outputExeName}`, [], { shell: true, stdio: 'inherit' });
|
|
188
188
|
currentAppProcess.on('close', (code) => {
|
|
189
|
-
if (code !== null) console.log("-".repeat(40)
|
|
189
|
+
if (code !== null) console.log(`${colors.gray}${"-".repeat(40)}${colors.reset}\n${colors.red}🛑 Process exited (code ${code})${colors.reset}`);
|
|
190
190
|
});
|
|
191
191
|
} else {
|
|
192
|
-
console.log(`\n❌ BUILD FAILED`);
|
|
192
|
+
console.log(`\n${colors.red}${colors.bold}❌ BUILD FAILED${colors.reset}`);
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
function watchProject() {
|
|
197
|
-
|
|
197
|
+
if (!checkEnv()) return;
|
|
198
|
+
console.clear();
|
|
199
|
+
console.log(`${colors.cyan}${colors.bold}👀 PRO C++ Watcher Started${colors.reset}`);
|
|
198
200
|
buildAndRun();
|
|
199
201
|
|
|
200
202
|
fs.watch(process.cwd(), { recursive: true }, (eventType, filename) => {
|
|
201
|
-
// Игнорируем всё, что происходит внутри папки .build
|
|
202
203
|
if (filename && (filename.endsWith('.cpp') || filename.endsWith('.ixx') || filename.endsWith('.h')) && !filename.includes('.build')) {
|
|
203
204
|
clearTimeout(watchTimeout);
|
|
204
205
|
watchTimeout = setTimeout(() => {
|
|
205
206
|
console.clear();
|
|
206
|
-
console.log(
|
|
207
|
+
console.log(`${colors.gray}[${new Date().toLocaleTimeString()}] Change detected: ${filename}${colors.reset}`);
|
|
207
208
|
buildAndRun();
|
|
208
209
|
}, 300);
|
|
209
210
|
}
|
|
210
211
|
});
|
|
211
212
|
}
|
|
212
213
|
|
|
214
|
+
// --- CLI ROUTER ---
|
|
215
|
+
|
|
216
|
+
const versionFlags = ['-v', '--version', 'version'];
|
|
217
|
+
if (versionFlags.includes(command)) {
|
|
218
|
+
console.log(`${colors.bold}pro-cpp-cli-core v${packageJson.version}${colors.reset}`);
|
|
219
|
+
process.exit(0);
|
|
220
|
+
}
|
|
221
|
+
|
|
213
222
|
switch (command) {
|
|
214
223
|
case 'init': initProject(); break;
|
|
215
224
|
case 'run': buildAndRun(); break;
|
|
216
225
|
case 'watch': watchProject(); break;
|
|
217
|
-
default:
|
|
226
|
+
default:
|
|
227
|
+
console.log(`${colors.bold}🛠️ PRO CPP CLI v${packageJson.version}${colors.reset}`);
|
|
228
|
+
console.log(`Usage: procpp <init|run|watch|version>`);
|
|
229
|
+
break;
|
|
218
230
|
}
|
package/package.json
CHANGED
|
@@ -1,29 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pro-cpp-cli-core",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"
|
|
5
|
-
"type": "git",
|
|
6
|
-
"url": "git+https://github.com/anton-po-github/pro-cpp-cli-core.git"
|
|
7
|
-
},
|
|
8
|
-
"bugs": {
|
|
9
|
-
"url": "https://github.com/anton-po-github/pro-cpp-cli-core/issues"
|
|
10
|
-
},
|
|
11
|
-
"homepage": "https://github.com/anton-po-github/pro-cpp-cli-core#readme",
|
|
12
|
-
"description": "The ultimate C++ Developer Experience for Windows",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "The ultimate C++ Developer Experience for Windows.",
|
|
13
5
|
"main": "index.js",
|
|
14
6
|
"bin": {
|
|
15
|
-
"procpp": "index.js"
|
|
16
|
-
},
|
|
17
|
-
"scripts": {
|
|
18
|
-
"start": "node index.js"
|
|
7
|
+
"procpp": "./index.js"
|
|
19
8
|
},
|
|
20
9
|
"keywords": [
|
|
21
10
|
"cpp",
|
|
22
11
|
"c++",
|
|
23
12
|
"cli",
|
|
24
13
|
"watch",
|
|
25
|
-
"
|
|
14
|
+
"hot-reload",
|
|
15
|
+
"c++20",
|
|
16
|
+
"msvc"
|
|
26
17
|
],
|
|
27
18
|
"author": "PRO Developer",
|
|
28
19
|
"license": "MIT"
|
|
29
|
-
}
|
|
20
|
+
}
|