Module: Howzit::StringUtils

Included in:
String
Defined in:
lib/howzit/stringutils.rb

Overview

String Extensions

Instance Method Summary collapse

Instance Method Details

#available?Boolean

Test if an executable is available on the system

Returns:

  • (Boolean)

    executable is available



209
210
211
# File 'lib/howzit/stringutils.rb', line 209

def available?
  Util.valid_command?(self)
end

#build_note?Boolean

Test if the filename matches the conditions to be a build note

Returns:

  • (Boolean)

    true if filename passes test



11
12
13
14
15
16
17
# File 'lib/howzit/stringutils.rb', line 11

def build_note?
  return false if downcase !~ /^(howzit[^.]*|build[^.]+)/

  return false if Howzit.config.should_ignore(self)

  true
end

#cString

Shortcut for calling Color.template

Returns:

  • (String)

    colorized string



82
83
84
# File 'lib/howzit/stringutils.rb', line 82

def c
  Color.template(self)
end

#extract_metadataHash

Split the content at the first top-level header and assume everything before it is metadata. Passes to

get_metadata for processing

Returns:

  • (Hash)

    key/value pairs



277
278
279
280
281
282
283
284
# File 'lib/howzit/stringutils.rb', line 277

def 
  if File.exist?(self)
    leader = Util.read_file(self).split(/^#/)[0].strip
    leader.length > 0 ? leader. : {}
  else
    {}
  end
end

#format_header(opts = {}) ⇒ String

Make a fancy title line for the topic

Parameters:

  • opts (Hash) (defaults to: {})

    options

Returns:

  • (String)

    formatted string



351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/howzit/stringutils.rb', line 351

def format_header(opts = {})
  title = dup
  options = {
    hr: "\u{254C}",
    color: '{bg}',
    border: '{x}',
    mark: should_mark_iterm?
  }

  options.merge!(opts)

  case Howzit.options[:header_format]
  when :block
    Color.template("#{options[:color]}\u{258C}#{title}#{should_mark_iterm? && options[:mark] ? iterm_marker : ''}{x}")
  else
    cols = TTY::Screen.columns

    cols = Howzit.options[:wrap] if (Howzit.options[:wrap]).positive? && cols > Howzit.options[:wrap]
    title = Color.template("#{options[:border]}#{options[:hr] * 2}( #{options[:color]}#{title}#{options[:border]} )")

    tail = if should_mark_iterm?
             "#{options[:hr] * (cols - title.uncolor.length - 15)}#{options[:mark] ? iterm_marker : ''}"
           else
             options[:hr] * (cols - title.uncolor.length)
           end
    Color.template("#{title}#{tail}{x}")
  end
end

#get_metadataHash

Examine text for multimarkdown-style metadata and return key/value pairs

Returns:

  • (Hash)

    The metadata as key/value pairs



291
292
293
294
295
296
297
298
299
300
# File 'lib/howzit/stringutils.rb', line 291

def 
  data = {}
  scan(/(?mi)^(\S[\s\S]+?): ([\s\S]*?)(?=\n\S[\s\S]*?:|\Z)/).each do |m|
    data[m[0].strip.downcase] = m[1]
  end
  out = (data)
  Howzit.named_arguments ||= {}
  Howzit.named_arguments = out.merge(Howzit.named_arguments)
  out
end

#iterm_markerString

Output an iTerm marker

Returns:

  • (String)

    ANSI escape sequence for iTerm marker



341
342
343
# File 'lib/howzit/stringutils.rb', line 341

def iterm_marker
  "\e]1337;SetMark\a" if should_mark_iterm?
end

#normalize_metadata(meta) ⇒ Hash

Autocorrect some keys

Parameters:

  • meta (Hash)

    The metadata

Returns:

  • (Hash)

    corrected metadata



309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/howzit/stringutils.rb', line 309

def (meta)
  data = {}
  meta.each do |k, v|
    case k
    when /^te?m?pl(ate)?s?$/
      data['template'] = v
    when /^req\w*$/
      data['required'] = v
    else
      data[k] = v
    end
  end
  data
end

#note_title(file, truncate = 0) ⇒ Object

Get the title of the build note (top level header)

Parameters:

  • truncate (Integer) (defaults to: 0)

    Truncate to width



24
25
26
27
28
29
30
31
32
33
# File 'lib/howzit/stringutils.rb', line 24

def note_title(file, truncate = 0)
  title = match(/(?:^(\S.*?)(?=\n==)|^# ?(.*?)$)/)
  title = if title
            title[1].nil? ? title[2] : title[1]
          else
            file.sub(/(\.\w+)?$/, '')
          end

  title && truncate.positive? ? title.trunc(truncate) : title
end

#preserve_escapesString

Replace slash escaped characters in a string with a zero-width space that will prevent a shell from interpreting them when output to console

Returns:



42
43
44
# File 'lib/howzit/stringutils.rb', line 42

def preserve_escapes
  gsub(/\\([a-z])/, '\​\1')
end

#render_argumentsString

Render $X placeholders based on positional arguments

Returns:

  • (String)

    rendered string



247
248
249
250
251
252
# File 'lib/howzit/stringutils.rb', line 247

def render_arguments
  str = dup
  str.render_named_placeholders
  str.render_numeric_placeholders
  Howzit.arguments.nil? ? str : str.gsub(/\$[@*]/, Shellwords.join(Howzit.arguments))
end

#render_named_placeholdersObject



254
255
256
257
258
259
260
# File 'lib/howzit/stringutils.rb', line 254

def render_named_placeholders
  gsub!(/\$\{(?<name>[A-Z0-9_]+(?::.*?)?)\}/i) do
    m = Regexp.last_match
    arg, default = m['name'].split(/:/).map(&:strip)
    Howzit.named_arguments.key?(arg) && !Howzit.named_arguments[arg].nil? ? Howzit.named_arguments[arg] : default
  end
end

#render_numeric_placeholdersObject



262
263
264
265
266
267
268
# File 'lib/howzit/stringutils.rb', line 262

def render_numeric_placeholders
  gsub!(/\$\{?(\d+)\}?/) do
    arg, default = Regexp.last_match(1).split(/:/)
    idx = arg.to_i - 1
    Howzit.arguments.length > idx ? Howzit.arguments[idx] : default || Regexp.last_match(0)
  end
end

#render_template(vars) ⇒ String

Render [%variable] placeholders in a templated string

Parameters:

  • vars (Hash)

    Key/value pairs of variable values

Returns:

  • (String)

    Rendered string



221
222
223
224
225
226
227
228
229
230
231
# File 'lib/howzit/stringutils.rb', line 221

def render_template(vars)
  vars.each do |k, v|
    gsub!(/\[%#{k}(:.*?)?\]/, v)
  end

  # Replace empty variables with default
  gsub!(/\[%(.*?):(.*?)\]/, '\2')

  # Remove remaining empty variables
  gsub(/\[%(.*?)\]/, '')
end

#render_template!(vars) ⇒ Object

Render [%variable] placeholders in place

Parameters:

  • vars (Hash)

    Key/value pairs of variable values



238
239
240
# File 'lib/howzit/stringutils.rb', line 238

def render_template!(vars)
  replace render_template(vars)
end

#should_mark_iterm?Boolean

Test if iTerm markers should be output. Requires that the $TERM_PROGRAM be iTerm and howzit is not running directives or paginating output

Returns:

  • (Boolean)

    should mark?



331
332
333
# File 'lib/howzit/stringutils.rb', line 331

def should_mark_iterm?
  ENV['TERM_PROGRAM'] =~ /^iTerm/ && !Howzit.options[:run] && !Howzit.options[:paginate]
end

#split_line(width, indent = '') ⇒ Object

Splits a line at nearest word break

Parameters:

  • width (Integer)

    The width of the first segment

  • indent (String) (defaults to: '')

    The indent string



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/howzit/stringutils.rb', line 187

def split_line(width, indent = '')
  line = dup
  at = line.index(/\s/)
  last_at = at

  while !at.nil? && at < width
    last_at = at
    at = line.index(/\s/, last_at + 1)
  end

  if last_at.nil?
    [indent + line[0, width], line[width, line.length]]
  else
    [indent + line[0, last_at], line[last_at + 1, line.length]]
  end
end

#to_config_value(orig_value = nil) ⇒ Object

Convert a string to a valid YAML value

Parameters:

  • orig_value (defaults to: nil)

    The original value from which type will be determined

Returns:

  • coerced value



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/howzit/stringutils.rb', line 53

def to_config_value(orig_value = nil)
  if orig_value
    case orig_value.class.to_s
    when /Integer/
      to_i
    when /(True|False)Class/
      self =~ /^(t(rue)?|y(es)?|1)$/i ? true : false
    else
      self
    end
  else
    case self
    when /^[0-9]+$/
      to_i
    when /^(t(rue)?|y(es)?)$/i
      true
    when /^(f(alse)?|n(o)?)$/i
      false
    else
      self
    end
  end
end

#to_rxRegexp

Convert a string to a regex object based on matching settings

Returns:

  • (Regexp)

    Receive regex representation of the object.



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/howzit/stringutils.rb', line 91

def to_rx
  case Howzit.options[:matching]
  when 'exact'
    /^#{self}$/i
  when 'beginswith'
    /^#{self}/i
  when 'fuzzy'
    /#{split(//).join('.{0,3}?')}/i
  else
    /#{self}/i
  end
end

#trunc(len) ⇒ Object

Truncate string to nearest word

Parameters:

  • len (Integer)

    max length of string



164
165
166
167
168
169
170
# File 'lib/howzit/stringutils.rb', line 164

def trunc(len)
  split(/ /).each_with_object([]) do |x, ob|
    break ob unless ob.join(' ').length + ' '.length + x.length <= len

    ob.push(x)
  end.join(' ').strip
end

#trunc!(len) ⇒ Object

Truncate string in place (destructive)

Parameters:

  • len (Integer)

    The length to truncate at



177
178
179
# File 'lib/howzit/stringutils.rb', line 177

def trunc!(len)
  replace trunc(len)
end

#uncolorObject

Just strip out color codes when requested



105
106
107
# File 'lib/howzit/stringutils.rb', line 105

def uncolor
  gsub(/\e\[[\d;]+m/, '').gsub(/\e\]1337;SetMark/,'')
end

#wrap(width) ⇒ String

Wrap text at a specified width.

Adapted from https://github.com/pazdera/word_wrap/, copyright (c) 2014, 2015 Radek Pazdera Distributed under the MIT License

Parameters:

  • width (Integer)

    The width at which to wrap lines

Returns:



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
# File 'lib/howzit/stringutils.rb', line 120

def wrap(width)
  width ||= 80
  output = []
  indent = ''

  text = gsub(/\t/, '  ')

  text.lines do |line|
    line.chomp! "\n"
    if line.length > width
      indent = if line.uncolor =~ /^(\s*(?:[+\-*]|\d+\.) )/
                 ' ' * Regexp.last_match[1].length
               else
                 ''
               end
      new_lines = line.split_line(width)

      while new_lines.length > 1 && new_lines[1].length + indent.length > width
        output.push new_lines[0]

        new_lines = new_lines[1].split_line(width, indent)
      end
      output += [new_lines[0], indent + new_lines[1]]
    else
      output.push line
    end
  end
  output.map!(&:rstrip)
  output.join("\n")
end

#wrap!(width) ⇒ Object

Wrap string in place (destructive)

Parameters:

  • width (Integer)

    The width at which to wrap



156
157
158
# File 'lib/howzit/stringutils.rb', line 156

def wrap!(width)
  replace(wrap(width))
end