PageRenderTime 25ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/rouge/lexers/shell.rb

https://gitlab.com/lukas.mesicek/gitlab-rouge
Ruby | 152 lines | 124 code | 19 blank | 9 comment | 4 complexity | f8c564cf9a0f341cedfd9803be86ebbd MD5 | raw file
  1. # -*- coding: utf-8 -*- #
  2. module Rouge
  3. module Lexers
  4. class Shell < RegexLexer
  5. title "shell"
  6. desc "Various shell languages, including sh and bash"
  7. tag 'shell'
  8. aliases 'bash', 'zsh', 'ksh', 'sh'
  9. filenames '*.sh', '*.bash', '*.zsh', '*.ksh',
  10. '.bashrc', '.zshrc', '.kshrc', '.profile', 'PKGBUILD'
  11. mimetypes 'application/x-sh', 'application/x-shellscript'
  12. def self.analyze_text(text)
  13. text.shebang?(/(ba|z|k)?sh/) ? 1 : 0
  14. end
  15. KEYWORDS = %w(
  16. if fi else while do done for then return function
  17. select continue until esac elif in
  18. ).join('|')
  19. BUILTINS = %w(
  20. alias bg bind break builtin caller cd command compgen
  21. complete declare dirs disown echo enable eval exec exit
  22. export false fc fg getopts hash help history jobs kill let
  23. local logout popd printf pushd pwd read readonly set shift
  24. shopt source suspend test time times trap true type typeset
  25. ulimit umask unalias unset wait
  26. ).join('|')
  27. state :basic do
  28. rule /#.*$/, Comment
  29. rule /\b(#{KEYWORDS})\s*\b/, Keyword
  30. rule /\bcase\b/, Keyword, :case
  31. rule /\b(#{BUILTINS})\s*\b(?!\.)/, Name::Builtin
  32. rule /^\S*[\$%>#] +/, Generic::Prompt
  33. rule /(\b\w+)(=)/ do |m|
  34. groups Name::Variable, Operator
  35. end
  36. rule /[\[\]{}()=]/, Operator
  37. rule /&&|\|\|/, Operator
  38. # rule /\|\|/, Operator
  39. rule /<<</, Operator # here-string
  40. rule /<<-?\s*(\'?)\\?(\w+)\1/ do |m|
  41. lsh = Str::Heredoc
  42. token lsh
  43. heredocstr = Regexp.escape(m[2])
  44. push do
  45. rule /\s*#{heredocstr}\s*\n/, lsh, :pop!
  46. rule /.*?\n/, lsh
  47. end
  48. end
  49. end
  50. state :double_quotes do
  51. # NB: "abc$" is literally the string abc$.
  52. # Here we prevent :interp from interpreting $" as a variable.
  53. rule /(?:\$#?)?"/, Str::Double, :pop!
  54. mixin :interp
  55. rule /[^"`\\$]+/, Str::Double
  56. end
  57. state :single_quotes do
  58. rule /'/, Str::Single, :pop!
  59. rule /[^']+/, Str::Single
  60. end
  61. state :data do
  62. rule /\s+/, Text
  63. rule /\\./, Str::Escape
  64. rule /\$?"/, Str::Double, :double_quotes
  65. # single quotes are much easier than double quotes - we can
  66. # literally just scan until the next single quote.
  67. # POSIX: Enclosing characters in single-quotes ( '' )
  68. # shall preserve the literal value of each character within the
  69. # single-quotes. A single-quote cannot occur within single-quotes.
  70. rule /$?'/, Str::Single, :single_quotes
  71. rule /\*/, Keyword
  72. rule /;/, Text
  73. rule /[^=\*\s{}()$"'`\\<]+/, Text
  74. rule /\d+(?= |\Z)/, Num
  75. rule /</, Text
  76. mixin :interp
  77. end
  78. state :curly do
  79. rule /}/, Keyword, :pop!
  80. rule /:-/, Keyword
  81. rule /[a-zA-Z0-9_]+/, Name::Variable
  82. rule /[^}:"`'$]+/, Punctuation
  83. mixin :root
  84. end
  85. state :paren do
  86. rule /\)/, Keyword, :pop!
  87. mixin :root
  88. end
  89. state :math do
  90. rule /\)\)/, Keyword, :pop!
  91. rule %r([-+*/%^|&]|\*\*|\|\|), Operator
  92. rule /\d+/, Num
  93. mixin :root
  94. end
  95. state :case do
  96. rule /\besac\b/, Keyword, :pop!
  97. rule /\|/, Punctuation
  98. rule /\)/, Punctuation, :case_stanza
  99. mixin :root
  100. end
  101. state :case_stanza do
  102. rule /;;/, Punctuation, :pop!
  103. mixin :root
  104. end
  105. state :backticks do
  106. rule /`/, Str::Backtick, :pop!
  107. mixin :root
  108. end
  109. state :interp do
  110. rule /\\$/, Str::Escape # line continuation
  111. rule /\\./, Str::Escape
  112. rule /\$\(\(/, Keyword, :math
  113. rule /\$\(/, Keyword, :paren
  114. rule /\${#?/, Keyword, :curly
  115. rule /`/, Str::Backtick, :backticks
  116. rule /\$#?(\w+|.)/, Name::Variable
  117. end
  118. state :root do
  119. mixin :basic
  120. mixin :data
  121. end
  122. end
  123. end
  124. end