Compared files  

Left
C:\SDK\wxWidgets-2.6.2\contrib\src\stc\scintilla\src\LexRuby.cxx
Last modified2004-02-18 17:28:54.001 +0100
Size10.6 Kb (366 Lines)
EncodingLatin 1 - ANSI (CP1252) default
Right
C:\SDK\wxWidgets-2.6.3\contrib\src\stc\scintilla\src\LexRuby.cxx
Last modified2006-03-16 13:07:08.000 +0100
Size52.6 Kb (1543 Lines)
EncodingLatin 1 - ANSI (CP1252) default


   Comparison Statistics  

Detailed Statistics

All Changes
 BlocksLines
Unchanged5499
Inserted6214
Deleted325
Ignored00
Changed441472



   Comparison Details  

18 skipped lines
19 19 #include "Scintilla.h"
20 20 #include "SciLexer.h"
21 21  
  22 #ifdef SCI_NAMESPACE
  23 using namespace Scintilla;
  24 #endif
  25  
  26 //XXX Identical to Perl, put in common area
  27 static inline bool isEOLChar(char ch) {
  28     return (ch == '\r') || (ch == '\n');
  29 }
  30  
  31 #define isSafeASCII(ch) ((unsigned int)(ch) <= 127)
55 skipped lines
  87 }
  88  
  89 // Forward declarations
  90 static bool keywordIsAmbiguous(const char *prevWord);
  91 static bool keywordDoStartsLoop(int pos,
  92                                 Accessor &styler);
  93 static bool keywordIsModifier(const char *word,
  94                               int pos,
  95                               Accessor &styler);
  96  
