lib/rouge/lexers/batchfile.rb
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
module Rouge
module Lexers
class Batchfile < RegexLexer
title "Batchfile"
desc "Windows Batch File"
tag 'batchfile'
aliases 'bat', 'batch', 'dosbatch', 'winbatch'
filenames '*.bat', '*.cmd'
mimetypes 'application/bat', 'application/x-bat', 'application/x-msdos-program'
def self.keywords
@keywords ||= %w(
if else for in do goto call exit
)
end
def self.operator_words
@operator_words ||= %w(
exist defined errorlevel cmdextversion not equ neq lss leq gtr geq
)
end
def self.devices
@devices ||= %w(
con prn aux nul com1 com2 com3 com4 com5 com6 com7 com8 com9 lpt1 lpt2
lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9
)
end
def self.builtin_commands
@builtin_commands ||= %w(
assoc attrib break bcdedit cacls cd chcp chdir chkdsk chkntfs choice
cls cmd color comp compact convert copy date del dir diskpart doskey
dpath driverquery echo endlocal erase fc find findstr format fsutil
ftype gpresult graftabl help icacls label md mkdir mklink mode more
move openfiles path pause popd print prompt pushd rd recover ren
rename replace rmdir robocopy setlocal sc schtasks shift shutdown sort
start subst systeminfo takeown tasklist taskkill time timeout title
tree type ver verify vol xcopy waitfor wmic
)
end
def self.other_commands
@other_commands ||= %w(
addusers admodcmd ansicon arp at bcdboot bitsadmin browstat certreq
certutil change cidiag cipher cleanmgr clip cmdkey compress convertcp
coreinfo csccmd csvde cscript curl debug defrag delprof deltree devcon
diamond dirquota diruse diskshadow diskuse dism dnscmd dsacls dsadd
dsget dsquery dsmod dsmove dsrm dsmgmt dsregcmd edlin eventcreate
expand extract fdisk fltmc forfiles freedisk ftp getmac gpupdate
hostname ifmember inuse ipconfig kill lgpo lodctr logman logoff
logtime makecab mapisend mbsacli mem mountvol moveuser msg mshta
msiexec msinfo32 mstsc nbtstat net net1 netdom netsh netstat nlsinfo
nltest now nslookup ntbackup ntdsutil ntoskrnl ntrights nvspbind
pathping perms ping portqry powercfg pngout pnputil printbrm prncnfg
prnmngr procdump psexec psfile psgetsid psinfo pskill pslist
psloggedon psloglist pspasswd psping psservice psshutdown pssuspend
qbasic qgrep qprocess query quser qwinsta rasdial reg reg1 regdump
regedt32 regsvr32 regini reset restore rundll32 rmtshare route rpcping
run runas scandisk setspn setx sfc share shellrunas shortcut sigcheck
sleep slmgr strings subinacl sysmon telnet tftp tlist touch tracerpt
tracert tscon tsdiscon tskill tttracer typeperf tzutil undelete
unformat verifier vmconnect vssadmin w32tm wbadmin wecutil wevtutil
wget where whoami windiff winrm winrs wpeutil wpr wusa wuauclt wscript
)
end
def self.attributes
@attributes ||= %w(
on off disable enableextensions enabledelayedexpansion
)
end
state :basic do
# Comments
rule %r/@?\brem\b.*$/i, Comment
# Empty Labels
rule %r/^::.*$/, Comment
# Labels
rule %r/:[a-z]+/i, Name::Label
rule %r/([a-z]\w*)(\.exe|com|bat|cmd|msi)?/i do |m|
if self.class.devices.include? m[1]
groups Keyword::Reserved, Error
elsif self.class.keywords.include? m[1]
groups Keyword, Error
elsif self.class.operator_words.include? m[1]
groups Operator::Word, Error
elsif self.class.builtin_commands.include? m[1]
token Name::Builtin
elsif self.class.other_commands.include? m[1]
token Name::Builtin
elsif self.class.attributes.include? m[1]
groups Name::Attribute, Error
elsif "set".casecmp m[1]
groups Keyword::Declaration, Error
else
token Text
end
end
rule %r/((?:[\/\+]|--?)[a-z]+)\s*/i, Name::Attribute
mixin :expansions
rule %r/[<>&|(){}\[\]\-+=;,~?*]/, Operator
end
state :escape do
rule %r/\^./m, Str::Escape
end
state :expansions do
# Normal and Delayed expansion
rule %r/[%!]+([a-z_$@#]+)[%!]+/i, Name::Variable
# For Variables
rule %r/(\%+~?[a-z]+\d?)/i, Name::Variable::Magic
end
state :double_quotes do
mixin :escape
rule %r/["]/, Str::Double, :pop!
mixin :expansions
rule %r/[^\^"%!]+/, Str::Double
end
state :single_quotes do
mixin :escape
rule %r/[']/, Str::Single, :pop!
mixin :expansions
rule %r/[^\^'%!]+/, Str::Single
end
state :backtick do
mixin :escape
rule %r/[`]/, Str::Backtick, :pop!
mixin :expansions
rule %r/[^\^`%!]+/, Str::Backtick
end
state :data do
rule %r/\s+/, Text
rule %r/0x[0-9a-f]+/i, Literal::Number::Hex
rule %r/[0-9]/, Literal::Number
rule %r/["]/, Str::Double, :double_quotes
rule %r/[']/, Str::Single, :single_quotes
rule %r/[`]/, Str::Backtick, :backtick
rule %r/[^\s&|()\[\]{}\^=;!%+\-,"'`~?*]+/, Text
mixin :escape
end
state :root do
mixin :basic
mixin :data
end
end
end
end