Class: Remoji

Inherits:
Object
  • Object
show all
Defined in:
lib/remoji.rb

Overview

The Remoji command

Constant Summary collapse

EMOJI_TABLE =

rubocop:disable Metrics/ClassLength

'http://unicode.org/emoji/charts/full-emoji-list.html'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ Remoji

Returns a new instance of Remoji.



68
69
70
71
72
# File 'lib/remoji.rb', line 68

def initialize(args)
  @args = args
  @options = OpenStruct.new verbose: 0
  verify_cache!
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



67
68
69
# File 'lib/remoji.rb', line 67

def args
  @args
end

Class Method Details

.run!(args) ⇒ Object



16
17
18
# File 'lib/remoji.rb', line 16

def self.run!(args)
  new(args).execute!
end

Instance Method Details

#bighead(elem) ⇒ Object



44
45
46
# File 'lib/remoji.rb', line 44

def bighead(elem)
  elem.css('th[class=bighead]').empty? ? nil : elem.css('th[class=bighead]')
end

#cat_opt(opt) ⇒ Object



218
219
220
# File 'lib/remoji.rb', line 218

def cat_opt(opt)
  opt.on('-cCAT', '--cat CAT', 'Find matches in a category') { |s| @options.cat = s }
end

#categoriesObject



20
21
22
# File 'lib/remoji.rb', line 20

def categories
  @categories ||= filter_hash.map { |_k, v| v[:cat] }.uniq
end

#cats_opt(opt) ⇒ Object



200
201
202
203
204
205
# File 'lib/remoji.rb', line 200

def cats_opt(opt)
  opt.on('--subs', '--subcategories', 'List subcategories') do
    ap subcategories
    exit
  end
end

#details_opt(opt) ⇒ Object



222
223
224
# File 'lib/remoji.rb', line 222

def details_opt(opt)
  opt.on('-n', '--no-details', 'Just print the string with :emojis: substituded') { |_| @options.no = true }
end

#die!(msg, code = 1) ⇒ Object



226
227
228
229
# File 'lib/remoji.rb', line 226

def die!(msg, code = 1)
  warn msg
  exit code
end

#emoji_fileObject



74
75
76
77
78
79
80
# File 'lib/remoji.rb', line 74

def emoji_file
  return @emoji_file if @emoji_file

  local = Pathname(ENV['HOME']).join('.local/remoji')
  FileUtils.mkdir_p local.to_s unless local.exist?
  @emoji_file = local.join('emojis.json')
end

#emoji_tableObject



48
49
50
51
52
# File 'lib/remoji.rb', line 48

def emoji_table
  doc = Nokogiri(open(EMOJI_TABLE).read) # rubocop:disable Security/Open
  tds = doc.xpath('//table/tr/td')
  tds.each_slice 15
end

#exact_opt(opt) ⇒ Object



188
189
190
# File 'lib/remoji.rb', line 188

def exact_opt(opt)
  opt.on('-e', '--exact', 'Exactly match the emoji given, do not search for it') { @options.exact = true }
end

#execute!Object



112
113
114
115
116
117
118
119
120
# File 'lib/remoji.rb', line 112

def execute!
  parse_opts! args
  if args.empty?
    puts output(filter_array)
    exit
  end

  puts output
end

#filter_arrayObject



95
96
97
# File 'lib/remoji.rb', line 95

def filter_array
  @filter_array ||= filter_hash.to_a
end

#filter_hashObject



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/remoji.rb', line 99

