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.
data/bin/jtag CHANGED
@@ -1,236 +1,331 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
- require 'gli'
4
- require 'jtag'
3
+ require "gli"
4
+ require "jtag"
5
+ require "fcntl"
5
6
 
6
7
  include GLI::App
7
8
 
8
- program_desc 'Autotagging for Jekyll'
9
+ program_desc "Autotagging for Jekyll"
9
10
 
10
11
  version Jtag::VERSION
11
12
 
12
- @config_files = %w{blacklist.txt config.yml stopwords.txt synonyms.yml}
13
- @config_target = File.expand_path("~/.jtag")
14
13
  @piped_content = nil
15
14
 
16
- def config_files_complete?
17
- @config_files.each do |file|
18
- return false unless File.exist?(File.join(@config_target, file))
19
- end
20
- true
21
- end
15
+ ##
16
+ ## Define global flags and switches
17
+ ##
18
+ desc "Expect input from STDIN to be null (0)-delimited: Useful for piping file lists from `find` or `grep`"
19
+ default_value false
20
+ switch %i[0 null], negatable: false
22
21
 
23
- desc 'Debug level'
24
- default_value '0'
25
- arg_name 'debug_level'
26
- flag %i[d debug], :must_match => /\d+/, :type => Integer, :default_value => 0
22
+ desc "Path to alternate configuration directory"
23
+ arg_name "config_dir"
24
+ flag %i[c config_dir], :type => String
27
25
 
28
- desc 'Run silently'
29
- switch %i[s silent]
26
+ desc "Debug level: Set the debug level for the application. 0 is silent, 1 is errors only, 2 is errors and warnings, 3 is errors, warnings and info"
27
+ arg_name "debug_level"
28
+ flag %i[d debug], :must_match => /\d+/, :type => Integer, :default_value => 3
30
29
 
31
- desc 'Perform case-insensitive matches and searches'
32
- switch %i[i case_insensitive]
30
+ desc "Perform case-insensitive matches and searches: Useful for case-insensitive filesystems or when you're not sure of the case of your tags"
31
+ switch %i[i case_insensitive], negatable: false
33
32
 
34
- desc "Test (dry run, don't update files)"
35
- long_desc "Run all commands and show results on the command line, but don't overwrite/update any files"
36
- default_value false
37
- switch %i[t test]
33
+ desc "Run silently: Suppress all output to STDOUT, same as debug level 0"
34
+ switch %i[s silent], negatable: false
38
35
 
39
- def console_log(msg="", options={})
40
- err = options[:err] || false
41
- options[:log] ||= false
36
+ desc "Test (dry run, don't update files): Run all commands and show results on the command line, but don't overwrite/update any files"
37
+ default_value false
38
+ switch %i[t test], negatable: false
42
39
 
43
- if options[:log]
44
- if err
45
- @log.warn(msg)
46
- else
47
- @log.info(msg)
48
- end
49
- end
40
+ # Add a command to update and notify the user of the configuration files location
41
+ desc "Update and notify user of configuration files location"
42
+ command :config do |c|
43
+ # Add a switch to reset all configuration files to default values
44
+ c.desc "Reset all configuration files to default values"
45
+ c.switch %i[r reset]
50
46
 
51
- return if @silent
47
+ c.desc "Ignore prompts and answer yes to all questions."
48
+ c.switch %i[y yes], negatable: false
52
49
 
53
- unless err
54
- $stdout.puts msg
55
- else
56
- warn msg
57
- end
58
- end
50
+ c.desc "Set a specific configuration value"
51
+ c.arg_name "key"
52
+ c.flag %i[s set]
59
53
 
60
- desc 'Update and notify user of configuration files location'
61
- command :config do |c|
62
- c.desc 'Reset all configuration files to default values'
63
- c.switch [:r,'reset']
54
+ c.desc "The value to set for key"
55
+ c.arg_name "value"
56
+ c.flag %i[v value]
64
57
 
58
+ # Skip the pre block for this command
65
59
  c.skips_pre
66
- c.action do |global_options,options,args|
67
- if options[:r]
68
- print "Are you sure you want to reset all config files? y/N: "
69
- response = STDIN.gets.strip
70
- if response =~ /^y/i
71
- write_config(true)
72
- console_log "Config files reset"
60
+
61
+ # Define the action to be taken when the command is executed
62
+ c.action do |global_options, options, args|
63
+ if options[:set]
64
+ config = YAML.load_file(File.join(@util.config_target, "config.yml"))
65
+ config[options[:set]] = options[:value]
66
+ File.open(File.join(@util.config_target, "config.yml"), "w") do |f|
67
+ f.write(config.to_yaml)
73
68
  end
74
- else
75
- write_config(false)
69
+ return
76
70
  end
77
- end
78
- end
79
-
80
- def write_config(atomic=false)
81
- gem_root = Gem.loaded_specs['jtag'].full_gem_path
82
- gem_lib = File.join(gem_root, 'lib')
83
- config_source = File.join(gem_lib,'/jtag/config_files')
84
71
 
72
+ if options[:reset]
73
+ # Prompt the user for confirmation before resetting config files
74
+ if options[:yes]
75
+ res = true
76
+ else
77
+ print "Are you sure you want to reset all config files? y/N: "
78
+ response = STDIN.gets.strip
79
+ res = response =~ /^y/i
80
+ end
85
81
 
86
-
87
- unless File.directory?(@config_target) || atomic
88
- FileUtils.cp_r(config_source,@config_target)
89
- console_log "Configuration files are located in the folder: " + @config_target
90
- console_log %Q{Make sure that "tags_location" in config.yml is set to your tags.json url.}
91
- console_log "Configuration files written to #{@config_target}"
92
- end
93
-
94
- @config_files.each do |file|
95
- unless File.exist?(File.join(@config_target,file))
96
- source_file = File.join(config_source,file)
97
- target_file = File.join(@config_target,file)
98
- FileUtils.cp(source_file, target_file)
99
- console_log "Config file #{file} added."
82
+ if res
83
+ # Reset config files to default values
84
+ @util.write_config(true)
85
+ @util.console_log "Config files reset"
86
+ end
87
+ else
88
+ # Update config files without overwriting existing files
89
+ @util.write_config(false)
100
90
  end
