CodeEditorTagIdentation.diff

Current working version - Zbigniew Rebacz, 02/07/2016 06:02 PM

Download (11.6 KB)

View differences:

CodeEditor.h (kopia robocza)
141 141
	virtual ~EditorBar();
142 142
};
143 143

  
144
class Ident {
145
public:
146
	enum Type {
147
		Tab = 0,
148
		Space,
149
		Unknown
150
	};
151

  
152
public:
153
	static Type FindType(CodeEditor& editor);
154
	static Type FindType(const WString& line);
155
	static Type FindType(const WString& line, CodeEditor& editor);
156
	static int  FindSize(const WString& line, Ident::Type type);
157
	static int  FindSpaceSize(CodeEditor& editor);
158
	
159
	static char   GetChar(Ident::Type type);
160
	static String GetString(Ident::Type type, int identLevel = 1);
161
	
162
private:
163
	Ident();
164
	Ident(const Ident&);
165
	Ident& operator=(Ident&);
166
	~Ident();
167
};
168

  
144 169
struct IdentPos {
145 170
	int    begin;
146 171
	int    end;
CodeEditor.upp (kopia robocza)
29 29
	TagSyntax.h,
30 30
	TagSyntax.cpp,
31 31
	PythonSyntax readonly separator,
32
	PythonSyntax.h,
32 33
	PythonSyntax.cpp,
33
	PythonSyntax.h,
34 34
	LogSyntax readonly separator,
35 35
	LogSyntax.h,
36 36
	LogSyntax.cpp,
......
38 38
	EditorBar.cpp,
39 39
	FindReplace.cpp,
40 40
	Lang.cpp,
41
	Indent.cpp,
41 42
	CodeEditor.cpp,
42 43
	CodeEditor.lay,
43 44
	CodeEditor.iml,
44 45
	CodeEditor.t,
46
	Indent readonly separator,
47
	Indent.h,
45 48
	Info readonly separator,
46 49
	Copying;
47 50

  
PythonSyntax.cpp (kopia robocza)
70 70
{
71 71
	if(chr == '\n') {
72 72
		while(count--) {
73
			WString cursorLine = editor.GetWLine(editor.GetCursorLine());
73
			WString cline = editor.GetWLine(editor.GetCursorLine());
74 74
			editor.InsertChar('\n', 1);
75 75
			
76
			Identation::Type idType = FindIdentationType(editor, cursorLine);
77
			char idChar = GetIdentationByType(idType);
76
			Ident::Type identType = Ident::FindType(cline, editor);
77
			char identChar = Ident::GetChar(identType);
78 78
			int mult = 1;
79
			if(idType == Identation::Space)
80
				mult = CalculateSpaceIndetationSize(editor);
81
			if(LineHasColon(cursorLine))
82
				editor.InsertChar(idChar, mult);
83
			editor.InsertChar(idChar, CalculateLineIndetations(cursorLine, idType));
79
			if(identType == Ident::Space)
80
				mult = Ident::FindSpaceSize(editor);
81
			if(LineHasColon(cline))
82
				editor.InsertChar(identChar, mult);
83
			editor.InsertChar(identChar, Ident::FindSize(cline, identType));
84 84
		}
85 85
	}
86 86
	if(count > 0)
......
149 149
	return false;
150 150
}
151 151

  
152
int PythonSyntax::CalculateLineIndetations(const WString& line, Identation::Type type)
153
{
154
	int count = 0;
155
	for(int i = 0; i < line.GetLength(); i++) {
156
		if(type == Identation::Tab && line[i] == '\t')
157
			count++;
158
		else
159
		if(type == Identation::Space && line[i] == ' ')
160
			count++;
161
		else
162
			break;
163
	}
164
	return count;
165
}
166

  
167
PythonSyntax::Identation::Type PythonSyntax::FindIdentationType(CodeEditor& editor, const WString& line)
168
{
169
	Identation::Type type = Identation::None;
170
	if(line.StartsWith("\t"))
171
		type = Identation::Tab;
172
	else
173
	if(line.StartsWith(" "))
174
		type = Identation::Space;
175
	else {
176
		for(int i = 0; i < editor.GetLineCount(); i++) {
177
			WString cLine = editor.GetWLine(i);
178
			if(cLine.StartsWith("\t")) {
179
				type = Identation::Tab;
180
				break;
181
			}
182
			else
183
			if(cLine.StartsWith(" ")) {
184
				type = Identation::Space;
185
				break;
186
			}
187
		}
188
	}
189
	return type;
190
}
191

  
192
int PythonSyntax::CalculateSpaceIndetationSize(CodeEditor& editor)
193
{
194
	int current = 0;
195
	for(int i = 0; i < editor.GetLineCount(); i++) {
196
		WString line = editor.GetWLine(i);
197
		for(int j = 0; j < line.GetLength(); j++) {
198
			if(line[j] == ' ')
199
				current++;
200
			else
201
				break;
202
		}
203
		
204
		if(current > 0)
205
			break;
206
	}
207
	
208
	// TODO: 4 is magic numer - try to find the way to get this number from ide constants
209
	return current > 0 ? current : 4;
210
}
211

  
212
char PythonSyntax::GetIdentationByType(Identation::Type type)
213
{
214
	if(type == Identation::Space)
215
		return ' ';
216
	return '\t';
217
}
218

  
219 152
END_UPP_NAMESPACE
PythonSyntax.h (kopia robocza)
26 26
	void LoadSyntax(const char* keywordsArray[], const char* specialVarsArray[]);
27 27
	
28 28
	bool             LineHasColon(const WString& line);
29
	int              CalculateLineIndetations(const WString& line, Identation::Type type);
30
	int              CalculateSpaceIndetationSize(CodeEditor& editor);
31
	Identation::Type FindIdentationType(CodeEditor& editor, const WString& line);
32
	char             GetIdentationByType(Identation::Type type);
33 29
	
34 30
private:
35 31
	Index<String> keywords;
TagSyntax.cpp (kopia robocza)
8 8
	hout = NULL;
9 9
	html = true;
10 10
	witz = false;
11
	
12
	InitSpecialTags();
11 13
}
12 14

  
13 15
void TagSyntax::Clear()
......
278 280

  
279 281
void TagSyntax::IndentInsert(CodeEditor& editor, int chr, int count)
280 282
{
281
	if(status == SCRIPT)
283
	if(status == SCRIPT) {
282 284
		script.IndentInsert(editor, chr, count);
285
		return;
286
	}
287
	
288
	if(chr == '\n') {
289
		while(count--) {
290
			WString line = editor.GetWLine(editor.GetCursorLine());
291
			Ident::Type type = Ident::FindType(line);
292
			
293
			int currentLevel = Ident::FindSize(line, type);
294
			int newLevel = GetNewIdnetations(editor);
295
			int wholeLevel = currentLevel + newLevel;
296
			
297
			String afterCursor;
298
			if(newLevel > 0) {
299
				WString rightSide = GetCursorRightSide(editor);
300
				if(rightSide.StartsWith("<")) {
301
					afterCursor = "\n";
302
					for(int i = 0; i < wholeLevel - 1; i++)
303
						afterCursor += Ident::GetString(type);
304
				}
305
				else
306
				if(!rightSide.IsEmpty()) {
307
					wholeLevel = 0;
308
				}
309
			}
310
			
311
			editor.InsertChar('\n', 1);
312
			editor.InsertChar('\t', wholeLevel);
313
			editor.Insert(editor.GetCursor(), afterCursor);
314
		}
315
	}
283 316
	else
317
	if(count > 0)
284 318
		editor.InsertChar(chr, count);
285 319
}
286 320

  
......
291 325
	return false;
