jtag 0.1.17 → 0.1.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/jtag +241 -203
- data/lib/jtag/jekylltag.rb +2 -2
- data/lib/jtag/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71af8eca8dc4710dbb6d924c08a68cc834ab90e15f29d533809bdc1a2e269c6a
|
4
|
+
data.tar.gz: 964a8e7a5bc147edbd6006d2721ec57d89ca11fd77e77b189f5c0bfa8e6691db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13c13c4f35e36c9a9015082a370127bcc2e83f0d7682e1821390fc949534b45d0d134cadcbbe057a669582f16039cc7e7cc1a6f05e1d17edeec92f9663d371b0
|
7
|
+
data.tar.gz: 3c0b420b164c1f5fe67e09a6bd4827195c84fe51a8adb6ae153189ec18d75dc649820b3b7c539b780d37d1d311acc2309beeae4f3df59795a57039253ea8f12b
|
data/bin/jtag
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "gli"
|
4
|
+
require "jtag"
|
5
|
+
require "fcntl"
|
5
6
|
|
6
7
|
include GLI::App
|
7
8
|
|
8
|
-
program_desc
|
9
|
+
program_desc "Autotagging for Jekyll"
|
9
10
|
|
10
11
|
version Jtag::VERSION
|
11
12
|
|
@@ -15,20 +16,29 @@ version Jtag::VERSION
|
|
15
16
|
|
16
17
|
def config_files_complete?
|
17
18
|
@config_files.each do |file|
|
18
|
-
return false unless File.
|
19
|
+
return false unless File.exist?(File.join(@config_target, file))
|
19
20
|
end
|
20
21
|
true
|
21
22
|
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
class ::String
|
25
|
+
def file_list?
|
26
|
+
self.strip.split("\n").each do |line|
|
27
|
+
return false unless File.exist?(line)
|
28
|
+
end
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Debug level"
|
34
|
+
default_value "0"
|
35
|
+
arg_name "debug_level"
|
26
36
|
flag %i[d debug], :must_match => /\d+/, :type => Integer, :default_value => 0
|
27
37
|
|
28
|
-
desc
|
38
|
+
desc "Run silently"
|
29
39
|
switch %i[s silent]
|
30
40
|
|
31
|
-
desc
|
41
|
+
desc "Perform case-insensitive matches and searches"
|
32
42
|
switch %i[i case_insensitive]
|
33
43
|
|
34
44
|
desc "Test (dry run, don't update files)"
|
@@ -36,7 +46,7 @@ long_desc "Run all commands and show results on the command line, but don't over
|
|
36
46
|
default_value false
|
37
47
|
switch %i[t test]
|
38
48
|
|
39
|
-
def console_log(msg="", options={})
|
49
|
+
def console_log(msg = "", options = {})
|
40
50
|
err = options[:err] || false
|
41
51
|
options[:log] ||= false
|
42
52
|
|
@@ -57,13 +67,13 @@ def console_log(msg="", options={})
|
|
57
67
|
end
|
58
68
|
end
|
59
69
|
|
60
|
-
desc
|
70
|
+
desc "Update and notify user of configuration files location"
|
61
71
|
command :config do |c|
|
62
|
-
c.desc
|
63
|
-
c.switch [:r,
|
72
|
+
c.desc "Reset all configuration files to default values"
|
73
|
+
c.switch [:r, "reset"]
|
64
74
|
|
65
75
|
c.skips_pre
|
66
|
-
c.action do |global_options,options,args|
|
76
|
+
c.action do |global_options, options, args|
|
67
77
|
if options[:r]
|
68
78
|
print "Are you sure you want to reset all config files? y/N: "
|
69
79
|
response = STDIN.gets.strip
|
@@ -77,24 +87,22 @@ command :config do |c|
|
|
77
87
|
end
|
78
88
|
end
|
79
89
|
|
80
|
-
def write_config(atomic=false)
|
81
|
-
gem_root = Gem.loaded_specs[
|
82
|
-
gem_lib = File.join(gem_root,
|
83
|
-
config_source = File.join(gem_lib,
|
84
|
-
|
85
|
-
|
90
|
+
def write_config(atomic = false)
|
91
|
+
gem_root = Gem.loaded_specs["jtag"].full_gem_path
|
92
|
+
gem_lib = File.join(gem_root, "lib")
|
93
|
+
config_source = File.join(gem_lib, "/jtag/config_files")
|
86
94
|
|
87
95
|
unless File.directory?(@config_target) || atomic
|
88
|
-
FileUtils.cp_r(config_source
|
96
|
+
FileUtils.cp_r(config_source, @config_target)
|
89
97
|
console_log "Configuration files are located in the folder: " + @config_target
|
90
98
|
console_log %Q{Make sure that "tags_location" in config.yml is set to your tags.json url.}
|
91
99
|
console_log "Configuration files written to #{@config_target}"
|
92
100
|
end
|
93
101
|
|
94
102
|
@config_files.each do |file|
|
95
|
-
unless File.
|
96
|
-
source_file = File.join(config_source,file)
|
97
|
-
target_file = File.join(@config_target,file)
|
103
|
+
unless File.exist?(File.join(@config_target, file))
|
104
|
+
source_file = File.join(config_source, file)
|
105
|
+
target_file = File.join(@config_target, file)
|
98
106
|
FileUtils.cp(source_file, target_file)
|
99
107
|
console_log "Config file #{file} added."
|
100
108
|
end
|
@@ -104,102 +112,105 @@ def write_config(atomic=false)
|
|
104
112
|
console_log %Q{Make sure that "tags_location" in the config.yml file is set to your tags json file.}
|
105
113
|
end
|
106
114
|
|
107
|
-
desc
|
108
|
-
long_desc
|
109
|
-
arg_name
|
115
|
+
desc "List tags, optionally filter for keywords/regular expressions (OR)"
|
116
|
+
long_desc "This command can be used to find the exact format for a given tag to keep spaces, underscores, capitalization and pluralization consistent"
|
117
|
+
arg_name "keyword", :multiple
|
110
118
|
command :search do |c|
|
111
|
-
c.desc
|
112
|
-
c.arg_name
|
113
|
-
c.default_value
|
119
|
+
c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
|
120
|
+
c.arg_name "output_format"
|
121
|
+
c.default_value "yaml"
|
114
122
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/i, :type => String
|
115
123
|
|
116
|
-
c.desc
|
117
|
-
c.arg_name
|
124
|
+
c.desc "Include tag counts"
|
125
|
+
c.arg_name "counts"
|
118
126
|
c.default_value false
|
119
127
|
c.switch %i[c counts]
|
120
128
|
|
121
|
-
c.action do |global_options,options,args|
|
122
|
-
tags = @jt.get_tags({:counts => true})
|
129
|
+
c.action do |global_options, options, args|
|
130
|
+
tags = @jt.get_tags({ :counts => true })
|
123
131
|
if args.length > 0
|
124
132
|
re = args.join("|")
|
125
|
-
tags.delete_if {|tag|
|
126
|
-
if tag && tag[
|
133
|
+
tags.delete_if { |tag|
|
134
|
+
if tag && tag["name"] =~ /(#{re})/i
|
127
135
|
false
|
128
136
|
else
|
129
137
|
true
|
130
138
|
end
|
131
139
|
}
|
132
140
|
if options[:c]
|
133
|
-
tags.map! {|tag| "#{tag[
|
141
|
+
tags.map! { |tag| "#{tag["name"]} (#{tag["count"]})" }
|
134
142
|
else
|
135
|
-
tags.map! {|tag| tag[
|
143
|
+
tags.map! { |tag| tag["name"] }
|
136
144
|
end
|
137
|
-
output_tags(tags,{ :format => options[:format] })
|
145
|
+
output_tags(tags, { :format => options[:format] })
|
138
146
|
else
|
139
|
-
tags.delete_if {|tag| !tag }
|
147
|
+
tags.delete_if { |tag| !tag }
|
140
148
|
if options[:c]
|
141
|
-
tags.map! {|tag| "#{tag[
|
149
|
+
tags.map! { |tag| "#{tag["name"]} (#{tag["count"]})" }
|
142
150
|
else
|
143
|
-
tags.map! {|tag| tag[
|
151
|
+
tags.map! { |tag| tag["name"] }
|
144
152
|
end
|
145
|
-
output_tags(tags,{ :format => options[:format] })
|
153
|
+
output_tags(tags, { :format => options[:format] })
|
146
154
|
end
|
147
155
|
end
|
148
156
|
end
|
149
157
|
|
150
|
-
desc
|
151
|
-
arg_name
|
158
|
+
desc "List posts with tag(s)"
|
159
|
+
arg_name "tags", :multiple
|
152
160
|
command :posts_tagged do |c|
|
153
|
-
c.desc
|
154
|
-
c.arg_name
|
155
|
-
c.default_value
|
161
|
+
c.desc "Boolean operator for multiple tags (AND/OR/NOT)"
|
162
|
+
c.arg_name "bool"
|
163
|
+
c.default_value "OR"
|
156
164
|
c.flag %i[b bool], :must_match => /(AND|OR|NOT)/i, :type => String
|
157
165
|
|
158
|
-
c.desc
|
159
|
-
c.arg_name
|
160
|
-
c.default_value
|
166
|
+
c.desc "Format to use when outputting file list: list, json, plist, csv or yaml. Defaults to list."
|
167
|
+
c.arg_name "output_format"
|
168
|
+
c.default_value "list"
|
161
169
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
|
162
170
|
|
163
|
-
c.desc
|
171
|
+
c.desc "If output format is list, print without newlines."
|
164
172
|
c.switch [:print0]
|
165
173
|
|
166
|
-
c.action do |global_options,options,args|
|
174
|
+
c.action do |global_options, options, args|
|
167
175
|
bool = options[:bool].upcase
|
168
176
|
files = []
|
169
177
|
tags = []
|
170
178
|
matches = []
|
171
179
|
args.length.times do
|
172
180
|
arg = args.pop
|
173
|
-
if File.
|
181
|
+
if File.exist?(arg)
|
174
182
|
files.push(arg)
|
175
183
|
else
|
176
184
|
tags.push(arg)
|
177
185
|
end
|
178
186
|
end
|
187
|
+
|
188
|
+
files.concat(@piped_content.split("\n")) if @piped_content
|
189
|
+
|
179
190
|
if files.empty?
|
180
|
-
if @jt.default_post_location && File.
|
191
|
+
if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
|
181
192
|
files = Dir.glob(@jt.default_post_location)
|
182
193
|
end
|
183
194
|
end
|
184
195
|
exit_now! "No valid filename in arguments" if files.empty?
|
185
|
-
files.each {|file|
|
186
|
-
if File.
|
196
|
+
files.each { |file|
|
197
|
+
if File.exist?(file)
|
187
198
|
post_tags = @jt.post_tags(file)
|
188
199
|
|
189
200
|
if bool == "AND"
|
190
201
|
matched = 0
|
191
|
-
tags.each {|tag|
|
202
|
+
tags.each { |tag|
|
192
203
|
matched += 1 if post_tags.include?(tag)
|
193
204
|
}
|
194
205
|
matches.push(file) if matched == tags.length
|
195
206
|
elsif bool == "NOT"
|
196
207
|
matched = false
|
197
|
-
tags.each {|tag|
|
208
|
+
tags.each { |tag|
|
198
209
|
matched = true if post_tags.include?(tag)
|
199
210
|
}
|
200
211
|
matches.push(file) unless matched
|
201
212
|
else
|
202
|
-
tags.each {|tag|
|
213
|
+
tags.each { |tag|
|
203
214
|
if post_tags.include?(tag)
|
204
215
|
matches.push(file) unless matches.include?(file)
|
205
216
|
end
|
@@ -214,23 +225,23 @@ command :posts_tagged do |c|
|
|
214
225
|
if matches.empty?
|
215
226
|
console_log "No matching files found for #{search_string}"
|
216
227
|
else
|
217
|
-
console_log "(#{search_string})", {:err => true}
|
228
|
+
console_log "(#{search_string})", { :err => true }
|
218
229
|
output_tags(matches, { :format => options[:format], :print0 => options[:print0], :grouping => "files" })
|
219
230
|
end
|
220
231
|
end
|
221
232
|
end
|
222
233
|
|
223
|
-
desc
|
224
|
-
arg_name
|
234
|
+
desc "Show tags with fewer than X posts attached to them, optionally removing them from specified posts"
|
235
|
+
arg_name "file_pattern", :multiple
|
225
236
|
command :loners do |c|
|
226
|
-
c.desc
|
227
|
-
c.arg_name
|
228
|
-
c.default_value
|
237
|
+
c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
|
238
|
+
c.arg_name "output_format"
|
239
|
+
c.default_value "yaml"
|
229
240
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
|
230
241
|
|
231
|
-
c.desc
|
232
|
-
c.arg_name
|
233
|
-
c.default_value
|
242
|
+
c.desc "Upper limit for how many posts a tag can be attached to and still be a loner"
|
243
|
+
c.arg_name "max"
|
244
|
+
c.default_value "2"
|
234
245
|
c.flag %i[m max], :default_value => 2, :must_match => /^\d+$/
|
235
246
|
|
236
247
|
c.desc "Remove tags with fewer than X posts attached"
|
@@ -239,32 +250,32 @@ command :loners do |c|
|
|
239
250
|
c.desc "Display output without attached occurence counts"
|
240
251
|
c.switch [:no_counts], :default_value => false
|
241
252
|
|
242
|
-
c.desc
|
243
|
-
c.arg_name
|
253
|
+
c.desc "Output a file list of tags that can be edited and passed back in for removing"
|
254
|
+
c.arg_name "filename"
|
244
255
|
c.flag %i[e edit], :default_value => false, :type => String
|
245
256
|
|
246
|
-
c.action do |global_options,options,args|
|
257
|
+
c.action do |global_options, options, args|
|
247
258
|
max = options[:m].to_i
|
248
|
-
loner_tags = @jt.get_tags({:counts => true})
|
259
|
+
loner_tags = @jt.get_tags({ :counts => true })
|
249
260
|
loner_tags.delete_if { |tag|
|
250
|
-
tag.class == FalseClass || tag[
|
261
|
+
tag.class == FalseClass || tag["count"] > max
|
251
262
|
}
|
252
|
-
loner_tags.sort_by! {|tag| tag[
|
263
|
+
loner_tags.sort_by! { |tag| tag["count"] }
|
253
264
|
|
254
265
|
exit_now! "No tags matched the criteria" if loner_tags.empty? || loner_tags.nil?
|
255
266
|
|
256
267
|
if options[:e]
|
257
268
|
path = File.expand_path(options[:e])
|
258
|
-
while File.
|
269
|
+
while File.exist?(path)
|
259
270
|
if path =~ /(\d+)(\.[^\.]+?)?$/
|
260
271
|
path.sub!(/(\d+)(\.[^\.]+?)?$/) do |m|
|
261
272
|
$1.next! + $2
|
262
273
|
end
|
263
274
|
else
|
264
|
-
path.sub!(/(\.[^\.]+?)?$/,'01\1')
|
275
|
+
path.sub!(/(\.[^\.]+?)?$/, '01\1')
|
265
276
|
end
|
266
277
|
end
|
267
|
-
File.open(path,
|
278
|
+
File.open(path, "w+") do |f|
|
268
279
|
f.puts "# Edit this file to remove tags you want to keep,"
|
269
280
|
f.puts "# then run `jtag remove -p '#{path}' [/path/to/posts/*.md]`"
|
270
281
|
f.puts "# to remove any tags left in the file."
|
@@ -273,33 +284,36 @@ command :loners do |c|
|
|
273
284
|
f.puts "# be automatically ignored when reading the list back in."
|
274
285
|
f.puts "#"
|
275
286
|
f.puts "# Lines beginning with a # are comments (ignored), but you probably figured that out."
|
276
|
-
loner_tags.each{ |t|
|
277
|
-
f.printf "% 3d |\t%s\n", t[
|
287
|
+
loner_tags.each { |t|
|
288
|
+
f.printf "% 3d |\t%s\n", t["count"], t["name"]
|
278
289
|
}
|
279
290
|
end
|
280
291
|
|
281
292
|
console_log "A list of results and instructions for use have been written to #{path}."
|
282
|
-
if ENV[
|
293
|
+
if ENV["EDITOR"]
|
283
294
|
console_log
|
284
|
-
print "Would you like to open the file in #{ENV[
|
295
|
+
print "Would you like to open the file in #{ENV["EDITOR"]} now? (y/N) "
|
285
296
|
input = STDIN.gets
|
286
297
|
if input =~ /^y/i
|
287
|
-
system "#{ENV[
|
298
|
+
system "#{ENV["EDITOR"]} '#{path}'"
|
288
299
|
end
|
289
300
|
end
|
290
301
|
elsif options[:r]
|
291
302
|
files = []
|
292
303
|
args.length.times do
|
293
304
|
arg = args.pop
|
294
|
-
files.push(arg) if File.
|
305
|
+
files.push(arg) if File.exist?(arg)
|
295
306
|
end
|
307
|
+
|
308
|
+
files.concat(@piped_content.split("\n")) if @piped_content
|
309
|
+
|
296
310
|
if files.empty?
|
297
|
-
if @jt.default_post_location && File.
|
311
|
+
if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
|
298
312
|
files = Dir.glob(@jt.default_post_location)
|
299
313
|
end
|
300
314
|
end
|
301
315
|
exit_now! "No valid filename in arguments" if files.empty?
|
302
|
-
files.each {|file|
|
316
|
+
files.each { |file|
|
303
317
|
tags = @jt.post_tags(file)
|
304
318
|
loner_tags.each { |d|
|
305
319
|
tags.delete_if { |tag|
|
@@ -317,69 +331,76 @@ command :loners do |c|
|
|
317
331
|
|
318
332
|
console_log
|
319
333
|
console_log File.basename(file) + ":"
|
320
|
-
output_tags(tags, :format => options[:format], :filename => file
|
334
|
+
output_tags(tags, :format => options[:format], :filename => file)
|
321
335
|
}
|
322
336
|
else
|
323
|
-
output_tags(loner_tags.map{|tag|
|
324
|
-
count = options[:no_counts] ? "" : " (#{tag[
|
325
|
-
"#{tag[
|
337
|
+
output_tags(loner_tags.map { |tag|
|
338
|
+
count = options[:no_counts] ? "" : " (#{tag["count"]})"
|
339
|
+
"#{tag["name"]}#{count}"
|
340
|
+
}, :format => options[:format])
|
326
341
|
end
|
327
342
|
end
|
328
343
|
end
|
329
344
|
|
330
|
-
|
331
|
-
|
332
|
-
arg_name 'file_pattern', :multiple
|
345
|
+
desc "Show the current tags for posts"
|
346
|
+
arg_name "file_pattern", :multiple
|
333
347
|
command :tags do |c|
|
334
|
-
c.desc
|
335
|
-
c.arg_name
|
336
|
-
c.default_value
|
348
|
+
c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
|
349
|
+
c.arg_name "output_format"
|
350
|
+
c.default_value "yaml"
|
337
351
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
|
338
352
|
|
339
|
-
c.action do |global_options,options,args|
|
353
|
+
c.action do |global_options, options, args|
|
354
|
+
files = []
|
355
|
+
args.length.times do
|
356
|
+
arg = args.pop
|
357
|
+
if File.exist?(arg)
|
358
|
+
files.push(arg)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
files.concat(@piped_content.split("\n")) if @piped_content && @piped_content.file_list?
|
363
|
+
|
364
|
+
tags = []
|
365
|
+
files.each do |file|
|
366
|
+
tags.concat(@jt.post_tags(file)) if File.exist?(file)
|
340
367
|
|
341
|
-
|
342
|
-
tags = @jt.post_tags(@piped_content, true)
|
343
|
-
if args.length > 1
|
368
|
+
if args.length > 0
|
344
369
|
console_log
|
345
|
-
console_log
|
346
|
-
end
|
347
|
-
if tags.empty? || tags.nil?
|
348
|
-
console_log "No tags in post", {:err => true}
|
349
|
-
else
|
350
|
-
output_tags(tags,{ :format => options[:format] })
|
370
|
+
console_log "STDIN:"
|
351
371
|
end
|
352
372
|
end
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
console_log "No tags in post", {:err => true}
|
362
|
-
else
|
363
|
-
output_tags(tags,{ :format => options[:format], :filename => file })
|
364
|
-
end
|
365
|
-
else
|
366
|
-
raise "File not found: #{file}"
|
367
|
-
end
|
368
|
-
}
|
373
|
+
|
374
|
+
if tags.empty? || tags.nil?
|
375
|
+
console_log "No tags in post", { :err => true }
|
376
|
+
else
|
377
|
+
tags.sort!
|
378
|
+
tags.uniq!
|
379
|
+
output_tags(tags, { :format => options[:format] })
|
380
|
+
end
|
369
381
|
end
|
370
382
|
end
|
371
383
|
|
372
|
-
|
373
|
-
|
374
|
-
arg_name 'file_pattern', :multiple
|
384
|
+
desc "Sort the existing tags for posts"
|
385
|
+
arg_name "file_pattern", :multiple
|
375
386
|
command :sort do |c|
|
376
|
-
c.desc
|
377
|
-
c.arg_name
|
378
|
-
c.default_value
|
387
|
+
c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
|
388
|
+
c.arg_name "output_format"
|
389
|
+
c.default_value "yaml"
|
379
390
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
|
380
391
|
|
381
|
-
c.action do |global_options,options,args|
|
382
|
-
|
392
|
+
c.action do |global_options, options, args|
|
393
|
+
files = []
|
394
|
+
args.length.times do
|
395
|
+
arg = args.pop
|
396
|
+
if File.exist?(arg)
|
397
|
+
files.push(arg)
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
files.concat(@piped_content.split("\n")) if @piped_content
|
402
|
+
|
403
|
+
files.each do |file|
|
383
404
|
tags = @jt.post_tags(file)
|
384
405
|
tags.uniq!
|
385
406
|
tags.sort!
|
@@ -390,21 +411,21 @@ command :sort do |c|
|
|
390
411
|
console_log File.basename(file) + ":"
|
391
412
|
|
392
413
|
if tags.empty? || tags.nil?
|
393
|
-
console_log "No tags in post", {:err => true}
|
414
|
+
console_log "No tags in post", { :err => true }
|
394
415
|
else
|
395
|
-
output_tags(tags,{ :format => options[:format], :filename => file })
|
416
|
+
output_tags(tags, { :format => options[:format], :filename => file })
|
396
417
|
end
|
397
|
-
|
418
|
+
end
|
398
419
|
end
|
399
420
|
end
|
400
421
|
|
401
|
-
desc
|
402
|
-
long_desc
|
403
|
-
arg_name
|
422
|
+
desc "Merge multiple tags into one"
|
423
|
+
long_desc "Scans the specified posts for any of the tags, merging any found into the last one in the list"
|
424
|
+
arg_name "tags to merge merge_tag"
|
404
425
|
command :merge do |c|
|
405
|
-
c.desc
|
406
|
-
c.arg_name
|
407
|
-
c.default_value
|
426
|
+
c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
|
427
|
+
c.arg_name "output_format"
|
428
|
+
c.default_value "yaml"
|
408
429
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
|
409
430
|
|
410
431
|
c.action do |global_options, options, args|
|
@@ -412,14 +433,17 @@ command :merge do |c|
|
|
412
433
|
tags = []
|
413
434
|
args.length.times do
|
414
435
|
arg = args.pop
|
415
|
-
if File.
|
436
|
+
if File.exist?(arg)
|
416
437
|
files.push(arg)
|
417
438
|
else
|
418
439
|
tags.push(arg)
|
419
440
|
end
|
420
441
|
end
|
442
|
+
|
443
|
+
files.concat(@piped_content.split("\n")) if @piped_content
|
444
|
+
|
421
445
|
if files.empty?
|
422
|
-
if @jt.default_post_location && File.
|
446
|
+
if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
|
423
447
|
files = Dir.glob(@jt.default_post_location)
|
424
448
|
end
|
425
449
|
end
|
@@ -428,8 +452,8 @@ command :merge do |c|
|
|
428
452
|
tags.reverse!
|
429
453
|
merge_tag = tags.pop
|
430
454
|
console_log %Q{Merging #{tags.join(", ")} to #{merge_tag}}
|
431
|
-
files.each {|file|
|
432
|
-
new_tags = @jt.merge_tags(tags,merge_tag,file)
|
455
|
+
files.each { |file|
|
456
|
+
new_tags = @jt.merge_tags(tags, merge_tag, file)
|
433
457
|
next unless new_tags
|
434
458
|
unless global_options[:t]
|
435
459
|
@jt.update_file_tags(file, new_tags)
|
@@ -439,20 +463,18 @@ command :merge do |c|
|
|
439
463
|
|
440
464
|
console_log
|
441
465
|
console_log File.basename(file) + ":"
|
442
|
-
output_tags(new_tags,{ :format => options[:format], :filename => file })
|
443
|
-
|
466
|
+
output_tags(new_tags, { :format => options[:format], :filename => file })
|
444
467
|
}
|
445
468
|
end
|
446
469
|
end
|
447
470
|
|
448
|
-
|
449
|
-
|
450
|
-
arg_name 'tag [tag2...]'
|
471
|
+
desc "Blacklist a specific tag"
|
472
|
+
arg_name "tag [tag2...]"
|
451
473
|
command :blacklist do |c|
|
452
474
|
c.desc "Remove (unblacklist) the arguments"
|
453
|
-
c.switch [:r,
|
475
|
+
c.switch [:r, "remove"]
|
454
476
|
|
455
|
-
c.action do |global_options,options,args|
|
477
|
+
c.action do |global_options, options, args|
|
456
478
|
if options[:r]
|
457
479
|
@jt.unblacklist(args)
|
458
480
|
console_log "Removed #{args.join(", ")} from blacklist."
|
@@ -463,36 +485,38 @@ command :blacklist do |c|
|
|
463
485
|
end
|
464
486
|
end
|
465
487
|
|
466
|
-
desc
|
467
|
-
arg_name
|
468
|
-
arg_name
|
488
|
+
desc "Add tags to post(s)"
|
489
|
+
arg_name "tags", :multiple
|
490
|
+
arg_name "file_pattern"
|
469
491
|
command :add do |c|
|
470
|
-
c.desc
|
471
|
-
c.arg_name
|
472
|
-
c.default_value
|
492
|
+
c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
|
493
|
+
c.arg_name "output_format"
|
494
|
+
c.default_value "yaml"
|
473
495
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
|
474
496
|
|
475
|
-
|
476
|
-
c.action do |global_options,options,args|
|
497
|
+
c.action do |global_options, options, args|
|
477
498
|
files = []
|
478
499
|
new_tags = []
|
479
500
|
args.length.times do
|
480
501
|
arg = args.pop
|
481
|
-
if File.
|
502
|
+
if File.exist?(arg)
|
482
503
|
files.push(arg)
|
483
504
|
else
|
484
505
|
new_tags.push(arg)
|
485
506
|
end
|
486
507
|
end
|
508
|
+
|
509
|
+
files.concat(@piped_content.split("\n")) if @piped_content
|
510
|
+
|
487
511
|
if files.empty?
|
488
|
-
if @jt.default_post_location && File.
|
512
|
+
if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
|
489
513
|
files = Dir.glob(@jt.default_post_location)
|
490
514
|
end
|
491
515
|
end
|
492
516
|
exit_now! "No valid filename in arguments" if files.empty?
|
493
517
|
exit_now! "No tags found in arguments" if new_tags.empty?
|
494
518
|
|
495
|
-
files.each {|file|
|
519
|
+
files.each { |file|
|
496
520
|
tags = @jt.post_tags(file)
|
497
521
|
tags.concat(new_tags)
|
498
522
|
tags.uniq!
|
@@ -509,32 +533,35 @@ command :add do |c|
|
|
509
533
|
end
|
510
534
|
end
|
511
535
|
|
512
|
-
desc
|
513
|
-
arg_name
|
536
|
+
desc "Remove tags from post(s)"
|
537
|
+
arg_name "tags", :multiple
|
514
538
|
command :remove do |c|
|
515
|
-
c.desc
|
516
|
-
c.arg_name
|
517
|
-
c.default_value
|
539
|
+
c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
|
540
|
+
c.arg_name "output_format"
|
541
|
+
c.default_value "yaml"
|
518
542
|
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
|
519
543
|
|
520
|
-
c.desc
|
521
|
-
c.long_desc
|
522
|
-
c.arg_name
|
544
|
+
c.desc "A filepath to a list of tags to be removed"
|
545
|
+
c.long_desc "One tag per line, and leading numbers and pipes (|) will be ignored. This file format is generated automatically by the `loners` command, but any text file will do the trick."
|
546
|
+
c.arg_name "input_file"
|
523
547
|
c.flag %i[p path], :type => String
|
524
548
|
|
525
|
-
c.action do |global_options,options,args|
|
549
|
+
c.action do |global_options, options, args|
|
526
550
|
files = []
|
527
551
|
remove_tags = []
|
528
552
|
args.length.times do
|
529
553
|
arg = args.pop
|
530
|
-
if File.
|
554
|
+
if File.exist?(arg)
|
531
555
|
files.push(arg)
|
532
556
|
else
|
533
557
|
remove_tags.push(arg) unless options[:p]
|
534
558
|
end
|
535
559
|
end
|
560
|
+
|
561
|
+
files.concat(@piped_content.split("\n")) if @piped_content
|
562
|
+
|
536
563
|
if files.empty?
|
537
|
-
if @jt.default_post_location && File.
|
564
|
+
if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
|
538
565
|
files = Dir.glob(@jt.default_post_location)
|
539
566
|
end
|
540
567
|
end
|
@@ -542,8 +569,8 @@ command :remove do |c|
|
|
542
569
|
|
543
570
|
if options[:p]
|
544
571
|
path = File.expand_path(options[:p])
|
545
|
-
exit_now! "Input file does not appear to be where you think it is." unless File.
|
546
|
-
IO.read(path).each_line {|l|
|
572
|
+
exit_now! "Input file does not appear to be where you think it is." unless File.exist?(path)
|
573
|
+
IO.read(path).each_line { |l|
|
547
574
|
next if l =~ /^\s*#/
|
548
575
|
if l =~ /^(?:[\s\d])*(?:\|\s*)?(\S.*?)$/
|
549
576
|
remove_tags.push($1.strip)
|
@@ -554,7 +581,7 @@ command :remove do |c|
|
|
554
581
|
|
555
582
|
exit_now! "No tags found in input, my work here is done" if remove_tags.empty?
|
556
583
|
|
557
|
-
files.each {|file|
|
584
|
+
files.each { |file|
|
558
585
|
tags = @jt.post_tags(file)
|
559
586
|
remove_tags.each { |d|
|
560
587
|
tags.delete_if { |tag|
|
@@ -572,33 +599,42 @@ command :remove do |c|
|
|
572
599
|
|
573
600
|
console_log
|
574
601
|
console_log File.basename(file) + ":"
|
575
|
-
output_tags(tags,{ :format => options[:format], :filename => file })
|
602
|
+
output_tags(tags, { :format => options[:format], :filename => file })
|
576
603
|
}
|
577
604
|
end
|
578
605
|
end
|
579
606
|
|
580
|
-
desc
|
581
|
-
arg_name
|
607
|
+
desc "Generate a list of recommended tags, updating the file (unless dry run)"
|
608
|
+
arg_name "file_pattern", :multiple
|
582
609
|
command :tag do |c|
|
583
610
|
c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Use "complete" to output full text when input is STDIN.'
|
584
|
-
c.arg_name
|
585
|
-
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist|complete)$/, :type => String, :default_value =>
|
611
|
+
c.arg_name "output_format"
|
612
|
+
c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist|complete)$/, :type => String, :default_value => "yaml"
|
586
613
|
|
587
614
|
c.action do |global_options, options, args|
|
588
|
-
if @piped_content
|
615
|
+
if @piped_content && !@piped_content.file_list?
|
589
616
|
suggestions = @jt.suggest(@piped_content)
|
590
617
|
if args.length > 0
|
591
618
|
console_log
|
592
|
-
console_log
|
619
|
+
console_log "STDIN:", :err => true
|
593
620
|
end
|
594
|
-
if options[:format] ==
|
621
|
+
if options[:format] == "complete"
|
595
622
|
@jt.update_file_tags(@piped_content, suggestions, true)
|
596
623
|
else
|
597
624
|
output_tags(suggestions, :format => options[:format], :filename => nil)
|
598
625
|
end
|
599
626
|
end
|
600
|
-
|
601
|
-
|
627
|
+
|
628
|
+
files = []
|
629
|
+
args.length.times do
|
630
|
+
arg = args.pop
|
631
|
+
files.push(arg) if File.exist?(arg)
|
632
|
+
end
|
633
|
+
|
634
|
+
files.concat(@piped_content.split("\n")) if @piped_content && @piped_content.file_list?
|
635
|
+
|
636
|
+
files.each do |file|
|
637
|
+
if File.exist?(File.expand_path(file))
|
602
638
|
input = IO.read(File.expand_path(file))
|
603
639
|
suggestions = @jt.suggest(input)
|
604
640
|
|
@@ -616,26 +652,26 @@ command :tag do |c|
|
|
616
652
|
console_log
|
617
653
|
console_log File.basename(file) + ":", :err => true, :log => true
|
618
654
|
end
|
619
|
-
output_tags(suggestions, :format => options[:format], :filename => file
|
655
|
+
output_tags(suggestions, :format => options[:format], :filename => file)
|
620
656
|
end
|
621
657
|
suggestions = nil
|
622
658
|
else
|
623
659
|
raise "No such file: #{file}"
|
624
660
|
end
|
625
|
-
|
661
|
+
end
|
626
662
|
end
|
627
663
|
end
|
628
664
|
|
629
|
-
def output_tags(tags,options)
|
630
|
-
format = options[:format] ||
|
665
|
+
def output_tags(tags, options)
|
666
|
+
format = options[:format] || "yaml"
|
631
667
|
print0 = options[:print0] || false
|
632
668
|
filename = options[:filename] || false
|
633
669
|
case format
|
634
|
-
when
|
670
|
+
when "list"
|
635
671
|
unless print0
|
636
672
|
console_log tags.join("\n")
|
637
673
|
else
|
638
|
-
console_log tags.map {|tag|
|
674
|
+
console_log tags.map { |tag|
|
639
675
|
if tag.strip =~ /\b\s\b/
|
640
676
|
%Q{"#{tag.strip}"}
|
641
677
|
else
|
@@ -643,19 +679,19 @@ def output_tags(tags,options)
|
|
643
679
|
end
|
644
680
|
}.join(" ")
|
645
681
|
end
|
646
|
-
when
|
682
|
+
when "csv"
|
647
683
|
console_log tags.to_csv
|
648
|
-
when
|
684
|
+
when "json"
|
649
685
|
out = {}
|
650
|
-
out[
|
651
|
-
out[
|
686
|
+
out["tags"] = tags
|
687
|
+
out["path"] = filename if filename
|
652
688
|
console_log out.to_json
|
653
|
-
when
|
689
|
+
when "plist"
|
654
690
|
out = {}
|
655
|
-
out[
|
691
|
+
out["path"] = filename if filename
|
656
692
|
console_log tags.to_plist
|
657
693
|
else
|
658
|
-
|
694
|
+
out = {}
|
659
695
|
options[:grouping] ||= "tags"
|
660
696
|
out[options[:grouping]] = tags
|
661
697
|
console_log out.to_yaml
|
@@ -677,29 +713,31 @@ pre do |global, command, options, args|
|
|
677
713
|
# on that command only
|
678
714
|
@silent = global[:silent]
|
679
715
|
|
680
|
-
|
716
|
+
Signal.trap("PIPE", "EXIT")
|
717
|
+
|
718
|
+
@logfile = File.open(File.join(Dir.tmpdir, "jtag_actions.log"), "a")
|
681
719
|
|
682
720
|
@log = Logger.new(@logfile, shift_age = 7, shift_size = 1048576)
|
683
721
|
|
684
722
|
unless config_files_complete?
|
685
723
|
write_config
|
686
|
-
console_log "Missing config files written to #{@config_target}. Please check your configuration.", {:err => true}
|
724
|
+
console_log "Missing config files written to #{@config_target}. Please check your configuration.", { :err => true }
|
687
725
|
return false
|
688
726
|
end
|
689
727
|
|
690
728
|
configfile = File.expand_path("~/.jtag/config.yml")
|
691
729
|
|
692
|
-
global[:config] = YAML::load(File.open(configfile,"r"))
|
730
|
+
global[:config] = YAML::load(File.open(configfile, "r"))
|
693
731
|
global[:support] = File.expand_path("~/.jtag")
|
694
732
|
|
695
|
-
@piped_content =
|
733
|
+
@piped_content = $stdin.read if $stdin.fcntl(Fcntl::F_GETFL, 0) == 0 || $stdin.stat.pipe?
|
696
734
|
|
697
735
|
@jt = JTag.new(global[:support], global[:config])
|
698
736
|
|
699
737
|
true
|
700
738
|
end
|
701
739
|
|
702
|
-
post do |global,command,options,args|
|
740
|
+
post do |global, command, options, args|
|
703
741
|
# Post logic here
|
704
742
|
# Use skips_post before a command to skip this
|
705
743
|
# block on that command only
|
data/lib/jtag/jekylltag.rb
CHANGED
@@ -64,7 +64,7 @@ class JTag
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def synonyms
|
67
|
-
if File.
|
67
|
+
if File.exist?(File.join(@support,"synonyms.yml"))
|
68
68
|
syn = YAML::load(File.open(File.join(@support,"synonyms.yml")))
|
69
69
|
compiled = {}
|
70
70
|
syn.each {|k,v|
|
@@ -193,7 +193,7 @@ class JTag
|
|
193
193
|
|
194
194
|
def update_file_tags(file, tags, piped = false)
|
195
195
|
begin
|
196
|
-
if File.
|
196
|
+
if File.exist?(file) || piped
|
197
197
|
yaml, after = split_post(file, piped)
|
198
198
|
yaml[@tags_key] = tags
|
199
199
|
if piped
|
data/lib/jtag/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jtag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|