101
91
  end
102
- console_log
103
- console_log "Configuration files are located in the folder: " + @config_target
104
- console_log %Q{Make sure that "tags_location" in the config.yml file is set to your tags json file.}
105
92
  end
106
93
 
107
- desc 'List tags, optionally filter for keywords/regular expressions (OR)'
108
- long_desc 'This command can be used to find the exact format for a given tag to keep spaces, underscores, capitalization and pluralization consistent'
109
- arg_name 'keyword', :multiple
94
+ desc "List tags, optionally filter for keywords/regular expressions (OR)"
95
+ long_desc "This command can be used to find the exact format for a given tag to keep spaces, underscores, capitalization and pluralization consistent"
96
+ arg_name "keyword", :multiple
110
97
  command :search do |c|
111
- c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml.'
112
- c.arg_name 'output_format'
113
- c.default_value 'yaml'
98
+ c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
99
+ c.arg_name "output_format"
100
+ c.default_value "yaml"
114
101
  c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/i, :type => String
115
102
 
116
- c.desc 'Include tag counts'
117
- c.arg_name 'counts'
103
+ c.desc "Include tag counts"
104
+ c.arg_name "counts"
118
105
  c.default_value false
119
106
  c.switch %i[c counts]
120
107
 
121
- c.action do |global_options,options,args|
122
- tags = @jt.get_tags({:counts => true})
123
- if args.length > 0
124
- re = args.join("|")
125
- tags.delete_if {|tag|
126
- if tag && tag['name'] =~ /(#{re})/i
127
- false
128
- else
129
- true
108
+ c.desc "Boolean operator for multiple tags (AND/OR/NOT)"
109
+ c.arg_name "bool"
110
+ c.default_value "OR"
111
+ c.flag %i[b bool], :must_match => /^([aon])(?:.*)$/i, :type => String
112
+
113
+ c.desc "Match type: exact, fuzzy, starts_with, contains"
114
+ c.arg_name "match_type"
115
+ c.default_value "contains"
116
+ c.flag %i[m match], :must_match => /^([exfsc])(?:.*)$/i, :type => String
117
+
118
+ c.desc "Case-sensitive matching"
119
+ c.switch %i[I s case_sensitive], negatable: true
120
+
121
+ c.desc "Fuzzy match distance"
122
+ c.arg_name "distance"
123
+ c.default_value 2
124
+ c.flag %i[d distance], :must_match => /^\d+$/, :type => Integer
125
+
126
+ c.action do |global_options, options, args|
127
+ # Initialize arrays to store files and keywords
128
+ files = []
129
+ keywords = []
130
+ bool_op = options[:bool].to_bool
131
+
132
+ # Iterate over the arguments and separate files from keywords
133
+ args.length.times do
134
+ arg = args.pop
135
+ if File.file?(File.expand_path(arg))
136
+ files.push(File.expand_path(arg)) # Add existing files to the files array
137
+ else
138
+ keywords.push(arg) # Add non-file arguments to the keywords array
139
+ end
140
+ end
141
+
142
+ # If piped content is provided and it is a list of files, add them to the files array
143
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
144
+
145
+ # If no files are provided, use the default post location
146
+ if files.empty?
147
+ if File.exist?(File.expand_path(@jt.tags_loc))
148
+ files = nil
149
+ else
150
+ if @jt.default_post_location && File.exist?(File.expand_path(@jt.default_post_location))
151
+ # Retrieves a list of files from the default post location with the specified post extension.
152
+ # The files are located using a glob pattern that matches all files with the given extension.
153
+ #
154
+ # @return [Array<String>] an array of file paths matching the specified pattern
155
+ files = Dir.glob(File.join(File.expand_path(@jt.default_post_location), "**", "*.#{@jt.post_extension}"))
130
156
  end
131
- }
132
- if options[:c]
133
- tags.map! {|tag| "#{tag['name']} (#{tag['count']})" }
157
+ end
158
+ else
159
+ tags = {}
160
+ end
161
+
162
+ # Get tags with counts for the specified files
163
+ if @piped_content && !@piped_content.file_list?(global_options[:null])
164
+ if @piped_content.yaml?
165
+ tags = YAML.load(@piped_content).to_counts
166
+ elsif @piped_content.json?
167
+ tags = JSON.parse(@piped_content).to_counts
168
+ elsif @piped_content.tag_list?
169
+ tags = @piped_content.split("\n").map(&:strip).to_counts
134
170
  else
135
- tags.map! {|tag| tag['name'] }
171
+ tags = @jt.tags({ :counts => true, :files => files })
136
172
  end
137
- output_tags(tags,{ :format => options[:format] })
138
173
  else
139
- tags.delete_if {|tag| !tag }
140
- if options[:c]
141
- tags.map! {|tag| "#{tag['name']} (#{tag['count']})" }
174
+ tags = @jt.tags({ :counts => true, :files => files })
175
+ end
176
+
177
+ exit_now! "No source tag list found" if !tags || tags.empty?
178
+
179
+ match_options = {
180
+ exact: false,
181
+ contains: false,
182
+ starts_with: false,
183
+ fuzzy: false,
184
+ case_sensitive: options[:case_sensitive],
185
+ distance: options[:distance],
186
+ }
187
+
188
+ if options[:match] =~ /^[ex]/i
189
+ match_options[:exact] = true
190
+ elsif options[:match] =~ /^s/i
191
+ match_options[:starts_with] = true
192
+ elsif options[:match] =~ /^f/i
193
+ match_options[:fuzzy] = true
194
+ else
195
+ match_options[:contains] = true
196
+ end
197
+
198
+ # If keywords are provided, filter tags based on the keywords
199
+ if keywords.length > 0
200
+ if bool_op == :and
201
+ tags.delete_if { |tag| tag && !keywords.all? { |keyword| tag["name"].match_keyword(keyword, match_options) } }
202
+ elsif bool_op == :not
203
+ re = keywords.join("|") # Join keywords with OR operator
204
+ # Remove tags that match the keywords
205
+ tags.delete_if { |tag| tag && keywords.any? { |keyword| tag["name"].match_keyword(keyword, match_options) } }
142
206
  else
143
- tags.map! {|tag| tag['name'] }
207
+ # :or
208
+ # Filter tags based on any keywords
209
+ tags.delete_if { |tag| tag && !keywords.any? { |keyword| tag["name"].match_keyword(keyword, match_options) } }
144
210
  end
145
- output_tags(tags,{ :format => options[:format] })
146
211
  end
212
+
213
+ # Remove nil and false values from the tags array
214
+ tags.delete_if { |tag| !tag }
215
+
216
+ exit_now! "No matching tags found" if tags.nil? || tags.empty?
217
+
218
+ # Format tags with counts if the counts option is enabled
219
+ if options[:count]
220
+ tags.map! { |tag| "#{tag["name"]} (#{tag["count"]})" }
221
+ else
222
+ tags.map! { |tag| tag["name"] }
223
+ end
224
+
225
+ # Output the formatted tags
226
+ @util.output_tags(tags, { :format => options[:format] })
147
227
  end
148
228
  end
149
229
 
150
- desc 'List posts with tag(s)'
151
- arg_name 'tags', :multiple
230
+ desc "List posts with tag(s)"
231
+ arg_name "tags", :multiple
152
232
  command :posts_tagged do |c|
153
- c.desc 'Boolean operator for multiple tags (AND/OR/NOT)'
154
- c.arg_name 'bool'
155
- c.default_value 'OR'
233
+ c.desc "Boolean operator for multiple tags (AND/OR/NOT)"
234
+ c.arg_name "bool"
235
+ c.default_value "OR"
156
236
  c.flag %i[b bool], :must_match => /(AND|OR|NOT)/i, :type => String
157
237
 
158
- c.desc 'Format to use when outputting file list: list, json, plist, csv or yaml. Defaults to list.'
159
- c.arg_name 'output_format'
160
- c.default_value 'list'
238
+ c.desc "Format to use when outputting file list: list, json, plist, csv or yaml. Defaults to list."
239
+ c.arg_name "output_format"
240
+ c.default_value "list"
161
241
  c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
162
242
 
163
- c.desc 'If output format is list, print without newlines.'
243
+ c.desc "If output format is list, print without newlines."
164
244
  c.switch [:print0]
165
245
 
166
- c.action do |global_options,options,args|
246
+ c.action do |global_options, options, args|
247
+ # Convert the boolean operator to uppercase for consistency
167
248
  bool = options[:bool].upcase
249
+
250
+ # Initialize arrays to store files, tags, and matches
168
251
  files = []
169
252
  tags = []
170
253
  matches = []
254
+
255
+ # Separate files and tags from the arguments
171
256
  args.length.times do
172
257
  arg = args.pop
173
258
  if File.exist?(arg)
174
- files.push(arg)
259
+ files.push(arg) # Add existing files to the files array
175
260
  else
176
- tags.push(arg)
261
+ tags.push(arg) # Add non-file arguments to the tags array
177
262
  end
178
263
  end
264
+
265
+ # If piped content is provided and it is a list of files, add them to the files array
266
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
267
+
268
+ # If no files are provided, use the default post location
179
269
  if files.empty?
180
- if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
181
- files = Dir.glob(@jt.default_post_location)
270
+ if @jt.default_post_location && File.exist?(@jt.default_post_location)
271
+ # Retrieves a list of files from the default post location with the specified post extension.
272
+ # The files are located using a glob pattern that matches all files with the given extension.
273
+ files = Dir.glob(File.join(@jt.default_post_location, "*.#{@jt.post_extension}"))
182
274
  end
183
275
  end
184
- exit_now! "No valid filename in arguments" if files.empty?
185
- files.each {|file|
276
+
277
+ # Exit if no valid filenames are found in the arguments
278
+ raise NoValidFile if files.empty?
279
+
280
+ # Iterate over each file to find matches based on the boolean operator
281
+ files.each do |file|
186
282
  if File.exist?(file)
187
- post_tags = @jt.post_tags(file)
283
+ post_tags = @jt.post_tags(file) # Get tags for the current file
188
284
 
189
285
  if bool == "AND"
286
+ # Check if all tags are present in the post tags
190
287
  matched = 0
191
- tags.each {|tag|
192
- matched += 1 if post_tags.include?(tag)
193
- }
288
+ tags.each { |tag| matched += 1 if post_tags.include?(tag) }
194
289
  matches.push(file) if matched == tags.length
195
290
  elsif bool == "NOT"
291
+ # Check if none of the tags are present in the post tags
196
292
  matched = false
197
- tags.each {|tag|
198
- matched = true if post_tags.include?(tag)
199
- }
293
+ tags.each { |tag| matched = true if post_tags.include?(tag) }
200
294
  matches.push(file) unless matched
201
295
  else
202
- tags.each {|tag|
203
- if post_tags.include?(tag)
204
- matches.push(file) unless matches.include?(file)
205
- end
206
- }
296
+ # Default to OR: Check if any of the tags are present in the post tags
297
+ tags.each { |tag| matches.push(file) unless matches.include?(file) if post_tags.include?(tag) }
207
298
  end
208
299
  else
209
- raise "File not found: #{file}"
300
+ # Exit if the file is not found
301
+ raise FileNotFound, "File not found: #{file}"
210
302
  end
211
- }
303
+ end
212
304
 
305
+ # Create a search string from the tags and boolean operator
213
306
  search_string = tags.join(" #{bool} ")
307
+
308
+ # Output the results
214
309
  if matches.empty?
215
- console_log "No matching files found for #{search_string}"
310
+ @util.console_log "No matching files found for #{search_string}"
216
311
  else
217
- console_log "(#{search_string})", {:err => true}
218
- output_tags(matches, { :format => options[:format], :print0 => options[:print0], :grouping => "files" })
312
+ @util.console_log "(#{search_string})", { err: true }
313
+ @util.output_tags(matches, { format: options[:format], print0: options[:print0], grouping: "files" })
219
314
  end
220
315
  end
221
316
  end
222
317
 
223
- desc 'Show tags with fewer than X posts attached to them, optionally removing them from specified posts'
224
- arg_name 'file_pattern', :multiple
318
+ desc "Show tags with fewer than X posts attached to them, optionally removing them from specified posts"
319
+ arg_name "file_pattern", :multiple
225
320
  command :loners do |c|
226
- c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml.'
227
- c.arg_name 'output_format'
228
- c.default_value 'yaml'
321
+ c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
322
+ c.arg_name "output_format"
323
+ c.default_value "yaml"
229
324
  c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
230
325
 
231
- c.desc 'Upper limit for how many posts a tag can be attached to and still be a loner'
232
- c.arg_name 'max'
233
- c.default_value '2'
326
+ c.desc "Upper limit for how many posts a tag can be attached to and still be a loner"
327
+ c.arg_name "max"
328
+ c.default_value "2"
234
329
  c.flag %i[m max], :default_value => 2, :must_match => /^\d+$/
235
330
 
236
331
  c.desc "Remove tags with fewer than X posts attached"
@@ -239,20 +334,53 @@ command :loners do |c|
239
334
  c.desc "Display output without attached occurence counts"
240
335
  c.switch [:no_counts], :default_value => false
241
336
 
242
- c.desc 'Output a file list of tags that can be edited and passed back in for removing'
243
- c.arg_name 'filename'
337
+ c.desc "Output a file list of tags that can be edited and passed back in for removing"
338
+ c.arg_name "filename"
244
339
  c.flag %i[e edit], :default_value => false, :type => String
245
340
 
246
- c.action do |global_options,options,args|
341
+ c.action do |global_options, options, args|
342
+ # Convert the max option to an integer
247
343
  max = options[:m].to_i
248
- loner_tags = @jt.get_tags({:counts => true})
344
+
345
+ # Initialize arrays to store files and keywords
346
+ files = []
347
+ keywords = []
348
+
349
+ # Separate files and keywords from the arguments
350
+ args.length.times do
351
+ arg = args.pop
352
+ if File.exist?(arg)
353
+ files.push(arg) # Add existing files to the files array
354
+ else
355
+ keywords.push(arg) # Add non-file arguments to the keywords array
356
+ end
357
+ end
358
+
359
+ # If piped content is provided and it is a list of files, add them to the files array
360
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
361
+
362
+ # If no files are provided, use the default post location
363
+ if files.empty?
364
+ if @jt.default_post_location && File.exist?(@jt.default_post_location)
365
+ files = Dir.glob(File.join(@jt.default_post_location, "*.#{@jt.post_extension}"))
366
+ end
367
+ end
368
+
369
+ # Get tags with counts for the specified files
370
+ loner_tags = @jt.tags({ :counts => true, :files => files })
371
+
372
+ # Remove tags that are not loners (i.e., tags with counts greater than max)
249
373
  loner_tags.delete_if { |tag|
250
- tag.class == FalseClass || tag['count'] > max
374
+ tag.class == FalseClass || tag["count"] > max
251
375
  }
252
- loner_tags.sort_by! {|tag| tag['count']}
253
376
 
377
+ # Sort loner tags by count
378
+ loner_tags.sort_by! { |tag| tag["count"] }
379
+
380
+ # Exit if no tags matched the criteria
254
381
  exit_now! "No tags matched the criteria" if loner_tags.empty? || loner_tags.nil?
255
382
 
383
+ # If the edit option is provided, write the loner tags to a file for editing
256
384
  if options[:e]
257
385
  path = File.expand_path(options[:e])
258
386
  while File.exist?(path)
@@ -261,45 +389,51 @@ command :loners do |c|
261
389
  $1.next! + $2
262
390
  end
263
391
  else
264
- path.sub!(/(\.[^\.]+?)?$/,'01\1')
392
+ path.sub!(/(\.[^\.]+?)?$/, '01\1')
265
393
  end
266
394
  end
267
- File.open(path, 'w+') do |f|
395
+ File.open(path, "w+") do |f|
268
396
  f.puts "# Edit this file to remove tags you want to keep,"
269
397
  f.puts "# then run `jtag remove -p '#{path}' [/path/to/posts/*.md]`"
270
- f.puts "# to remove any tags left in the file."
398
+ f.puts "# to remove any tags left in this file."
271
399
  f.puts "#"
272
400
  f.puts "# The post counts are included for your convenience, and will"
273
401
  f.puts "# be automatically ignored when reading the list back in."
274
402
  f.puts "#"
275
403
  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['count'], t['name']
404
+ loner_tags.each { |t|
405
+ f.printf "% 3d |\t%s\n", t["count"], t["name"]
278
406
  }
279
407
  end
280
408
 
281
- console_log "A list of results and instructions for use have been written to #{path}."
282
- if ENV['EDITOR']
283
- console_log
284
- print "Would you like to open the file in #{ENV['EDITOR']} now? (y/N) "
409
+ @util.console_log "A list of results and instructions for use have been written to #{path}."
410
+ if ENV["EDITOR"]
411
+ @util.console_log
412
+ print "Would you like to open the file in #{ENV["EDITOR"]} now? (y/N) "
285
413
  input = STDIN.gets
286
414
  if input =~ /^y/i
287
- system "#{ENV['EDITOR']} '#{path}'"
415
+ system "#{ENV["EDITOR"]} '#{path}'"
288
416
  end
289
417
  end
418
+
419
+ # If the remove option is provided, remove the loner tags from the specified files
290
420
  elsif options[:r]
291
421
  files = []
292
422
  args.length.times do
293
423
  arg = args.pop
294
424
  files.push(arg) if File.exist?(arg)
295
425
  end
426
+
427
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
428
+
296
429
  if files.empty?
297
- if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
298
- files = Dir.glob(@jt.default_post_location)
430
+ if @jt.default_post_location && File.exist?(@jt.default_post_location)
431
+ files = Dir.glob(File.join(@jt.default_post_location, "*.#{@jt.post_extension}"))
299
432
  end
300
433
  end
301
434
  exit_now! "No valid filename in arguments" if files.empty?
302
- files.each {|file|
435
+
436
+ files.each { |file|
303
437
  tags = @jt.post_tags(file)
304
438
  loner_tags.each { |d|
305
439
  tags.delete_if { |tag|
@@ -312,99 +446,108 @@ command :loners do |c|
312
446
  }
313
447
  unless global_options[:t]
314
448
  @jt.update_file_tags(file, tags)
315
- console_log "Updated tags for #{file}", :log => true
449
+ @util.console_log "Updated tags for #{file}", :log => true, level: :warn
316
450
  end
317
451
 
318
- console_log
319
- console_log File.basename(file) + ":"
320
- output_tags(tags, :format => options[:format], :filename => file )
452
+ @util.console_log level: :info
453
+ @util.console_log File.basename(file) + ":", level: :info
454
+ @util.output_tags(tags, :format => options[:format], :filename => file)
321
455
  }
456
+
457
+ # Otherwise, output the loner tags
322
458
  else
323
- output_tags(loner_tags.map{|tag|
324
- count = options[:no_counts] ? "" : " (#{tag['count']})"
325
- "#{tag['name']}#{count}"}, :format => options[:format] )
459
+ @util.output_tags(loner_tags.map { |tag|
460
+ count = options[:no_counts] ? "" : " (#{tag["count"]})"
461
+ "#{tag["name"]}#{count}"
462
+ }, :format => options[:format])
326
463
  end
327
464
  end
328
465
  end
329
466
 
330
-
331
- desc 'Show the current tags for posts'
332
- arg_name 'file_pattern', :multiple
467
+ desc "Show the current tags for posts"
468
+ arg_name "file_pattern", :multiple
333
469
  command :tags do |c|
334
- c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml.'
335
- c.arg_name 'output_format'
336
- c.default_value 'yaml'
470
+ c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
471
+ c.arg_name "output_format"
472
+ c.default_value "yaml"
337
473
  c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
338
474
 
339
- c.action do |global_options,options,args|
340
-
341
- if @piped_content
342
- tags = @jt.post_tags(@piped_content, true)
343
- if args.length > 1
344
- console_log
345
- console_log 'STDIN:'
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] })
475
+ c.action do |global_options, options, args|
476
+ files = []
477
+ args.length.times do
478
+ arg = args.pop
479
+ if File.exist?(arg)
480
+ files.push(arg)
351
481
  end
