jtag 0.1.18 → 0.1.21

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