class Pincerna::Base

Base class for all filter.

@attribute [r] output

@return [String] The output of filtering.

@attribute [r] format

@return [Symbol] The format of output. Can be `:xml` (default) or `:yml`.

@attribute [r] format_content_type

@return [String] The content type of the format. Can be `text/xml` (default) or `text/x-yaml`.

Constants

CACHE_ROOT

The root of the cache

FULL_NAME

The full name of the gem

MATCHER

The expression to match.

RELEVANT_MATCHES

Relevant groups in the match.

ROOT

The root of the pincerna gem

TYPES

Recognized types of filtering

WORKFLOW_ROOT

The root of alfred workflows

Attributes

format[R]
format_content_type[R]
output[R]

Public Class Methods

execute!(type, query, format = :xml, debug = nil) click to toggle source

Executes a filtering query.

@param type [Symbol] The type of the query. @param query [String] The argument of the query. @param format [String] The format to use. Valid values are `:xml` (default) and `:yml`. @param debug [String] The debug mode. @return [String] The result of the query.

# File lib/pincerna/base.rb, line 61
def self.execute!(type, query, format = :xml, debug = nil)
  instance = nil

  type = catch(:type) do
    TYPES.each do |file, matcher|
      throw(:type, file) if type =~ matcher
    end

    nil
  end

  if type
    instance = find_class(type).new(query, format, debug)
    instance.filter
  end

  instance
end
new(query, requested_format = "xml", debug = nil) click to toggle source

Creates a new query.

@param query [String] The argument of the query. @param requested_format [String] The format to use. Valid values are `xml` (default), `yaml` or `yml`. @param debug [String] The debug mode.

# File lib/pincerna/base.rb, line 85
def initialize(query, requested_format = "xml", debug = nil)
  @query = query.strip.gsub("\\ ", " ")
  @cache_dir = CACHE_ROOT

  if requested_format =~ /^y(a?)ml$/i then
    @format = :yml
    @format_content_type = "text/x-yaml"
  else
    @format = :xml
    @format_content_type = "text/xml"
  end

  @debug = debug
  @feedback_items = []
end

Protected Class Methods

find_class(file) click to toggle source

Instantiates the new class.

@param file [String] The file name.

# File lib/pincerna/base.rb, line 186
def self.find_class(file)
  Pincerna.const_get(file.capitalize.gsub(/_(.)/) { $1.upcase})
end

Public Instance Methods

add_feedback_item(item) click to toggle source

Adds a feedback items.

@param item [Array] The items to add.

# File lib/pincerna/base.rb, line 138
def add_feedback_item(item)
  @feedback_items << item
end
filter() click to toggle source

Filters a query.

@return [String] The feedback items of the query, formatted as XML.

# File lib/pincerna/base.rb, line 104
def filter
  # Match the query
  matches = self.class::MATCHER.match(@query)

  if matches then
    # Execute the filtering
    results = execute_filtering(matches)

    # Show results if appropriate
    process_results(results).each {|r| add_feedback_item(r) } if !results.empty?
  end

  output_feedback
end
format_float(value, precision = 3) click to toggle source

Rounds a float to a certain precision and prints it as a string. Unneeded leading zero are remove.

@param value [Float] The value to print. @param precision [Fixnum] The precision to use. @return [String] The formatted value.

# File lib/pincerna/base.rb, line 176
def format_float(value, precision = 3)
  value = round_float(value, precision)
  value = "%0.#{precision}f" % value
  value.gsub(/\.?0+$/, "")
end
output_feedback() click to toggle source

Prepares the feedback for output.

# File lib/pincerna/base.rb, line 143
def output_feedback
  if format == :xml then
    @output = Nokogiri::XML::Builder.new { |xml|
      xml.items do
        @feedback_items.each do |item|
          childs, attributes = split_output_item(item)

          xml.item(attributes) do
            childs.each { |name, value| xml.send(name, value) }
          end
        end
      end
    }.to_xml
  else
    @output = @feedback_items.to_yaml
  end
end
perform_filtering(*args) click to toggle source

Filters a query.

@param args [Array] The arguments of the query. @return [Array] A list of items to process.

# File lib/pincerna/base.rb, line 123
def perform_filtering(*args)
  raise ArgumentError.new("Must be overriden by subclasses.")
end
process_results(results) click to toggle source

Processes items to obtain feedback items.

@param results [Array] The items to process. @return [Array] The feedback items.

# File lib/pincerna/base.rb, line 131
def process_results(results)
  raise ArgumentError.new("Must be overriden by subclasses.")
end
round_float(value, precision = 3) click to toggle source

Rounds a float to a certain precision.

@param value [Float] The value to convert. @param precision [Fixnum] The precision to use. @return [Float] The rounded value.

# File lib/pincerna/base.rb, line 166
def round_float(value, precision = 3)
  factor = 10**precision
  (value * factor).round.to_f / factor
end

Protected Instance Methods

array_to_hash(array) click to toggle source

Converts an array of key-value pairs to an hash.

@param array [Array] The array to convert. @return [Hash] The converted hash.

# File lib/pincerna/base.rb, line 212
def array_to_hash(array)
  array.reduce({}){ |rv, entry|
    rv[entry[0]] = entry[1]
    rv
  }
end
debug_mode() click to toggle source

Returns the current debug mode.

@return [Boolean|NilClass] The current debug mode.

# File lib/pincerna/base.rb, line 253
def debug_mode
  mode = ENV["PINCERNA_DEBUG"] || @debug
  !mode.nil? ? mode.to_sym : nil
end
execute_command(*args) click to toggle source

Executes a command and returns its output.

@param args [Array] The command to execute, with its arguments. @return [String] The output of the command

# File lib/pincerna/base.rb, line 244
def execute_command(*args)
  rv = ""
  IO.popen(args) {|f| rv = f.read }
  rv
end
execute_filtering(matches) click to toggle source

Executes filtering on matched data.

@param matches [MatchData] The matched data. @return [Array] The results of filtering.

# File lib/pincerna/base.rb, line 194
def execute_filtering(matches)
  # Get relevant matches and arguments.
  relevant = self.class::RELEVANT_MATCHES
  args = relevant.map {|key, value| value.call(self, matches[key]) }

  # Now perform the operation
  begin
    perform_filtering(*args)
  rescue => e
    raise e if debug_mode == :error
    []
  end
end
fetch_remote_resource(url, params, json = true) click to toggle source

Fetches remote JSON resource.

@param url [String] The URL to get. @param params [Hash] The parameters to pass to the server. @param json [Boolean] If the response is a JSON object. @return [Hash] The server's response.

# File lib/pincerna/base.rb, line 233
def fetch_remote_resource(url, params, json = true)
  args = {query: params}
  args[:head] = {"accept" => "application/json"} if json
  response = EM::HttpRequest.new(url, {connect_timeout: 5}).get(args).response
  json ? Oj.load(response) : response
end
split_output_item(item) click to toggle source

Gets attributes and children for output.

@param item [Hash] The output item. @return [Array] An array with children and attributes.

# File lib/pincerna/base.rb, line 223
def split_output_item(item)
  item.partition {|k, _| [:title, :subtitle, :icon].include?(k) }.map {|a| array_to_hash(a) }
end