352
482
  end
353
- args.each{|file|
354
- if File.exist?(file)
355
- tags = @jt.post_tags(file)
356
- if args.length > 1
357
- console_log
358
- console_log File.basename(file) + ":"
359
- end
360
- if tags.empty? || tags.nil?
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}"
483
+
484
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
485
+
486
+ tags = []
487
+ files.each do |file|
488
+ tags.concat(@jt.post_tags(file)) if File.exist?(file)
489
+
490
+ if args.length > 0
491
+ @util.console_log level: :info
492
+ @util.console_log "STDIN:", level: :info
367
493
  end
368
- }
494
+ end
495
+
496
+ if tags.empty? || tags.nil?
497
+ @util.console_log "No tags in post", err: true, level: :info
498
+ else
499
+ tags.sort!
500
+ tags.uniq!
501
+ @util.output_tags(tags, { :format => options[:format] })
502
+ end
369
503
  end
370
504
  end
371
505
 
372
-
373
- desc 'Sort the existing tags for posts'
374
- arg_name 'file_pattern', :multiple
506
+ desc "Sort the existing tags for posts"
507
+ arg_name "file_pattern", :multiple
375
508
  command :sort do |c|
376
- c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml.'
377
- c.arg_name 'output_format'
378
- c.default_value 'yaml'
509
+ c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
510
+ c.arg_name "output_format"
511
+ c.default_value "yaml"
379
512
  c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
