PageRenderTime 17ms CodeModel.GetById 1ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/cui/codebox.d

http://github.com/wilkie/djehuty
D | 134 lines | 80 code | 26 blank | 28 comment | 10 complexity | 9c6099e58d15fc6b0f2513511f0ce044 MD5 | raw file
  1/*
  2 * codebox.d
  3 *
  4 * This module implements a code aware text-editor TUI widget.
  5 *
  6 * Author: Dave Wilkinson
  7 * Originated: August 6th, 2009
  8 *
  9 */
 10
 11module cui.codebox;
 12
 13import cui.textbox;
 14
 15import djehuty;
 16
 17import io.console;
 18
 19class CuiCodeBox : CuiTextBox {
 20
 21	// Constructors
 22
 23	this(uint x, uint y, uint width, uint height) {
 24		super(x,y,width,height);
 25	}
 26
 27	// Events
 28
 29	override void onLineChanged(uint lineNumber) {
 30		// When a line is changed, look for language syntax features
 31		string line = _lines[lineNumber].value;
 32
 33		// Reset formatting
 34		_lines[lineNumber].format = null;
 35
 36		string work;
 37		int pos;
 38		int findPos;
 39
 40		int currentRulePos = int.max;
 41		int currentRuleLength;
 42		int currentRule = int.max;
 43
 44		// Keyword Parse
 45		do {
 46			currentRule = int.max;
 47			currentRulePos = int.max;
 48
 49			foreach(i, rule; _rules) {
 50				work = Regex.eval(line, rule.regex);
 51
 52				// Did it match?
 53				if (work !is null) {
 54					findPos = _position;
 55					if (findPos < currentRulePos) {
 56						currentRulePos = findPos;
 57						currentRuleLength = work.length;
 58						currentRule = i;
 59					}
 60				}
 61			}
 62
 63			// If there was a match, format the line with the earliest
 64			if (currentRule != int.max) {
 65				findPos = currentRulePos;
 66				pos += findPos;
 67
 68				addFormat(lineNumber, pos, currentRuleLength, _rules[currentRule].forecolor, _rules[currentRule].backcolor);
 69
 70				pos += currentRuleLength;
 71				findPos += currentRuleLength;
 72				line = line.substring(findPos);
 73			}
 74		} while (currentRule != int.max)
 75	}
 76
 77	// Properties
 78
 79private:
 80
 81	void addFormat(uint lineNumber, uint firstPos, uint length, Color forecolor, Color backcolor) {
 82		if (_lines[lineNumber].format is null) {
 83			// Simply add
 84			_lines[lineNumber].format = [
 85				new LineFormat(_forecolor, _backcolor, firstPos),
 86				new LineFormat(forecolor, backcolor, length),
 87				new LineFormat(_forecolor, _backcolor, _lines[lineNumber].value.length - (firstPos + length))
 88			];
 89		}
 90		else {
 91			LineFormat[] newFormat;
 92
 93			uint last;
 94			uint pos;
 95			uint formatIdx;
 96			for (uint idx = 0; idx < _lines[lineNumber].format.length; idx++) {
 97				pos += _lines[lineNumber].format[idx].len;
 98				if (pos > firstPos) {
 99					formatIdx = idx;
100					break;
101				}
102				last = pos;
103			}
104
105			// Split format at firstPos
106			newFormat = _lines[lineNumber].format[0..formatIdx+1];
107			newFormat[formatIdx+1].len = firstPos - last;
108			newFormat ~= [new LineFormat(forecolor, backcolor, length)];
109			newFormat ~= _lines[lineNumber].format[formatIdx..formatIdx+1];
110			newFormat[formatIdx+2].len = pos - (firstPos + length);
111
112			_lines[lineNumber].format = newFormat;
113		}
114	}
115
116	struct SyntaxRule {
117		string regex;
118		Color forecolor;
119		Color backcolor;
120	}
121
122	SyntaxRule[] _rules = [
123		// Line Comments
124//		{ `//([^\n\r]*)`, Color.Green, Color.Black},
125		// Block Comments
126//		{ `/\*([^\*](?:\*[^/])?)*(?:\*/)?`, Color.Green, Color.Black},
127		// Double Quote strings
128//		{ `"((?:[^\\"](?:\\.)?)*)"?`, Color.Magenta, Color.Black},
129		// Keywords
130		{ `\b(abstract|alias|align|asm|assert|auto|body|bool|break|byte|case|cast|catch|cdouble|cent|cfloat|char|class|const|continue|creal|dchar|debug|default|delegate|delete|deprecated|do|double|else|enum|export|extern|false|final|finally|float|for|foreach|foreach_reverse|function|goto|idouble|if|ifloat|import|in|inout|int|interface|invariant|ireal|is|lazy|long|macro|mixin|module|new|null|out|override|package|pragma|private|protected|public|real|ref|return|scope|short|static|struct|super|switch|synchronized|template|this|throw|__traits|true|try|typedef|typeof|ubyte|ucent|uint|ulong|union|unittest|ushort|version|void|volatile|wchar|while|with)\b`, Color.Blue, Color.Black },
131		// Operators
132//		{ `[\(\)]+`, Color.Red, Color.Black}
133	];
134}