File: sed.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 (167 lines) | stat: -rw-r--r-- 3,915 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
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
module Rugments
  module Lexers
    class Sed < RegexLexer
      title 'sed'
      desc 'sed, the ultimate stream editor'

      tag 'sed'
      filenames '*.sed'
      mimetypes 'text/x-sed'

      def self.analyze_text(text)
        return 1 if text.shebang? 'sed'
      end

      class Regex < RegexLexer
        state :root do
          rule /\\./, Str::Escape
          rule /\[/, Punctuation, :brackets
          rule /[$^.*]/, Operator
          rule /[()]/, Punctuation
          rule /./, Str::Regex
        end

        state :brackets do
          rule /\^?/ do
            token Punctuation
            goto :brackets_int
          end
        end

        state :brackets_int do
          # ranges
          rule /.-./, Name::Variable
          rule /\]/, Punctuation, :pop!
          rule /./, Str::Regex
        end
      end

      class Replacement < RegexLexer
        state :root do
          rule /\\./m, Str::Escape
          rule /&/, Operator
          rule /[^\\&]+/m, Text
        end
      end

      def regex
        @regex ||= Regex.new(options)
      end

      def replacement
        @replacement ||= Replacement.new(options)
      end

      start { regex.reset!; replacement.reset! }

      state :whitespace do
        rule /\s+/m, Text
        rule(/#.*?\n/) { token Comment; reset_stack }
        rule(/\n/) { token Text; reset_stack }
        rule(/;/) { token Punctuation; reset_stack }
      end

      state :root do
        mixin :addr_range
      end

      edot = /\\.|./m

      state :command do
        mixin :whitespace

        # subst and transliteration
        rule /(s)(.)(#{edot}*?)(\2)(#{edot}*?)(\2)/m do |m|
          token Keyword, m[1]
          token Punctuation, m[2]
          delegate regex, m[3]
          token Punctuation, m[4]
          delegate replacement, m[5]
          token Punctuation, m[6]

          goto :flags
        end

        rule /(y)(.)(#{edot}*?)(\2)(#{edot}*?)(\2)/m do |m|
          token Keyword, m[1]
          token Punctuation, m[2]
          delegate replacement, m[3]
          token Punctuation, m[4]
          delegate replacement, m[5]
          token Punctuation, m[6]

          pop!
        end

        # commands that take a text segment as an argument
        rule /([aic])(\s*)/ do
          groups Keyword, Text; goto :text
        end

        rule /[pd]/, Keyword

        # commands that take a number argument
        rule /([qQl])(\s+)(\d+)/i do
          groups Keyword, Text, Num
          pop!
        end

        # no-argument commands
        rule /[={}dDgGhHlnpPqx]/, Keyword, :pop!

        # commands that take a filename argument
        rule /([rRwW])(\s+)(\S+)/ do
          groups Keyword, Text, Name
          pop!
        end

        # commands that take a label argument
        rule /([:btT])(\s+)(\S+)/ do
          groups Keyword, Text, Name::Label
          pop!
        end
      end

      state :addr_range do
        mixin :whitespace

        ### address ranges ###
        addr_tok = Keyword::Namespace
        rule /\d+/, addr_tok
        rule /[$,~+!]/, addr_tok

        rule %r{(/)(\\.|.)*?(/)} do |m|
          token addr_tok, m[1]; delegate regex, m[2]; token addr_tok, m[3]
        end

        # alternate regex rage delimiters
        rule %r{(\\)(.)(\\.|.)*?(\2)} do |m|
          token addr_tok, m[1] + m[2]
          delegate regex, m[3]
          token addr_tok, m[4]
        end

        rule(//) { push :command }
      end

      state :text do
        rule /[^\\\n]+/, Str
        rule /\\\n/, Str::Escape
        rule /\\/, Str
        rule /\n/, Text, :pop!
      end

      state :flags do
        rule /[gp]+/, Keyword, :pop!

        # writing to a file with the subst command.
        # who'da thunk...?
        rule /([wW])(\s+)(\S+)/ do
          token Keyword; token Text; token Name
        end

        rule(//) { pop! }
      end
    end
  end
end