jtag 0.1.19 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,267 +1,314 @@
1
1
  # encoding: utf-8
2
2
 
3
- class JTag
4
- attr_reader :default_post_location
5
- attr_accessor :tags_key
3
+ module JekyllTag
4
+ class JTag
5
+ attr_reader :default_post_location
6
+ attr_reader :tags_loc
7
+ attr_reader :post_extension
8
+ attr_accessor :tags_key
6
9
 
7
- def initialize(support_dir, config)
8
- @support = support_dir
9
- begin
10
- @tags_loc = config['tags_location']
11
- @tags_loc.sub!(/^https?:\/\//,'')
12
- rescue
13
- raise "No tags location in configuration."
14
- end
15
- @min_matches = config['min_matches'] || 2
16
- @tags_key = config['tags_key'] || 'tags'
10
+ def initialize(support_dir, config, options = {})
11
+ config = config.symbolize_keys
12
+ @support = support_dir
13
+ @util = JekyllTag::Util.new
14
+ begin
15
+ if options[:files]
16
+ @tags_loc = :auto
17
+ files = options[:files].map(&:File.expand_path)
18
+ elsif config[:tags_location].to_s =~ /^(auto|posts?)$/
19
+ @tags_loc = :auto
20
+ files = Dir.glob(File.expand_path(File.join(config[:default_post_location], "**", "*.#{config[:post_extension]}")))
21
+ else
22
+ @tags_loc = config[:tags_location]
23
+ if File.exist?(File.expand_path(@tags_loc))
24
+ @tags_loc = File.expand_path(@tags_loc)
25
+ else
26
+ @tags_loc.sub!(/^https?:\/\//, "")
27
+ end
28
+ files = nil
29
+ end
30
+ rescue StandardError => e
31
+ raise InvalidTagsFile, "Error reading configured tags locatio (#{e})"
32
+ end
33
+
34
+ @min_matches = config[:min_matches] || 2
35
+ @post_extension = config[:post_extension] || "md"
36
+ @post_extension.sub!(/^\./, "")
37
+ @tags_key = config[:tags_key] || "tags"
17
38
 
18
- if config.has_key? 'default_post_location'
19
- @default_post_location = File.expand_path(config['default_post_location']) || false
20
- else
21
- console_log "#{color('yellow')}No #{color('boldyellow')}default_post_location#{color('yellow')} set.", :err => true
22
- console_log "If you commonly work on the same posts you can add the path and *.ext", :err => true
23
- console_log "to this key in ~/.jtag/config.yml. Then, if you don't specify files", :err => true
24
- console_log "to act on in a command, it will fall back to those. Nice!#{color('default')}", :err => true
25
- @default_post_location = false
39
+ if config.has_key? :default_post_location
40
+ @default_post_location = File.expand_path(config[:default_post_location]) || false
41
+ else
42
+ str = ["#{color("yellow")}No #{color("boldyellow")}default_post_location#{color("yellow")} set.",
43
+ "If you commonly work on the same posts you can add the path and extension",
44
+ "to these key in ~/.jtag/config.yml. Then, if you don't specify files",
45
+ "to act on in a command, it will fall back to those. Nice!#{color("default")}"].join("\n")
46
+ @util.console_log str, err: true, level: :error
47
+ @default_post_location = false
48
+ end
49
+ @blacklistfile = File.join(@support, "blacklist.txt")
50
+ @blacklist = IO.read(@blacklistfile).split("\n") || []
51
+ @skipwords = IO.read(File.join(support_dir, "stopwords.txt")).split("\n") || []
52
+ remote_tags = tags(files: files)
53
+ @tags = {}
54
+ remote_tags.each do |tag|
55
+ @tags[tag.root_words] = tag if tag
56
+ end
57
+ synonyms.each { |k, v|
58
+ @tags[k.to_s.downcase] = v unless @blacklist.include?(k.to_s.downcase)
59
+ }
26
60
  end
27
- @blacklistfile = File.join(@support,'blacklist.txt')
28
- @blacklist = IO.read(@blacklistfile).split("\n") || []
29
- @skipwords = IO.read(File.join(support_dir,'stopwords.txt')).split("\n") || []
30
- remote_tags = get_tags
31
- @tags = {}
32
- remote_tags.each {|tag| @tags[Text::PorterStemming.stem(tag).downcase] = tag if tag}
33
- synonyms.each { |k,v|
34
- @tags[k.to_s.downcase] = v unless @blacklist.include?(k.to_s.downcase)
35
- }
36
- end
37
61
 
38
- def get_tags(options={})
39
- blacklisted = options[:blacklisted] || false
40
- counts = options[:counts] || false
41
- host, path = @tags_loc.match(/^([^\/]+)(\/.*)/)[1,2]
42
- tags = ""
43
- # http = Net::HTTP.new(host, 80)
44
- # http.start do |http|
45
- # request = Net::HTTP::Get.new(path)
46
- # response = http.request(request)
47
- # response.value
48
- # tags = response.body
49
- # end
50
- tags = `curl -sSL "#{@tags_loc}"`
51
- tags = JSON.parse(tags)
52
- if tags && tags.key?("tags")
53
- if counts
54
- return tags["tags_count"]
62
+ def tags(options = {})
63
+ blacklisted = options[:blacklisted] || false
64
+ counts = options[:counts] || false
65
+ if options[:files]
66
+ tags = {}
67
+ tag_counts = {}
68
+ options[:files].each do |file|
69
+ tags["tags"] ||= []
70
+
71
+ file_tags = post_tags(File.expand_path(file))
72
+ file_tags.each do |tag|
73
+ tag_counts[tag] ||= 0
74
+ tag_counts[tag] += 1
75
+ tags["tags"].push(tag)
76
+ end
77
+ end
78
+ tags["tags_count"] = []
79
+ tag_counts.each { |k, v| tags["tags_count"] << { "name" => k, "count" => v } }
80
+ elsif File.exist?(@tags_loc)
81
+ begin
82
+ tags = YAML.load_file(@tags_loc)
83
+ rescue LoadError
84
+ tags = JSON.parse(IO.read(@tags_loc))
85
+ rescue
86
+ raise InvalidTagsFile, "Tags file is not in YAML or JSON format."
87
+ end
55
88
  else
56
- unless blacklisted
57
- tags["tags"].delete_if {|tag| !tag || @blacklist.include?(tag.downcase) }
89
+ host, path = @tags_loc.match(/^([^\/]+)(\/.*)/)[1, 2]
90
+ tags = ""
91
+ # http = Net::HTTP.new(host, 80)
92
+ # http.start do |http|
93
+ # request = Net::HTTP::Get.new(path)
94
+ # response = http.request(request)
95
+ # response.value
96
+ # tags = response.body
97
+ # end
98
+ tags = `curl -sSL "#{@tags_loc}"`
99
+ tags = YAML.load(tags) rescue JSON.parse(tags)
100
+ raise InvalidTagsFile, "Tags file is not in YAML or JSON format." unless tags
101
+ end
102
+ if tags && tags.key?("tags")
103
+ if counts && tags.key?("tags_count")
104
+ tags["tags_count"].delete_if { |tag| !tag || @blacklist.include?(tag["name"].downcase) } unless blacklisted
105
+ return tags["tags_count"]
106
+ else
107
+ tags["tags"].delete_if { |tag| !tag || @blacklist.include?(tag.downcase) } unless blacklisted
108
+ return tags["tags"]
58
109
  end
59
- return tags["tags"]
110
+ else
111
+ return false
60
112
  end
61
- else
62
- return false
63
113
  end
64
- end
65
114
 
66
- def synonyms
67
- if File.exist?(File.join(@support,"synonyms.yml"))
68
- syn = YAML::load(File.open(File.join(@support,"synonyms.yml")))
69
- compiled = {}
70
- syn.each {|k,v|
71
- v.each {|synonym|
72
- compiled[synonym] = k
115
+ def synonyms
116
+ if File.exist?(File.join(@support, "synonyms.yml"))
117
+ syn = YAML::load(File.open(File.join(@support, "synonyms.yml")))
118
+ compiled = {}
119
+ syn.each { |k, v|
120
+ v.each { |synonym|
121
+ compiled[synonym] = k
122
+ }
73
123
  }
74
- }
75
- else
76
- return false
77
- end
78
- compiled
79
- end
80
-
81
- def split_post(file, piped = false)
82
- input = piped ? file : IO.read(file)
83
- # Check to see if it's a full post with YAML headers
84
- post_parts = input.split(/^[\.\-]{3}\s*$/)
85
- if post_parts.length >= 3
86
- after = post_parts[2].strip
87
- yaml = YAML::load(input)
88
- else
89
- after = input
90
- yaml = YAML::load("--- title: #{File.basename(file)}")
124
+ else
125
+ return false
126
+ end
127
+ compiled
91
128
  end
92
- [yaml, after]
93
- end
94
129
 
95
- def post_tags(file, piped=false)
96
- begin
97
- input = piped ? file.strip : IO.read(file)
98
- yaml = YAML::load(input)
99
- return yaml[@tags_key] || []
100
- rescue
101
- return []
130
+ def split_post(file, piped = false)
131
+ input = piped ? file : IO.read(file)
132
+ # Check to see if it's a full post with YAML headers
133
+ post_parts = input.split(/^[\.\-]{3}\s*$/)
134
+ if post_parts.length >= 3
135
+ after = post_parts[2].strip
136
+ yaml = YAML::load(input)
137
+ else
138
+ after = input
139
+ yaml = YAML::load("--- title: #{File.basename(file)}")
140
+ end
141
+ [yaml, after]
102
142
  end
103
- end
104
143
 
105
- def merge_tags(tags, merged, file)
106
- current_tags = post_tags(file)
107
- post_has_tag = false
108
- tags.each {|tag|
109
- if current_tags.include?(tag)
110
- current_tags.delete(tag)
111
- post_has_tag = true
144
+ def post_tags(file, piped = false)
145
+ begin
146
+ input = piped ? file.strip : IO.read(File.expand_path(file))
147
+ yaml = YAML::load(input)
148
+ return yaml[@tags_key] || []
149
+ rescue
150
+ return []
112
151
  end
113
- }
114
- return false unless post_has_tag
115
- current_tags.push(merged)
116
- current_tags.uniq!
117
- current_tags.sort
118
- end
152
+ end
119
153
 
154
+ def merge_tags(tags, merged, file)
155
+ current_tags = post_tags(file)
156
+ post_has_tag = false
157
+ tags.each { |tag|
158
+ if current_tags.include?(tag)
159
+ current_tags.delete(tag)
160
+ post_has_tag = true
161
+ end
162
+ }
163
+ return false unless post_has_tag
164
+ current_tags.push(merged)
165
+ current_tags.uniq!
166
+ current_tags.sort
167
+ end
120
168
 
121
- def suggest(input)
122
- parts = input.split(/^[\.\-]{3}\s*$/)
123
- if parts.length >= 2
124
- begin
125
- yaml = YAML::load(parts[1])
126
- current_tags = yaml[@tags_key] || []
127
- title = yaml["title"] || ""
128
- rescue
169
+ def suggest(input)
170
+ parts = input.split(/^[\.\-]{3}\s*$/)
171
+ if parts.length >= 2
172
+ begin
173
+ yaml = YAML::load(parts[1])
174
+ current_tags = yaml[@tags_key] || []
175
+ title = yaml["title"] || ""
176
+ rescue
177
+ current_tags = []
178
+ title = ""
179
+ end
180
+ else
129
181
  current_tags = []
130
182
  title = ""
131
183
  end
132
- else
133
- current_tags = []
134
- title = ""
184
+ @content = (title + parts[2..-1].join(" ")).strip_all.strip_urls rescue input.strip_all.strip_urls
185
+ @words = split_words
186
+ @auto_tags = []
187
+ populate_auto_tags
188
+
189
+ @auto_tags.concat(current_tags).uniq
135
190
  end
136
- @content = (title + parts[2..-1].join(" ")).strip_all.strip_urls rescue input.strip_all.strip_urls
137
- @words = split_words
138
- @auto_tags = []
139
- populate_auto_tags
140
191
 
141
- @auto_tags.concat(current_tags).uniq
142
- end
192
+ def split_words
193
+ @content.gsub(/([\/\\]|\s+)/, " ").gsub(/[^a-z0-9\s-]/i, "").split(" ").delete_if { |word|
194
+ word =~ /^[^a-z]+$/ || word.length < 4
195
+ }.map! { |word|
196
+ Text::PorterStemming.stem(word).downcase
197
+ }.delete_if { |word|
198
+ @skipwords.include?(word) && !@tags.keys.include?(word)
199
+ }
200
+ end
143
201
 
144
- def split_words
145
- @content.gsub(/([\/\\]|\s+)/,' ').gsub(/[^A-Za-z0-9\s-]/,'').split(" ").delete_if { |word|
146
- word =~ /^[^a-z]+$/ || word.length < 4
147
- }.map! { |word|
148
- Text::PorterStemming.stem(word).downcase
149
- }.delete_if{ |word|
150
- @skipwords.include?(word) && !@tags.keys.include?(word)
151
- }
152
- end
202
+ def populate_auto_tags
203
+ freqs = Hash.new(0)
204
+ @words.each { |word| freqs[word] += 1 }
205
+ freqs.delete_if { |k, v| v < @min_matches }
153
206
 
154
- def populate_auto_tags
155
- freqs = Hash.new(0)
156
- @words.each { |word| freqs[word] += 1 }
157
- freqs.delete_if {|k,v| v < @min_matches }
207
+ return [] if freqs.empty?
158
208
 
159
- return [] if freqs.empty?
209
+ freqs.sort_by { |k, v| [v * -1, k] }.each { |word|
210
+ index = @tags.keys.index(word[0])
211
+ unless index.nil? || @blacklist.include?(@tags.keys[index])
212
+ @auto_tags.push(@tags[@tags.keys[index]]) unless index.nil?
213
+ end
214
+ }
160
215
 
161
- freqs.sort_by {|k,v| [v * -1, k] }.each {|word|
162
- index = @tags.keys.index(word[0])
163
- unless index.nil? || @blacklist.include?(@tags.keys[index])
164
- @auto_tags.push(@tags[@tags.keys[index]]) unless index.nil?
165
- end
166
- }
216
+ @tags.each { |k, v|
217
+ occurrences = @content.scan(/\b#{k}\b/i)
218
+ if occurrences.count >= @min_matches
219
+ @auto_tags.push(v)
220
+ end
221
+ }
222
+ end
167
223
 
168
- @tags.each{|k,v|
169
- occurrences = @content.scan(/\b#{k}\b/i)
170
- if occurrences.count >= @min_matches
171
- @auto_tags.push(v)
224
+ def blacklist(tags)
225
+ tags.each { |word|
226
+ @blacklist.push(word.downcase)
227
+ }
228
+ File.open(@blacklistfile, "w+") do |f|
229
+ f.puts @blacklist.uniq.sort.join("\n")
172
230
  end
173
- }
174
- end
175
-
176
- def blacklist(tags)
177
- tags.each {|word|
178
- @blacklist.push(word.downcase)
179
- }
180
- File.open(@blacklistfile,'w+') do |f|
181
- f.puts @blacklist.uniq.sort.join("\n")
182
231
  end
183
- end
184
232
 
185
- def unblacklist(tags)
186
- tags.each {|word|
187
- @blacklist.delete_if { |x| x == word }
188
- }
189
- File.open(@blacklistfile,'w+') do |f|
190
- f.puts @blacklist.uniq.sort.join("\n")
233
+ def unblacklist(tags)
234
+ tags.each { |word|
235
+ @blacklist.delete_if { |x| x == word }
236
+ }
237
+ File.open(@blacklistfile, "w+") do |f|
238
+ f.puts @blacklist.uniq.sort.join("\n")
239
+ end
191
240
  end
192
- end
193
241
 
194
- def update_file_tags(file, tags, piped = false)
195
- begin
196
- if File.exist?(file) || piped
197
- yaml, after = split_post(file, piped)
198
- yaml[@tags_key] = tags
199
- if piped
200
- puts yaml.to_yaml
201
- puts "---"
202
- puts after
203
- else
204
- File.open(file,'w+') do |f|
205
- f.puts yaml.to_yaml
206
- f.puts "---"
207
- f.puts after
242
+ def update_file_tags(file, tags, piped = false)
243
+ begin
244
+ if File.exist?(file) || piped
245
+ yaml, after = split_post(file, piped)
246
+ yaml[@tags_key] = tags
247
+ if piped
248
+ puts yaml.to_yaml
249
+ puts "---"
250
+ puts after
251
+ else
252
+ File.open(file, "w+") do |f|
253
+ f.puts yaml.to_yaml
254
+ f.puts "---"
255
+ f.puts after
256
+ end
208
257
  end
258
+ else
259
+ raise "File does not exist: #{file}"
209
260
  end
210
- else
211
- raise "File does not exist: #{file}"
261
+ return true
262
+ rescue Exception => e
263
+ raise e
264
+ return false
212
265
  end
213
- return true
214
- rescue Exception => e
215
- raise e
216
- return false
217
266
  end
218
- end
219
267
 
220
- private
221
-
222
- def color(name)
268
+ def color(name)
223
269
  color = {}
224
- color['black'] = "\033[0;30m"
225
- color['red'] = "\033[0;31m"
226
- color['green'] = "\033[0;32m"
227
- color['yellow'] = "\033[0;33m"
228
- color['blue'] = "\033[0;34m"
229
- color['magenta'] = "\033[0;35m"
230
- color['cyan'] = "\033[0;36m"
231
- color['white'] = "\033[0;37m"
232
- color['bgblack'] = "\033[0;40m"
233
- color['bgred'] = "\033[0;41m"
234
- color['bggreen'] = "\033[0;42m"
235
- color['bgyellow'] = "\033[0;43m"
236
- color['bgblue'] = "\033[0;44m"
237
- color['bgmagenta'] = "\033[0;45m"
238
- color['bgcyan'] = "\033[0;46m"
239
- color['bgwhite'] = "\033[0;47m"
240
- color['boldblack'] = "\033[1;30m"
241
- color['boldred'] = "\033[1;31m"
242
- color['boldgreen'] = "\033[1;32m"
243
- color['boldyellow'] = "\033[1;33m"
244
- color['boldblue'] = "\033[1;34m"
245
- color['boldmagenta'] = "\033[1;35m"
246
- color['boldcyan'] = "\033[1;36m"
247
- color['boldwhite'] = "\033[1;37m"
248
- color['boldbgblack'] = "\033[1;40m"
249
- color['boldbgred'] = "\033[1;41m"
250
- color['boldbggreen'] = "\033[1;42m"
251
- color['boldbgyellow'] = "\033[1;43m"
252
- color['boldbgblue'] = "\033[1;44m"
253
- color['boldbgmagenta'] = "\033[1;45m"
254
- color['boldbgcyan'] = "\033[1;46m"
255
- color['boldbgwhite'] = "\033[1;47m"
256
- color['default'] = "\033[0;39m"
257
- color['warning'] = color['yellow']
258
- color['warningb'] = color['boldyellow']
259
- color['success'] = color['green']
260
- color['successb'] = color['boldgreen']
261
- color['neutral'] = color['white']
262
- color['neutralb'] = color['boldwhite']
263
- color['info'] = color['cyan']
264
- color['infob'] = color['boldcyan']
265
- color[name]
270
+ color["black"] = "\033[0;30m"
271
+ color["red"] = "\033[0;31m"
272
+ color["green"] = "\033[0;32m"
273
+ color["yellow"] = "\033[0;33m"
274
+ color["blue"] = "\033[0;34m"
275
+ color["magenta"] = "\033[0;35m"
276
+ color["cyan"] = "\033[0;36m"
277
+ color["white"] = "\033[0;37m"
278
+ color["bgblack"] = "\033[0;40m"
279
+ color["bgred"] = "\033[0;41m"
280
+ color["bggreen"] = "\033[0;42m"
281
+ color["bgyellow"] = "\033[0;43m"
282
+ color["bgblue"] = "\033[0;44m"
283
+ color["bgmagenta"] = "\033[0;45m"
284
+ color["bgcyan"] = "\033[0;46m"
285
+ color["bgwhite"] = "\033[0;47m"
286
+ color["boldblack"] = "\033[1;30m"
287
+ color["boldred"] = "\033[1;31m"
288
+ color["boldgreen"] = "\033[1;32m"
289
+ color["boldyellow"] = "\033[1;33m"
290
+ color["boldblue"] = "\033[1;34m"
291
+ color["boldmagenta"] = "\033[1;35m"
292
+ color["boldcyan"] = "\033[1;36m"
293
+ color["boldwhite"] = "\033[1;37m"
294
+ color["boldbgblack"] = "\033[1;40m"
295
+ color["boldbgred"] = "\033[1;41m"
296
+ color["boldbggreen"] = "\033[1;42m"
297
+ color["boldbgyellow"] = "\033[1;43m"
298
+ color["boldbgblue"] = "\033[1;44m"
299
+ color["boldbgmagenta"] = "\033[1;45m"
300
+ color["boldbgcyan"] = "\033[1;46m"
301
+ color["boldbgwhite"] = "\033[1;47m"
302
+ color["default"] = "\033[0;39m"
303
+ color["warning"] = color["yellow"]
304
+ color["warningb"] = color["boldyellow"]
305
+ color["success"] = color["green"]
306
+ color["successb"] = color["boldgreen"]
307
+ color["neutral"] = color["white"]
308
+ color["neutralb"] = color["boldwhite"]
309
+ color["info"] = color["cyan"]
310
+ color["infob"] = color["boldcyan"]
311
+ color[name.to_s]
312
+ end
266
313
  end
267
314
  end