OSDN Git Service

Add SCI Edit to GitBlameView
[tortoisegit/TortoiseGitJp.git] / ext / scintilla / src / LexPowerShell.cxx
1 // Scintilla source code edit control\r
2 /** @file LexPowerShell.cxx\r
3  ** Lexer for PowerShell scripts.\r
4  **/\r
5 // Copyright 2008 by Tim Gerundt <tim@gerundt.de>\r
6 // The License.txt file describes the conditions under which this software may be distributed.\r
7 \r
8 #include <stdlib.h>\r
9 #include <string.h>\r
10 #include <ctype.h>\r
11 #include <stdio.h>\r
12 #include <stdarg.h>\r
13 \r
14 #include "Platform.h"\r
15 \r
16 #include "PropSet.h"\r
17 #include "Accessor.h"\r
18 #include "StyleContext.h"\r
19 #include "KeyWords.h"\r
20 #include "Scintilla.h"\r
21 #include "SciLexer.h"\r
22 \r
23 #ifdef SCI_NAMESPACE\r
24 using namespace Scintilla;\r
25 #endif\r
26 \r
27 // Extended to accept accented characters\r
28 static inline bool IsAWordChar(int ch) {\r
29         return ch >= 0x80 || isalnum(ch) || ch == '-';\r
30 }\r
31 \r
32 static void ColourisePowerShellDoc(unsigned int startPos, int length, int initStyle,\r
33                            WordList *keywordlists[], Accessor &styler) {\r
34 \r
35         WordList &keywords = *keywordlists[0];\r
36         WordList &keywords2 = *keywordlists[1];\r
37         WordList &keywords3 = *keywordlists[2];\r
38 \r
39         styler.StartAt(startPos);\r
40 \r
41         StyleContext sc(startPos, length, initStyle, styler);\r
42 \r
43         for (; sc.More(); sc.Forward()) {\r
44 \r
45                 if (sc.state == SCE_POWERSHELL_COMMENT) {\r
46                         if (sc.atLineEnd) {\r
47                                 sc.SetState(SCE_POWERSHELL_DEFAULT);\r
48                         }\r
49                 } else if (sc.state == SCE_POWERSHELL_STRING) {\r
50                         // This is a doubles quotes string\r
51                         if (sc.ch == '\"') {\r
52                                 sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);\r
53                         }\r
54                 } else if (sc.state == SCE_POWERSHELL_CHARACTER) {\r
55                         // This is a single quote string\r
56                         if (sc.ch == '\'') {\r
57                                 sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);\r
58                         }\r
59                 } else if (sc.state == SCE_POWERSHELL_NUMBER) {\r
60                         if (!IsADigit(sc.ch)) {\r
61                                 sc.SetState(SCE_POWERSHELL_DEFAULT);\r
62                         }\r
63                 } else if (sc.state == SCE_POWERSHELL_VARIABLE) {\r
64                         if (!IsAWordChar(sc.ch)) {\r
65                                 sc.SetState(SCE_POWERSHELL_DEFAULT);\r
66                         }\r
67                 } else if (sc.state == SCE_POWERSHELL_OPERATOR) {\r
68                         if (!isoperator(static_cast<char>(sc.ch))) {\r
69                                 sc.SetState(SCE_POWERSHELL_DEFAULT);\r
70                         }\r
71                 } else if (sc.state == SCE_POWERSHELL_IDENTIFIER) {\r
72                         if (!IsAWordChar(sc.ch)) {\r
73                                 char s[100];\r
74                                 sc.GetCurrentLowered(s, sizeof(s));\r
75 \r
76                                 if (keywords.InList(s)) {\r
77                                         sc.ChangeState(SCE_POWERSHELL_KEYWORD);\r
78                                 } else if (keywords2.InList(s)) {\r
79                                         sc.ChangeState(SCE_POWERSHELL_CMDLET);\r
80                                 } else if (keywords3.InList(s)) {\r
81                                         sc.ChangeState(SCE_POWERSHELL_ALIAS);\r
82                                 }\r
83                                 sc.SetState(SCE_POWERSHELL_DEFAULT);\r
84                         }\r
85                 }\r
86 \r
87                 // Determine if a new state should be entered.\r
88                 if (sc.state == SCE_POWERSHELL_DEFAULT) {\r
89                         if (sc.ch == '#') {\r
90                                 sc.SetState(SCE_POWERSHELL_COMMENT);\r
91                         } else if (sc.ch == '\"') {\r
92                                 sc.SetState(SCE_POWERSHELL_STRING);\r
93                         } else if (sc.ch == '\'') {\r
94                                 sc.SetState(SCE_POWERSHELL_CHARACTER);\r
95                         } else if (sc.ch == '$') {\r
96                                 sc.SetState(SCE_POWERSHELL_VARIABLE);\r
97                         } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {\r
98                                 sc.SetState(SCE_POWERSHELL_NUMBER);\r
99                         } else if (isoperator(static_cast<char>(sc.ch))) {\r
100                                 sc.SetState(SCE_POWERSHELL_OPERATOR);\r
101                         } else if (IsAWordChar(sc.ch)) {\r
102                                 sc.SetState(SCE_POWERSHELL_IDENTIFIER);\r
103                         }\r
104                 }\r
105         }\r
106         sc.Complete();\r
107 }\r
108 \r
109 // Store both the current line's fold level and the next lines in the\r
110 // level store to make it easy to pick up with each increment\r
111 // and to make it possible to fiddle the current level for "} else {".\r
112 static void FoldPowerShellDoc(unsigned int startPos, int length, int,\r
113                            WordList *[], Accessor &styler) {\r
114         bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;\r
115         bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;\r
116         unsigned int endPos = startPos + length;\r
117         int visibleChars = 0;\r
118         int lineCurrent = styler.GetLine(startPos);\r
119         int levelCurrent = SC_FOLDLEVELBASE;\r
120         if (lineCurrent > 0)\r
121                 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;\r
122         int levelMinCurrent = levelCurrent;\r
123         int levelNext = levelCurrent;\r
124         char chNext = styler[startPos];\r
125         int styleNext = styler.StyleAt(startPos);\r
126         for (unsigned int i = startPos; i < endPos; i++) {\r
127                 char ch = chNext;\r
128                 chNext = styler.SafeGetCharAt(i + 1);\r
129                 int style = styleNext;\r
130                 styleNext = styler.StyleAt(i + 1);\r
131                 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');\r
132                 if (style == SCE_POWERSHELL_OPERATOR) {\r
133                         if (ch == '{') {\r
134                                 // Measure the minimum before a '{' to allow\r
135                                 // folding on "} else {"\r
136                                 if (levelMinCurrent > levelNext) {\r
137                                         levelMinCurrent = levelNext;\r
138                                 }\r
139                                 levelNext++;\r
140                         } else if (ch == '}') {\r
141                                 levelNext--;\r
142                         }\r
143                 }\r
144                 if (!IsASpace(ch))\r
145                         visibleChars++;\r
146                 if (atEOL || (i == endPos-1)) {\r
147                         int levelUse = levelCurrent;\r
148                         if (foldAtElse) {\r
149                                 levelUse = levelMinCurrent;\r
150                         }\r
151                         int lev = levelUse | levelNext << 16;\r
152                         if (visibleChars == 0 && foldCompact)\r
153                                 lev |= SC_FOLDLEVELWHITEFLAG;\r
154                         if (levelUse < levelNext)\r
155                                 lev |= SC_FOLDLEVELHEADERFLAG;\r
156                         if (lev != styler.LevelAt(lineCurrent)) {\r
157                                 styler.SetLevel(lineCurrent, lev);\r
158                         }\r
159                         lineCurrent++;\r
160                         levelCurrent = levelNext;\r
161                         levelMinCurrent = levelCurrent;\r
162                         visibleChars = 0;\r
163                 }\r
164         }\r
165 }\r
166 \r
167 static const char * const powershellWordLists[] = {\r
168         "Commands",\r
169         "Cmdlets",\r
170         "Aliases",\r
171         0\r
172 };\r
173 \r
174 LexerModule lmPowerShell(SCLEX_POWERSHELL, ColourisePowerShellDoc, "powershell", FoldPowerShellDoc, powershellWordLists);\r
175 \r