1+ function applyCodeInsertions(rootPath , jsonPath )
2+ % APPLYCODEINSERTIONS Apply code insertions/replacements described in JSON.
3+ % Skips any insertion if the same TAG is already present in the target file.
4+ %
5+ % applyCodeInsertions(rootPath, jsonPath)
6+ %
7+ % Inputs
8+ % rootPath - repository root (string)
9+ % jsonPath - path to JSON config (string)
10+ %
11+ % Behavior
12+ % - For each file entry in JSON, reads the file into memory and processes
13+ % insertions in ascending line order.
14+ % - Before applying an insertion/replacement that would add a TAG block,
15+ % searches the file for the start tag "<comment_style> TAG: <tag>".
16+ % If found, the insertion/replacement is skipped to avoid duplicate inserts.
17+ % - Writes updated file content with LF line endings.
18+
19+ % Load and decode the JSON configuration file
20+ jsonText = fileread(jsonPath );
21+ config = jsondecode(jsonText );
22+
23+ % Iterate over each file entry in the JSON
24+ for f = 1 : length(config .files )
25+ fileEntry = config .files(f );
26+
27+ % Convert relative path to platform-specific format
28+ relParts = strsplit(fileEntry .path , ' /' ); % Split path by '/'
29+ relPath = fullfile(relParts{: }); % Reconstruct using platform-specific separator
30+ filePath = fullfile(rootPath , relPath ); % Combine with root path
31+
32+ % Check if the file exists before attempting to modify
33+ if ~isfile(filePath )
34+ error(' File not found: %s ' , filePath );
35+ end
36+
37+ % Determine tag prefix from JSON or fallback to default
38+ if isfield(fileEntry , ' comment_style' )
39+ tagPrefix = strtrim(fileEntry .comment_style ); % Use specified comment style
40+ else
41+ tagPrefix = ' //' ; % Default to C/C++ style
42+ end
43+
44+ % Read the file content into a string array (one line per element)
45+ fileContent = readlines(filePath );
46+
47+ % Sort insertions by line number ascending
48+ % This ensures we apply edits top-to-bottom and can track line shifts correctly
49+ insertions = fileEntry .insertions ;
50+ [~ , idx ] = sort([insertions .line ]);
51+ insertions = insertions(idx );
52+
53+ % Initialize line shift tracker
54+ % This variable tracks how many lines have been added or removed
55+ % so that subsequent operations can adjust their target line numbers
56+ lineShift = 0 ;
57+
58+ % Process each insertion or replacement in order
59+ for i = 1 : length(insertions )
60+ ins = insertions(i );
61+ originalLine = ins .line ; % Line number from JSON
62+ adjustedLine = originalLine + lineShift ; % Adjusted for prior edits
63+
64+ codeBlock = string(ins .code ); % Convert code block to string array
65+ opType = lower(strtrim(ins .type )); % Normalize operation type
66+ tag = strtrim(ins .tag ); % Clean up tag string
67+
68+ % Wrap code block with tag markers using appropriate comment style
69+ startTagLine = strcat(tagPrefix , " TAG: " , tag );
70+ endTagLine = strcat(tagPrefix , " END TAG: " , tag );
71+ taggedBlock = [startTagLine ; string(codeBlock ); endTagLine ];
72+
73+ % If the tag already exists anywhere in the file, skip this insertion
74+ % We search for an exact line match of the start tag.
75+ tagExistsIdx = find(fileContent == startTagLine , 1 , ' first' );
76+ if ~isempty(tagExistsIdx )
77+ fprintf(' Skipping insertion for tag "%s " in %s : tag already present at line %d .\n ' , tag , filePath , tagExistsIdx );
78+ % Do not modify fileContent or lineShift; continue to next insertion
79+ continue ;
80+ end
81+
82+ % Apply the operation
83+ switch opType
84+ case " insert"
85+ % Insert the tagged block before the adjusted line
86+ fileContent = [fileContent(1 : adjustedLine - 1 ); taggedBlock ; fileContent(adjustedLine : end )];
87+ lineShift = lineShift + length(taggedBlock ); % Update shift by number of inserted lines
88+ fprintf(' Inserted tag "%s " into %s at line %d .\n ' , tag , filePath , adjustedLine );
89+
90+ case " replace"
91+ % Replace the adjusted line with the tagged block
92+ fileContent = [fileContent(1 : adjustedLine - 1 ); taggedBlock ; fileContent(adjustedLine + 1 : end )];
93+ lineShift = lineShift + length(taggedBlock ) - 1 ; % Update shift by net line change
94+ fprintf(' Replaced line %d in %s with tag "%s ".\n ' , adjustedLine , filePath , tag );
95+
96+ otherwise
97+ error(' Unknown operation type "%s " in file %s .' , opType , filePath );
98+ end
99+ end
100+
101+ % Write the modified content back to the original file
102+ writeLinesWithLF(fileContent , filePath );
103+ end
104+ end
105+
106+ function writeLinesWithLF(lines , filePath )
107+ % WRITELINESWITHLF Writes lines to a file using LF-only line endings.
108+ % This avoids platform-dependent CRLF endings (e.g., on Windows).
109+ fid = fopen(filePath , ' w' );
110+ if fid == - 1
111+ error(' Failed to open file: %s ' , filePath );
112+ end
113+
114+ for i = 1 : length(lines )-1
115+ fprintf(fid , ' %s\n ' , lines(i )); % Explicitly use \n for LF
116+ end
117+ % LF not needed for last line
118+ fprintf(fid , ' %s ' , lines(length(lines )));
119+ fclose(fid );
120+ end
0 commit comments