File: viml.rb

package info (click to toggle)
ruby-rugments 1.0.0~beta8-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 820 kB
  • sloc: ruby: 10,293; makefile: 2
file content (99 lines) | stat: -rw-r--r-- 2,611 bytes parent folder | download | duplicates (3)
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
module Rugments
  module Lexers
    class VimL < RegexLexer
      title 'VimL'
      desc 'VimL, the scripting language for the Vim editor (vim.org)'
      tag 'viml'
      aliases 'vim', 'vimscript', 'ex'
      filenames '*.vim', '*.vba', '.vimrc', '.exrc', '.gvimrc',
                '_vimrc', '_exrc', '_gvimrc' # _ names for windows

      mimetypes 'text/x-vim'

      def self.keywords
        load Pathname.new(__FILE__).dirname.join('viml/keywords.rb')
        keywords
      end

      state :root do
        rule /^(\s*)(".*?)$/ do
          groups Text, Comment
        end

        rule /^\s*\\/, Str::Escape

        rule /[ \t]+/, Text

        # TODO: regexes can have other delimiters
        rule %r{/(\\\\|\\/|[^\n/])*/}, Str::Regex
        rule %r{"(\\\\|\\"|[^\n"])*"}, Str::Double
        rule %r{'(\\\\|\\'|[^\n'])*'}, Str::Single

        # if it's not a string, it's a comment.
        rule /(?<=\s)"[^-:.%#=*].*?$/, Comment

        rule /-?\d+/, Num
        rule /#[0-9a-f]{6}/i, Num::Hex
        rule /^:/, Punctuation
        rule /[():<>+=!\[\]{}\|,~.-]/, Punctuation
        rule /\b(let|if|else|endif|elseif|fun|function|endfunction)\b/,
             Keyword

        rule /\b(NONE|bold|italic|underline|dark|light)\b/, Name::Builtin

        rule /[absg]:\w+\b/, Name::Variable
        rule /\b\w+\b/ do |m|
          name = m[0]
          keywords = self.class.keywords

          if mapping_contains?(keywords[:command], name)
            token Keyword
          elsif mapping_contains?(keywords[:option], name)
            token Name::Builtin
          elsif mapping_contains?(keywords[:auto], name)
            token Name::Builtin
          else
            token Text
          end
        end

        # no errors in VimL!
        rule /./m, Text
      end

      def mapping_contains?(mapping, word)
        shortest, longest = find_likely_mapping(mapping, word)

        shortest and word.start_with?(shortest) and
          longest and longest.start_with?(word)
      end

      # binary search through the mappings to find the one that's likely
      # to actually work.
      def find_likely_mapping(mapping, word)
        min = 0
        max = mapping.size

        until max == min
          mid = (max + min) / 2

          cmp, _ = mapping[mid]

          case word <=> cmp
          when 1
            # too low
            min = mid + 1
          when -1
            # too high
            max = mid
          when 0
            # just right, abort!
            return mapping[mid]
          end
        end

        mapping[max - 1]
      end
    end
  end
end