Class: Agentilda::Feature

Inherits:
Data
  • Object
show all
Includes:
Comparable
Defined in:
lib/agentilda/feature.rb

Overview

One NNN.MM-<emoji>--<slug> folder, decoded.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#dirnameString (readonly)

Returns exactly as it is on disk.

Returns:

  • (String)

    exactly as it is on disk



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
# File 'lib/agentilda/feature.rb', line 73

Feature = Data.define(:ordinal, :status, :slug, :dirname, :path) do
  include Comparable

  # Decode a folder name, or return nil when it is not a plan folder.
  #
  # @param path [String] absolute path to a candidate directory
  # @return [Agentilda::Feature, nil]
  def self.parse(path)
    dirname = File.basename(path)
    ordinal = Ordinal.from_dirname(dirname) or return nil

    rest = dirname.sub(/\A[\d.]+[-_]/, "")
    head, tail = rest.split(/[-_]/, 2)

    # A leading segment with no ASCII word character is the status emoji.
    # The slug strips any further separators: the canonical spelling puts
    # two dashes after the emoji, and folders from before that rule put one.
    status = (Agentilda.status_for_emoji(head) if tail && !head.to_s.empty? && !head.match?(/[A-Za-z0-9]/))
    slug = status ? tail.sub(/\A[-_]+/, "") : rest

    new(ordinal:, status: status || STATUS_BY_KEY.fetch(:new), slug:, dirname:, path:)
  end

  # @return [String] proper name, e.g. "Law as Data"
  def title = Agentilda.titleize(slug)

  # The folder name this feature would carry in a given state — the slug
  # never moves, and the number is always rendered canonically, so this is
  # also what repairs a folder written `018-⚪️--foo` before the `NNN.MM` rule.
  #
  # @param status [Agentilda::Status]
  # @return [String]
  def dirname_as(status) = Agentilda.plan_dirname(ordinal, status, slug)

  # The number exactly as the folder writes it, which is not always the
  # canonical rendering: `018-⚪️--foo` yields "018" where {#ordinal} renders
  # "018.00".
  #
  # @return [String]
  def dirname_ordinal = dirname.to_s[/\A[\d.]+/].to_s

  # @return [Boolean] whether the number is written in full `NNN.MM` form
  def padded? = dirname_ordinal == ordinal.to_s

  # Whether the folder is already named the way this tool would name it —
  # number padded, emoji matching the state it claims, slug unchanged.
  #
  # @return [Boolean]
  def canonical? = dirname == dirname_as(status)

  # @param other [Object]
  # @return [Integer, nil]
  def <=>(other) = other.is_a?(self.class) ? [ordinal, dirname] <=> [other.ordinal, other.dirname] : nil
end

#ordinalAgentilda::Ordinal (readonly)

Returns:



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
# File 'lib/agentilda/feature.rb', line 73

Feature = Data.define(:ordinal, :status, :slug, :dirname, :path) do
  include Comparable

  # Decode a folder name, or return nil when it is not a plan folder.
  #
  # @param path [String] absolute path to a candidate directory
  # @return [Agentilda::Feature, nil]
  def self.parse(path)
    dirname = File.basename(path)
    ordinal = Ordinal.from_dirname(dirname) or return nil

    rest = dirname.sub(/\A[\d.]+[-_]/, "")
    head, tail = rest.split(/[-_]/, 2)

    # A leading segment with no ASCII word character is the status emoji.
    # The slug strips any further separators: the canonical spelling puts
    # two dashes after the emoji, and folders from before that rule put one.
    status = (Agentilda.status_for_emoji(head) if tail && !head.to_s.empty? && !head.match?(/[A-Za-z0-9]/))
    slug = status ? tail.sub(/\A[-_]+/, "") : rest

    new(ordinal:, status: status || STATUS_BY_KEY.fetch(:new), slug:, dirname:, path:)
  end

  # @return [String] proper name, e.g. "Law as Data"
  def title = Agentilda.titleize(slug)

  # The folder name this feature would carry in a given state — the slug
  # never moves, and the number is always rendered canonically, so this is
  # also what repairs a folder written `018-⚪️--foo` before the `NNN.MM` rule.
  #
  # @param status [Agentilda::Status]
  # @return [String]
  def dirname_as(status) = Agentilda.plan_dirname(ordinal, status, slug)

  # The number exactly as the folder writes it, which is not always the
  # canonical rendering: `018-⚪️--foo` yields "018" where {#ordinal} renders
  # "018.00".
  #
  # @return [String]
  def dirname_ordinal = dirname.to_s[/\A[\d.]+/].to_s

  # @return [Boolean] whether the number is written in full `NNN.MM` form
  def padded? = dirname_ordinal == ordinal.to_s

  # Whether the folder is already named the way this tool would name it —
  # number padded, emoji matching the state it claims, slug unchanged.
  #
  # @return [Boolean]
  def canonical? = dirname == dirname_as(status)

  # @param other [Object]
  # @return [Integer, nil]
  def <=>(other) = other.is_a?(self.class) ? [ordinal, dirname] <=> [other.ordinal, other.dirname] : nil
