cloving 0.3.5 → 0.3.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 +8 -2
- package/dist/cloving_gpt/index.js +1 -1
- package/dist/commands/config.js +2 -2
- package/dist/commands/generate/context.js +3 -3
- package/dist/commands/init.js +3 -218
- package/dist/commands/tokens.js +2 -2
- package/dist/index.js +3 -2
- package/dist/managers/BlockManager.js +125 -0
- package/dist/managers/ChatManager.js +89 -18
- package/dist/managers/ChunkManager.js +12 -0
- package/dist/managers/CodeManager.js +5 -5
- package/dist/managers/InitManager.js +216 -0
- package/dist/managers/ProxyManager.js +11 -3
- package/dist/managers/ReviewManager.js +14 -2
- package/dist/managers/ShellManager.js +7 -2
- package/dist/managers/UnitTestManager.js +3 -3
- package/dist/package.json +1 -1
- package/dist/utils/prompt_utils.js +515 -0
- package/dist/utils/string_utils.js +22 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
# Cloving
|
|
1
|
+
# Cloving
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An AI pair-programmer for the command line.
|
|
4
|
+
|
|
5
|
+
LLM-powered shell commands, code generation, commit messages, code reviews, unit test generation, and more. Works with most popular LLMs including OpenAI, Claude, Gemini, Ollama, and more.
|
|
6
|
+
|
|
7
|
+
[](https://asciinema.org/a/SCcxw4B2XFQaTD0GeDTk0xbuq)
|
|
8
|
+
|
|
9
|
+
Cloving CLI is a command line utility which integrates AI into your development workflow.
|
|
4
10
|
|
|
5
11
|
What makes the Cloving CLI different from other AI tools is that it builds sophisticated context-aware prompts to generate code, commit messages, and more.
|
|
6
12
|
|
|
@@ -169,7 +169,7 @@ class ClovingGPT {
|
|
|
169
169
|
if (errorMessage === '') {
|
|
170
170
|
errorMessage = 'connection error';
|
|
171
171
|
}
|
|
172
|
-
console.error(`Error communicating with the GPT server (${this.adapter.getEndpoint(this.stream)})\n\n${JSON.stringify(error.response?.data || "''", null, 2)}\n`);
|
|
172
|
+
console.error(`Error communicating with the GPT server (${this.adapter.getEndpoint(this.stream)})\n\n${colors_1.default.red.bold(JSON.stringify(error.response?.data || "''", null, 2))}\n`);
|
|
173
173
|
throw error;
|
|
174
174
|
}
|
|
175
175
|
}
|
package/dist/commands/config.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.config = void 0;
|
|
4
4
|
const config_utils_1 = require("../utils/config_utils");
|
|
5
|
-
const
|
|
5
|
+
const prompt_utils_1 = require("../utils/prompt_utils");
|
|
6
6
|
const prompts_1 = require("@inquirer/prompts");
|
|
7
7
|
const config = async () => {
|
|
8
8
|
let currentConfig = (0, config_utils_1.getConfig)({});
|
|
@@ -10,7 +10,7 @@ const config = async () => {
|
|
|
10
10
|
if (!currentConfig.models) {
|
|
11
11
|
currentConfig.models = {};
|
|
12
12
|
}
|
|
13
|
-
const models = await (0,
|
|
13
|
+
const models = await (0, prompt_utils_1.fetchModels)();
|
|
14
14
|
if (models.length === 0) {
|
|
15
15
|
console.error('No models available.');
|
|
16
16
|
throw new Error('No models available');
|
|
@@ -8,10 +8,10 @@ const copy_paste_1 = __importDefault(require("copy-paste"));
|
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const prompts_1 = require("@inquirer/prompts");
|
|
11
|
-
const
|
|
11
|
+
const prompt_utils_1 = require("../../utils/prompt_utils");
|
|
12
12
|
const config_utils_1 = require("../../utils/config_utils");
|
|
13
13
|
const generateContextPrompt = (files, contextFiles) => {
|
|
14
|
-
const specialFileContents = (0,
|
|
14
|
+
const specialFileContents = (0, prompt_utils_1.collectSpecialFileContents)();
|
|
15
15
|
const specialFiles = Object.keys(specialFileContents)
|
|
16
16
|
.map((file) => `### Contents of ${file}\n\n${JSON.stringify(specialFileContents[file], null, 2)}\n\n`)
|
|
17
17
|
.join('\n');
|
|
@@ -55,7 +55,7 @@ const context = async (options) => {
|
|
|
55
55
|
message: 'Enter the relative path of a file or directory you would like to include as context (or press enter to continue):',
|
|
56
56
|
});
|
|
57
57
|
if (contextFile) {
|
|
58
|
-
contextFiles = await (0,
|
|
58
|
+
contextFiles = await (0, prompt_utils_1.addFileOrDirectoryToContext)(contextFile, contextFiles, options);
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
61
61
|
includeMoreFiles = false;
|
package/dist/commands/init.js
CHANGED
|
@@ -4,225 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.init = void 0;
|
|
7
|
-
const
|
|
8
|
-
const os_1 = __importDefault(require("os"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const prompts_1 = require("@inquirer/prompts");
|
|
11
|
-
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
12
|
-
const ignore_1 = __importDefault(require("ignore"));
|
|
13
|
-
const string_utils_1 = require("../utils/string_utils");
|
|
14
|
-
const config_utils_1 = require("../utils/config_utils");
|
|
15
|
-
const command_utils_1 = require("../utils/command_utils");
|
|
16
|
-
// Main function for the describe command
|
|
7
|
+
const InitManager_1 = __importDefault(require("../managers/InitManager"));
|
|
17
8
|
const init = async (options) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const specialFileContents = (0, command_utils_1.collectSpecialFileContents)();
|
|
21
|
-
const specialFileNames = Object.keys(specialFileContents).map((file) => ' - ' + file);
|
|
22
|
-
// Initialize chat history
|
|
23
|
-
const chatHistory = [
|
|
24
|
-
{
|
|
25
|
-
role: 'system',
|
|
26
|
-
content: `You are an AI assistant helping to initialize a project by analyzing its structure and technologies.
|
|
27
|
-
|
|
28
|
-
Please return JSON-formatted metadata about the project, including:
|
|
29
|
-
|
|
30
|
-
- The programming language(s) used
|
|
31
|
-
- The detected framework(s) (if any)
|
|
32
|
-
- The version of the language(s)
|
|
33
|
-
|
|
34
|
-
Here is a typescript interface for the expected response:
|
|
35
|
-
|
|
36
|
-
interface LanguageConfig {
|
|
37
|
-
name: string
|
|
38
|
-
version?: string
|
|
39
|
-
primary?: boolean
|
|
40
|
-
directory: string
|
|
41
|
-
extension: string
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface FrameworkConfig {
|
|
45
|
-
name: string
|
|
46
|
-
type: string
|
|
47
|
-
version?: string
|
|
48
|
-
primary?: boolean
|
|
49
|
-
directory?: string
|
|
50
|
-
extension?: string
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
interface TestingFrameworkConfig {
|
|
54
|
-
name: string
|
|
55
|
-
type: string
|
|
56
|
-
version?: string
|
|
57
|
-
directory?: string
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
interface BuildToolConfig {
|
|
61
|
-
name: string
|
|
62
|
-
type: string
|
|
63
|
-
version?: string
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface LinterConfig {
|
|
67
|
-
name: string
|
|
68
|
-
version?: string
|
|
69
|
-
type?: string
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
interface DatabaseConfig {
|
|
73
|
-
name: string
|
|
74
|
-
primary?: boolean
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface ClovingfileConfig {
|
|
78
|
-
languages: LanguageConfig[]
|
|
79
|
-
frameworks: FrameworkConfig[]
|
|
80
|
-
testingFrameworks?: TestingFrameworkConfig[]
|
|
81
|
-
buildTools: BuildToolConfig[]
|
|
82
|
-
packageManager: string
|
|
83
|
-
linters: LinterConfig[]
|
|
84
|
-
databases?: DatabaseConfig[]
|
|
85
|
-
projectType: string
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
Here is an example response:
|
|
89
|
-
|
|
90
|
-
{
|
|
91
|
-
"languages": [
|
|
92
|
-
{
|
|
93
|
-
"name": "TypeScript",
|
|
94
|
-
"version": "~> 5.5.3"
|
|
95
|
-
"primary": true,
|
|
96
|
-
"directory": "src",
|
|
97
|
-
"extension": ".ts"
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
"name": "JavaScript",
|
|
101
|
-
"version": "ES6+",
|
|
102
|
-
"directory": "src",
|
|
103
|
-
"extension": ".js"
|
|
104
|
-
}
|
|
105
|
-
],
|
|
106
|
-
"frameworks": [
|
|
107
|
-
{
|
|
108
|
-
"name": "Node.js",
|
|
109
|
-
"type": "Runtime environment",
|
|
110
|
-
"primary": true,
|
|
111
|
-
"directory": "src",
|
|
112
|
-
"extension": ".js"
|
|
113
|
-
}
|
|
114
|
-
],
|
|
115
|
-
"testingFrameworks": [
|
|
116
|
-
{
|
|
117
|
-
"name": "Jest",
|
|
118
|
-
"type": "Testing framework",
|
|
119
|
-
"version": "29.7.0"
|
|
120
|
-
"directory": "tests"
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
"buildTools": [
|
|
124
|
-
{
|
|
125
|
-
"name": "TypeScript Compiler (tsc)",
|
|
126
|
-
"type": "Transpiler"
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"name": "Vite",
|
|
130
|
-
"type": "Build tool",
|
|
131
|
-
"version": "5.3.3"
|
|
132
|
-
}
|
|
133
|
-
],
|
|
134
|
-
"packageManager": "Yarn",
|
|
135
|
-
"linters": [
|
|
136
|
-
{
|
|
137
|
-
"name": "ESLint",
|
|
138
|
-
"version": "9.6.0"
|
|
139
|
-
}
|
|
140
|
-
],
|
|
141
|
-
"databases": [
|
|
142
|
-
{
|
|
143
|
-
"name": "MongoDB",
|
|
144
|
-
"version": "5.0.3",
|
|
145
|
-
"primary": true
|
|
146
|
-
}
|
|
147
|
-
],
|
|
148
|
-
"projectType": "Command-line tool",
|
|
149
|
-
}`,
|
|
150
|
-
},
|
|
151
|
-
];
|
|
152
|
-
if (!options.silent) {
|
|
153
|
-
if (specialFileNames.length > 0) {
|
|
154
|
-
console.log(`Cloving will analyze the list of files and the contents of the following files:
|
|
155
|
-
|
|
156
|
-
${specialFileNames.join('\n')}
|
|
157
|
-
|
|
158
|
-
Cloving will send AI a request to summarize the technologies used in this project.
|
|
159
|
-
|
|
160
|
-
This will provide better context for future Cloving requests.`);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
console.log(`
|
|
164
|
-
This script will analyze the list of files in the current directory using GPT to summarize the
|
|
165
|
-
technologies used. This will provide better context for future Cloving requests.
|
|
166
|
-
`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
const config = (0, config_utils_1.getConfig)(options);
|
|
170
|
-
if (!config || !config?.models) {
|
|
171
|
-
console.error('No cloving configuration found. Please run `cloving config`');
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (!(0, command_utils_1.checkForSpecialFiles)()) {
|
|
175
|
-
console.error('No dependencies files detected. Please add a dependency file (e.g. package.json, Gemfile, requirements.txt, etc.) to your project and run `cloving init` again.');
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const tempFilePath = path_1.default.join(os_1.default.tmpdir(), `describe_${Date.now()}.tmp`);
|
|
179
|
-
try {
|
|
180
|
-
const gitignorePath = path_1.default.join(process.cwd(), '.gitignore');
|
|
181
|
-
const ig = (0, ignore_1.default)();
|
|
182
|
-
if (fs_1.default.existsSync(gitignorePath)) {
|
|
183
|
-
const gitignoreContent = fs_1.default.readFileSync(gitignorePath, 'utf-8');
|
|
184
|
-
ig.add(gitignoreContent);
|
|
185
|
-
}
|
|
186
|
-
const fileList = await (0, command_utils_1.generateFileList)();
|
|
187
|
-
const filteredFileList = fileList.filter((file) => {
|
|
188
|
-
try {
|
|
189
|
-
return !ig.ignores(file);
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
const limitedFileList = filteredFileList.slice(0, 100);
|
|
196
|
-
const projectDetails = {
|
|
197
|
-
files: limitedFileList,
|
|
198
|
-
specialFiles: specialFileContents,
|
|
199
|
-
};
|
|
200
|
-
const prompt = `Here is a JSON object describing my project:
|
|
201
|
-
${JSON.stringify(projectDetails, null, 2)}`;
|
|
202
|
-
chatHistory.push({ role: 'user', content: prompt });
|
|
203
|
-
const aiChatResponse = await gpt.generateText({ prompt, messages: chatHistory });
|
|
204
|
-
chatHistory.push({ role: 'assistant', content: aiChatResponse });
|
|
205
|
-
const cleanAiChatResponse = (0, string_utils_1.extractJsonMetadata)(aiChatResponse);
|
|
206
|
-
fs_1.default.writeFileSync(tempFilePath, cleanAiChatResponse);
|
|
207
|
-
// Save the AI chat response to cloving.json
|
|
208
|
-
fs_1.default.writeFileSync('cloving.json', cleanAiChatResponse);
|
|
209
|
-
console.log('Project data saved to cloving.json');
|
|
210
|
-
// Prompt the user if they want to review the generated cloving.json
|
|
211
|
-
if (!options.silent) {
|
|
212
|
-
const reviewAnswer = await (0, prompts_1.confirm)({
|
|
213
|
-
message: 'Do you want to review the generated data?',
|
|
214
|
-
default: true,
|
|
215
|
-
});
|
|
216
|
-
if (reviewAnswer) {
|
|
217
|
-
console.log(cleanAiChatResponse);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
// Clean up
|
|
221
|
-
fs_1.default.unlinkSync(tempFilePath);
|
|
222
|
-
}
|
|
223
|
-
catch (error) {
|
|
224
|
-
console.error('Error describing the project:', error.message);
|
|
225
|
-
}
|
|
9
|
+
const initManager = new InitManager_1.default(options);
|
|
10
|
+
await initManager.initialize();
|
|
226
11
|
};
|
|
227
12
|
exports.init = init;
|
|
228
13
|
exports.default = exports.init;
|
package/dist/commands/tokens.js
CHANGED
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const fs_1 = __importDefault(require("fs"));
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const config_utils_1 = require("../utils/config_utils");
|
|
9
|
-
const
|
|
9
|
+
const prompt_utils_1 = require("../utils/prompt_utils");
|
|
10
10
|
const tokens = async (options) => {
|
|
11
11
|
let contextFiles = {};
|
|
12
12
|
let files = options.files || '.';
|
|
@@ -18,7 +18,7 @@ const tokens = async (options) => {
|
|
|
18
18
|
.stat(filePath)
|
|
19
19
|
.then((stat) => stat.isDirectory())
|
|
20
20
|
.catch(() => false)) {
|
|
21
|
-
const dirFiles = await (0,
|
|
21
|
+
const dirFiles = await (0, prompt_utils_1.getAllFilesInDirectory)(filePath);
|
|
22
22
|
expandedFiles = expandedFiles.concat(dirFiles.map((f) => path_1.default.relative(process.cwd(), f)));
|
|
23
23
|
}
|
|
24
24
|
else {
|
package/dist/index.js
CHANGED
|
@@ -17,12 +17,12 @@ const commit_1 = __importDefault(require("./commands/generate/commit"));
|
|
|
17
17
|
const context_1 = __importDefault(require("./commands/generate/context"));
|
|
18
18
|
const unit_tests_1 = __importDefault(require("./commands/generate/unit_tests"));
|
|
19
19
|
const review_1 = __importDefault(require("./commands/generate/review"));
|
|
20
|
-
const
|
|
20
|
+
const prompt_utils_1 = require("./utils/prompt_utils");
|
|
21
21
|
const program = new commander_1.Command();
|
|
22
22
|
program
|
|
23
23
|
.name('cloving')
|
|
24
24
|
.description('Integrate AI into your development workflow for generating commit messages, code reviews, and unit tests.')
|
|
25
|
-
.version((0,
|
|
25
|
+
.version((0, prompt_utils_1.getPackageVersion)());
|
|
26
26
|
program
|
|
27
27
|
.command('config')
|
|
28
28
|
.description('Configure cloving with your API key and models to use')
|
|
@@ -71,6 +71,7 @@ generate
|
|
|
71
71
|
.command('shell')
|
|
72
72
|
.alias('sh')
|
|
73
73
|
.description('Generate a shell command based on a prompt')
|
|
74
|
+
.option('-e, --exec', 'Automatically execute the generated shell command')
|
|
74
75
|
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
75
76
|
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
76
77
|
.option('-p, --prompt <prompt>', 'Specify the prompt to use')
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const events_1 = require("events");
|
|
4
|
+
// Passes through string chunks, looking for code blocks, when it finds one, it starts buffering until it finds the end of the block
|
|
5
|
+
// Then it emits the code block and clears the buffer and continues
|
|
6
|
+
class BlockManager extends events_1.EventEmitter {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.buffer = '';
|
|
10
|
+
this.codeBuffer = '';
|
|
11
|
+
this.isBufferingCode = false;
|
|
12
|
+
this.isWaitingForContent = false;
|
|
13
|
+
}
|
|
14
|
+
// add content to the buffer, watching for code blocks along the way
|
|
15
|
+
addContent(content) {
|
|
16
|
+
// when getting ` , just add it to the buffer until we get a char that isn't `
|
|
17
|
+
if (content.includes('`')) {
|
|
18
|
+
this.isWaitingForContent = true;
|
|
19
|
+
this.buffer += content;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
else if (this.isWaitingForContent) {
|
|
23
|
+
content = this.buffer + content;
|
|
24
|
+
this.buffer = '';
|
|
25
|
+
}
|
|
26
|
+
const codeBlockMarker = '\n```';
|
|
27
|
+
let markerIndex = content.indexOf(codeBlockMarker);
|
|
28
|
+
if (content.startsWith('```'))
|
|
29
|
+
markerIndex = 0;
|
|
30
|
+
if (markerIndex !== -1) {
|
|
31
|
+
if (this.isBufferingCode) {
|
|
32
|
+
// End of code block
|
|
33
|
+
this.codeBuffer += content.slice(0, markerIndex + codeBlockMarker.length);
|
|
34
|
+
const rest = content.slice(markerIndex + codeBlockMarker.length);
|
|
35
|
+
this.emit('endGeneratingCode');
|
|
36
|
+
this.emitCodeBlock();
|
|
37
|
+
this.emit('content', rest);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Start of code block
|
|
41
|
+
this.emitBuffer(content.slice(0, markerIndex));
|
|
42
|
+
this.codeBuffer = content.slice(markerIndex);
|
|
43
|
+
this.emit('startGeneratingCode');
|
|
44
|
+
this.isBufferingCode = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// No code block marker found
|
|
49
|
+
if (this.isBufferingCode) {
|
|
50
|
+
this.codeBuffer += content;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this.buffer += content;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (!this.isBufferingCode && this.buffer) {
|
|
57
|
+
this.emitBuffer();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
emitBuffer(additionalContent = '') {
|
|
61
|
+
const contentToEmit = this.buffer + additionalContent;
|
|
62
|
+
if (contentToEmit) {
|
|
63
|
+
this.emit('content', contentToEmit);
|
|
64
|
+
this.clearBuffer();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
emitCodeBlock() {
|
|
68
|
+
if (this.codeBuffer.length > 0) {
|
|
69
|
+
const codeParts = this.parseCodeBuffer();
|
|
70
|
+
if (codeParts) {
|
|
71
|
+
const { language, currentStart, newEnd, currentCode, newCode } = codeParts;
|
|
72
|
+
this.emit('codeBlock', {
|
|
73
|
+
language,
|
|
74
|
+
currentStart,
|
|
75
|
+
newEnd,
|
|
76
|
+
currentCode,
|
|
77
|
+
newCode,
|
|
78
|
+
raw: this.codeBuffer,
|
|
79
|
+
});
|
|
80
|
+
this.emit('content', this.buffer);
|
|
81
|
+
this.clearBuffer();
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
this.emit('content', this.codeBuffer);
|
|
85
|
+
this.clearBuffer();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parses a code buffer into its constituent parts.
|
|
91
|
+
*
|
|
92
|
+
* This function takes a code buffer as a string, splits it into lines, and identifies the language,
|
|
93
|
+
* current start index, divider index, and new end index. It then extracts the current code and new code
|
|
94
|
+
* from the buffer based on these indices.
|
|
95
|
+
*
|
|
96
|
+
* @return {{ language: string, currentStart: string, newEnd: string, current: string, newCode: string, afterCode: string }}
|
|
97
|
+
* An object containing the language, current start, new end, current code, and new code.
|
|
98
|
+
*/
|
|
99
|
+
parseCodeBuffer() {
|
|
100
|
+
const lines = this.codeBuffer.split('\n');
|
|
101
|
+
const language = lines[0].trim().slice(3); // Remove '```' from the language line
|
|
102
|
+
const currentStartIndex = lines.findIndex((line) => line.startsWith('<<<<<<< CURRENT'));
|
|
103
|
+
const dividerIndex = lines.findIndex((line) => line === '=======');
|
|
104
|
+
const newEndIndex = lines.findIndex((line) => line.startsWith('>>>>>>> NEW'));
|
|
105
|
+
if (currentStartIndex === -1 || dividerIndex === -1 || newEndIndex === -1) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const currentCode = lines.slice(currentStartIndex + 1, dividerIndex).join('\n');
|
|
109
|
+
const newCode = lines.slice(dividerIndex + 1, newEndIndex).join('\n');
|
|
110
|
+
return {
|
|
111
|
+
language,
|
|
112
|
+
currentStart: lines[currentStartIndex],
|
|
113
|
+
newEnd: lines[newEndIndex],
|
|
114
|
+
currentCode,
|
|
115
|
+
newCode,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
clearBuffer() {
|
|
119
|
+
this.buffer = '';
|
|
120
|
+
this.codeBuffer = '';
|
|
121
|
+
this.isBufferingCode = false;
|
|
122
|
+
this.isWaitingForContent = false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.default = BlockManager;
|