2828#include " utils-renumber.h"
2929
3030
31+ #define APOSTROPHE_COMMENT_REGEXPR " \\ '[^\\ n\\ ']*[\\ ']?"
32+ #define GCODE_COMMENT_REGEXPR " \\ ([^\\ n\\ )]*[\\ )]?"
33+ #define N_MARK_REGEXPR " ^([ \\ t]*N\\ b[ \\ t]*)"
34+ #define N_WORD_REGEXPR " ([ \\ t]*N([0-9 \\ t]*[0-9])[ \\ t]*)"
35+ #define SINUMERIK_COMMENT_REGEXPR " ;[^\\ n]*"
36+
37+
3138bool Utils::renumber (QString& text, const RenumberOptions& opt, const std::function<bool (int )>& interrupt)
3239{
3340 bool changed = false ;
3441 QString result;
3542 int num = opt.startAt ;
43+ int width = opt.applyWidth ? opt.width : 0 ;
3644 int substr_start = 0 ;
3745 int substr_end = 0 ;
3846
@@ -48,19 +56,19 @@ bool Utils::renumber(QString& text, const RenumberOptions& opt, const std::funct
4856
4957 switch (opt.mode ) {
5058 case RenumberOptions::RenumberWithN:
51- localChange = renumberWithN (line, num, opt);
59+ localChange = renumberWithN (line, num, width, opt. from , opt. to , opt. renumMarked );
5260 break ;
5361
5462 case RenumberOptions::RenumberAll:
55- localChange = renumberAll (line, num, opt);
63+ localChange = renumberAll (line, num, width, opt. renumEmpty , opt. renumComm , true );
5664 break ;
5765
5866 case RenumberOptions::RemoveAll:
59- localChange = renumberRemoveAll (line);
67+ localChange = renumberRemoveAll (line, true );
6068 break ;
6169
6270 case RenumberOptions::RenumberWithoutN:
63- localChange = renumberWithoutN (line, num, opt);
71+ localChange = renumberWithoutN (line, num, width, opt. renumEmpty );
6472 break ;
6573
6674 default :
@@ -79,189 +87,171 @@ bool Utils::renumber(QString& text, const RenumberOptions& opt, const std::funct
7987 return changed;
8088}
8189
82- bool Utils::renumberWithoutN (QString& line, int num, const RenumberOptions& opt )
90+ bool Utils::renumberWithoutN (QString& line, int num, int width, bool renumAll )
8391{
84- bool changed = false ;
85- QString i_tx;
86- QRegularExpression regex;
87-
88- regex.setPatternOptions (QRegularExpression::CaseInsensitiveOption);
89- regex.setPattern (" ^[0-9]{1,9}\\ s\\ s" );
90-
91- i_tx = QString (" %1" ).arg (num, opt.width );
92- i_tx.replace (QLatin1Char (' ' ), QLatin1Char (' 0' ));
93- i_tx += " " ;
94-
95- auto match = regex.match (line);
92+ static QRegularExpression regex{
93+ " ^([0-9]{1,9}[ \\ t]{2,2})" ,
94+ QRegularExpression::CaseInsensitiveOption
95+ };
96+ QRegularExpressionMatch&& match = regex.match (line);
97+ QString n_word = QString (" %1 " ).arg (num, width, 10 , QLatin1Char{' ' });
9698
9799 if (match.hasMatch ()) {
98- line.replace (match.capturedStart (), match.capturedLength (), i_tx);
99- changed = true ;
100+ line.replace (match.capturedStart (1 ), match.capturedLength (1 ), n_word);
101+ } else if (renumAll) {
102+ line.insert (0 , n_word);
100103 } else {
101- if (opt.renumEmpty ) {
102- line.insert (0 , i_tx);
103- changed = true ;
104- }
104+ return false ;
105105 }
106106
107- return changed ;
107+ return true ;
108108}
109109
110- bool Utils::renumberWithN (QString& line, int num, const RenumberOptions& opt )
110+ bool Utils::renumberWithN (QString& line, int num, int width, int from, int to, bool renumMarked )
111111{
112- bool changed = false ;
113- int pos;
114- long int i, it;
115- QString f_tx;
116- QRegularExpression regex;
117- bool ok, insertSpace;
118-
119- pos = 0 ;
120- regex.setPatternOptions (QRegularExpression::CaseInsensitiveOption);
121- regex.setPattern (" [N]{1,1}[0-9\\ s]+|\\ ([^\\ n\\ r]*\\ )|\' [^\\ n\\ r]*\' |;[^\\ n\\ r]*" );
122- auto match = regex.match (line);
123-
124- while (match.hasMatch ()) {
125- pos = match.capturedStart ();
126- f_tx = match.captured ();
127-
128- // qDebug() << f_tx;
129-
130- if (pos > 0 )
131- if (line[pos - 1 ].isLetterOrNumber ()) {
132- pos = match.capturedEnd ();
133- continue ;
134- }
135-
136- insertSpace = true ;
137-
138- if (f_tx.endsWith (QLatin1Char (' ' ))) {
139- insertSpace = false ;
140- }
141-
142- if (!f_tx.contains (QLatin1Char (' ' )) && !f_tx.contains (QLatin1Char (' \n ' ))) {
143- i = match.capturedLength ();
144- } else {
145- i = match.capturedLength () - 1 ;
112+ static QRegularExpression check_num{
113+ N_WORD_REGEXPR // groups 1 and 2
114+ " |"
115+ N_MARK_REGEXPR // group 3
116+ " |"
117+ GCODE_COMMENT_REGEXPR
118+ " |"
119+ APOSTROPHE_COMMENT_REGEXPR
120+ " |"
121+ SINUMERIK_COMMENT_REGEXPR,
122+ QRegularExpression::CaseInsensitiveOption
123+ };
124+ QRegularExpressionMatch&& match = check_num.match (line);
125+ bool num_captured = match.capturedLength (2 ) > 0 ;
126+ bool mark_captured = match.capturedLength (3 ) > 0 ;
127+
128+ if (num_captured) {
129+ QString digits = match.captured (2 );
130+ digits.remove (' ' );
131+ digits.remove (' \t ' );
132+ int current = digits.toInt ();
133+
134+ if (current < from || current > to) {
135+ return false ;
146136 }
147137
148- if (!f_tx.contains (QLatin1Char (' (' )) && !f_tx.contains (QLatin1Char (' \' ' ))
149- && !f_tx.contains (QLatin1Char (' ;' ))) {
150- f_tx.remove (0 , 1 );
151- f_tx.remove (QLatin1Char (' ' ));
152-
153- if (!f_tx.isEmpty ()) {
154- it = f_tx.toInt (&ok);
155- } else {
156- it = 0 ;
157- }
158-
159- if (((it >= opt.from ) || (opt.renumMarked && it == 0 )) && (it < opt.to )) {
160- f_tx = QString (QLatin1String (" N%1" )).arg (num, opt.width );
161- f_tx.replace (QLatin1Char (' ' ), QLatin1Char (' 0' ));
138+ line.remove (match.capturedStart (1 ), match.capturedLength (1 ));
139+ } else if (mark_captured && renumMarked) {
140+ line.remove (match.capturedStart (3 ), match.capturedLength (3 ));
162141
163- if (insertSpace) {
164- f_tx.append (QLatin1String (" " ));
165- }
166-
167- line.replace (pos, i, f_tx);
168- changed = true ;
169- }
142+ // The regular expression N_MARK_REGEXPR can capture the end-of-line character.
143+ if (line.isEmpty ()) {
144+ line.append (' \n ' );
170145 }
171-
172- match = regex. match (line, match. capturedEnd ()) ;
146+ } else {
147+ return false ;
173148 }
174149
175- return changed;
150+ insertNWord (line, num, width);
151+ return true ;
176152}
177153
178- bool Utils::renumberAll (QString& line, int num, const RenumberOptions& opt )
154+ bool Utils::renumberAll (QString& line, int num, int width, bool renumEmpty, bool renumComm, bool keepExisting )
179155{
180- int pos;
181- QString f_tx, i_tx;
182- QRegularExpression regex;
183-
184- regex.setPatternOptions (QRegularExpression::CaseInsensitiveOption);
185- regex.setPattern (" [Nn]{1,1}[0-9]+[\\ s]{0,}|\\ ([^\\ n\\ r]*\\ )|\' [^\\ n\\ r]*\' |;[^\\ n\\ r]*" );
156+ bool changed = false ;
157+ static QRegularExpression check_num{
158+ " ^[ \\ t]*(:|%|\\ $|O|PM\\ W)" // group 1
159+ " |"
160+ N_WORD_REGEXPR // groups 2 and 3
161+ " |"
162+ N_MARK_REGEXPR // group 4
163+ " |"
164+ GCODE_COMMENT_REGEXPR
165+ " |"
166+ APOSTROPHE_COMMENT_REGEXPR
167+ " |"
168+ SINUMERIK_COMMENT_REGEXPR,
169+ QRegularExpression::CaseInsensitiveOption
170+ };
171+ QRegularExpressionMatch&& match = check_num.match (line);
172+ bool stop_captured = match.capturedLength (1 ) > 0 ;
173+ bool num_captured = match.capturedLength (2 ) > 0 ;
174+ bool mark_captured = match.capturedLength (4 ) > 0 ;
175+
176+ // Exit if line start with ':', '%', '$', 'O' or 'PM'
177+ // TODO: add signatures for blocks that cannot be numbered
178+ if (stop_captured) {
179+ return false ;
180+ }
186181
187- pos = 0 ;
182+ if (num_captured) {
183+ line.remove (match.capturedStart (2 ), match.capturedLength (2 ));
184+ changed = true ;
185+ } else if (mark_captured) {
186+ line.remove (match.capturedStart (4 ), match.capturedLength (4 ));
187+ changed = true ;
188188
189- if ( line. isEmpty ()) {
190- if (!opt. renumEmpty ) {
191- return false ;
189+ // The regular expression N_MARK_REGEXPR can capture the end-of- line character.
190+ if (line. isEmpty () ) {
191+ line. append ( ' \n ' ) ;
192192 }
193-
194- f_tx = QString (QLatin1String (" N%1" )).arg (num, opt.width );
195- f_tx.replace (QLatin1Char (' ' ), QLatin1Char (' 0' ));
196- line.insert (0 , f_tx);
197- return true ;
198193 }
199194
200- auto match = regex.match (line, pos);
201-
202- if (match.hasMatch () && (line.at (0 ) != QLatin1Char (' $' ))) {
203- pos = match.capturedStart ();
204- i_tx = match.captured ();
205- i_tx.remove (' \n ' );
206-
207- if ((!i_tx.contains (QLatin1Char (' (' )) && !i_tx.contains (QLatin1Char (' \' ' ))
208- && !i_tx.contains (QLatin1Char (' ;' )))) {
209- f_tx = QString (QLatin1String (" N%1" )).arg (num, opt.width );
210- f_tx.replace (QLatin1Char (' ' ), QLatin1Char (' 0' ));
211- f_tx.append (QLatin1String (" " ));
212- line.replace (i_tx, f_tx);
213- return true ;
214- } else if (opt.renumComm ) {
215- return false ;
216- }
195+ static QRegularExpression check_empty{
196+ " ([A-Z@#])" // group 1
197+ " |"
198+ " (" GCODE_COMMENT_REGEXPR " )" // group 2
199+ " |"
200+ " (" APOSTROPHE_COMMENT_REGEXPR " )" // group 3
201+ " |"
202+ " (" SINUMERIK_COMMENT_REGEXPR " )" , // group 4
203+ QRegularExpression::CaseInsensitiveOption
204+ };
205+ match = check_empty.match (line);
206+ bool not_empty = match.capturedLength (1 ) > 0 ;
207+ bool comments_captured = match.capturedLength (2 ) > 0 || match.capturedLength (3 ) > 0 || match.capturedLength (4 ) > 0 ;
208+ bool insert = ((num_captured || mark_captured) && keepExisting) || not_empty || renumEmpty || (renumComm
209+ && comments_captured);
210+
211+ if (insert) {
212+ insertNWord (line, num, width);
213+ changed = true ;
217214 }
218215
219- if ((line.at (0 ) == QLatin1Char (' N' )) && (!line.at (1 ).isLetter ())) {
220- f_tx = QString (QLatin1String (" N%1" )).arg (num, opt.width );
221- f_tx.replace (QLatin1Char (' ' ), QLatin1Char (' 0' ));
222- f_tx.append (QLatin1String (" " ));
223- line.replace (0 , 1 , f_tx);
224- return true ;
225- }
216+ return changed;
217+ }
226218
227- if (((line.at (0 ) != QLatin1Char (' %' )) && (line.at (0 ) != QLatin1Char (' :' ))
228- && (line.at (0 ) != QLatin1Char (' O' )) && (line.at (0 ) != QLatin1Char (' $' )))) {
229- f_tx = QString (QLatin1String (" N%1" )).arg (num, opt.width );
230- f_tx.replace (QLatin1Char (' ' ), QLatin1Char (' 0' ));
231- f_tx.append (QLatin1String (" " ));
232- line.insert (0 , f_tx);
233- return true ;
219+ bool Utils::renumberRemoveAll (QString& line, bool removeMarked)
220+ {
221+ static QRegularExpression check_num{
222+ N_WORD_REGEXPR // group 1 and 2
223+ " |"
224+ N_MARK_REGEXPR // group 3
225+ " |"
226+ GCODE_COMMENT_REGEXPR
227+ " |"
228+ APOSTROPHE_COMMENT_REGEXPR
229+ " |"
230+ SINUMERIK_COMMENT_REGEXPR,
231+ QRegularExpression::CaseInsensitiveOption
232+ };
233+ QRegularExpressionMatch&& match = check_num.match (line);
234+ bool num_captured = match.capturedLength (1 ) > 0 ;
235+ bool mark_captured = match.capturedLength (3 ) > 0 ;
236+
237+ if (num_captured) {
238+ line.remove (match.capturedStart (1 ), match.capturedLength (1 ));
239+ } else if (mark_captured && removeMarked) {
240+ line.remove (match.capturedStart (3 ), match.capturedLength (3 ));
241+ } else {
242+ return false ;
234243 }
235244
236- return false ;
245+ return true ;
237246}
238247
239- bool Utils::renumberRemoveAll (QString& line)
248+ void Utils::insertNWord (QString& line, int num, int width )
240249{
241- bool changed = false ;
242- QString f_tx;
243- QRegularExpression regex;
244-
245- regex.setPatternOptions (QRegularExpression::CaseInsensitiveOption);
246- regex.setPattern (" [N]{1,1}[0-9\\ s]+|\\ ([^\\ n\\ r]*\\ )|\' [^\\ n\\ r]*\' |;[^\\ n\\ r]*" );
247- auto match = regex.match (line);
250+ QString n_word = QString (QLatin1String (" N%1" )).arg (num, width, 10 , QLatin1Char{' 0' });
248251
249- while (match.hasMatch ()) {
250- int pos = match.capturedStart ();
251- f_tx = match.captured ();
252-
253- // qDebug() << f_tx;
254-
255- if (!f_tx.contains (QLatin1Char (' (' )) && !f_tx.contains (QLatin1Char (' \' ' ))
256- && !f_tx.contains (QLatin1Char (' ;' ))) {
257- line.remove (pos, match.capturedLength ());
258- changed = true ;
259- } else {
260- pos = match.capturedEnd ();
261- }
262-
263- match = regex.match (line, pos);
252+ if (line.size () > 0 && line.at (0 ) != ' \n ' ) {
253+ n_word.append (' ' );
264254 }
265255
266- return changed ;
256+ line. prepend (n_word) ;
267257}
0 commit comments