end

#pathString (readonly)

Returns absolute.

Returns:

  • (String)

    absolute



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
# File 'lib/agentilda/feature.rb', line 73

Feature = Data.define(:ordinal, :status, :slug, :dirname, :path) do
  include Comparable

  # Decode a folder name, or return nil when it is not a plan folder.
  #
  # @param path [String] absolute path to a candidate directory
  # @return [Agentilda::Feature, nil]
  def self.parse(path)
    dirname = File.basename(path)
    ordinal = Ordinal.from_dirname(dirname) or return nil

    rest = dirname.sub(/\A[\d.]+[-_]/, "")
    head, tail = rest.split(/[-_]/, 2)

    # A leading segment with no ASCII word character is the status emoji.
    # The slug strips any further separators: the canonical spelling puts
    # two dashes after the emoji, and folders from before that rule put one.
    status = (Agentilda.status_for_emoji(head) if tail && !head.to_s.empty? && !head.match?(/[A-Za-z0-9]/))
    slug = status ? tail.sub(/\A[-_]+/, "") : rest

    new(ordinal:, status: status || STATUS_BY_KEY.fetch(:new), slug:, dirname:, path:)
  end

  # @return [String] proper name, e.g. "Law as Data"
  def title = Agentilda.titleize(slug)

  # The folder name this feature would carry in a given state — the slug
  # never moves, and the number is always rendered canonically, so this is
  # also what repairs a folder written `018-⚪️--foo` before the `NNN.MM` rule.
  #
  # @param status [Agentilda::Status]
  # @return [String]
  def dirname_as(status) = Agentilda.plan_dirname(ordinal, status, slug)

  # The number exactly as the folder writes it, which is not always the
  # canonical rendering: `018-⚪️--foo` yields "018" where {#ordinal} renders
  # "018.00".
  #
  # @return [String]
  def dirname_ordinal = dirname.to_s[/\A[\d.]+/].to_s

  # @return [Boolean] whether the number is written in full `NNN.MM` form
  def padded? = dirname_ordinal == ordinal.to_s

  # Whether the folder is already named the way this tool would name it —
  # number padded, emoji matching the state it claims, slug unchanged.
  #
  # @return [Boolean]
  def canonical? = dirname == dirname_as(status)

  # @param other [Object]
  # @return [Integer, nil]
  def <=>(other) = other.is_a?(self.class) ? [ordinal, dirname] <=> [other.ordinal, other.dirname] : nil
end

#slugString (readonly)

Returns:

  • (String)


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
# File 'lib/agentilda/feature.rb', line 73

Feature = Data.define(:ordinal, :status, :slug, :dirname, :path) do
  include Comparable

  # Decode a folder name, or return nil when it is not a plan folder.
  #
  # @param path [String] absolute path to a candidate directory
  # @return [Agentilda::Feature, nil]
  def self.parse(path)
    dirname = File.basename(path)
    ordinal = Ordinal.from_dirname(dirname) or return nil

    rest = dirname.sub(/\A[\d.]+[-_]/, "")
    head, tail = rest.split(/[-_]/, 2)

    # A leading segment with no ASCII word character is the status emoji.
    # The slug strips any further separators: the canonical spelling puts
    # two dashes after the emoji, and folders from before that rule put one.
    status = (Agentilda.status_for_emoji(head) if tail && !head.to_s.empty? && !head.match?(/[A-Za-z0-9]/))
    slug = status ? tail.sub(/\A[-_]+/, "") : rest

    new(ordinal:, status: status || STATUS_BY_KEY.fetch(:new), slug:, dirname:, path:)
  end

  # @return [String] proper name, e.g. "Law as Data"
  def title = Agentilda.titleize(slug)

  # The folder name this feature would carry in a given state — the slug
  # never moves, and the number is always rendered canonically, so this is
  # also what repairs a folder written `018-⚪️--foo` before the `NNN.MM` rule.
  #
  # @param status [Agentilda::Status]
  # @return [String]
  def dirname_as(status) = Agentilda.plan_dirname(ordinal, status, slug)

  # The number exactly as the folder writes it, which is not always the
  # canonical rendering: `018-⚪️--foo` yields "018" where {#ordinal} renders
  # "018.00".
  #
  # @return [String]
  def dirname_ordinal = dirname.to_s[/\A[\d.]+/].to_s

  # @return [Boolean] whether the number is written in full `NNN.MM` form
  def padded? = dirname_ordinal == ordinal.to_s

  # Whether the folder is already named the way this tool would name it —
  # number padded, emoji matching the state it claims, slug unchanged.
  #
  # @return [Boolean]
  def canonical? = dirname == dirname_as(status)

  # @param other [Object]
  # @return [Integer, nil]
  def <=>(other) = other.is_a?(self.class) ? [ordinal, dirname] <=> [other.ordinal, other.dirname] : nil
end

#statusAgentilda::Status (readonly)

Returns:



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
# File 'lib/agentilda/feature.rb', line 73

