Skip to content

Commit

Permalink
Add arbitrary uda support
Browse files Browse the repository at this point in the history
  • Loading branch information
dropofwill committed May 12, 2015
1 parent c868e10 commit 2409971
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 40 deletions.
6 changes: 4 additions & 2 deletions lib/rtasklib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
require_relative "rtasklib/models"
require_relative "rtasklib/execute"
require_relative "rtasklib/controller"
require_relative "rtasklib/helpers"
require_relative "rtasklib/taskrc"

require "open3"
require "pathname"

module Rtasklib

class TaskWarrior
attr_reader :version, :data_location, :taskrc,
attr_reader :version, :data_location, :taskrc, :udas,
:override, :override_a, :override_str

include Controller
Expand All @@ -31,6 +31,8 @@ def initialize data="#{Dir.home}/.task", opts = {}
@override = Taskrc.new(override_h, :hash)
@override_a = override.model_to_rc
@taskrc = get_rc
@udas = get_udas
add_uda_to_model udas

# Check TaskWarrior version, and throw warning if unavailable
begin
Expand Down
13 changes: 11 additions & 2 deletions lib/rtasklib/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def process_ids ids
ids
end
end
private :process_ids

def process_tags tags
end
Expand Down Expand Up @@ -96,14 +97,23 @@ def uda_attr? attr
def arbitrary_attr attr, depth: 1
attr.to_s.split("_")[depth]
end
private :arbitrary_attr

# Returns all attribute string after given depth
def deep_attr attr, depth: 2
attr.to_s.split("_")[depth..-1].join("_")
end
private :deep_attr


def add_uda_to_model uda_hash, model=Rtasklib::Models::TaskModel
uda_hash.each do |uda|
uda.each do |attr, val|
model.attribute attr, String
end
end
end
private :add_uda_to_model

# Retrieve an array of the uda names
#
# @return [Array<String>]
Expand Down Expand Up @@ -163,6 +173,5 @@ def to_gem_version raw
Gem::Version.new std_ver
end
private :to_gem_version

end
end
33 changes: 33 additions & 0 deletions lib/rtasklib/helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

module Rtasklib

module Helpers
# make this module a stateless, singleton
extend self

# Int needs to precede float because ints are also floats
def determine_type value
if boolean? value
return Axiom::Types::Boolean
elsif integer? value
return Integer
elsif float? value
return Float
else
return String
end
end

def integer? value
value.to_i.to_s == value
end

def float? value
Float(value) rescue false
end

def boolean? value
["on", "off", "yes", "no", "false", "true"].include? value.to_s.downcase
end
end
end
44 changes: 33 additions & 11 deletions lib/rtasklib/models.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
require "virtus"
require "active_model"
require 'iso8601'
require 'date'

module Rtasklib::Models
ValidationError = Class.new RuntimeError

class UUID < Virtus::Attribute
def coerce(value)
value.to_s
# A subclass of the ISO8601::Duration object that use `task calc` to parse
# string names like 'weekly', 'biannual', and '3 quarters'
#
# Modifies the #initialize method, preserving the original string duration
class TWDuration < ISO8601::Duration
attr_accessor :negative
attr_reader :frozen_value

def initialize input, base=nil
@frozen_value = input.dup.freeze
@negative = false
parsed = `task calc #{input}`.chomp

if parsed.include?("-")
parsed.gsub!(/\-/, "")
negative = true
else
negative = false
end

super parsed, base
end
end

# Custom coercer to change a string input into an TWDuration object
class VirtusDuration < Virtus::Attribute
def coerce(v)
if v.nil? || v.blank? then "" else TWDuration.new(v) end
end
end

RcBooleans = Virtus.model do |mod|
mod.coerce = true
mod.coercer.config.string.boolean_map = {
'no' => false,
'yes' => true,
'on' => true,
'off' => false }
'yes' => true, 'on' => true,
'no' => false, 'off' => false }
end

class TaskrcModel
Expand Down Expand Up @@ -61,7 +85,7 @@ class TaskModel
attribute :wait, DateTime

# Required only for tasks that are Recurring or have Recurring Parent
attribute :recur, DateTime
attribute :recur, VirtusDuration

# Optional except for tasks with Recurring Parents
attribute :due, DateTime
Expand All @@ -74,8 +98,6 @@ class TaskModel
attribute :imask, String
attribute :modified, DateTime

# TODO: handle arbitrary UDA's

# Refactoring idea, need to understand Virtus internals a bit better
# [:mask, :imask, :modified, :status, :uuid, :entry].each do |ro_attr|
# define_method("set_#{ro_attr.to_s}") do |value|
Expand Down
35 changes: 10 additions & 25 deletions lib/rtasklib/taskrc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ def model_to_s

# Dynamically add a Virtus attr, detect Boolean, Integer, and Float types
# based on the value, otherwise just treat it like a string.
# Int needs to precede float because ints are also floats
# Modifies the config instance variable
# TODO: May also be able to detect arrays
#
Expand All @@ -132,15 +131,16 @@ def model_to_s
# @return [undefined]
# @api private
def add_model_attr attr, value
if boolean? value
config.attribute attr.to_sym, Axiom::Types::Boolean
elsif integer? value
config.attribute attr.to_sym, Integer
elsif float? value
config.attribute attr.to_sym, Float
else
config.attribute attr.to_sym, String
end
config.attribute(attr.to_sym, Helpers.determine_type(value))
# if boolean? value
# config.attribute attr.to_sym, Axiom::Types::Boolean
# elsif integer? value
# config.attribute attr.to_sym, Integer
# elsif float? value
# config.attribute attr.to_sym, Float
# else
# config.attribute attr.to_sym, String
# end
end
private :add_model_attr

Expand Down Expand Up @@ -194,20 +194,5 @@ def path_exist? path
end
end
private :path_exist?

def integer? value
value.to_i.to_s == value
end
private :integer?

def float? value
Float(value) rescue false
end
private :float?

def boolean? value
["on", "off", "yes", "no", "false", "true"].include? value.to_s.downcase
end
private :boolean?
end
end

0 comments on commit 2409971

Please sign in to comment.