-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathIniLexer.cs
More file actions
210 lines (156 loc) · 6.59 KB
/
IniLexer.cs
File metadata and controls
210 lines (156 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#region Using Directives
using System;
using System.Drawing;
using ScintillaNET;
#endregion Using Directives
namespace WeCode1._0
{
// A helper class to use the Scintilla container as an INI lexer.
// We'll ignore the fact that SciLexer.DLL already has an INI capable lexer. ;)
internal sealed class IniLexer
{
#region Constants
private const int EOL = -1;
// SciLexer's weird choice for a default style _index
private const int DEFAULT_STYLE = 32;
// Our custom styles (indexes chosen not to conflict with anything else)
private const int KEY_STYLE = 11;
private const int VALUE_STYLE = 12;
private const int ASSIGNMENT_STYLE = 13;
private const int SECTION_STYLE = 14;
private const int COMMENT_STYLE = 15;
private const int QUOTED_STYLE = 16;
#endregion Constants
#region Fields
private Scintilla _scintilla;
private int _startPos;
private int _index;
private string _text;
#endregion Fields
#region Methods
public static void Init(Scintilla scintilla)
{
// Reset any current language and enable the StyleNeeded
// event by setting the lexer to container.
scintilla.Indentation.SmartIndentType = SmartIndent.None;
scintilla.ConfigurationManager.Language = String.Empty;
scintilla.Lexing.LexerName = "container";
scintilla.Lexing.Lexer = Lexer.Container;
// Add our custom styles to the collection
scintilla.Styles[QUOTED_STYLE].ForeColor = Color.FromArgb(153, 51, 51);
scintilla.Styles[KEY_STYLE].ForeColor = Color.FromArgb(0, 0, 153);
scintilla.Styles[ASSIGNMENT_STYLE].ForeColor = Color.OrangeRed;
scintilla.Styles[VALUE_STYLE].ForeColor = Color.FromArgb(102, 0, 102);
scintilla.Styles[COMMENT_STYLE].ForeColor = Color.FromArgb(102, 102, 102);
scintilla.Styles[SECTION_STYLE].ForeColor = Color.FromArgb(0, 0, 102);
scintilla.Styles[SECTION_STYLE].Bold = true;
}
private int Read()
{
if (_index < _text.Length)
return _text[_index];
return EOL;
}
private void SetStyle(int style, int length)
{
if (length > 0)
{
// TODO Still using old API
// This will style the _length of chars and advance the style pointer.
((INativeScintilla)_scintilla).SetStyling(length, style);
}
}
public void Style()
{
// TODO Still using the old API
// Signals that we're going to begin styling from this point.
((INativeScintilla)_scintilla).StartStyling(_startPos, 0x1F);
// Run our humble lexer...
StyleWhitespace();
switch(Read())
{
case '[':
// Section, default, comment
StyleUntilMatch(SECTION_STYLE, new char[] { ']' });
StyleCh(SECTION_STYLE);
StyleUntilMatch(DEFAULT_STYLE, new char[] { ';' });
goto case ';';
case ';':
// Comment
SetStyle(COMMENT_STYLE, _text.Length - _index);
break;
default:
// Key, assignment, quote, value, comment
StyleUntilMatch(KEY_STYLE, new char[] { '=', ';' });
switch (Read())
{
case '=':
// Assignment, quote, value, comment
StyleCh(ASSIGNMENT_STYLE);
switch (Read())
{
case '"':
// Quote
StyleCh(QUOTED_STYLE); // '"'
StyleUntilMatch(QUOTED_STYLE, new char[] { '"' });
// Make sure it wasn't an escaped quote
if (_index > 0 && _index < _text.Length && _text[_index - 1] == '\\')
goto case '"';
StyleCh(QUOTED_STYLE); // '"'
goto default;
default:
// Value, comment
StyleUntilMatch(VALUE_STYLE, new char[] { ';' });
SetStyle(COMMENT_STYLE, _text.Length - _index);
break;
}
break;
default: // ';', EOL
// Comment
SetStyle(COMMENT_STYLE, _text.Length - _index);
break;
}
break;
}
}
private void StyleCh(int style)
{
// Style just one char and advance
SetStyle(style, 1);
_index++;
}
public static void StyleNeeded(Scintilla scintilla, Range range)
{
// Create an instance of our lexer and bada-bing the line!
IniLexer lexer = new IniLexer(scintilla, range.Start, range.StartingLine.Length);
lexer.Style();
}
private void StyleUntilMatch(int style, char[] chars)
{
// Advance until we match a char in the array
int startIndex = _index;
while (_index < _text.Length && Array.IndexOf<char>(chars, _text[_index]) < 0)
_index++;
if (startIndex != _index)
SetStyle(style, _index - startIndex);
}
private void StyleWhitespace()
{
// Advance the _index until non-whitespace character
int startIndex = _index;
while (_index < _text.Length && Char.IsWhiteSpace(_text[_index]))
_index++;
SetStyle(DEFAULT_STYLE, _index - startIndex);
}
#endregion Methods
#region Constructors
private IniLexer(Scintilla scintilla, int startPos, int length)
{
this._scintilla = scintilla;
this._startPos = startPos;
// One line of _text
this._text = scintilla.GetRange(startPos, startPos + length).Text;
}
#endregion Constructors
}
}