checkoff 0.66.0 → 0.67.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/GLOSSARY.md +11 -0
- data/Gemfile.lock +1 -1
- data/lib/checkoff/internal/section_selector_evaluator.rb +56 -0
- data/lib/checkoff/internal/selector_classes/section/function_evaluator.rb +33 -0
- data/lib/checkoff/internal/selector_classes/section.rb +31 -0
- data/lib/checkoff/internal/selector_classes/task.rb +3 -1
- data/lib/checkoff/my_tasks.rb +2 -1
- data/lib/checkoff/project_selectors.rb +0 -2
- data/lib/checkoff/section_selectors.rb +77 -0
- data/lib/checkoff/sections.rb +7 -4
- data/lib/checkoff/task_selectors.rb +0 -2
- data/lib/checkoff/tasks.rb +10 -0
- data/lib/checkoff/version.rb +1 -1
- data/lib/checkoff.rb +1 -0
- metadata +7 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 63b887dd83f103cab32923b8326be62de742bc54b4e137a390d005366d57d1c6
         | 
| 4 | 
            +
              data.tar.gz: b65f844a89f4bb5821fec1845d417838b61ef317e59b93c1b4825daf97a59ac2
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 27ecc27a347c29621c95690e93c3614955295b231dec563703f5db8b2a7647c013eacf70b79c6756b6a39dfb5f1b7bcdbfe2fe56a70ab668e40c2ff66d339f22
         | 
| 7 | 
            +
              data.tar.gz: 8633ada2cb84d24b32ab6fa1585a648902718d4cf318f5c15ebb6fc1d36bcce076aff818e4406a7931c3450136cd04f4f3d47a4e3e13f2cfb9c60b9b827028a3
         | 
    
        data/GLOSSARY.md
    ADDED
    
    | @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            # Glossary
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * ready/due: See tasks.rb#task_ready?.  Indicates a task is ready for
         | 
| 4 | 
            +
              a person to work on it.  This is subtly different than what is used
         | 
| 5 | 
            +
              by Asana to mark a date as red/green!  A task is ready if it is not
         | 
| 6 | 
            +
              dependent on an incomplete task and one of these is true:
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              * start is null and due on is today
         | 
| 9 | 
            +
              * start is null and due at is after now
         | 
| 10 | 
            +
              * start on is today
         | 
| 11 | 
            +
              * start at is after now
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative 'selector_classes/common'
         | 
| 4 | 
            +
            require_relative 'selector_classes/section'
         | 
| 5 | 
            +
            require_relative 'selector_evaluator'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Checkoff
         | 
| 8 | 
            +
              # Evaluates section selectors against a section
         | 
| 9 | 
            +
              class SectionSelectorEvaluator < SelectorEvaluator
         | 
| 10 | 
            +
                # @param section [Asana::Resources::Project]
         | 
| 11 | 
            +
                # @param client [Asana::Client]
         | 
| 12 | 
            +
                # @param projects [Checkoff::Projects]
         | 
| 13 | 
            +
                # @param sections [Checkoff::Sections]
         | 
| 14 | 
            +
                def initialize(section:,
         | 
| 15 | 
            +
                               client:,
         | 
| 16 | 
            +
                               projects: Checkoff::Projects.new(client: client),
         | 
| 17 | 
            +
                               sections: Checkoff::Sections.new)
         | 
| 18 | 
            +
                  @item = section
         | 
| 19 | 
            +
                  @client = client
         | 
| 20 | 
            +
                  @projects = projects
         | 
| 21 | 
            +
                  @sections = sections
         | 
| 22 | 
            +
                  super()
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                private
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                COMMON_FUNCTION_EVALUATORS = (Checkoff::SelectorClasses::Common.constants.map do |const|
         | 
| 28 | 
            +
                  Checkoff::SelectorClasses::Common.const_get(const)
         | 
| 29 | 
            +
                end - [Checkoff::SelectorClasses::Common::FunctionEvaluator]).freeze
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                SECTION_FUNCTION_EVALUATORS = (Checkoff::SelectorClasses::Section.constants.map do |const|
         | 
| 32 | 
            +
                  Checkoff::SelectorClasses::Section.const_get(const)
         | 
| 33 | 
            +
                end - [Checkoff::SelectorClasses::Section::FunctionEvaluator]).freeze
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                FUNCTION_EVALUTORS = (COMMON_FUNCTION_EVALUATORS + SECTION_FUNCTION_EVALUATORS).freeze
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # @return [Array<Class<ProjectSelectorClasses::FunctionEvaluator>>]
         | 
