<commit_before>
require 'chef/knife/cloud/command'

class Chef
  class Knife
    class Cloud
      class ResourceListCommand < Command
        attr_accessor :resource_filters # array of filters in form {:attribute => attribute-name, :regex => 'filter regex value'}

        def exec_command(*params)
          @resource_filters = params[0] if !params.empty? # TODO - we can also take this from cli, for now let cloud-plugin set this.

          # exec the cmd
          resources = query_resource

          # handle the response
          list(resources)
        end

        def query_resource
          # specific resource type must override this.
          raise Chef::Exceptions::Override, "You must override query_resource in #{self.to_s} to return resources."
        end

        def is_resource_filtered?(attribute, value)
          return false if resource_filters.nil?
          resource_filters.each do |filter|
            if attribute == filter[:attribute] and value =~ filter[:regex]
              return true
            end
          end
          false
        end

        # When columns_with_info is nil display all
        # columns_with_info is array of hash with label, key and attribute extraction callback, ex [{'label' => "Label text", key => 'key', value_callback => callback_method to extract/format the required value}, ...]
        def list(resources, columns_with_info = [])
          # display column wise only if columns_with_info is specified, else as a json for readable display.
          begin
            resource_list = columns_with_info.map { |col_info| ui.color(col_info[:label], :bold) } if columns_with_info.length > 0
            resources.sort_by(&:id).each do |resource|
              resource_filtered = false
              if columns_with_info.length > 0
                list = []
                columns_with_info.each do |col_info|
                  value = (col_info[:value_callback].nil? ? resource.send(col_info[:key]).to_s : col_info[:value_callback].call(resource.send(col_info[:key])))
                  if !@app.config[:disable_filter]
                    resource_filtered = true if is_resource_filtered?(col_info[:key], value)
                  end
                  list << value
                end
                resource_list.concat(list) unless resource_filtered
              else
                puts resource.to_json
                puts "\n"
              end
            end
          rescue Excon::Errors::BadRequest => e<commit_msg>make sort field configurable for resource listing.<commit_after>
require 'chef/knife/cloud/command'

class Chef
  class Knife
    class Cloud
      class ResourceListCommand < Command
        attr_accessor :sort_by_field
        attr_accessor :resource_filters # array of filters in form {:attribute => attribute-name, :regex => 'filter regex value'}

        def initialize(app, service)
          super
          @sort_by_field = "id" # default sort by id
        end

        def exec_command(*params)
          @resource_filters = params[0] if !params.empty? # TODO - we can also take this from cli, for now let cloud-plugin set this.

          # exec the cmd
          resources = query_resource

          # handle the response
          list(resources)
        end

        def query_resource
          # specific resource type must override this.
          raise Chef::Exceptions::Override, "You must override query_resource in #{self.to_s} to return resources."
        end

        def is_resource_filtered?(attribute, value)
          return false if resource_filters.nil?
          resource_filters.each do |filter|
            if attribute == filter[:attribute] and value =~ filter[:regex]
              return true
            end
          end
          false
        end

        # When columns_with_info is nil display all
        # columns_with_info is array of hash with label, key and attribute extraction callback, ex [{'label' => "Label text", key => 'key', value_callback => callback_method to extract/format the required value}, ...]
        def list(resources, columns_with_info = [])
          # display column wise only if columns_with_info is specified, else as a json for readable display.
          begin
            resource_list = columns_with_info.map { |col_info| ui.color(col_info[:label], :bold) } if columns_with_info.length > 0
            resources.sort_by(&sort_by_field.to_sym).each do |resource|
              resource_filtered = false
              if columns_with_info.length > 0
                list = []
                columns_with_info.each do |col_info|
                  value = (col_info[:value_callback].nil? ? resource.send(col_info[:key]).to_s : col_info[:value_callback].call(resource.send(col_info[:key])))
                  if !@app.config[:disable_filter]
                    resource_filtered = true if is_resource_filtered?(col_info[:key], value)
                  end
                  list << value
                end
                resource_list.concat(list) unless resource_filtered
              else
                puts resource.to_json
                puts "\n"
              end
            end
          rescue Excon::Errors::BadRequest => e
{'fraction_non_alphanumeric': 0.07972403219624377, 'fraction_numerical': 0.0011498658489842851, 'mean_word_length': 2.0502630040911747, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '404873', 'n_tokens_mistral': 1350, 'n_tokens_neox': 1300, 'n_words': 408}