LexProps.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Scintilla source code edit control
  2. /** @file LexProps.cxx
  3. ** Lexer for properties files.
  4. **/
  5. // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
  6. // The License.txt file describes the conditions under which this software may be distributed.
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #include <assert.h>
  12. #include <ctype.h>
  13. #include "ILexer.h"
  14. #include "Scintilla.h"
  15. #include "SciLexer.h"
  16. #include "WordList.h"
  17. #include "LexAccessor.h"
  18. #include "Accessor.h"
  19. #include "StyleContext.h"
  20. #include "CharacterSet.h"
  21. #include "LexerModule.h"
  22. #ifdef SCI_NAMESPACE
  23. using namespace Scintilla;
  24. #endif
  25. static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
  26. return (styler[i] == '\n') ||
  27. ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
  28. }
  29. static inline bool isassignchar(unsigned char ch) {
  30. return (ch == '=') || (ch == ':');
  31. }
  32. static void ColourisePropsLine(
  33. char *lineBuffer,
  34. Sci_PositionU lengthLine,
  35. Sci_PositionU startLine,
  36. Sci_PositionU endPos,
  37. Accessor &styler,
  38. bool allowInitialSpaces) {
  39. Sci_PositionU i = 0;
  40. if (allowInitialSpaces) {
  41. while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces
  42. i++;
  43. } else {
  44. if (isspacechar(lineBuffer[i])) // don't allow initial spaces
  45. i = lengthLine;
  46. }
  47. if (i < lengthLine) {
  48. if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
  49. styler.ColourTo(endPos, SCE_PROPS_COMMENT);
  50. } else if (lineBuffer[i] == '[') {
  51. styler.ColourTo(endPos, SCE_PROPS_SECTION);
  52. } else if (lineBuffer[i] == '@') {
  53. styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL);
  54. if (isassignchar(lineBuffer[i++]))
  55. styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
  56. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  57. } else {
  58. // Search for the '=' character
  59. while ((i < lengthLine) && !isassignchar(lineBuffer[i]))
  60. i++;
  61. if ((i < lengthLine) && isassignchar(lineBuffer[i])) {
  62. styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY);
  63. styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
  64. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  65. } else {
  66. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  67. }
  68. }
  69. } else {
  70. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  71. }
  72. }
  73. static void ColourisePropsDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
  74. char lineBuffer[1024];
  75. styler.StartAt(startPos);
  76. styler.StartSegment(startPos);
  77. Sci_PositionU linePos = 0;
  78. Sci_PositionU startLine = startPos;
  79. // property lexer.props.allow.initial.spaces
  80. // For properties files, set to 0 to style all lines that start with whitespace in the default style.
  81. // This is not suitable for SciTE .properties files which use indentation for flow control but
  82. // can be used for RFC2822 text where indentation is used for continuation lines.
  83. bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
  84. for (Sci_PositionU i = startPos; i < startPos + length; i++) {
  85. lineBuffer[linePos++] = styler[i];
  86. if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
  87. // End of line (or of line buffer) met, colourise it
  88. lineBuffer[linePos] = '\0';
  89. ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces);
  90. linePos = 0;
  91. startLine = i + 1;
  92. }
  93. }
  94. if (linePos > 0) { // Last line does not have ending characters
  95. ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces);
  96. }
  97. }
  98. // adaption by ksc, using the "} else {" trick of 1.53
  99. // 030721
  100. static void FoldPropsDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
  101. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  102. Sci_PositionU endPos = startPos + length;
  103. int visibleChars = 0;
  104. Sci_Position lineCurrent = styler.GetLine(startPos);
  105. char chNext = styler[startPos];
  106. int styleNext = styler.StyleAt(startPos);
  107. bool headerPoint = false;
  108. int lev;
  109. for (Sci_PositionU i = startPos; i < endPos; i++) {
  110. char ch = chNext;
  111. chNext = styler[i+1];
  112. int style = styleNext;
  113. styleNext = styler.StyleAt(i + 1);
  114. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  115. if (style == SCE_PROPS_SECTION) {
  116. headerPoint = true;
  117. }
  118. if (atEOL) {
  119. lev = SC_FOLDLEVELBASE;
  120. if (lineCurrent > 0) {
  121. int levelPrevious = styler.LevelAt(lineCurrent - 1);
  122. if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
  123. lev = SC_FOLDLEVELBASE + 1;
  124. } else {
  125. lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
  126. }
  127. }
  128. if (headerPoint) {
  129. lev = SC_FOLDLEVELBASE;
  130. }
  131. if (visibleChars == 0 && foldCompact)
  132. lev |= SC_FOLDLEVELWHITEFLAG;
  133. if (headerPoint) {
  134. lev |= SC_FOLDLEVELHEADERFLAG;
  135. }
  136. if (lev != styler.LevelAt(lineCurrent)) {
  137. styler.SetLevel(lineCurrent, lev);
  138. }
  139. lineCurrent++;
  140. visibleChars = 0;
  141. headerPoint = false;
  142. }
  143. if (!isspacechar(ch))
  144. visibleChars++;
  145. }
  146. if (lineCurrent > 0) {
  147. int levelPrevious = styler.LevelAt(lineCurrent - 1);
  148. if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
  149. lev = SC_FOLDLEVELBASE + 1;
  150. } else {
  151. lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
  152. }
  153. } else {
  154. lev = SC_FOLDLEVELBASE;
  155. }
  156. int flagsNext = styler.LevelAt(lineCurrent);
  157. styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK));
  158. }
  159. static const char *const emptyWordListDesc[] = {
  160. 0
  161. };
  162. LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);