| 38 | 
            +
                def function_evaluators
         | 
| 39 | 
            +
                  FUNCTION_EVALUTORS
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                # @return [Hash]
         | 
| 43 | 
            +
                def initializer_kwargs
         | 
| 44 | 
            +
                  { sections: sections, projects: projects, client: client }
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # @return [Asana::Resources::Project]
         | 
| 48 | 
            +
                attr_reader :item
         | 
| 49 | 
            +
                # @return [Checkoff::Sections]
         | 
| 50 | 
            +
                attr_reader :sections
         | 
| 51 | 
            +
                # @return [Checkoff::Projects]
         | 
| 52 | 
            +
                attr_reader :projects
         | 
| 53 | 
            +
                # @return [Asana::Client]
         | 
| 54 | 
            +
                attr_reader :client
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative '../function_evaluator'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Checkoff
         | 
| 6 | 
            +
              module SelectorClasses
         | 
| 7 | 
            +
                module Section
         | 
| 8 | 
            +
                  # Base class to evaluate a project selector function given fully evaluated arguments
         | 
| 9 | 
            +
                  class FunctionEvaluator < ::Checkoff::SelectorClasses::FunctionEvaluator
         | 
| 10 | 
            +
                    # @param selector [Array<(Symbol, Array)>,String]
         | 
| 11 | 
            +
                    # @param client [Asana::Client]
         | 
| 12 | 
            +
                    # @param sections [Checkoff::Sections]
         | 
| 13 | 
            +
                    def initialize(selector:,
         | 
| 14 | 
            +
                                   sections:,
         | 
| 15 | 
            +
                                   client:,
         | 
| 16 | 
            +
                                   **)
         | 
| 17 | 
            +
                      @selector = selector
         | 
| 18 | 
            +
                      @sections = sections
         | 
| 19 | 
            +
                      @client = client
         | 
| 20 | 
            +
                      super()
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    private
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    # @return [Array<(Symbol, Array)>]
         | 
| 26 | 
            +
                    attr_reader :selector
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    # @return [Asana::Client]
         | 
| 29 | 
            +
                    attr_reader :client
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative 'section/function_evaluator'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Checkoff
         | 
| 6 | 
            +
              module SelectorClasses
         | 
| 7 | 
            +
                # Section selector classes
         | 
| 8 | 
            +
                module Section
         | 
| 9 | 
            +
                  # :ends_with_milestone function
         | 
| 10 | 
            +
                  class DueDateFunctionEvaluator < FunctionEvaluator
         | 
| 11 | 
            +
                    FUNCTION_NAME = :ends_with_milestone
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def matches?
         | 
| 14 | 
            +
                      fn?(selector, FUNCTION_NAME)
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    # @param section [Asana::Resources::Section]
         | 
| 18 | 
            +
                    #
         | 
| 19 | 
            +
                    # @sg-ignore
         | 
| 20 | 
            +
                    # @return [Boolean]
         | 
| 21 | 
            +
                    def evaluate(section)
         | 
| 22 | 
            +
                      tasks = client.tasks.get_tasks(section: section.gid,
         | 
| 23 | 
            +
                                                     per_page: 100,
         | 
| 24 | 
            +
                                                     options: { fields: ['resource_subtype'] })
         | 
| 25 | 
            +
                      # @sg-ignore
         | 
| 26 | 
            +
                      tasks.last&.resource_subtype == 'milestone'
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -335,7 +335,9 @@ module Checkoff | |
| 335 335 | 
             
                    # @param task [Asana::Resources::Task]
         | 
| 336 336 | 
             
                    # @return [Boolean]
         | 
| 337 337 | 
             
                    def evaluate(task)
         | 
| 338 | 
            -
                      custom_field =  | 
| 338 | 
            +
                      custom_field = pull_custom_field_by_name(task, 'Estimated time')
         | 
| 339 | 
            +
             | 
| 340 | 
            +
                      return false if custom_field.nil?
         | 
| 339 341 |  | 
| 340 342 | 
             
                      # @sg-ignore
         | 
