File: powershell.rb

package info (click to toggle)
ruby-rouge 4.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,844 kB
  • sloc: ruby: 38,489; sed: 2,071; perl: 152; makefile: 8
file content (248 lines) | stat: -rw-r--r-- 9,106 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

module Rouge
  module Lexers

    class Powershell < RegexLexer
      title 'powershell'
      desc 'powershell'
      tag 'powershell'
      aliases 'posh', 'microsoftshell', 'msshell'
      filenames '*.ps1', '*.psm1', '*.psd1', '*.psrc', '*.pssc'
      mimetypes 'text/x-powershell'

      # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_cmdletbindingattribute?view=powershell-6
      ATTRIBUTES = %w(
        ConfirmImpact DefaultParameterSetName HelpURI PositionalBinding
        SupportsPaging SupportsShouldProcess
      )

      # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-6
      AUTO_VARS = %w(
        \$\$ \$\? \$\^ \$_
        \$args \$ConsoleFileName \$Error \$Event \$EventArgs \$EventSubscriber
        \$ExecutionContext \$false \$foreach \$HOME \$Host \$input \$IsCoreCLR
        \$IsLinux \$IsMacOS \$IsWindows \$LastExitCode \$Matches \$MyInvocation
        \$NestedPromptLevel \$null \$PID \$PROFILE \$PSBoundParameters \$PSCmdlet
        \$PSCommandPath \$PSCulture \$PSDebugContext \$PSHOME \$PSItem
        \$PSScriptRoot \$PSSenderInfo \$PSUICulture \$PSVersionTable \$PWD
        \$REPORTERRORSHOWEXCEPTIONCLASS \$REPORTERRORSHOWINNEREXCEPTION
        \$REPORTERRORSHOWSOURCE \$REPORTERRORSHOWSTACKTRACE
        \$SENDER \$ShellId \$StackTrace \$switch \$this \$true
      ).join('|')

      # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_reserved_words?view=powershell-6
      KEYWORDS = %w(
        assembly exit process base filter public begin finally return break for
        sequence catch foreach static class from switch command function throw
        configuration hidden trap continue if try data in type define
        inlinescript until do interface using dynamicparam module var else
        namespace while elseif parallel workflow end param enum private
      ).join('|')

      # https://devblogs.microsoft.com/scripting/powertip-find-a-list-of-powershell-type-accelerators/
      # ([PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get).Keys -join ' '
      KEYWORDS_TYPE = %w(
        Alias AllowEmptyCollection AllowEmptyString AllowNull ArgumentCompleter
        array bool byte char CmdletBinding datetime decimal double DscResource
        float single guid hashtable int int32 int16 long int64 ciminstance
        cimclass cimtype cimconverter IPEndpoint NullString OutputType
        ObjectSecurity Parameter PhysicalAddress pscredential PSDefaultValue
        pslistmodifier psobject pscustomobject psprimitivedictionary ref
        PSTypeNameAttribute regex DscProperty sbyte string SupportsWildcards
        switch cultureinfo bigint securestring timespan uint16 uint32 uint64
        uri ValidateCount ValidateDrive ValidateLength ValidateNotNull
        ValidateNotNullOrEmpty ValidatePattern ValidateRange ValidateScript
        ValidateSet ValidateTrustedData ValidateUserDrive version void
        ipaddress DscLocalConfigurationManager WildcardPattern X509Certificate
        X500DistinguishedName xml CimSession adsi adsisearcher wmiclass wmi
        wmisearcher mailaddress scriptblock psvariable type psmoduleinfo
        powershell runspacefactory runspace initialsessionstate psscriptmethod
        psscriptproperty psnoteproperty psaliasproperty psvariableproperty
      ).join('|')

      OPERATORS = %w(
        -split -isplit -csplit -join -is -isnot -as -eq -ieq -ceq -ne -ine -cne
        -gt -igt -cgt -ge -ige -cge -lt -ilt -clt -le -ile -cle -like -ilike
        -clike -notlike -inotlike -cnotlike -match -imatch -cmatch -notmatch
        -inotmatch -cnotmatch -contains -icontains -ccontains -notcontains
        -inotcontains -cnotcontains -replace -ireplace -creplace -shl -shr -band
        -bor -bxor -and -or -xor -not \+= -= \*= \/= %=
      ).join('|')

      MULTILINE_KEYWORDS = %w(
        synopsis description parameter example inputs outputs notes link
        component role functionality forwardhelptargetname forwardhelpcategory
        remotehelprunspace externalhelp
      ).join('|')

      state :variable do
        rule %r/#{AUTO_VARS}/, Name::Builtin::Pseudo
        rule %r/(\$)(?:(\w+)(:))?(\w+|\{(?:[^`]|`.)+?\})/ do
          groups Name::Variable, Name::Namespace, Punctuation, Name::Variable
        end
        rule %r/\$\w+/, Name::Variable
        rule %r/\$\{(?:[^`]|`.)+?\}/, Name::Variable
      end

      state :multiline do
        rule %r/\.(?:#{MULTILINE_KEYWORDS})/i, Comment::Special
        rule %r/#>/, Comment::Multiline, :pop!
        rule %r/[^#.]+?/m, Comment::Multiline
        rule %r/[#.]+/, Comment::Multiline
      end

      state :interpol do
        rule %r/\)/, Str::Interpol, :pop!
        mixin :root
      end

      state :dq do
        # NB: "abc$" is literally the string abc$.
        # Here we prevent :interp from interpreting $" as a variable.
        rule %r/(?:\$#?)?"/, Str::Double, :pop!
        rule %r/\$\(/, Str::Interpol, :interpol
        rule %r/`$/, Str::Escape # line continuation
        rule %r/`./, Str::Escape
        rule %r/[^"`$]+/, Str::Double
        mixin :variable
      end

      state :sq do
        rule %r/'/, Str::Single, :pop!
        rule %r/[^']+/, Str::Single
      end

      state :heredoc do
        rule %r/(?:\$#?)?"@/, Str::Heredoc, :pop!
        rule %r/\$\(/, Str::Interpol, :interpol
        rule %r/`$/, Str::Escape # line continuation
        rule %r/`./, Str::Escape
        rule %r/[^"`$]+?/m, Str::Heredoc
        rule %r/"+/, Str::Heredoc
        mixin :variable
      end

      state :class do
        rule %r/\{/, Punctuation, :pop!
        rule %r/\s+/, Text::Whitespace
        rule %r/\w+/, Name::Class
        rule %r/[:,]/, Punctuation
      end

      state :expr do
        mixin :comments
        rule %r/"/, Str::Double, :dq
        rule %r/'/, Str::Single, :sq
        rule %r/@"/, Str::Heredoc, :heredoc
        rule %r/@'.*?'@/m, Str::Heredoc
        rule %r/\d*\.\d+/, Num::Float
        rule %r/\d+/, Num::Integer
        rule %r/@\{/, Punctuation, :hasht
        rule %r/@\(/, Punctuation, :array
        rule %r/{/, Punctuation, :brace
        rule %r/\[/, Punctuation, :bracket
      end

      state :hasht do
        rule %r/\}/, Punctuation, :pop!
        rule %r/=/, Operator
        rule %r/[,;]/, Punctuation
        mixin :expr
        rule %r/\w+/, Name::Other
        mixin :variable
      end

      state :array do
        rule %r/\s+/, Text::Whitespace
        rule %r/\)/, Punctuation, :pop!
        rule %r/[,;]/, Punctuation
        mixin :expr
        mixin :variable
      end

      state :brace do
        rule %r/[}]/, Punctuation, :pop!
        mixin :root
      end

      state :bracket do
        rule %r/\]/, Punctuation, :pop!
        rule %r/[A-Za-z]\w+\./, Name
        rule %r/([A-Za-z]\w+)/ do |m|
          if ATTRIBUTES.include? m[0]
            token Name::Builtin::Pseudo
          else
            token Name
          end
        end
        mixin :root
      end

      state :parameters do
        rule %r/`./m, Str::Escape
        rule %r/\)/ do
          token Punctuation
          pop!(2) if in_state?(:interpol) # pop :parameters and :interpol
        end
        rule %r/\s*?\n/, Text::Whitespace, :pop!
        rule %r/[;(){}\]]/, Punctuation, :pop!
        rule %r/[|=]/, Operator, :pop!
        rule %r/[\/\\~\w][-.:\/\\~\w]*/, Name::Other
        rule %r/\w[-\w]+/, Name::Other
        mixin :root
      end

      state :comments do
        rule %r/\s+/, Text::Whitespace
        rule %r/#.*/, Comment
        rule %r/<#/, Comment::Multiline, :multiline
      end

      state :root do
        mixin :comments
        rule %r/#requires\s-version \d(?:\.\d+)?/, Comment::Preproc

        rule %r/\.\.(?=\.?\d)/, Operator
        rule %r/(?:#{OPERATORS})\b/i, Operator

        rule %r/(class)(\s+)(\w+)/i do
          groups Keyword::Reserved, Text::Whitespace, Name::Class
          push :class
        end
        rule %r/(function)(\s+)(?:(\w+)(:))?(\w[-\w]+)/i do
          groups Keyword::Reserved, Text::Whitespace, Name::Namespace, Punctuation, Name::Function
        end
        rule %r/(?:#{KEYWORDS})\b(?![-.])/i, Keyword::Reserved

        rule %r/-{1,2}\w+/, Name::Tag

        rule %r/(\.)?([-\w]+)(\[)/ do |m|
          groups Operator, Name, Punctuation
          push :bracket
        end

        rule %r/([\/\\~[a-z]][-.:\/\\~\w]*)(\n)?/i do |m|
          groups Name, Text::Whitespace
          push :parameters
        end

        rule %r/(\.)([-\w]+)(?:(\()|(\n))?/ do |m|
          groups Operator, Name::Function, Punctuation, Text::Whitespace
          push :parameters unless m[3].nil?
        end

        rule %r/\?/, Name::Function, :parameters

        mixin :expr
        mixin :variable

        rule %r/[-+*\/%=!.&|]/, Operator
        rule %r/[{}(),:;]/, Punctuation

        rule %r/`$/, Str::Escape # line continuation
      end
    end
  end
end