380
513
 
381
- c.action do |global_options,options,args|
382
- args.each{|file|
514
+ c.action do |global_options, options, args|
515
+ files = []
516
+ args.length.times do
517
+ arg = args.pop
518
+ if File.exist?(arg)
519
+ files.push(arg)
520
+ end
521
+ end
522
+
523
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
524
+
525
+ files.each do |file|
383
526
  tags = @jt.post_tags(file)
384
527
  tags.uniq!
385
528
  tags.sort!
386
529
  unless global_options[:t]
387
530
  @jt.update_file_tags(file, tags)
388
531
  end
389
- console_log
390
- console_log File.basename(file) + ":"
532
+ @util.console_log level: :info
533
+ @util.console_log "#{File.basename(file)}:", level: :info
391
534
 
392
535
  if tags.empty? || tags.nil?
393
- console_log "No tags in post", {:err => true}
536
+ @util.console_log "No tags in post", err: true, level: :info
394
537
  else
395
- output_tags(tags,{ :format => options[:format], :filename => file })
538
+ @util.output_tags(tags, { :format => options[:format], :filename => file })
396
539
  end
397
- }
540
+ end
398
541
  end
399
542
  end
400
543
 
401
- desc 'Merge multiple tags into one'
402
- long_desc 'Scans the specified posts for any of the tags, merging any found into the last one in the list'
403
- arg_name 'tags to merge merge_tag'
544
+ desc "Merge multiple tags into one"
545
+ long_desc "Scans the specified posts for any of the tags, merging any found into the last one in the list"
546
+ arg_name "tags to merge merge_tag"
404
547
  command :merge do |c|
