/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. module cui.codebox;
  11. import cui.textbox;
  12. import djehuty;
  13. import io.console;
  14. class CuiCodeBox : CuiTextBox {
  15. // Constructors
  16. this(uint x, uint y, uint width, uint height) {
  17. super(x,y,width,height);
  18. }
  19. // Events
  20. override void onLineChanged(uint lineNumber) {
  21. // When a line is changed, look for language syntax features
  22. string line = _lines[lineNumber].value;
  23. // Reset formatting
  24. _lines[lineNumber].format = null;
  25. string work;
  26. int pos;
  27. int findPos;
  28. int currentRulePos = int.max;
  29. int currentRuleLength;
  30. int currentRule = int.max;
  31. // Keyword Parse
  32. do {
  33. currentRule = int.max;
  34. currentRulePos = int.max;
  35. foreach(i, rule; _rules) {
  36. work = Regex.eval(line, rule.regex);
  37. // Did it match?
  38. if (work !is null) {
  39. findPos = _position;
  40. if (findPos < currentRulePos) {
  41. currentRulePos = findPos;
  42. currentRuleLength = work.length;
  43. currentRule = i;
  44. }
  45. }
  46. }
  47. // If there was a match, format the line with the earliest
  48. if (currentRule != int.max) {
  49. findPos = currentRulePos;
  50. pos += findPos;
  51. addFormat(lineNumber, pos, currentRuleLength, _rules[currentRule].forecolor, _rules[currentRule].backcolor);
  52. pos += currentRuleLength;
  53. findPos += currentRuleLength;
  54. line = line.substring(findPos);
  55. }
  56. } while (currentRule != int.max)
  57. }
  58. // Properties
  59. private:
  60. void addFormat(uint lineNumber, uint firstPos, uint length, Color forecolor, Color backcolor) {
  61. if (_lines[lineNumber].format is null) {
  62. // Simply add
  63. _lines[lineNumber].format = [
  64. new LineFormat(_forecolor, _backcolor, firstPos),
  65. new LineFormat(forecolor, backcolor, length),
  66. new LineFormat(_forecolor, _backcolor, _lines[lineNumber].value.length - (firstPos + length))
  67. ];
  68. }
  69. else {
  70. LineFormat[] newFormat;
  71. uint last;
  72. uint pos;
  73. uint formatIdx;
  74. for (uint idx = 0; idx < _lines[lineNumber].format.length; idx++) {
  75. pos += _lines[lineNumber].format[idx].len;
  76. if (pos > firstPos) {
  77. formatIdx = idx;
  78. break;
  79. }
  80. last = pos;
  81. }
  82. // Split format at firstPos
  83. newFormat = _lines[lineNumber].format[0..formatIdx+1];
  84. newFormat[formatIdx+1].len = firstPos - last;
  85. newFormat ~= [new LineFormat(forecolor, backcolor, length)];
  86. newFormat ~= _lines[lineNumber].format[formatIdx..formatIdx+1];
  87. newFormat[formatIdx+2].len = pos - (firstPos + length);
  88. _lines[lineNumber].format = newFormat;
  89. }
  90. }
  91. struct SyntaxRule {
  92. string regex;
  93. Color forecolor;
  94. Color backcolor;
  95. }
  96. SyntaxRule[] _rules = [
  97. // Line Comments
  98. // { `//([^\n\r]*)`, Color.Green, Color.Black},
  99. // Block Comments
  100. // { `/\*([^\*](?:\*[^/])?)*(?:\*/)?`, Color.Green, Color.Black},
  101. // Double Quote strings
  102. // { `"((?:[^\\"](?:\\.)?)*)"?`, Color.Magenta, Color.Black},
  103. // Keywords
  104. { `\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 },
  105. // Operators
  106. // { `[\(\)]+`, Color.Red, Color.Black}
  107. ];
  108. }