| 341 343 | 
             
                      # @type [Integer, nil]
         | 
    
        data/lib/checkoff/my_tasks.rb
    CHANGED
    
    | @@ -61,7 +61,8 @@ module Checkoff | |
| 61 61 | 
             
                # @return [Hash<String, Enumerable<Asana::Resources::Task>>]
         | 
| 62 62 | 
             
                def by_my_tasks_section(tasks, project_gid)
         | 
| 63 63 | 
             
                  by_section = {}
         | 
| 64 | 
            -
                  sections = client.sections.get_sections_for_project(project_gid: project_gid | 
| 64 | 
            +
                  sections = client.sections.get_sections_for_project(project_gid: project_gid,
         | 
| 65 | 
            +
                                                                      options: { fields: ['name'] })
         | 
| 65 66 | 
             
                  sections.each_entry { |section| by_section[section_key(section.name)] = [] }
         | 
| 66 67 | 
             
                  tasks.each do |task|
         | 
| 67 68 | 
             
                    assignee_section = task.assignee_section
         | 
| @@ -9,8 +9,6 @@ require_relative 'internal/project_selector_evaluator' | |
| 9 9 | 
             
            require_relative 'workspaces'
         | 
| 10 10 | 
             
            require_relative 'clients'
         | 
| 11 11 |  | 
| 12 | 
            -
            # https://developers.asana.com/docs/project-selectors
         | 
| 13 | 
            -
             | 
| 14 12 | 
             
            module Checkoff
         | 
| 15 13 | 
             
              # Filter lists of projects using declarative selectors.
         | 
| 16 14 | 
             
              class ProjectSelectors
         | 
| @@ -0,0 +1,77 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # frozen_string_literal: true
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'forwardable'
         | 
| 6 | 
            +
            require 'cache_method'
         | 
| 7 | 
            +
            require_relative 'internal/config_loader'
         | 
| 8 | 
            +
            require_relative 'internal/section_selector_evaluator'
         | 
| 9 | 
            +
            require_relative 'workspaces'
         | 
| 10 | 
            +
            require_relative 'clients'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            module Checkoff
         | 
| 13 | 
            +
              # Filter lists of sections using declarative selectors.
         | 
| 14 | 
            +
              class SectionSelectors
         | 
| 15 | 
            +
                MINUTE = 60
         | 
| 16 | 
            +
                HOUR = MINUTE * 60
         | 
| 17 | 
            +
                DAY = 24 * HOUR
         | 
| 18 | 
            +
                REALLY_LONG_CACHE_TIME = HOUR * 1
         | 
| 19 | 
            +
                LONG_CACHE_TIME = MINUTE * 15
         | 
| 20 | 
            +
                SHORT_CACHE_TIME = MINUTE
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # @param config [Hash<Symbol, Object>]
         | 
| 23 | 
            +
                # @param workspaces [Checkoff::Workspaces]
         | 
| 24 | 
            +
                # @param sections [Checkoff::Sections]
         | 
| 25 | 
            +
                # @param clients [Checkoff::Clients]
         | 
| 26 | 
            +
                # @param client [Asana::Client]
         | 
| 27 | 
            +
                def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
         | 
| 28 | 
            +
                               workspaces: Checkoff::Workspaces.new(config: config),
         | 
| 29 | 
            +
                               sections: Checkoff::Sections.new(config: config),
         | 
| 30 | 
            +
                               clients: Checkoff::Clients.new(config: config),
         | 
| 31 | 
            +
                               client: clients.client)
         | 
| 32 | 
            +
                  @workspaces = workspaces
         | 
| 33 | 
            +
                  @sections = sections
         | 
| 34 | 
            +
                  @client = client
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # @param [Asana::Resources::Section] section
         | 
| 38 | 
            +
                # @param [Array<(Symbol, Array)>] section_selector Filter based on
         | 
| 39 | 
            +
                #        section details.  Examples: [:tag, 'foo'] [:not, [:tag, 'foo']] [:tag, 'foo']
         | 
| 40 | 
            +
                # @return [Boolean]
         | 
| 41 | 
            +
                def filter_via_section_selector(section, section_selector)
         | 
| 42 | 
            +
                  # @sg-ignore
         | 
| 43 | 
            +
                  evaluator = SectionSelectorEvaluator.new(section: section, sections: sections, client: client)
         | 
