File: level.rb

package info (click to toggle)
ruby-yell 2.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 272 kB
  • sloc: ruby: 1,125; makefile: 2
file content (213 lines) | stat: -rw-r--r-- 5,497 bytes parent folder | download
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
module Yell #:nodoc:

  # The +Level+ class handles the severities for you in order to determine 
  # if an adapter should log or not.
  #
  # In order to setup your level, you have certain modifiers available:
  #   at :warn    # will be set to :warn level only
  #   gt :warn    # Will set from :error level onwards
  #   gte :warn   # Will set from :warn level onwards
  #   lt :warn    # Will set from :info level an below
  #   lte :warn   # Will set from :warn level and below
  #
  # You are able to combine those modifiers to your convenience.
  #
  # @example Set from :info to :error (including)
  #   Yell::Level.new(:info).lte(:error)
  #
  # @example Set from :info to :error (excluding)
  #   Yell::Level.new(:info).lt(:error)
  #
  # @example Set at :info only
  #   Yell::Level.new.at(:info)
  class Level
    include Comparable

    InterpretRegexp = /(at|gt|gte|lt|lte)?\.?(#{Yell::Severities.join('|')})/i

    # Create a new level instance.
    #
    # @example Enable all severities
    #   Yell::Level.new
    #
    # @example Pass the minimum possible severity
    #   Yell::Level.new :warn
    #
    # @example Pass an array to exactly set the level at the given severities
    #   Yell::Level.new [:info, :error]
    #
    # @example Pass a range to set the level within the severities
    #   Yell::Level.new (:info..:error)
    #
    # @param [Integer,String,Symbol,Array,Range,nil] severity The severity for the level.
    def initialize( *severities )
      @tainted = false
      set(*severities)
    end

    # Set the severity to the given format
    def set( *severities )
      @severities = Yell::Severities.map { true }
      severity = severities.length > 1 ? severities : severities.first

      case severity
      when Array then at(*severity)
      when Range then gte(severity.first).lte(severity.last)
      when String then interpret(severity)
      when Integer, Symbol then gte(severity)
      when Yell::Level then @severities = severity.severities
      end
    end

    # Returns whether the level is allowed at the given severity
    #
    # @example
    #   at? :warn
    #   at? 0       # debug
    #
    # @return [Boolean] tru or false
    def at?( severity )
      index = index_from(severity)

      index.nil? ? false : @severities[index]
    end

    # Set the level at specific severities
    #
    # @example Set at :debug and :error only
    #   at :debug, :error
    #
    # @return [Yell::Level] the instance
    def at( *severities )
      severities.each { |severity| calculate! :==, severity }
      self
    end

    # Set the level to greater than the given severity
    #
    # @example Set to :error and above
    #   gt :warn
    #
    # @return [Yell::Level] the instance
    def gt( severity )
      calculate! :>, severity
      self
    end

    # Set the level greater or equal to the given severity
    #
    # @example Set to :warn and above
    #   gte :warn
    #
    # @return [Yell::Level] the instance
    def gte( severity )
      calculate! :>=, severity
      self
    end

    # Set the level lower than given severity
    #
    # @example Set to lower than :warn
    #   lt :warn
    #
    # @return [Yell::Level] the instance
    def lt( severity )
      calculate! :<, severity
      self
    end

    # Set the level lower or equal than given severity
    #
    # @example Set to lower or equal than :warn
    #   lte :warn
    #
    # @return [Yell::Level] the instance
    def lte( severity )
      calculate! :<=, severity
      self
    end

    # to_i implements backwards compatibility
    def to_i
      @severities.each_with_index { |s,i| return i if s == true }
    end
    alias :to_int :to_i

    # Get a pretty string representation of the level, including the severities.
    def inspect
      inspectables = Yell::Severities.select.with_index { |l, i| !!@severities[i] }
      "#<#{self.class.name} severities: #{inspectables * ', '}>"
    end

    # @private
    def severities
      @severities
    end

    # @private
    def ==(other)
      other.respond_to?(:severities) ? severities == other.severities : super
    end

    # @private
    def <=>( other )
      other.is_a?(Numeric) ? to_i <=> other : super
    end


    private

    def interpret( severities )
      severities.split( ' ' ).each do |severity|
        if m = InterpretRegexp.match(severity)
          m[1].nil? ? __send__( :gte, m[2] ) : __send__( m[1], m[2] )
        end
      end
    end

    def calculate!( modifier, severity )
      index = index_from(severity)
      return if index.nil?

      case modifier
      when :>   then ascending!( index+1 )
      when :>=  then ascending!( index )
      when :<   then descending!( index-1 )
      when :<=  then descending!( index )
      else set!( index ) # :==
      end

      @tainted = true unless @tainted
    end

    def index_from( severity )
      case severity
      when String, Symbol then Yell::Severities.index(severity.to_s.upcase)
      else Integer(severity)
      end
    end

    def ascending!( index )
      each { |s, i| @severities[i] = i < index ? false : true }
    end

    def descending!( index )
      each { |s, i| @severities[i] = index < i ? false : true }
    end

    def each
      @severities.each_with_index do |s, i|
        next if s == false # skip

        yield(s, i)
      end
    end

    def set!( index, val = true )
      @severities.map! { false } unless @tainted

      @severities[index] = val
    end

  end
end