def filter_hash
  return @filter_hash if @filter_hash

  db = JSON.parse(emoji_file.read, symbolize_names: true)
  @filter_hash = if @options.subcat
                   db.select { |_k, v| v[:subcat] =~ /#{@options.subcat}/i }
                 elsif @options.cat
                   db.select { |_k, v| v[:cat] =~ /#{@options.cat}/i }
                 else
                   db
                 end
end

#find_bighead(elem) ⇒ Object



38
39
40
41
42
# File 'lib/remoji.rb', line 38

def find_bighead(elem)
  return bighead(elem).text if bighead(elem)

  find_bighead(elem.previous_sibling)
end

#find_in_filter_array(arg) ⇒ Object



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

def find_in_filter_array(arg)
  find_in_filter_hash(arg).to_a || []
end

#find_in_filter_hash(arg) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/remoji.rb', line 160

def find_in_filter_hash(arg)
  filter_hash.select do |k, _v|
    s = k.to_s
    if @options.exact
      s == arg
    elsif @options.regex
      s =~ /#{arg}/
    else
      s =~ /#{arg}/i
    end
  end
end

#find_medhead(elem) ⇒ Object



28
29
30
31
32
# File 'lib/remoji.rb', line 28

def find_medhead(elem)
  return medhead(elem).text if medhead(elem)

  find_medhead(elem.previous_sibling)
end

#formatted(name, attrs) ⇒ Object



122
123
124
125
126
127
# File 'lib/remoji.rb', line 122

def formatted(name, attrs)
  return attrs[:sym] if @options.no
  return "#{name}: #{attrs}" if @options.verbose.positive?

  [attrs[:sym], name].join(' : ')
end

#import_emojis!Object



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/remoji.rb', line 54

def import_emojis!
  hash = {}
  emoji_table.each do |n|
    hash[n.last.text] = {
      code: n[1].text,
      sym: n[2].text,
      cat: find_bighead(n.last.parent),
      subcat: find_medhead(n.last.parent)
    }
  end
  emoji_file.open('w+') { |f| f.puts JSON.pretty_generate(hash) }
end

#medhead(elem) ⇒ Object



34
35
36
# File 'lib/remoji.rb', line 34

def medhead(elem)
  elem.css('th[class=mediumhead]').empty? ? nil : elem.css('th[class=mediumhead]')
end

#output(arr = nil) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/remoji.rb', line 129

def output(arr = nil)
  if arr
    strings = arr.map { |name, attrs| formatted name, attrs }
    sep = @options.no ? ' ' : "\n"
    return strings.join(sep)
  end
  return replace_emojis args.join(' ') if @options.no

  args.each_with_object([]) do |q, s|
    s << string_for(q)
  end.join.squeeze(' ')
end

#parse_opts!(args) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/remoji.rb', line 173

def parse_opts!(args)
  OptionParser.new do |o|
    o.banner = "#{$PROGRAM_NAME} [options] <EMOJI ANOTHER_EMOJI ... | String With :substitutions: (with -n)>"
    o.separator 'Where EMOJI is an emoji name to search for'
    o.separator 'With -n, all arguments are treated as a string and :emoji: blocks are replaced with matches, if any'
    %i[cat subcat details cats subcats verbose exact regex].each do |sym|
      send "#{sym}_opt".to_sym, o
    end
    o.on('-h', '--help') do
      puts o
      exit
    end
  end.parse!(args)
end

#regex_opt(opt) ⇒ Object



192
193
194
# File 'lib/remoji.rb', line 192

def regex_opt(opt)
  opt.on('-r', '--regex', 'Consider each argument a regular expression') { @options.regex = true }
end

#replace_emojis(string) ⇒ Object



150
151
152
153
154
# File 'lib/remoji.rb', line 150

def replace_emojis(string)
  string.gsub(/:[^:]*:/) do |r|
    r == '::' ? '' : string_for(r[1..-2])
  end
end

#string_for(emoji) ⇒ Object



142
143
144
145
146
147
148
# File 'lib/remoji.rb', line 142

def string_for(emoji)
  found = find_in_filter_array(emoji).each_with_object([]) { |f, arr| arr << f }
  sep = @options.no ? ' ' : "\n"
  found.each_with_object([]) do |f, s|
    s << formatted(*f)
  end.join sep
end

#subcat_opt(opt) ⇒ Object



214
215
216
# File 'lib/remoji.rb', line 214

def subcat_opt(opt)
  opt.on('-sCAT', '--subcat CAT', 'Find matches in a subcategory') { |s| @options.subcat = s }
end

#subcategoriesObject



24
25
26
# File 'lib/remoji.rb', line 24

def subcategories
  @subcategories ||= filter_hash.map { |_k, v| v[:subcat] }.uniq
end

#subcats_opt(opt) ⇒ Object



207
208
209
210
211
212
# File 'lib/remoji.rb', line 207

def subcats_opt(opt)
  opt.on('--cats', '--categories', 'List Categories') do
    ap categories
    exit
  end
end

#verbose_opt(opt) ⇒ Object



196
197
198
# File 'lib/remoji.rb', line 196

def verbose_opt(opt)
  opt.on('-v', '--verbose', 'Increase verbosity') { @options.verbose += 1 }
end

#verify_cache!Object



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/remoji.rb', line 82

def verify_cache!
  return if emoji_file.exist?

  warn "No #{@emoji_file} found. Import?"
  yn = $stdin.getc
  unless yn =~ /^y/i
    warn 'Ok, Bailing!'
    exit 1
  end
  warn 'Ok, importing'
  import_emojis!
end