22 static void ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) { 97 static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
23 98     char s[100];
  99     unsigned int i, j;
24     bool wordIsNumber = isdigit(styler[start]) != 0; 100     unsigned int lim = end - start + 1; // num chars to copy
  101     if (lim >= MAX_KEYWORD_LENGTH) {
  102         lim = MAX_KEYWORD_LENGTH - 1;
  103     }
25     for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { 104     for (i = start, j = 0; j < lim; i++, j++) {
26         s[i] = styler[start + i]; 105         s[j] = styler[i];
27         s[i + 1] = '\0';  
28 106     }
  107     s[j] = '\0';
29     char chAttr = SCE_P_IDENTIFIER; 108     int chAttr;
30 109     if (0 == strcmp(prevWord, "class"))
31         chAttr = SCE_P_CLASSNAME; 110         chAttr = SCE_RB_CLASSNAME;
32 111     else if (0 == strcmp(prevWord, "module"))
33         chAttr = SCE_P_CLASSNAME; 112         chAttr = SCE_RB_MODULE_NAME;
34 113     else if (0 == strcmp(prevWord, "def"))
35         chAttr = SCE_P_DEFNAME; 114         chAttr = SCE_RB_DEFNAME;
36     else if (wordIsNumber) 115     else if (keywords.InList(s) && !followsDot(start - 1, styler)) {
37         chAttr = SCE_P_NUMBER;  
38     else if (keywords.InList(s)) 116         if (keywordIsAmbiguous(s)
39         chAttr = SCE_P_WORD; 117             && keywordIsModifier(s, start, styler)) {
  118              
  119             // Demoted keywords are colored as keywords,
  120             // but do not affect changes in indentation.
  121             //
40     // make sure that dot-qualifiers inside the word are lexed correct 122             // Consider the word 'if':
  123             // 1. <<if test ...>> : normal
  124             // 2. <<stmt if test>> : demoted
41     else for (unsigned int i = 0; i < end - start + 1; i++) { 125             // 3. <<lhs = if ...>> : normal: start a new indent level
42         if (styler[start + i] == '.') { 126             // 4. <<obj.if = 10>> : color as identifer, since it follows '.'
  127              
  128             chAttr = SCE_RB_WORD_DEMOTED;
  129         } else {
  130             chAttr = SCE_RB_WORD;
  131         }
  132     } else
  133         chAttr = SCE_RB_IDENTIFIER;
43         styler.ColourTo(start + i - 1, chAttr); 134     styler.ColourTo(end, chAttr);
  135     if (chAttr == SCE_RB_WORD) {
  136         strcpy(prevWord, s);
  137     } else {
  138         prevWord[0] = 0;
  139     }
  140     return chAttr;
  141 }
  142  
  143  
  144 //XXX Identical to Perl, put in common area
  145 static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {
  146     if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {
  147         return false;
  148     }
  149     while (*val) {
  150         if (*val != styler[pos++]) {
44         styler.ColourTo(start + i, SCE_P_OPERATOR); 151         return false;
45 152         }
  153         val++;
46 154     }
47     styler.ColourTo(end, chAttr);  
48     strcpy(prevWord, s); 155     return true;
49 156 }
50 157  
  158 // Do Ruby better -- find the end of the line, work back,
  159 // and then check for leading white space
  160  
  161 // Precondition: the here-doc target can be indented
51 static bool IsRbComment(Accessor &styler, int pos, int len) { 162 static bool lookingAtHereDocDelim(Accessor     &styler,
  163                                   int   pos,
  164                                   int   lengthDoc,
  165                                   const char   *HereDocDelim)
  166 {
  167     if (!isMatch(styler, lengthDoc, pos, HereDocDelim)) {
  168         return false;
  169     }
  170     while (--pos > 0) {
52     return len>0 && styler[pos]=='#'; 171         char ch = styler[pos];
  172         if (isEOLChar(ch)) {
  173             return true;
  174         } else if (ch != ' ' && ch != '\t') {
  175             return false;
  176         }
  177     }
  178     return false;
53 179 }
54 180  
  181 //XXX Identical to Perl, put in common area
55 static bool IsRbStringStart(char ch, char chNext, char chNext2) { 182 static char opposite(char ch) {
56     if (ch == '\'' || ch == '"') 183     if (ch == '(')
57         return true; 184         return ')';
58     if (ch == 'u' || ch == 'U') { 185     if (ch == '[')
  186         return ']';
59         if (chNext == '"' || chNext == '\'') 187     if (ch == '{')
60         return true; 188         return '}';
61         if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\'')) 189     if (ch == '<')
  190         return '>';
62         return true; 191     return ch;
63     } 192 }
64     if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\'')) 193  
65         return true; 194 // Null transitions when we see we've reached the end
  195 // and need to relex the curr char.
66 196  
  197 static void redo_char(int &i, char &ch, char &chNext, char &chNext2,
  198                       int &state) {
  199     i--;
  200     chNext2 = chNext;
  201     chNext = ch;
67     return false; 202     state = SCE_RB_DEFAULT;
68 203 }
69 204  
70 static bool IsRbWordStart(char ch, char chNext, char chNext2) { 205 static void advance_char(int &i, char &ch, char &chNext, char &chNext2) {
  206     i++;
  207     ch = chNext;
71     return (iswordchar(ch) && !IsRbStringStart(ch, chNext, chNext2)); 208     chNext = chNext2;
72 209 }
73 210  
74 /* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */ 211 // precondition: startPos points to one after thEOL char
75 static int GetRbStringState(Accessor &styler, int i, int *nextIndex) { 212 static bool currLineContainsHereDelims(int& startPos,
76     char ch = styler.SafeGetCharAt(i);  
77     char chNext = styler.SafeGetCharAt(i + 1);  
78    
79     // Advance beyond r, u, or ur prefix, but bail if there are any unexpected chars  
80     if (ch == 'r' || ch == 'R') {  
81         i++;  
82         ch = styler.SafeGetCharAt(i);  
83         chNext = styler.SafeGetCharAt(i + 1); 213                                        Accessor &styler) {
84     }  
85     else if (ch == 'u' || ch == 'U') {  
86         if (chNext == 'r' || chNext == 'R') 214     if (startPos <= 1)
87         i += 2; 215         return false;
88         else  
89         i += 1;  
90         ch = styler.SafeGetCharAt(i);  
91         chNext = styler.SafeGetCharAt(i + 1);  
92     }  
93 216  
  217     int pos;
  218     for (pos = startPos - 1; pos > 0; pos--) {
  219         char ch = styler.SafeGetCharAt(pos);
94     if (ch != '"' && ch != '\'') { 220         if (isEOLChar(ch)) {
95         *nextIndex = i + 1; 221             // Leave the pointers where they are -- there are no
  222             // here doc delims on the current line, even if
  223             // the EOL isn't default style
  224              
  225             return false;
  226         } else {
  227             styler.Flush();
96         return SCE_P_DEFAULT; 228             if (actual_style(styler.StyleAt(pos)) == SCE_RB_HERE_DELIM) {
  229                 break;
  230             }
  231         }
  232     }
  233     if (pos == 0) {
  234         return false;
  235     }
  236     // Update the pointers so we don't have to re-analyze the string
  237     startPos = pos;
  238     return true;
97     } 239 }
98 240  
99     if (i>0 && styler.SafeGetCharAt(i-1) == '$') {  
100         *nextIndex = i + 1;  
101         return SCE_P_DEFAULT;  
102     }  
103 241  
  242 static bool isEmptyLine(int pos,
  243                         Accessor &styler) {
  244     int spaceFlags = 0;
104     if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) { 245     int lineCurrent = styler.GetLine(pos);
105         *nextIndex = i + 3; 246     int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
  247     return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0;
  248 }
  249  
  250 static bool RE_CanFollowKeyword(const char *keyword) {
  251     if (!strcmp(keyword, "and")
  252         || !strcmp(keyword, "begin")
  253         || !strcmp(keyword, "break")
  254         || !strcmp(keyword, "case")
  255         || !strcmp(keyword, "do")
  256         || !strcmp(keyword, "else")
3 skipped lines
  260         || !strcmp(keyword, "return")
  261         || !strcmp(keyword, "when")
  262         || !strcmp(keyword, "unless")
  263         || !strcmp(keyword, "until")
  264         || !strcmp(keyword, "not")
  265         || !strcmp(keyword, "or")) {
  266         return true;
  267     }
  268     return false;
  269 }
106 270  
107         if (ch == '"') 271 // Look at chars up to but not including endPos
108         return SCE_P_TRIPLEDOUBLE; 272 // Don't look at styles in case we're looking forward
109         else  
110         return SCE_P_TRIPLE;  
111     } else {  
112         *nextIndex = i + 1;  
113 273  
  274 static int skipWhitespace(int startPos,
  275                            int endPos,
  276                            Accessor &styler) {
  277     for (int i = startPos; i < endPos; i++) {
  278         if (!iswhitespace(styler[i])) {
  279             return i;
  280         }
  281     }
  282     return endPos;
  283 }
261 skipped lines
  545     int lineStart;
  546     for (lineStart = styler.GetLine(pos); lineStart > 0; lineStart--) {
  547         // Now look at the style before the previous line's EOL
  548         pos = styler.LineStart(lineStart) - 1;
  549         if (pos <= 10) {
  550             lineStart = 0;
  551             break;
  552         }
  553         char ch = styler.SafeGetCharAt(pos);
  554         char chPrev = styler.SafeGetCharAt(pos - 1);
114         if (ch == '"') 555         if (ch == '\n' && chPrev == '\r') {
  556             pos--;
  557         }
  558         if (styler.SafeGetCharAt(pos - 1) == '\\') {
  559             // Continuation line -- keep going
115         return SCE_P_STRING; 560         } else if (actual_style(styler.StyleAt(pos)) != SCE_RB_DEFAULT) {
  561             // Part of multi-line construct -- keep going
116         else 562         } else if (currLineContainsHereDelims(pos, styler)) {
  563             // Keep going, with pos and length now pointing
  564             // at the end of the here-doc delimiter
  565         } else if (skipWhiteSpace && isEmptyLine(pos, styler)) {
  566             // Keep going
  567         } else {
  568             break;
  569         }
  570     }
  571     pos = styler.LineStart(lineStart);
  572     length += (startPos - pos);
  573     startPos = pos;
117         return SCE_P_CHARACTER; 574     initStyle = SCE_RB_DEFAULT;
118     }  
119 575 }
120 576  
121 577 static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle,
122 578            WordList *keywordlists[], Accessor &styler) {
123 579  
  580     // Lexer for Ruby often has to backtrack to start of current style to determine
  581     // which characters are being used as quotes, how deeply nested is the
  582     // start position and what the termination string is for here documents
  583      
124     int lengthDoc = startPos + length; 584     WordList &keywords = *keywordlists[0];
125 585  
126     // Backtrack to previous line in case need to fix its tab whinging 586     class HereDocCls {
127     if (startPos > 0) { 587     public:
128         int lineCurrent = styler.GetLine(startPos); 588         int State;
  589         // States
  590         // 0: '<<' encountered
  591         // 1: collect the delimiter
  592         // 1b: text between the end of the delimiter and the EOL
  593         // 2: here doc text (lines after the delimiter)
  594         char Quote;     // the char after '<<'
  595         bool Quoted;// true if Quote in ('\'','"','`')
  596         int DelimiterLength;// strlen(Delimiter)
  597         char Delimiter[256];// the Delimiter, limit of 256: from Perl
  598         bool CanBeIndented;
129         if (lineCurrent > 0) { 599         HereDocCls() {
130         startPos = styler.LineStart(lineCurrent-1); 600         State = 0;
131         if (startPos == 0) 601         DelimiterLength = 0;
132         initStyle = SCE_P_DEFAULT; 602         Delimiter[0] = '\0';
133         else  
134         initStyle = styler.StyleAt(startPos-1); 603             CanBeIndented = false;
135 604         }
136     } 605     };
  606     HereDocCls HereDoc;   
137 607  
138     // Ruby uses a different mask because bad indentation is marked by oring with 32 608     class QuoteCls {
  609         public:
  610         int  Count;
  611         char Up;
  612         char Down;
  613         QuoteCls() {
  614         this->New();
  615         }
  616         void New() {
  617         Count = 0;
  618         Up    = '\0';
  619         Down  = '\0';
  620         }
  621         void Open(char u) {
  622         Count++;
  623         Up    = u;
  624         Down  = opposite(Up);
  625         }
  626     };
