Module: Doing::StringTags

Included in:
String
Defined in:
lib/doing/string/tags.rb

Overview

Handling of @tags in strings

Instance Method Summary collapse

Instance Method Details

#add_atString

Add @ prefix to string if needed, maintains +/- prefix



11
12
13
# File 'lib/doing/string/tags.rb', line 11

def add_at
  strip.sub(/^([+-]*)@?/, '\1@')
end

#add_tags(tags, remove: false) ⇒ String

Adds tags to a string



59
60
61
62
63
64
# File 'lib/doing/string/tags.rb', line 59

def add_tags(tags, remove: false)
  title = dup
  tags = tags.to_tags
  tags.each { |tag| title.tag!(tag, remove: remove) }
  title
end

#add_tags!(tags, remove: false) ⇒ Object

See Also:



67
68
69
# File 'lib/doing/string/tags.rb', line 67

def add_tags!(tags, remove: false)
  replace add_tags(tags, remove: remove)
end

#dedup_tagsObject

Remove duplicate tags, leaving only first occurrence



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/doing/string/tags.rb', line 162

def dedup_tags
  title = dup
  tags = title.scan(/(?<=\A| )(@(\S+?)(\([^)]+\))?)(?= |\Z)/).uniq
  tags.each do |tag|
    found = false
    title.gsub!(/( |^)#{Regexp.escape(tag[1])}(\([^)]+\))?(?= |$)/) do |m|
      if found
        ''
      else
        found = true
        m
      end
    end
  end
  title
end

#dedup_tags!Object

See Also:



180
181
182
# File 'lib/doing/string/tags.rb', line 180

def dedup_tags!
  replace dedup_tags
end

#remove_atString

Removes @ prefix if needed, maintains +/- prefix



20
21
22
# File 'lib/doing/string/tags.rb', line 20

def remove_at
  strip.sub(/^([+-]*)@?/, '\1')
end

#split_tagsArray

Split a string of tags, remove @ symbols, with or without @ symbols, with or without parenthetical values



31
32
33
# File 'lib/doing/string/tags.rb', line 31

def split_tags
  gsub(/ *, */, ' ').scan(/(@?(?:\S+(?:\(.+\)))|@?(?:\S+))/).map(&:first).map(&:remove_at).sort.uniq
end

#tag(tag, value: nil, remove: false, rename_to: nil, regex: false, single: false, force: false) ⇒ String

Add, rename, or remove a tag



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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/doing/string/tags.rb', line 93

def tag(tag, value: nil, remove: false, rename_to: nil, regex: false, single: false, force: false)
  log_level = single ? :info : :debug
  title = dup
  title.chomp!
  tag = tag.sub(/^@?/, '')
  case_sensitive = tag !~ /[A-Z]/

  rx_tag = if regex
             tag.gsub(/\./, '\S')
           else
             tag.gsub(/\?/, '.').gsub(/\*/, '\S*?')
           end

  if remove || rename_to
    rx = Regexp.new("(?<=^| )@#{rx_tag}(?<parens>\\((?<value>[^)]*)\\))?(?= |$)", case_sensitive)
    m = title.match(rx)

    if m.nil? && rename_to && force
      title.tag!(rename_to, value: value, single: single)
    elsif m
      title.gsub!(rx) do
        if rename_to
          "@#{rename_to}#{value.nil? ? m['parens'] : "(#{value})"}"
        else
          ''
        end
      end

      title.dedup_tags!
      title.chomp!

      f = "@#{tag}".cyan
      if rename_to
        t = "@#{rename_to}".cyan
        Doing.logger.write(log_level, 'Tag:', %(renamed #{f} to #{t} in "#{title}"))
      else
        Doing.logger.write(log_level, 'Tag:', %(removed #{f} from "#{title}"))
      end
    else
      Doing.logger.debug('Skipped:', "not tagged #{"@#{tag}".cyan}")
    end
  elsif title =~ /@#{tag}(?=[ (]|$)/ && !value.good?
    Doing.logger.debug('Skipped:', "already tagged #{"@#{tag}".cyan}")
    return title
  else
    add = tag
    add += "(#{value})" unless value.nil?

    title.chomp!

    if value && title =~ /@#{tag}(?=[ (]|$)/
      title.sub!(/@#{tag}(\(.*?\))?/, "@#{add}")
    else
      title += " @#{add}"
    end

    title.dedup_tags!
    title.chomp!
    Doing.logger.write(log_level, 'Tag:', %(added #{"@#{tag}".cyan} to "#{title}"))
  end

  title.gsub(/ +/, ' ')
end

#tag!(tag, **options) ⇒ Object

Add, rename, or remove a tag in place

See Also:



76
77
78
# File 'lib/doing/string/tags.rb', line 76

def tag!(tag, **options)
  replace tag(tag, **options)
end

#to_tagsArray

Convert a list of tags to an array. Tags can be with or without @ symbols, separated by any character, and can include parenthetical values (with spaces)



42
43
44
45
46
47
48
49
# File 'lib/doing/string/tags.rb', line 42

def to_tags
  arr = split_tags.map(&:add_at)
  if block_given?
    yield arr
  else
    arr
  end
end