405
- c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml.'
406
- c.arg_name 'output_format'
407
- c.default_value 'yaml'
548
+ c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
549
+ c.arg_name "output_format"
550
+ c.default_value "yaml"
408
551
  c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
409
552
 
410
553
  c.action do |global_options, options, args|
@@ -418,62 +561,62 @@ command :merge do |c|
418
561
  tags.push(arg)
419
562
  end
420
563
  end
564
+
565
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
566
+
421
567
  if files.empty?
422
- if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
423
- files = Dir.glob(@jt.default_post_location)
568
+ if @jt.default_post_location && File.exist?(@jt.default_post_location)
569
+ files = Dir.glob(File.join(@jt.default_post_location, "*.#{@jt.post_extension}"))
424
570
  end
425
571
  end
426
572
  exit_now! "No valid filename in arguments" if files.empty?
427
573
  exit_now! "Needs at least two tag inputs, one or more to merge, one to merge to" if tags.length < 2
428
574
  tags.reverse!
429
575
  merge_tag = tags.pop
430
- console_log %Q{Merging #{tags.join(", ")} to #{merge_tag}}
431
- files.each {|file|
432
- new_tags = @jt.merge_tags(tags,merge_tag,file)
576
+ @util.console_log %(Merging #{tags.join(", ")} to #{merge_tag}), level: :info
577
+ files.each do |file|
578
+ new_tags = @jt.merge_tags(tags, merge_tag, file)
433
579
  next unless new_tags
434
- unless global_options[:t]
580
+ unless global_options[:test]
435
581
  @jt.update_file_tags(file, new_tags)
436
- console_log
437
- console_log "Updated tags for #{file}", :log => true
582
+ @util.console_log level: :info
583
+ @util.console_log "Updated tags for #{file}", log: true, level: :warn
438
584
  end
439
585
 
440
- console_log
441
- console_log File.basename(file) + ":"
442
- output_tags(new_tags,{ :format => options[:format], :filename => file })
443
-
444
- }
586
+ @util.console_log level: :info
587
+ @util.console_log "#{File.basename(file)}:", level: :info
588
+ @util.output_tags(new_tags, { format: options[:format], filename: file })
589
+ end
445
590
  end
446
591
  end
447
592
 
448
-
449
- desc 'Blacklist a specific tag'
450
- arg_name 'tag [tag2...]'
593
+ desc "Blacklist a specific tag"
594
+ arg_name "tag [tag2...]"
451
595
  command :blacklist do |c|
452
596
  c.desc "Remove (unblacklist) the arguments"
453
- c.switch [:r,'remove']
597
+ c.switch [:r, "remove"]
454
598
 
455
- c.action do |global_options,options,args|
599
+ c.action do |global_options, options, args|
456
600
  if options[:r]
457
601
  @jt.unblacklist(args)
458
- console_log "Removed #{args.join(", ")} from blacklist."
602
+ @util.console_log "Removed #{args.join(", ")} from blacklist.", level: :info, err: true
459
603
  else
460
604
  @jt.blacklist(args)
461
- console_log "Blacklisted #{args.join(", ")}."
605
+ @util.console_log "Blacklisted #{args.join(", ")}.", level: :info, err: true
462
606
  end
463
607
  end
464
608
  end
465
609
 
466
- desc 'Add tags to post(s)'
467
- arg_name 'tags', :multiple
468
- arg_name 'file_pattern'
610
+ desc "Add tags to post(s)"
611
+ arg_name "tags... file(s)", :multiple
469
612
  command :add do |c|
470
- c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml.'
471
- c.arg_name 'output_format'
472
- c.default_value 'yaml'
473
- c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
613
+ c.desc "Format to use when outputting tags to console: list, json, plist, csv, yaml, or complete. Defaults to yaml."
614
+ c.long_desc "Use 'complete' to output full text when input is STDIN. First two letters of format are also accepted."
615
+ c.arg_name "output_format"
616
+ c.default_value "yaml"
617
+ c.flag %i[f format], :must_match => /^(csv?|l(?:i(?:st)?)?|y(?:a(?:ml)?)?|j(?:s(?:on)?)?|p(?:l(?:ist)?)?|co(?:mp(?:lete)?)?)$/, :type => String
474
618
 
475
-
476
- c.action do |global_options,options,args|
619
+ c.action do |global_options, options, args|
477
620
  files = []
478
621
  new_tags = []
479
622
  args.length.times do
@@ -484,45 +627,58 @@ command :add do |c|
484
627
  new_tags.push(arg)
485
628
  end
486
629
  end
487
- if files.empty?
488
- if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
489
- files = Dir.glob(@jt.default_post_location)
490
- end
491
- end
492
- exit_now! "No valid filename in arguments" if files.empty?
493
- exit_now! "No tags found in arguments" if new_tags.empty?
494
630
 
495
- files.each {|file|
496
- tags = @jt.post_tags(file)
631
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
632
+
633
+ # if files.empty?
634
+ # if @jt.default_post_location && File.exist?(@jt.default_post_location)
635
+ # files = Dir.glob(File.join(@jt.default_post_location, "*.#{@jt.post_extension}"))
636
+ # end
637
+ # end
638
+ # raise NoValidFile if files.empty?
639
+ raise NoTagsFound, "No tags to add specified" if new_tags.empty?
640
+
641
+ if @piped_content && !@piped_content.file_list?(global_options[:null])
642
+ tags = @jt.post_tags(@piped_content, true)
497
643
  tags.concat(new_tags)
498
- tags.uniq!
499
644
  tags.sort!
500
- unless global_options[:t]
501
- @jt.update_file_tags(file, tags)
502
- console_log "Updated tags for #{file}", :log => true
503
- end
645
+ tags.uniq!
646
+ @util.console_log "STDIN:", level: :debug
647
+ # TODO: Add debug level to console_log
648
+ @util.output_tags(tags, format: options[:format], content: @piped_content)
649
+ else
650
+ files.each do |file|
651
+ tags = @jt.post_tags(file)
652
+ tags.concat(new_tags)
653
+ tags.sort!
654
+ tags.uniq!
655
+ unless global_options[:t]
656
+ @jt.update_file_tags(file, tags)
657
+ @util.console_log "Updated tags for #{file}", log: true, level: :warn
658
+ end
504
659
 
505
- console_log
506
- console_log File.basename(file) + ":"
507
- output_tags(tags, :format => options[:format], :filename => file)
508
- }
660
+ @util.console_log level: :info
661
+ @util.console_log "#{File.basename(file)}:", level: :info
662
+ @util.output_tags(tags, :format => options[:format], :filename => file)
663
+ end
664
+ end
509
665
  end
510
666
  end
511
667
 
512
- desc 'Remove tags from post(s)'
513
- arg_name 'tags', :multiple
668
+ desc "Remove tags from post(s)"
669
+ arg_name "tags", :multiple
514
670
  command :remove do |c|
515
- c.desc 'Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml.'
516
- c.arg_name 'output_format'
517
- c.default_value 'yaml'
671
+ c.desc "Format to use when outputting tags to console: list, json, plist, csv or yaml. Defaults to yaml."
672
+ c.arg_name "output_format"
673
+ c.default_value "yaml"
518
674
  c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist)$/, :type => String
519
675
 
520
- c.desc 'A filepath to a list of tags to be removed'
521
- 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.'
522
- c.arg_name 'input_file'
676
+ c.desc "A filepath to a list of tags to be removed"
677
+ 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."
678
+ c.arg_name "input_file"
523
679
  c.flag %i[p path], :type => String
524
680
 
525
- c.action do |global_options,options,args|
681
+ c.action do |global_options, options, args|
526
682
  files = []
527
683
  remove_tags = []
528
684
  args.length.times do
@@ -533,9 +689,12 @@ command :remove do |c|
533
689
  remove_tags.push(arg) unless options[:p]
534
690
  end
535
691
  end
692
+
693
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
694
+
536
695
  if files.empty?
537
- if @jt.default_post_location && File.exist?(File.dirname(@jt.default_post_location))
538
- files = Dir.glob(@jt.default_post_location)
696
+ if @jt.default_post_location && File.exist?(@jt.default_post_location)
697
+ files = Dir.glob(File.join(@jt.default_post_location, "*.#{@jt.post_extension}"))
539
698
  end
540
699
  end
541
700
  exit_now! "No valid filename in arguments" if files.empty?
@@ -543,18 +702,18 @@ command :remove do |c|
543
702
  if options[:p]
544
703
  path = File.expand_path(options[:p])
545
704
  exit_now! "Input file does not appear to be where you think it is." unless File.exist?(path)
546
- IO.read(path).each_line {|l|
705
+ IO.read(path).each_line { |l|
547
706
  next if l =~ /^\s*#/
548
707
  if l =~ /^(?:[\s\d])*(?:\|\s*)?(\S.*?)$/
549
708
  remove_tags.push($1.strip)
550
709
  end
551
710
  }
552
- console_log "Found #{remove_tags.length} tags in #{File.basename(path)}..."
711
+ @util.console_log "Found #{remove_tags.length} tags in #{File.basename(path)}...", level: :info, err: true
553
712
  end
554
713
 
555
- exit_now! "No tags found in input, my work here is done" if remove_tags.empty?
714
+ raise NoTagsFound if remove_tags.empty?
556
715
 
557
- files.each {|file|
716
+ files.each { |file|
558
717
  tags = @jt.post_tags(file)
559
718
  remove_tags.each { |d|
560
719
  tags.delete_if { |tag|
@@ -567,98 +726,80 @@ command :remove do |c|
567
726
  }
568
727
  unless global_options[:t]
569
728
  @jt.update_file_tags(file, tags)
570
- console_log "Updated tags for #{file}", :log => true
729
+ @util.console_log "Updated tags for #{file}", log: true, level: :warn, err: true
571
730
  end
572
731
 
573
- console_log
574
- console_log File.basename(file) + ":"
575
- output_tags(tags,{ :format => options[:format], :filename => file })
732
+ @util.console_log level: :info
733
+ @util.console_log "#{File.basename(file)}:", level: :info
734
+ @util.output_tags(tags, { :format => options[:format], :filename => file })
576
735
  }
577
736
  end
578
737
  end
579
738
 
580
- desc 'Generate a list of recommended tags, optionally updating the file'
581
- arg_name 'file_pattern', :multiple
739
+ desc "Generate a list of recommended tags, updating the file (unless dry run)"
740
+ arg_name "file_pattern", :multiple
582
741
  command :tag do |c|
583
742
  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 'output_format'
585
- c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist|complete)$/, :type => String, :default_value => 'yaml'
743
+ c.arg_name "output_format"
744
+ c.flag %i[f format], :must_match => /^(csv|list|yaml|json|plist|complete)$/, :type => String, :default_value => "yaml"
586
745
 
587
746
  c.action do |global_options, options, args|
588
- if @piped_content
747
+ if @piped_content && !@piped_content.file_list?(global_options[:null])
589
748
  suggestions = @jt.suggest(@piped_content)
590
749
  if args.length > 0
591
- console_log
592
- console_log 'STDIN:', :err => true
593
- end
594
- if options[:format] == 'complete'
595
- @jt.update_file_tags(@piped_content, suggestions, true)
596
- else
597
- output_tags(suggestions, :format => options[:format], :filename => nil)
750
+ @util.console_log level: :info
751
+ @util.console_log "STDIN:", level: info, err: true
598
752
  end
753
+
754
+ @util.output_tags(suggestions, :format => options[:format], :filename => nil)
599
755
  end
600
- args.each {|file|
756
+
757
+ files = []
758
+ args.length.times do
759
+ arg = args.pop
760
+ files.push(arg) if File.exist?(arg)
761
+ end
762
+
763
+ files.concat(@piped_content.split(global_options[:null] ? "\x00" : "\n")) if @piped_content && @piped_content.file_list?(global_options[:null])
764
+
765
+ files.each do |file|
601
766
  if File.exist?(File.expand_path(file))
602
767
  input = IO.read(File.expand_path(file))
603
768
  suggestions = @jt.suggest(input)
604
769
 
605
770
  unless global_options[:t]
606
771
  if @jt.update_file_tags(file, suggestions)
607
- console_log
608
- console_log "Updated file #{file} with:", :log => true
772
+ @util.console_log level: :info
773
+ @util.console_log "Updated file #{file} with:", log: true, level: :warn
609
774
  else
610
- console_log
611
- console_log "Failed to update #{file} with:", :log => true
775
+ @util.console_log level: :info
776
+ @util.console_log "Failed to update #{file} with:", log: true, level: :error
612
777
  end
613
778
  end
614
779
  if !global_options[:s] || global_options[:t]
615
780
  if args.length > 1
616
- console_log
617
- console_log File.basename(file) + ":", :err => true, :log => true
781
+ @util.console_log level: :info
782
+ @util.console_log "#{File.basename(file)}:", err: true, level: :info
618
783
  end
619
- output_tags(suggestions, :format => options[:format], :filename => file )
784
+ @util.output_tags(suggestions, :format => options[:format], :filename => file)
620
785
  end
621
786
  suggestions = nil
622
787
  else
623
- raise "No such file: #{file}"
788
+ raise FileNotFound, "No such file: #{file}"
624
789
  end
625
- }
790
+ end
626
791
  end
627
792
  end
628
793
 
629
- def output_tags(tags,options)
630
- format = options[:format] || 'yaml'
631
- print0 = options[:print0] || false
632
- filename = options[:filename] || false
633
- case format
634
- when 'list'
635
- unless print0
636
- console_log tags.join("\n")
637
- else
638
- console_log tags.map {|tag|
639
- if tag.strip =~ /\b\s\b/
640
- %Q{"#{tag.strip}"}
641
- else
642
- tag.strip
643
- end
644
- }.join(" ")
645
- end
646
- when 'csv'
647
- console_log tags.to_csv
648
- when 'json'
649
- out = {}
650
- out['tags'] = tags
651
- out['path'] = filename if filename
652
- console_log out.to_json
653
- when 'plist'
654
- out = {}
655
- out['path'] = filename if filename
656
- console_log tags.to_plist
657
- else
658
- out = {}
659
- options[:grouping] ||= "tags"
660
- out[options[:grouping]] = tags
661
- console_log out.to_yaml
794
+ ##
795
+ ## Move deprecated config files to new location
796
+ ##
797
+ ## @return [void]
798
+ ##
799
+ def update_deprecated_config
800
+ if File.exist?(File.expand_path("~/.jtag"))
801
+ FileUtils.mv(File.expand_path("~/.jtag"), File.expand_path("~/.config/jtag"))
802
+ @util.console_log "Moved ~/.jtag to ~/.config/jtag", level: :info, err: true, log: false
662
803
  end
663
804
  end
664
805
 
@@ -673,40 +814,59 @@ end
673
814
  # end
674
815
 
675
816
  pre do |global, command, options, args|
676
- # Use skips_pre before a command to skip this block
677
- # on that command only
678
- @silent = global[:silent]
817
+ Signal.trap("PIPE", "EXIT")
818
+
819
+ @util = JekyllTag::Util.new
820
+ @util.config_target = if global[:config_dir]
821
+ File.expand_path(global[:config_dir])
822
+ else
823
+ File.expand_path("~/.config/jtag")
824
+ end
825
+
826
+ # if global[:debug] == 0 or global[:silent], run silently
827
+ @util.silent = global[:debug] == 0 || global[:silent]
828
+
829
+ # set up logging
830
+ logfile = File.open(File.join(Dir.tmpdir, "jtag_actions.log"), "a")
679
831
 
680
- @logfile = File.open(File.join(Dir.tmpdir, "jtag_actions.log"), 'a')
832
+ # set up logger
833
+ @util.log = Logger.new(logfile, shift_age = 7, shift_size = 1048576)
681
834
 
682
- @log = Logger.new(@logfile, shift_age = 7, shift_size = 1048576)
835
+ # set log level based on flags
836
+ @util.debug_level = @silent ? 0 : global[:debug]
683
837
 
684
- unless config_files_complete?
685
- write_config
686
- console_log "Missing config files written to #{@config_target}. Please check your configuration.", {:err => true}
838
+ # check for config files, write them if they don't exist
839
+ unless @util.config_files_complete?
840
+ @util.write_config
841
+ @util.console_log "Missing config files written to #{@util.config_target}. Please check your configuration.", err: true, level: :error
687
842
  return false
688
843
  end
689
844
 
690
- configfile = File.expand_path("~/.jtag/config.yml")
845
+ configfile = File.join(@util.config_target, "config.yml")
691
846
 
692
- global[:config] = YAML::load(File.open(configfile,"r"))
693
- global[:support] = File.expand_path("~/.jtag")
847
+ # load config file
848
+ config = YAML.load_file(configfile)
849
+ global[:config] = config.symbolize_keys
694
850
 
695
- @piped_content = STDIN.stat.size > 0 ? STDIN.read : nil
851
+ @piped_content = $stdin.read if $stdin.fcntl(Fcntl::F_GETFL, 0) == 0 || $stdin.stat.pipe?
696
852
 
697
- @jt = JTag.new(global[:support], global[:config])
853
+ @jt = JekyllTag::JTag.new(@util.config_target, global[:config])
698
854
 
699
855
  true
700
856
  end
701
857
 
702
- post do |global,command,options,args|
858
+ post do |global, command, options, args|
703
859
  # Post logic here
704
860
  # Use skips_post before a command to skip this
705
861
  # block on that command only
706
862
  end
707
863
 
708
864
  on_error do |exception|
709
- # Error logic here
865
+ if exception.is_a?(NoValidFile) || exception.is_a?(FileNotFound) || exception.is_a?(NoTagsFound)
866
+ @util.console_log "#{@jt.color(:red)}#{exception.message}", err: true, level: :error
867
+ return false
868
+ end
869
+
710
870
  # return false to skip default error handling
711
871
  true
712
872
  end