| 44 | 
            +
                  evaluator.evaluate(section_selector)
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                private
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                # @return [Checkoff::Workspaces]
         | 
| 50 | 
            +
                attr_reader :workspaces
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                # @return [Checkoff::Sections]
         | 
| 53 | 
            +
                attr_reader :sections
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                # @return [Asana::Client]
         | 
| 56 | 
            +
                attr_reader :client
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # bundle exec ./section_selectors.rb
         | 
| 59 | 
            +
                # :nocov:
         | 
| 60 | 
            +
                class << self
         | 
| 61 | 
            +
                  # @return [void]
         | 
| 62 | 
            +
                  def run
         | 
| 63 | 
            +
                    # workspace_name = ARGV[0] || raise('Please pass workspace name as first argument')
         | 
| 64 | 
            +
                    # section_selector_name = ARGV[1] || raise('Please pass section_selector name as second argument')
         | 
| 65 | 
            +
                    # section_selectors = Checkoff::SectionSelectors.new
         | 
| 66 | 
            +
                    # section_selector = section_selectors.section_selector_or_raise(workspace_name, section_selector_name)
         | 
| 67 | 
            +
                    # puts "Results: #{section_selector}"
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
                # :nocov:
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
            end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            # :nocov:
         | 
| 75 | 
            +
            abs_program_name = File.expand_path($PROGRAM_NAME)
         | 
| 76 | 
            +
            Checkoff::SectionSelectors.run if abs_program_name == File.expand_path(__FILE__)
         | 
| 77 | 
            +
            # :nocov:
         | 
    
        data/lib/checkoff/sections.rb
    CHANGED
    
    | @@ -52,12 +52,14 @@ module Checkoff | |
| 52 52 | 
             
                # Returns a list of Asana API section objects for a given project
         | 
| 53 53 | 
             
                # @param workspace_name [String]
         | 
| 54 54 | 
             
                # @param project_name [String, Symbol]
         | 
| 55 | 
            +
                # @param extra_fields [Array<String>]
         | 
| 55 56 | 
             
                #
         | 
| 56 57 | 
             
                # @return [Enumerable<Asana::Resources::Section>]
         | 
| 57 | 
            -
                def sections_or_raise(workspace_name, project_name)
         | 
| 58 | 
            +
                def sections_or_raise(workspace_name, project_name, extra_fields: [])
         | 
| 59 | 
            +
                  fields = %w[name] + extra_fields
         | 
| 58 60 | 
             
                  project = project_or_raise(workspace_name, project_name)
         | 
| 59 | 
            -
                   | 
| 60 | 
            -
             | 
| 61 | 
            +
                  client.sections.get_sections_for_project(project_gid: project.gid,
         | 
| 62 | 
            +
                                                           options: { fields: fields })
         | 
| 61 63 | 
             
                end
         | 
| 62 64 | 
             
                cache_method :sections_or_raise, SHORT_CACHE_TIME
         | 
| 63 65 |  | 
| @@ -173,7 +175,8 @@ module Checkoff | |
| 173 175 | 
             
                def by_section(tasks, project_gid)
         | 
| 174 176 | 
             
                  by_section = {}
         | 
| 175 177 | 
             
                  # @sg-ignore
         | 
