1 module dlangide.ui.dsourceedit; 2 3 /// DIDE source file editor 4 class DSourceEdit : SourceEdit { 5 this(string ID) { 6 super(ID); 7 styleId = null; 8 backgroundColor = 0xFFFFFF; 9 setTokenHightlightColor(TokenCategory.Comment, 0x008000); // green 10 setTokenHightlightColor(TokenCategory.Keyword, 0x0000FF); // blue 11 setTokenHightlightColor(TokenCategory.String, 0xA31515); // brown 12 setTokenHightlightColor(TokenCategory.Character, 0xA31515); // brown 13 setTokenHightlightColor(TokenCategory.Error, 0xFF0000); // red 14 setTokenHightlightColor(TokenCategory.Comment_Documentation, 0x206000); 15 //setTokenHightlightColor(TokenCategory.Identifier, 0x206000); // no colors 16 } 17 this() { 18 this("SRCEDIT"); 19 } 20 protected ProjectSourceFile _projectSourceFile; 21 @property ProjectSourceFile projectSourceFile() { return _projectSourceFile; } 22 /// load by filename 23 override bool load(string fn) { 24 _projectSourceFile = null; 25 bool res = super.load(fn); 26 setHighlighter(); 27 return res; 28 } 29 30 void setHighlighter() { 31 if (filename.endsWith(".d") || filename.endsWith(".dd") || filename.endsWith(".dh") || filename.endsWith(".ddoc")) { 32 content.syntaxHighlighter = new SimpleDSyntaxHighlighter(filename); 33 } else { 34 content.syntaxHighlighter = null; 35 } 36 } 37 38 /// load by project item 39 bool load(ProjectSourceFile f) { 40 if (!load(f.filename)) { 41 _projectSourceFile = null; 42 return false; 43 } 44 _projectSourceFile = f; 45 setHighlighter(); 46 return true; 47 } 48 } 49 50 51 52 class SimpleDSyntaxHighlighter : SyntaxHighlighter { 53 54 SourceFile _file; 55 ArraySourceLines _lines; 56 Tokenizer _tokenizer; 57 this (string filename) { 58 _file = new SourceFile(filename); 59 _lines = new ArraySourceLines(); 60 _tokenizer = new Tokenizer(_lines); 61 _tokenizer.errorTolerant = true; 62 } 63 64 TokenPropString[] _props; 65 66 /// categorize characters in content by token types 67 void updateHighlight(dstring[] lines, TokenPropString[] props, int changeStartLine, int changeEndLine) { 68 Log.d("updateHighlight"); 69 long ms0 = currentTimeMillis(); 70 _props = props; 71 changeStartLine = 0; 72 changeEndLine = lines.length; 73 _lines.init(lines[changeStartLine..$], _file, changeStartLine); 74 _tokenizer.init(_lines); 75 int tokenPos = 0; 76 int tokenLine = 0; 77 ubyte category = 0; 78 try { 79 for (;;) { 80 Token token = _tokenizer.nextToken(); 81 if (token is null) { 82 //Log.d("Null token returned"); 83 break; 84 } 85 if (token.type == TokenType.EOF) { 86 //Log.d("EOF token"); 87 break; 88 } 89 uint newPos = token.pos - 1; 90 uint newLine = token.line - 1; 91 92 //Log.d("", token.line, ":", token.pos, "\t", tokenLine + 1, ":", tokenPos + 1, "\t", token.toString); 93 94 // fill with category 95 for (int i = tokenLine; i <= newLine; i++) { 96 int start = i > tokenLine ? 0 : tokenPos; 97 int end = i < newLine ? lines[i].length : newPos; 98 for (int j = start; j < end; j++) 99 _props[i][j] = category; 100 } 101 102 // handle token - convert to category 103 switch(token.type) { 104 case TokenType.COMMENT: 105 category = token.isDocumentationComment ? TokenCategory.Comment_Documentation : TokenCategory.Comment; 106 break; 107 case TokenType.KEYWORD: 108 category = TokenCategory.Keyword; 109 break; 110 case TokenType.IDENTIFIER: 111 category = TokenCategory.Identifier; 112 break; 113 case TokenType.STRING: 114 category = TokenCategory.String; 115 break; 116 case TokenType.CHARACTER: 117 category = TokenCategory.Character; 118 break; 119 case TokenType.INTEGER: 120 category = TokenCategory.Integer; 121 break; 122 case TokenType.FLOAT: 123 category = TokenCategory.Float; 124 break; 125 case TokenType.INVALID: 126 switch (token.invalidTokenType) { 127 case TokenType.IDENTIFIER: 128 category = TokenCategory.Error_InvalidIdentifier; 129 break; 130 case TokenType.STRING: 131 category = TokenCategory.Error_InvalidString; 132 break; 133 case TokenType.COMMENT: 134 category = TokenCategory.Error_InvalidComment; 135 break; 136 case TokenType.FLOAT: 137 case TokenType.INTEGER: 138 category = TokenCategory.Error_InvalidNumber; 139 break; 140 default: 141 category = TokenCategory.Error; 142 break; 143 } 144 break; 145 default: 146 category = 0; 147 break; 148 } 149 tokenPos = newPos; 150 tokenLine= newLine; 151 152 } 153 } catch (Exception e) { 154 Log.e("exception while trying to parse D source", e); 155 } 156 _lines.close(); 157 _props = null; 158 Log.d("updateHighlight took ", currentTimeMillis() - ms0, "ms"); 159 } 160 } 161