139     styler.StartAt(startPos, 127); 627     QuoteCls Quote;
140 628  
141     WordList &keywords = *keywordlists[0]; 629     int numDots = 0;  // For numbers --
  630                       // Don't start lexing in the middle of a num
142 631  
  632     synchronizeDocStart(startPos, length, initStyle, styler, // ref args
  633                         false);
  634  
  635     bool preferRE = true;
143     int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); 636     int state = initStyle;
  637     int lengthDoc = startPos + length;
  638  
144     char prevWord[200]; 639     char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
145 640     prevWord[0] = '\0';
146 641     if (length == 0)
147         return ; 642         return;
148 643  
149     int state = initStyle & 31; 644     char chPrev = styler.SafeGetCharAt(startPos - 1);
150   645     char chNext = styler.SafeGetCharAt(startPos);
151     int nextIndex = 0; 646     // Ruby uses a different mask because bad indentation is marked by oring with 32
152     char chPrev = ' ';  
153     char chPrev2 = ' ';  
154     char chNext = styler[startPos]; 647     styler.StartAt(startPos, 127);
155 648     styler.StartSegment(startPos);
156     bool atStartLine = true;  
157     int spaceFlags = 0;  
158     for (int i = startPos; i < lengthDoc; i++) {  
159    
160         if (atStartLine) {  
10 skipped lines
171         chFlags = (spaceFlags & wsTab) ? chBad : chGood;  
172         }  
173         styler.SetFlags(chFlags, static_cast<char>(state));  
174         atStartLine = false;  
175         }  
176 649  
  650     static int q_states[] = {SCE_RB_STRING_Q,
  651                              SCE_RB_STRING_QQ,
  652                              SCE_RB_STRING_QR,
  653                              SCE_RB_STRING_QW,
  654                              SCE_RB_STRING_QW,
  655                              SCE_RB_STRING_QX};
  656     static const char* q_chars = "qQrwWx";
  657      
  658     for (int i = startPos; i < lengthDoc; i++) {
177 659         char ch = chNext;
178 660         chNext = styler.SafeGetCharAt(i + 1);
179 661         char chNext2 = styler.SafeGetCharAt(i + 2);
180 662  
181         if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {  
182         if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {  
183         // Perform colourisation of white space and triple quoted strings at end of each line to allow  
184         // tab marking to work inside white space and triple quoted strings  
185         styler.ColourTo(i, state);  
186         }  
187         atStartLine = true;  
188         }  
189    
190         if (styler.IsLeadByte(ch)) { 663         if (styler.IsLeadByte(ch)) {
191         chNext = styler.SafeGetCharAt(i + 2); 664         chNext = chNext2;
192 665         chPrev = ' ';
193         chPrev2 = ' ';  
194 666         i += 1;
195 667         continue;
196 668         }
  669          
  670         // skip on DOS/Windows
  671         //No, don't, because some things will get tagged on,
  672         // so we won't recognize keywords, for example
  673 #if 0
8 skipped lines
  682         styler.ColourTo(i-1, state);
  683             // Don't check for a missing quote, just jump into
  684             // the here-doc state
  685             state = SCE_RB_HERE_Q;
  686         }
197 687  
  688         // Regular transitions
198         if (state == SCE_P_STRINGEOL) { 689         if (state == SCE_RB_DEFAULT) {
199         if (ch != '\r' && ch != '\n') { 690             if (isSafeDigit(ch)) {
200         styler.ColourTo(i - 1, state); 691             styler.ColourTo(i - 1, state);
201         state = SCE_P_DEFAULT; 692         state = SCE_RB_NUMBER;
202         } 693                 numDots = 0;
203         }  
204         if (state == SCE_P_DEFAULT) {  
205         if (IsRbWordStart(ch, chNext, chNext2)) { 694             } else if (isHighBitChar(ch) || iswordstart(ch)) {
206         styler.ColourTo(i - 1, state); 695             styler.ColourTo(i - 1, state);
207         state = SCE_P_WORD; 696         state = SCE_RB_WORD;
208 697         } else if (ch == '#') {
209 698         styler.ColourTo(i - 1, state);
210         state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE; 699         state = SCE_RB_COMMENTLINE;
211         } else if (ch == '=' && chNext == 'b') { 700         } else if (ch == '=') {
212 701         // =begin indicates the start of a comment (doc) block
  702                 if (i == 0 || isEOLChar(chPrev)
  703                     && chNext == 'b'
  704                     && styler.SafeGetCharAt(i + 2) == 'e'
  705                     && styler.SafeGetCharAt(i + 3) == 'g'
  706                     && styler.SafeGetCharAt(i + 4) == 'i'
213         if(styler.SafeGetCharAt(i + 2) == 'e' && styler.SafeGetCharAt(i + 3) == 'g' && styler.SafeGetCharAt(i + 4) == 'i' && styler.SafeGetCharAt(i + 5) == 'n') { 707                     && styler.SafeGetCharAt(i + 5) == 'n'
  708                     && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) {
  709                     styler.ColourTo(i - 1, state);
  710                     state = SCE_RB_POD;
  711         } else {
214 712         styler.ColourTo(i - 1, state);
215         state = SCE_P_TRIPLEDOUBLE; //SCE_C_COMMENT; 713         styler.ColourTo(i, SCE_RB_OPERATOR);
  714         preferRE = true;
216 715         }
217         }  else if (IsRbStringStart(ch, chNext, chNext2)) { 716         } else if (ch == '"') {
218 717         styler.ColourTo(i - 1, state);
219         state = GetRbStringState(styler, i, &nextIndex); 718         state = SCE_RB_STRING;
  719         Quote.New();
  720         Quote.Open(ch);
220         if (nextIndex != i + 1) { 721         } else if (ch == '\'') {
221         i = nextIndex - 1; 722                 styler.ColourTo(i - 1, state);
222         ch = ' '; 723                 state = SCE_RB_CHARACTER;
223         chPrev = ' ';  
224         chNext = styler.SafeGetCharAt(i + 1); 724                 Quote.New();
225         } 725                 Quote.Open(ch);
226         } else if (isoperator(ch)) { 726         } else if (ch == '`') {
227 727         styler.ColourTo(i - 1, state);
  728         state = SCE_RB_BACKTICKS;
228         styler.ColourTo(i, SCE_P_OPERATOR); 729         Quote.New();
229         } 730         Quote.Open(ch);
230         } else if (state == SCE_P_WORD) { 731         } else if (ch == '@') {
231         if (!iswordchar(ch)) { 732                 // Instance or class var
232         ClassifyWordRb(styler.GetStartSegment(), i - 1, keywords, styler, prevWord); 733         styler.ColourTo(i - 1, state);
  734                 if (chNext == '@') {
  735                     state = SCE_RB_CLASS_VAR;
  736                     advance_char(i, ch, chNext, chNext2); // pass by ref
  737                 } else {
233         state = SCE_P_DEFAULT; 738                     state = SCE_RB_INSTANCE_VAR;
  739                 }
234         if (ch == '#') { 740         } else if (ch == '$') {
  741                 // Check for a builtin global
  742         styler.ColourTo(i - 1, state);
  743                 // Recognize it bit by bit
235         state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE; 744                 state = SCE_RB_GLOBAL;
236         } else if (IsRbStringStart(ch, chNext, chNext2)) { 745             } else if (ch == '/' && preferRE) {
  746                 // Ambigous operator
237         styler.ColourTo(i - 1, state); 747         styler.ColourTo(i - 1, state);
238         state = GetRbStringState(styler, i, &nextIndex); 748         state = SCE_RB_REGEX;
  749                 Quote.New();
  750                 Quote.Open(ch);
239         if (nextIndex != i + 1) { 751         } else if (ch == '<' && chNext == '<' && chNext2 != '=') {
240         i = nextIndex - 1; 752  
241         ch = ' '; 753                 // Recognise the '<<' symbol - either a here document or a binary op
  754         styler.ColourTo(i - 1, state);
  755                 i++;
  756                 chNext = chNext2;
  757         styler.ColourTo(i, SCE_RB_OPERATOR);
  758  
  759                 if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) {
  760                     // It's definitely not a here-doc,
  761                     // based on Ruby's lexer/parser in the
  762                     // heredoc_identifier routine.
  763                     // Nothing else to do.
110 skipped lines
  874             } else if (ch == '%') {
  875                 styler.ColourTo(i - 1, state);
  876                 bool have_string = false;
  877                 if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) {
  878                     Quote.New();
  879                     const char *hit = strchr(q_chars, chNext);
  880                     if (hit != NULL) {
  881                         state = q_states[hit - q_chars];
  882                         Quote.Open(chNext2);
  883                         i += 2;
242         chPrev = ' '; 884                         ch = chNext2;
243 885         chNext = styler.SafeGetCharAt(i + 1);
  886                         have_string = true;
  887                     }
  888                 } else if (!isSafeWordcharOrHigh(chNext)) {
  889                     // Ruby doesn't allow high bit chars here,
  890                     // but the editor host might
166 skipped lines
  1057         HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
  1058         } else {
  1059         styler.ColourTo(i - 1, state);
  1060                         redo_char(i, ch, chNext, chNext2, state);
  1061                         preferRE = false;
244 1062         }
245         } else if (isoperator(ch)) { 1063                 }
246         styler.ColourTo(i, SCE_P_OPERATOR);  
247         }  
248         }  
249         } else {  
250         if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) { 1064         if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) {
251         if (ch == '\r' || ch == '\n') {  
252 1065         styler.ColourTo(i - 1, state);
253         state = SCE_P_DEFAULT; 1066         state = SCE_RB_ERROR;
254         }  
255         } else if (state == SCE_P_STRING) {  
256         if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {  
257         styler.ColourTo(i - 1, state);  
258         state = SCE_P_STRINGEOL;  
259         } else if (ch == '\\') {  
260         if (chNext == '\"' || chNext == '\'' || chNext == '\\') {  
261         i++;  
262         ch = chNext;  
263         chNext = styler.SafeGetCharAt(i + 1);  
264         }  
265         } else if (ch == '\"') {  
266         styler.ColourTo(i, state);  
267         state = SCE_P_DEFAULT; 1067                     preferRE = false;
268 1068         }
  1069             }
  1070         } else if (state == SCE_RB_HERE_Q) {
  1071             // Not needed: HereDoc.State == 2
  1072             // Indentable here docs: look backwards
  1073             // Non-indentable: look forwards, like in Perl
  1074             //
  1075             // Why: so we can quickly resolve things like <<-" abc"
  1076  
  1077             if (!HereDoc.CanBeIndented) {
  1078                 if (isEOLChar(chPrev)
37 skipped lines
  1116                         advance_char(i, ch, chNext, chNext2);
  1117                     }
  1118                     styler.ColourTo(i, state);
  1119                     state = SCE_RB_DEFAULT;
  1120                 } else {
  1121                     styler.ColourTo(i - 1, state);
  1122                     redo_char(i, ch, chNext, chNext2, state); // pass by ref
  1123                 }
  1124                 preferRE = false;
  1125             }
269         } else if (state == SCE_P_CHARACTER) { 1126         } else if (state == SCE_RB_POD) {
  1127             // PODs end with ^=end\s, -- any whitespace can follow =end
  1128             if (strchr(" \t\n\r", ch) != NULL
  1129                 && i > 5
  1130                 && isEOLChar(styler[i - 5])
270         if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { 1131                 && isMatch(styler, lengthDoc, i - 4, "=end")) {
271         styler.ColourTo(i - 1, state); 1132                 styler.ColourTo(i - 1, state);
272         state = SCE_P_STRINGEOL; 1133                 state = SCE_RB_DEFAULT;
  1134                 preferRE = false;
  1135             }
273         } else if (ch == '\\') { 1136         } else if (state == SCE_RB_REGEX || state == SCE_RB_STRING_QR) {
274         if (chNext == '\"' || chNext == '\'' || chNext == '\\') { 1137             if (ch == '\\' && Quote.Up != '\\') {
  1138                 // Skip one
  1139                 advance_char(i, ch, chNext, chNext2);
  1140             } else if (ch == Quote.Down) {
  1141                 Quote.Count--;
  1142                 if (Quote.Count == 0) {
  1143                     // Include the options
  1144                     while (isSafeAlpha(chNext)) {
275         i++; 1145                         i++;
276 1146         ch = chNext;
277         chNext = styler.SafeGetCharAt(i + 1); 1147                         chNext = styler.SafeGetCharAt(i + 1);
278         } 1148                     }
279         } else if (ch == '\'') {  
280         styler.ColourTo(i, state); 1149                     styler.ColourTo(i, state);
281         state = SCE_P_DEFAULT; 1150                     state = SCE_RB_DEFAULT;
282         } 1151                     preferRE = false;
  1152                 }
283         } else if (state == SCE_P_TRIPLE) { 1153             } else if (ch == Quote.Up) {
  1154                 // Only if close quoter != open quoter
  1155                 Quote.Count++;
  1156                  
284         if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { 1157             } else if (ch == '#' ) {
  1158                 //todo: distinguish comments from pound chars
  1159                 // for now, handle as comment
285         styler.ColourTo(i, state); 1160                 styler.ColourTo(i - 1, state);
286         state = SCE_P_DEFAULT; 1161                 bool inEscape = false;
287         }  
288         } else if (state == SCE_P_TRIPLEDOUBLE) { 1162                 while (++i < lengthDoc) {
289         // =end terminates the comment block 1163                     ch = styler.SafeGetCharAt(i);
290         if (ch == 'd' && chPrev == 'n' && chPrev2 == 'e') { 1164                     if (ch == '\\') {
291         if  (styler.SafeGetCharAt(i - 3) == '=') { 1165                         inEscape = true;
  1166                     } else if (isEOLChar(ch)) {
  1167                         // Comment inside a regex
292         styler.ColourTo(i, state); 1168                         styler.ColourTo(i - 1, SCE_RB_COMMENTLINE);
293         state = SCE_P_DEFAULT; 1169                         break;
294         } 1170                     } else if (inEscape) {
295         } 1171                         inEscape = false;  // don't look at char
  1172                     } else if (ch == Quote.Down) {
  1173                         // Have the regular handler deal with this
  1174                         // to get trailing modifiers.
  1175                         i--;
  1176                         ch = styler[i];
  1177         break;
  1178                     }
  1179                 }
  1180                 chNext = styler.SafeGetCharAt(i + 1);
  1181                 chNext2 = styler.SafeGetCharAt(i + 2);
93 skipped lines
  1275     while (--pos >= lineStartPosn) {
  1276         style = actual_style(styler.StyleAt(pos));
  1277         if (style == SCE_RB_DEFAULT) {
  1278         if (iswhitespace(ch = styler[pos])) {
  1279         //continue
  1280         } else if (ch == '\r' || ch == '\n') {
  1281         // Scintilla's LineStart() and GetLine() routines aren't
  1282         // platform-independent, so if we have text prepared with
  1283         // a different system we can't rely on it.
  1284         return false;
296 1285         }
  1286         } else {
  1287             break;
297 1288         }
298         chPrev2 = chPrev; 1289     }
299         chPrev = ch; 1290     if (pos < lineStartPosn) {
300     } 1291         return false; //XXX not quite right if the prev line is a continuation
  1292     }
  1293     // First things where the action is unambiguous
  1294     switch (style) {
  1295         case SCE_RB_DEFAULT:
  1296         case SCE_RB_COMMENTLINE:
  1297         case SCE_RB_POD:
  1298         case SCE_RB_CLASSNAME:
  1299         case SCE_RB_DEFNAME:
  1300         case SCE_RB_MODULE_NAME:
  1301             return false;
  1302         case SCE_RB_OPERATOR:
  1303             break;
301     if (state == SCE_P_WORD) { 1304         case SCE_RB_WORD:
  1305             // Watch out for uses of 'else if'
  1306             //XXX: Make a list of other keywords where 'if' isn't a modifier
  1307             //     and can appear legitimately
  1308             // Formulate this to avoid warnings from most compilers
  1309             if (strcmp(word, "if") == 0) {
  1310                 char prevWord[MAX_KEYWORD_LENGTH + 1];
  1311                 getPrevWord(pos, prevWord, styler, SCE_RB_WORD);
302         ClassifyWordRb(styler.GetStartSegment(), lengthDoc-1, keywords, styler, prevWord); 1312                 return strcmp(prevWord, "else") != 0;
  1313             }
  1314             return true;
  1315         default:
  1316             return true;
  1317     }
  1318     // Assume that if the keyword follows an operator,
  1319     // usually it's a block assignment, like
303     } else { 1320     // a << if x then y else z
  1321      
304         styler.ColourTo(lengthDoc-1, state); 1322     ch = styler[pos];
  1323     switch (ch) {
  1324         case ')':
  1325         case ']':
  1326         case '}':
  1327             return true;
  1328         default:
  1329             return false;
305     } 1330     }
306 1331 }
307 1332  
  1333 #define WHILE_BACKWARDS "elihw"
  1334 #define UNTIL_BACKWARDS "litnu"
  1335  
  1336 // Nothing fancy -- look to see if we follow a while/until somewhere
  1337 // on the current line
  1338  
308 static void FoldRbDoc(unsigned int startPos, int length, int initStyle, 1339 static bool keywordDoStartsLoop(int pos,
  1340                                 Accessor &styler)
  1341 {
  1342     char ch;
  1343     int style;
  1344     int lineStart = styler.GetLine(pos);
  1345     int lineStartPosn = styler.LineStart(lineStart);
  1346     styler.Flush();
  1347     while (--pos >= lineStartPosn) {
  1348         style = actual_style(styler.StyleAt(pos));
  1349         if (style == SCE_RB_DEFAULT) {
  1350         if ((ch = styler[pos]) == '\r' || ch == '\n') {
  1351         // Scintilla's LineStart() and GetLine() routines aren't
  1352         // platform-independent, so if we have text prepared with
  1353         // a different system we can't rely on it.
  1354         return false;
  1355         }
309            WordList *[], Accessor &styler) { 1356         } else if (style == SCE_RB_WORD) {
  1357             // Check for while or until, but write the word in backwards
  1358             char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
  1359             char *dst = prevWord;
  1360             int wordLen = 0;
310     int lengthDoc = startPos + length; 1361             int start_word;
  1362             for (start_word = pos;
  1363                  start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD;
  1364                  start_word--) {
  1365                 if (++wordLen < MAX_KEYWORD_LENGTH) {
  1366                     *dst++ = styler[start_word];
  1367                 }
  1368             }
  1369             *dst = 0;
  1370             // Did we see our keyword?
  1371             if (!strcmp(prevWord, WHILE_BACKWARDS)
48 skipped lines
  1420  *  true undef
  1421  
  1422  *  Always increment:
  1423  *  begin  class def do for module when {
  1424  * 
  1425  *  Always decrement:
  1426  *  end }
  1427  * 
  1428  *  Increment if these start a statement
  1429  *  if unless until while -- do nothing if they're modifiers
311 1430  
  1431  *  These end a block if there's no modifier, but don't bother
  1432  *  break next redo retry return yield
  1433  * 
  1434  *  These temporarily de-indent, but re-indent
  1435  *  case else elsif ensure rescue
  1436  * 
  1437  *  This means that the folder reflects indentation rather
  1438  *  than setting it.  The language-service updates indentation
  1439  *  when users type return and finishes entering de-denters.
  1440  * 
  1441  *  Later offer to fold POD, here-docs, strings, and blocks of comments
  1442  */
  1443  
  1444 static void FoldRbDoc(unsigned int startPos, int length, int initStyle,
  1445                       WordList *[], Accessor &styler) {
  1446     const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
312     // Backtrack to previous line in case need to fix its fold status 1447     bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
  1448      
  1449     synchronizeDocStart(startPos, length, initStyle, styler, // ref args
  1450                         false);
  1451     unsigned int endPos = startPos + length;
  1452     int visibleChars = 0;
313 1453     int lineCurrent = styler.GetLine(startPos);
314     if (startPos > 0) {  
315         if (lineCurrent > 0) {  
316         lineCurrent--;  
317         startPos = styler.LineStart(lineCurrent);  
318         if (startPos == 0) 1454     int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent)
319         initStyle = SCE_P_DEFAULT; 1455                                          & SC_FOLDLEVELNUMBERMASK
320         else  
321         initStyle = styler.StyleAt(startPos-1);  
322         }  
323     }  
324     int state = initStyle & 31;  
325     int spaceFlags = 0;  
326     int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsRbComment); 1456                                          & ~SC_FOLDLEVELBASE);
327     if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))  
328         indentCurrent |= SC_FOLDLEVELWHITEFLAG; 1457     int levelCurrent = levelPrev;
329 1458     char chNext = styler[startPos];
  1459     int styleNext = styler.StyleAt(startPos);
  1460     int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1);
  1461     bool buffer_ends_with_eol = false;
330     for (int i = startPos; i < lengthDoc; i++) { 1462     for (unsigned int i = startPos; i < endPos; i++) {
331 1463         char ch = chNext;
332 1464         chNext = styler.SafeGetCharAt(i + 1);
  1465         int style = styleNext;
333         int style = styler.StyleAt(i) & 31; 1466         styleNext = styler.StyleAt(i + 1);
334    
335         if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) { 1467         bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
336         int lev = indentCurrent;  
337         int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsRbComment);  
338         if ((style == SCE_P_TRIPLE) || (style== SCE_P_TRIPLEDOUBLE)) 1468         if (style == SCE_RB_COMMENTLINE) {
339         indentNext |= SC_FOLDLEVELWHITEFLAG;  
340         if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { 1469             if (foldComment && stylePrev != SCE_RB_COMMENTLINE) {
341         // Only non whitespace lines can be headers  
342         if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { 1470                 if (chNext == '{') {
343         lev |= SC_FOLDLEVELHEADERFLAG; 1471         levelCurrent++;
344         } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {  
345         // Line after is blank so check the next - maybe should continue further?  
346         int spaceFlags2 = 0;  
347         int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsRbComment);  
348         if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { 1472         } else if (chNext == '}') {
349         lev |= SC_FOLDLEVELHEADERFLAG; 1473         levelCurrent--;
350         }  
351 1474         }
  1475             }
  1476         } else if (style == SCE_RB_OPERATOR) {
  1477         if (strchr("[{(", ch)) {
  1478         levelCurrent++;
  1479         } else if (strchr(")}]", ch)) {
  1480                 // Don't decrement below 0
  1481                 if (levelCurrent > 0)
  1482                     levelCurrent--;
352 1483         }
353         indentCurrent = indentNext; 1484         } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) {
  1485             // Look at the keyword on the left and decide what to do
  1486             char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
  1487             prevWord[0] = 0;
  1488             getPrevWord(i, prevWord, styler, SCE_RB_WORD);
  1489             if (!strcmp(prevWord, "end")) {
  1490                 // Don't decrement below 0
  1491                 if (levelCurrent > 0)
  1492                     levelCurrent--;
  1493             } else if (   !strcmp(prevWord, "if")
  1494                        || !strcmp(prevWord, "def")
9 skipped lines
  1504                           ) {
  1505         levelCurrent++;
  1506             }
  1507         }
  1508         if (atEOL) {
  1509         int lev = levelPrev;
  1510         if (visibleChars == 0 && foldCompact)
  1511         lev |= SC_FOLDLEVELWHITEFLAG;
  1512         if ((levelCurrent > levelPrev) && (visibleChars > 0))
  1513         lev |= SC_FOLDLEVELHEADERFLAG;
354         styler.SetLevel(lineCurrent, lev); 1514             styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE);
355 1515         lineCurrent++;
356         } 1516         levelPrev = levelCurrent;
357     } 1517         visibleChars = 0;
  1518             buffer_ends_with_eol = true;
  1519         } else if (!isspacechar(ch)) {
  1520         visibleChars++;
  1521             buffer_ends_with_eol = false;
  1522         }
  1523     }
  1524     // Fill in the real level of the next line, keeping the current flags as they will be filled in later
  1525     if (!buffer_ends_with_eol) {
  1526         lineCurrent++;
  1527         int new_lev = levelCurrent;
  1528         if (visibleChars == 0 && foldCompact)
  1529             new_lev |= SC_FOLDLEVELWHITEFLAG;
  1530         if ((levelCurrent > levelPrev) && (visibleChars > 0))
  1531         new_lev |= SC_FOLDLEVELHEADERFLAG;
  1532             levelCurrent = new_lev;
  1533     }
  1534     styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE);
358 1535 }
359 1536  
360 1537 static const char * const rubyWordListDesc[] = {
6 skipped lines

   Text comparison Options  

Syntax colouring language used: C / C++
Match character case: yes.
Match line endings: no.
Match spaces

At start of lines: yes,
In middle of lines: yes,
At end of lines: yes.
Blank lines as empty lines: no.
Activate comparison algorithm
At word level: yes,
At character level: no.


   Legend  

Unchanged lineExample of unchanged line
Modified lineExample of modified line
Added lineExample of added line
Removed lineExample of removed line
Ignored lineExample of ignored line

This report has been generated by Ellié Computing Merge on 2006-09-07 15:48:30.001 +0200.
© 2005-2006 Ellié Computing http://www.elliecomputing.com. All rights reserved.