| 176 | 
            -
                  sections = client.sections.get_sections_for_project(project_gid: project_gid | 
| 178 | 
            +
                  sections = client.sections.get_sections_for_project(project_gid: project_gid,
         | 
| 179 | 
            +
                                                                      options: { fields: ['name'] })
         | 
| 177 180 | 
             
                  sections.each_entry { |section| by_section[section_key(section.name)] = [] }
         | 
| 178 181 | 
             
                  tasks.each { |task| file_task_by_section(by_section, task, project_gid) }
         | 
| 179 182 | 
             
                  by_section
         | 
| @@ -9,8 +9,6 @@ require_relative 'internal/config_loader' | |
| 9 9 | 
             
            require_relative 'internal/task_selector_evaluator'
         | 
| 10 10 | 
             
            require_relative 'tasks'
         | 
| 11 11 |  | 
| 12 | 
            -
            # https://developers.asana.com/docs/task-selectors
         | 
| 13 | 
            -
             | 
| 14 12 | 
             
            module Checkoff
         | 
| 15 13 | 
             
              # Filter lists of tasks using declarative selectors.
         | 
| 16 14 | 
             
              class TaskSelectors
         | 
    
        data/lib/checkoff/tasks.rb
    CHANGED
    
    | @@ -42,6 +42,16 @@ module Checkoff | |
| 42 42 | 
             
                  @workspaces = workspaces
         | 
| 43 43 | 
             
                end
         | 
| 44 44 |  | 
| 45 | 
            +
                # Indicates a task is ready for a person to work on it.  This is
         | 
| 46 | 
            +
                # subtly different than what is used by Asana to mark a date as
         | 
| 47 | 
            +
                # red/green!  A task is ready if it is not dependent on an
         | 
| 48 | 
            +
                # incomplete task and one of these is true:
         | 
| 49 | 
            +
                #
         | 
| 50 | 
            +
                # * start is null and due on is today
         | 
| 51 | 
            +
                # * start is null and due at is after now
         | 
| 52 | 
            +
                # * start on is today
         | 
| 53 | 
            +
                # * start at is after now
         | 
| 54 | 
            +
                #
         | 
| 45 55 | 
             
                # @param task [Asana::Resources::Task]
         | 
| 46 56 | 
             
                # @param ignore_dependencies [Boolean]
         | 
| 47 57 | 
             
                def task_ready?(task, ignore_dependencies: false)
         | 
    
        data/lib/checkoff/version.rb
    CHANGED
    
    
    
        data/lib/checkoff.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: checkoff
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.67.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Vince Broz
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2023-10- | 
| 11 | 
            +
            date: 2023-10-20 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -103,6 +103,7 @@ files: | |
| 103 103 | 
             
            - CODE_OF_CONDUCT.md
         | 
| 104 104 | 
             
            - CONTRIBUTING.rst
         | 
| 105 105 | 
             
            - DEVELOPMENT.md
         | 
| 106 | 
            +
            - GLOSSARY.md
         | 
| 106 107 | 
             
            - Gemfile
         | 
| 107 108 | 
             
            - Gemfile.lock
         | 
| 108 109 | 
             
            - LICENSE
         | 
| @@ -140,11 +141,14 @@ files: | |
| 140 141 | 
             
            - lib/checkoff/internal/search_url/parser.rb
         | 
| 141 142 | 
             
            - lib/checkoff/internal/search_url/results_merger.rb
         | 
| 142 143 | 
             
            - lib/checkoff/internal/search_url/simple_param_converter.rb
         | 
| 144 | 
            +
            - lib/checkoff/internal/section_selector_evaluator.rb
         | 
| 143 145 | 
             
            - lib/checkoff/internal/selector_classes/common.rb
         | 
| 144 146 | 
             
            - lib/checkoff/internal/selector_classes/common/function_evaluator.rb
         | 
| 145 147 | 
             
            - lib/checkoff/internal/selector_classes/function_evaluator.rb
         | 
| 146 148 | 
             
            - lib/checkoff/internal/selector_classes/project.rb
         | 
| 147 149 | 
             
            - lib/checkoff/internal/selector_classes/project/function_evaluator.rb
         | 
| 150 | 
            +
            - lib/checkoff/internal/selector_classes/section.rb
         | 
| 151 | 
            +
            - lib/checkoff/internal/selector_classes/section/function_evaluator.rb
         | 
| 148 152 | 
             
            - lib/checkoff/internal/selector_classes/task.rb
         | 
| 149 153 | 
             
            - lib/checkoff/internal/selector_classes/task/function_evaluator.rb
         | 
| 150 154 | 
             
            - lib/checkoff/internal/selector_evaluator.rb
         | 
| @@ -152,6 +156,7 @@ files: | |
| 152 156 | 
             
            - lib/checkoff/my_tasks.rb
         | 
| 153 157 | 
             
            - lib/checkoff/project_selectors.rb
         | 
| 154 158 | 
             
            - lib/checkoff/projects.rb
         | 
| 159 | 
            +
            - lib/checkoff/section_selectors.rb
         | 
| 155 160 | 
             
            - lib/checkoff/sections.rb
         | 
| 156 161 | 
             
            - lib/checkoff/subtasks.rb
         | 
| 157 162 | 
             
            - lib/checkoff/tags.rb
         |