Feature = Data.define(:ordinal, :status, :slug, :dirname, :path) do
  include Comparable

  # Decode a folder name, or return nil when it is not a plan folder.
  #
  # @param path [String] absolute path to a candidate directory
  # @return [Agentilda::Feature, nil]
  def self.parse(path)
    dirname = File.basename(path)
    ordinal = Ordinal.from_dirname(dirname) or return nil

    rest = dirname.sub(/\A[\d.]+[-_]/, "")
    head, tail = rest.split(/[-_]/, 2)

    # A leading segment with no ASCII word character is the status emoji.
    # The slug strips any further separators: the canonical spelling puts
    # two dashes after the emoji, and folders from before that rule put one.
    status = (Agentilda.status_for_emoji(head) if tail && !head.to_s.empty? && !head.match?(/[A-Za-z0-9]/))
    slug = status ? tail.sub(/\A[-_]+/, "") : rest

    new(ordinal:, status: status || STATUS_BY_KEY.fetch(:new), slug:, dirname:, path:)
  end

  # @return [String] proper name, e.g. "Law as Data"
  def title = Agentilda.titleize(slug)

  # The folder name this feature would carry in a given state — the slug
  # never moves, and the number is always rendered canonically, so this is
  # also what repairs a folder written `018-⚪️--foo` before the `NNN.MM` rule.
  #
  # @param status [Agentilda::Status]
  # @return [String]
  def dirname_as(status) = Agentilda.plan_dirname(ordinal, status, slug)

  # The number exactly as the folder writes it, which is not always the
  # canonical rendering: `018-⚪️--foo` yields "018" where {#ordinal} renders
  # "018.00".
  #
  # @return [String]
  def dirname_ordinal = dirname.to_s[/\A[\d.]+/].to_s

  # @return [Boolean] whether the number is written in full `NNN.MM` form
  def padded? = dirname_ordinal == ordinal.to_s

  # Whether the folder is already named the way this tool would name it —
  # number padded, emoji matching the state it claims, slug unchanged.
  #
  # @return [Boolean]
  def canonical? = dirname == dirname_as(status)

  # @param other [Object]
  # @return [Integer, nil]
  def <=>(other) = other.is_a?(self.class) ? [ordinal, dirname] <=> [other.ordinal, other.dirname] : nil
end

Class Method Details

.parse(path) ⇒ Agentilda::Feature?

Decode a folder name, or return nil when it is not a plan folder.

Parameters:

  • path (String)

    absolute path to a candidate directory

Returns:



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/agentilda/feature.rb', line 80

def self.parse(path)
  dirname = File.basename(path)
  ordinal = Ordinal.from_dirname(dirname) or return nil

  rest = dirname.sub(/\A[\d.]+[-_]/, "")
  head, tail = rest.split(/[-_]/, 2)

  # A leading segment with no ASCII word character is the status emoji.
  # The slug strips any further separators: the canonical spelling puts
  # two dashes after the emoji, and folders from before that rule put one.
  status = (Agentilda.status_for_emoji(head) if tail && !head.to_s.empty? && !head.match?(/[A-Za-z0-9]/))
  slug = status ? tail.sub(/\A[-_]+/, "") : rest

  new(ordinal:, status: status || STATUS_BY_KEY.fetch(:new), slug:, dirname:, path:)
end

Instance Method Details

#<=>(other) ⇒ Integer?

Parameters:

  • other (Object)

Returns:

  • (Integer, nil)


125
# File 'lib/agentilda/feature.rb', line 125

def <=>(other) = other.is_a?(self.class) ? [ordinal, dirname] <=> [other.ordinal, other.dirname] : nil

#canonical?Boolean

Whether the folder is already named the way this tool would name it — number padded, emoji matching the state it claims, slug unchanged.

Returns:

  • (Boolean)


121
# File 'lib/agentilda/feature.rb', line 121

def canonical? = dirname == dirname_as(status)

#dirname_as(status) ⇒ String

The folder name this feature would carry in a given state — the slug never moves, and the number is always rendered canonically, so this is also what repairs a folder written 018-⚪️--foo before the NNN.MM rule.

Parameters:

Returns:

  • (String)


105
# File 'lib/agentilda/feature.rb', line 105

def dirname_as(status) = Agentilda.plan_dirname(ordinal, status, slug)

#dirname_ordinalString

The number exactly as the folder writes it, which is not always the canonical rendering: 018-⚪️--foo yields "018" where #ordinal renders "018.00".

Returns:

  • (String)


112
# File 'lib/agentilda/feature.rb', line 112

def dirname_ordinal = dirname.to_s[/\A[\d.]+/].to_s

#padded?Boolean

Returns whether the number is written in full NNN.MM form.

Returns:

  • (Boolean)

    whether the number is written in full NNN.MM form



115
# File 'lib/agentilda/feature.rb', line 115

def padded? = dirname_ordinal == ordinal.to_s

#titleString

Returns proper name, e.g. "Law as Data".

Returns:

  • (String)

    proper name, e.g. "Law as Data"



97
# File 'lib/agentilda/feature.rb', line 97

def title = Agentilda.titleize(slug)