pro-cpp-cli-core 1.0.3 → 1.0.5

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.
Files changed (2) hide show
  1. package/index.js +150 -121
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -1,15 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ /**
4
+ * PRO C++ CLI Core (With C++20 Modules Topological Sorter)
5
+ * FIX: Restored initProject!
6
+ * FIX: Smart post-build artifact routing to .build/ directory!
7
+ */
8
+
3
9
  const { execSync, spawn } = require('child_process');
4
10
  const fs = require('fs');
5
11
  const path = require('path');
6
12
 
7
13
  const [,, command, ...args] = process.argv;
8
-
9
14
  let currentAppProcess = null;
10
15
  let watchTimeout = null;
11
16
 
12
- // Helper: Safely execute synchronous shell commands
17
+ const BUILD_DIR = path.join(process.cwd(), '.build');
18
+
13
19
  function runSyncCommand(cmd) {
14
20
  try {
15
21
  execSync(cmd, { stdio: 'inherit' });
@@ -19,171 +25,194 @@ function runSyncCommand(cmd) {
19
25
  }
20
26
  }
21
27
 
22
- // Helper: Clean up old build files to save disk space
23
28
  function cleanupOldBuilds() {
24
- const files = fs.readdirSync(process.cwd());
25
- files.forEach(file => {
26
- if ((file.startsWith('app_build_') && file.endsWith('.exe')) || file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk')) {
27
- try {
28
- fs.unlinkSync(path.join(process.cwd(), file));
29
- } catch (err) {
30
- // Ignore errors: file might be locked by OS or Antivirus. We will try next time!
29
+ // 1. Clean .build folder
30
+ if (fs.existsSync(BUILD_DIR)) {
31
+ const files = fs.readdirSync(BUILD_DIR);
32
+ files.forEach(file => {
33
+ if (file.endsWith('.obj') || file.endsWith('.pdb') || file.endsWith('.ilk') || file.endsWith('.ifc') || file.startsWith('app_build_')) {
34
+ try { fs.unlinkSync(path.join(BUILD_DIR, file)); } catch (err) {}
31
35
  }
36
+ });
37
+ }
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) {}
32
43
  }
33
44
  });
34
45
  }
35
46
 
36
- // Helper: Get all .cpp files in the directory
37
- function getCppFiles() {
38
- const files = fs.readdirSync(process.cwd());
39
- return files.filter(file => file.endsWith('.cpp')).join(' ');
40
- }
41
-
42
- // Command: procpp init
43
- function initProject() {
44
- console.log("🚀 Initializing PRO C++ Project with C++20....");
47
+ function getSortedCppFiles() {
48
+ const fileList = [];
45
49
 
46
- const vscodeDir = path.join(process.cwd(), '.vscode');
47
- if (!fs.existsSync(vscodeDir)) {
48
- fs.mkdirSync(vscodeDir);
50
+ function scanDir(dir) {
51
+ const files = fs.readdirSync(dir);
52
+ for (const file of files) {
53
+ const filePath = path.join(dir, file);
54
+ if (fs.statSync(filePath).isDirectory()) {
55
+ // ИГНОРИРУЕМ ПАПКУ .build, ЧТОБЫ ВОЧЕР НЕ СОШЕЛ С УМА
56
+ if (file !== 'node_modules' && file !== '.vscode' && file !== '.build') {
57
+ scanDir(filePath);
58
+ }
59
+ } else if (filePath.endsWith('.cpp') || filePath.endsWith('.ixx')) {
60
+ fileList.push(filePath);
61
+ }
62
+ }
49
63
  }
64
+ scanDir(process.cwd());
50
65
 
51
- const mainCppPath = path.join(process.cwd(), 'main.cpp');
52
- const mainCppContent = `#include <iostream>\n\n// The main entry point of the application\nint main() {\n std::cout << "PRO CLI works like magic!\\n";\n return 0;\n}\n`;
66
+ const fileData = fileList.map(file => {
67
+ const content = fs.readFileSync(file, 'utf8');
68
+ const exportsMatch = content.match(/export\s+module\s+([a-zA-Z0-9_]+)\s*;/);
69
+ const importsMatches = [...content.matchAll(/import\s+([a-zA-Z0-9_]+)\s*;/g)].map(m => m[1]);
70
+
71
+ return { file, exports: exportsMatch ? exportsMatch[1] : null, imports: importsMatches };
72
+ });
53
73
 
54
- if (!fs.existsSync(mainCppPath)) {
55
- fs.writeFileSync(mainCppPath, mainCppContent);
56
- console.log("✅ Created main.cpp");
74
+ const sortedFiles = [];
75
+ const visited = new Set();
76
+ const processing = new Set();
77
+
78
+ function visit(node) {
79
+ if (visited.has(node.file)) return;
80
+ if (processing.has(node.file)) return;
81
+ processing.add(node.file);
82
+
83
+ node.imports.forEach(imp => {
84
+ const dep = fileData.find(f => f.exports === imp);
85
+ if (dep) visit(dep);
86
+ });
87
+
88
+ processing.delete(node.file);
89
+ visited.add(node.file);
90
+ sortedFiles.push(`"${node.file}"`);
57
91
  }
58
92
 
59
- // Generate tasks.json with C++20
93
+ fileData.forEach(visit);
94
+ return sortedFiles.join(' ');
95
+ }
96
+
97
+ function initProject() {
98
+ console.log("🚀 Initializing PRO C++ Project (C++20 Modules)...");
99
+ const vscodeDir = path.join(process.cwd(), '.vscode');
100
+ if (!fs.existsSync(vscodeDir)) fs.mkdirSync(vscodeDir);
101
+
102
+ // 1. tasks.json
60
103
  const tasksContent = {
61
104
  "version": "2.0.0",
62
- "tasks": [
63
- {
64
- "type": "cppbuild",
65
- "label": "DEBUG-BUILD-MSVC",
66
- "command": "cl.exe",
67
- "args": [
68
- "/std:c++20", "/Zi", "/EHsc", "/nologo",
69
- "/Fe${fileDirname}\\debug_build_999.exe",
70
- "${file}"
71
- ],
72
- "options": { "cwd": "${fileDirname}" },
73
- "problemMatcher": ["$msCompile"],
74
- "group": "build"
75
- }
76
- ]
105
+ "tasks": [{
106
+ "type": "cppbuild",
107
+ "label": "DEBUG-BUILD-MSVC",
108
+ "command": "cl.exe",
109
+ "args": ["/std:c++20", "/Zi", "/EHsc", "/nologo", "/Fe${fileDirname}\\.build\\debug_build.exe", "${file}"],
110
+ "problemMatcher": ["$msCompile"],
111
+ "group": "build"
112
+ }]
77
113
  };
78
114
  fs.writeFileSync(path.join(vscodeDir, 'tasks.json'), JSON.stringify(tasksContent, null, 4));
79
115
 
80
- // Generate launch.json for bulletproof debugging
81
- const launchContent = {
82
- "version": "0.2.0",
83
- "configurations": [
84
- {
85
- "name": "⚙️ PRO C++ Debug",
86
- "type": "cppvsdbg",
87
- "request": "launch",
88
- "program": "${fileDirname}\\debug_build_999.exe",
89
- "args": [],
90
- "stopAtEntry": false,
91
- "cwd": "${fileDirname}",
92
- "environment": [],
93
- "console": "integratedTerminal",
94
- "preLaunchTask": "DEBUG-BUILD-MSVC"
95
- }
96
- ]
116
+ // 2. c_cpp_properties.json (FIX FOR IDE SQUIGGLES!)
117
+ const propertiesContent = {
118
+ "configurations": [{
119
+ "name": "Win32",
120
+ "includePath": ["${workspaceFolder}/**"],
121
+ "compilerPath": "cl.exe",
122
+ "cStandard": "c17",
123
+ "cppStandard": "c++20",
124
+ "intelliSenseMode": "windows-msvc-x64",
125
+ "compilerArgs": [
126
+ "/std:c++20",
127
+ "/experimental:module",
128
+ "/ifcSearchDir", // Указываем IDE, где искать .ifc файлы!
129
+ "${workspaceFolder}/.build"
130
+ ]
131
+ }],
132
+ "version": 4
133
+ };
134
+ fs.writeFileSync(path.join(vscodeDir, 'c_cpp_properties.json'), JSON.stringify(propertiesContent, null, 4));
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"
97
143
  };
98
- fs.writeFileSync(path.join(vscodeDir, 'launch.json'), JSON.stringify(launchContent, null, 4));
144
+ fs.writeFileSync(path.join(vscodeDir, 'settings.json'), JSON.stringify(settingsContent, null, 4));
99
145
 
100
- console.log("✅ Created .vscode debugger configs (C++20 & F5 ready!)");
101
- console.log("🎯 Project initialized! Run 'procpp watch' to start developing.");
102
- }
146
+ // 4. main.cpp template
147
+ const mainCppPath = path.join(process.cwd(), 'main.cpp');
148
+ if (!fs.existsSync(mainCppPath)) {
149
+ fs.writeFileSync(mainCppPath, `import std.core;\n// C++20 Modules ready!\nint main() { return 0; }`);
150
+ }
103
151
 
104
- // Core Build and Run Logic
105
- function buildAndRun(isWatchMode = false) {
106
- const cppFiles = getCppFiles();
152
+ console.log("✅ Ready! .vscode configs created. IntelliSense is pointed to .build/");
153
+ }
107
154
 
155
+ function buildAndRun() {
156
+ const cppFiles = getSortedCppFiles();
108
157
  if (!cppFiles) {
109
- console.error("❌ No .cpp files found in this directory!");
158
+ console.error("❌ Error: No .cpp or .ixx files found!");
110
159
  return;
111
160
  }
112
161
 
113
- // 1. Kill previous running instance if it exists
114
- if (currentAppProcess) {
115
- currentAppProcess.kill();
116
- currentAppProcess = null;
117
- }
118
-
119
- // 2. Background cleanup of unlocked old files
162
+ if (currentAppProcess) currentAppProcess.kill();
120
163
  cleanupOldBuilds();
164
+ if (!fs.existsSync(BUILD_DIR)) fs.mkdirSync(BUILD_DIR);
121
165
 
122
- // 3. Generate unique executable name to bypass Antivirus/OS locks
123
- const timestamp = Date.now();
124
- const outputExe = `app_build_${timestamp}.exe`;
166
+ const outputExeName = `app_build_${Date.now()}.exe`;
167
+
168
+ console.log(`\n🔨 Compiling with SMART DEPENDENCY GRAPH...`);
125
169
 
126
- console.log(`\n🔨 Compiling (Standard: C++20)...`);
127
- const compileCmd = `cl.exe /std:c++20 /nologo /EHsc ${cppFiles} /Fe"${outputExe}"`;
170
+ // Компилируем чисто, без странных флагов
171
+ const compileCmd = `cl.exe /std:c++20 /nologo /EHsc ${cppFiles} /Fe"${outputExeName}"`;
128
172
 
129
- const success = runSyncCommand(compileCmd);
173
+ if (runSyncCommand(compileCmd)) {
174
+ // МАГИЯ ПЕРЕНОСА: Двигаем все созданные файлы в папку .build
175
+ const files = fs.readdirSync(process.cwd());
176
+ files.forEach(file => {
177
+ if (file.endsWith('.obj') || file.endsWith('.ifc') || file.endsWith('.pdb') || file.endsWith('.ilk') || file === outputExeName) {
178
+ try {
179
+ fs.renameSync(path.join(process.cwd(), file), path.join(BUILD_DIR, file));
180
+ } catch(e) {}
181
+ }
182
+ });
130
183
 
131
- if (success) {
132
- console.log(`🟢 RUNNING -> ${outputExe}\n` + "-".repeat(40));
133
-
134
- // 4. Run the new executable asynchronously so Node.js can keep watching
135
- currentAppProcess = spawn(`.\\${outputExe}`, [], { shell: true, stdio: 'inherit' });
184
+ console.log(`🟢 RUNNING -> .build\\${outputExeName}\n` + "-".repeat(40));
136
185
 
186
+ // Запускаем из папки .build
187
+ currentAppProcess = spawn(`.\\.build\\${outputExeName}`, [], { shell: true, stdio: 'inherit' });
137
188
  currentAppProcess.on('close', (code) => {
138
- if (code !== null) {
139
- console.log("-".repeat(40) + `\n🛑 Process exited with code ${code}`);
140
- }
189
+ if (code !== null) console.log("-".repeat(40) + `\n🛑 Process exited with code ${code}`);
141
190
  });
142
191
  } else {
143
192
  console.log(`\n❌ BUILD FAILED`);
144
193
  }
145
194
  }
146
195
 
147
- // Command: procpp watch
148
196
  function watchProject() {
149
- console.log("👀 PRO C++ Watcher Started (C++20 Mode)");
150
- console.log("Press Ctrl+C to stop. Watching for file changes...");
151
-
152
- // Initial build
153
- buildAndRun(true);
197
+ console.log("👀 PRO C++ Watcher Started (Mode: Smart C++20 Modules)");
198
+ buildAndRun();
154
199
 
155
- // Watch the current directory for changes
156
- fs.watch(process.cwd(), (eventType, filename) => {
157
- if (filename && (filename.endsWith('.cpp') || filename.endsWith('.h'))) {
158
- // Debounce to prevent multiple rapid triggers when saving
200
+ fs.watch(process.cwd(), { recursive: true }, (eventType, filename) => {
201
+ // Игнорируем всё, что происходит внутри папки .build
202
+ if (filename && (filename.endsWith('.cpp') || filename.endsWith('.ixx') || filename.endsWith('.h')) && !filename.includes('.build')) {
159
203
  clearTimeout(watchTimeout);
160
204
  watchTimeout = setTimeout(() => {
161
205
  console.clear();
162
- console.log(`[${new Date().toLocaleTimeString()}] Change detected in ${filename}`);
163
- buildAndRun(true);
164
- }, 300); // 300ms delay
206
+ console.log(`[${new Date().toLocaleTimeString()}] Change detected: ${filename}`);
207
+ buildAndRun();
208
+ }, 300);
165
209
  }
166
210
  });
167
211
  }
168
212
 
169
- // CLI Router
170
213
  switch (command) {
171
- case 'init':
172
- initProject();
173
- break;
174
- case 'run':
175
- buildAndRun(false);
176
- break;
177
- case 'watch':
178
- watchProject();
179
- break;
180
- default:
181
- console.log(`
182
- 🛠️ PRO CPP CLI 🛠️
183
- Usage:
184
- procpp init - Scaffold C++ project & VS Code debugger configs
185
- procpp run - Compile and run all .cpp files once
186
- procpp watch - Live reload! Auto-compile and run on file save
187
- `);
188
- break;
214
+ case 'init': initProject(); break;
215
+ case 'run': buildAndRun(); break;
216
+ case 'watch': watchProject(); break;
217
+ default: console.log("🛠️ PRO CPP CLI\nUsage: procpp <init|run|watch>"); break;
189
218
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pro-cpp-cli-core",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/anton-po-github/pro-cpp-cli-core.git"
@@ -12,7 +12,7 @@
12
12
  "description": "The ultimate C++ Developer Experience for Windows",
13
13
  "main": "index.js",
14
14
  "bin": {
15
- "procpp": "./index.js"
15
+ "procpp": "index.js"
16
16
  },
17
17
  "scripts": {
18
18
  "start": "node index.js"
@@ -26,4 +26,4 @@
26
26
  ],
27
27
  "author": "PRO Developer",
28
28
  "license": "MIT"
29
- }
29
+ }