292 326
}
293 327

  
328
bool TagSyntax::HasHtmlTags() const
329
{
330
	return html || witz;
331
}
332

  
333
int TagSyntax::GetIdentationsLevel(CodeEditor& editor) const
334
{
335
	int level = 0;
336
	WString line = editor.GetWLine(editor.GetCursorLine());
337
	for(int i = 0; i < line.GetCount(); i++) {
338
		if(line[i] == '\t')
339
			level++;
340
		else
341
			break;
342
	}
343
	return level;
344
}
345

  
346
int TagSyntax::GetNewIdnetations(CodeEditor& editor) const
347
{
348
	int level = 0;
349
	
350
	WString leftSide = GetCursorLeftSide(editor);
351
	WString rightSide = GetCursorRightSide(editor);
352
	Vector< Tuple2<String, int> > types = SplitTagsByType(leftSide);
353
	for(int i = 0; i < types.GetCount(); i++) {
354
		if(types[i].b == TAG)
355
			level++;
356
		else
357
		if(types[i].b == ENDTAG) {
358
			if(level > 0)
359
				level--;
360
		}
361
	}
362
	if(IsCursorInsideTag(leftSide, rightSide))
363
		level++;
364
	
365
	if(level < 0)
366
		level++;
367
	
368
	return level;
369
}
370

  
371
Vector< Tuple2<String, int> > TagSyntax::SplitTagsByType(const WString& s) const
372
{
373
	Vector< Tuple2<String, int> > tags;
374
	
375
	wchar  strc;
376
	bool   isStr = false;
377
	bool   isTag = false;
378
	int    type = TAG;
379
	String name;
380
	for(int i = 0; i < s.GetCount(); i++) {
381
		wchar c = s[i];
382
		
383
		if(c == '\'' || c == '\"') {
384
			if(!isStr) {
385
				isStr = true;
386
				strc = c;
387
			}
388
			else
389
			if(isStr && c == strc)
390
				isStr = false;
391
		}
392
		else
393
		if(c == '<') {
394
			isTag = true;
395
			if(i + 1 >= s.GetCount())
396
				continue;
397
			wchar nc = s[i + 1];
398
			if(nc == '/') {
399
				type = ENDTAG;
400
				i++;
401
			}
402
			else
403
			if(nc == '!' || nc == '?') {
404
				type = TAG0;
405
				i++;
406
			}
407
			i++;
408
			name = FindTagName(s, i);
409
		}
410
		else
411
		if(c == '>') {
412
			if(!isTag || i - 1 < 0)
413
				continue;
414
			
415
			wchar pc = s[i - 1];
416
			if(pc == '/' && type == TAG)
417
				type = TAG0;
418
			
419
			if(HasHtmlTags() && type != TAG0) {
420
				if(htmlSpecialTags.Find(name) > -1)
421
					type = TAG0;
422
			}
423
			
424
			tags.Add(Tuple<String, int>(name, type));
425
			type = TAG;
426
			isTag = false;
427
		}
428
	}
429
	
430
	return tags;
431
}
432

  
433
String TagSyntax::FindTagName(const WString& str, int& i) const
434
{
435
	String name;
436
	while(i < str.GetCount()) {
437
		if(str[i] == ' ' || str[i] == '>' || str[i] == '/') {
438
			i--;
439
			break;
440
		}
441
		name += str[i];
442
		i++;
443
	}
444
	return name;
445
}
446

  
447
WString TagSyntax::GetCursorLeftSide(CodeEditor& editor) const
448
{
449
	int cursor = editor.GetCursor();
450
	int line = editor.GetLinePos(cursor);
451
	WString lineStr = editor.GetWLine(line);
452
	if(cursor < lineStr.GetCount())
453
		lineStr.Trim(cursor);
454
	return lineStr;
455
}
456

  
457
WString TagSyntax::GetCursorRightSide(CodeEditor& editor) const
458
{
459
	int cursor = editor.GetCursor();
460
	int line = editor.GetLinePos(cursor);
461
	WString lineStr = editor.GetWLine(line);
462
	if(cursor < lineStr.GetCount())
463
		lineStr.Remove(0, cursor);
464
	else
465
		lineStr = "";
466
	return lineStr;
467
}
468

  
469
bool TagSyntax::IsCursorInsideTag(WString& leftSide, WString& rightSide) const
470
{
471
	for(int i = leftSide.GetCount() - 1; i >= 0; i--) {
472
		wchar c = leftSide[i];
473
		
474
		if(c == '>') {
475
			break;
476
		}
477
		else
478
		if(c == '<') {
479
			return true;
480
		}
481
	}
482
	
483
	return false;
484
}
485

  
294 486
void TagSyntax::Serialize(Stream& s)
295 487
{
296 488
	s % hl_ink
......
302 494
	  % html;
303 495
}
304 496

  
497
void TagSyntax::InitSpecialTags()
498
{
499
	static const char* htmlSpecialTags[] = {
500
		"meta", "link",
501
		"br",
502
		NULL
503
	};
504
	
505
	InitHtmlSpecialTags(htmlSpecialTags);
506
}
507

  
508
void TagSyntax::InitHtmlSpecialTags(const char* specialTags[])
509
{
510
	htmlSpecialTags.Clear();
511
	while(*specialTags) {
512
		htmlSpecialTags.Add(*specialTags++);
513
	}
514
}
515

  
305 516
END_UPP_NAMESPACE
TagSyntax.h (kopia robocza)
1 1
class TagSyntax : public EditorSyntax { // Tag based languages (XML, HTML)
2 2
public:
3
	TagSyntax&  Html(bool b)                                    { html = b; return *this; }
4
	TagSyntax&  Witz(bool b)                                    { witz = b; return *this; }
5
	CSyntax *GetScript()                                        { return status == SCRIPT ? &script : NULL; }
6

  
7
	TagSyntax();
8
	
9
public:
3 10
	virtual void            Clear();
4 11
	virtual void            ScanSyntax(const wchar *ln, const wchar *e, int line, int tab_size);
5 12
	virtual void            Serialize(Stream& s);
......
10 17
	virtual bool            CheckBrackets(CodeEditor& e, int& bpos0, int& bpos);
11 18

  
12 19
private:
13

  
14 20
	enum { TEXT, TAG0, TAG, ENDTAG, ATTR, COMMENT, DECL, PI, SCRIPT };
15 21
	
16 22
	bool    html;
......
22 28

  
23 29
	CSyntax script;     // for <style> or <script>
24 30
	enum { CSS, JS };
25
	int     script_type; 
31
	int     script_type;
26 32

  
27 33
	HighlightOutput *hout;
28 34

  
......
35 41
	void Put(int n = 1)                                         { Put0(hl_ink, n, hl_paper); }
36 42
	void SetPut(int ink, int n = 1, int paper = PAPER_NORMAL)   { Set(ink, paper); Put(n); }
37 43

  
38
public:
39
	TagSyntax&  Html(bool b)                                    { html = b; return *this; }
40
	TagSyntax&  Witz(bool b)                                    { html = b; return *this; }
41
	CSyntax *GetScript()                                        { return status == SCRIPT ? &script : NULL; }
42

  
43
	TagSyntax();
44
private:
45
	bool HasHtmlTags() const;
46
	
47
private:
48
	int  GetIdentationsLevel(CodeEditor& editor) const;
49
	int  GetNewIdnetations(CodeEditor& editor) const;
50
	
51
	Vector< Tuple2<String, int> > SplitTagsByType(const WString& str) const;
52
	String                        FindTagName(const WString& str, int& i) const;
53
	
54
	WString GetCursorLeftSide(CodeEditor& editor) const;
55
	WString GetCursorRightSide(CodeEditor& editor) const;
56
	
57
	bool IsCursorInsideTag(WString& leftSide, WString& rightSide) const;
58
	
59
private:
60
	void InitSpecialTags();
61
	void InitHtmlSpecialTags(const char* specialTags[]);
62
	
63
private:
64
	Index<String> htmlSpecialTags;
44 65
};