pdfh 3.1.0 → 3.3.0

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/lib/pdfh/main.rb CHANGED
@@ -4,13 +4,12 @@ module Pdfh
4
4
  # Main functionality. This class is intended to manage the pdf documents
5
5
  class Main
6
6
  class << self
7
+ # @param argv [Array<String>]
7
8
  # @return [void]
8
- def start
9
- arg_options = Pdfh::OptParser.parse_argv
9
+ def start(argv:)
10
+ arg_options = Pdfh::OptParser.new(argv: argv).parse_argv
10
11
  @options = Options.new(arg_options)
11
-
12
- Pdfh.instance_variable_set(:@options, options)
13
- Pdfh.instance_variable_set(:@console, Console.new(options.verbose?))
12
+ assign_global_utils(@options)
14
13
  Pdfh.print_options(arg_options)
15
14
 
16
15
  @settings = SettingsBuilder.build
@@ -22,6 +21,7 @@ module Pdfh
22
21
  Pdfh.create_settings_file
23
22
  exit(1)
24
23
  rescue StandardError => e
24
+ Pdfh.backtrace_print e if Pdfh.verbose?
25
25
  Pdfh.error_print(e.message)
26
26
  end
27
27
 
@@ -29,8 +29,15 @@ module Pdfh
29
29
 
30
30
  attr_reader :options, :settings
31
31
 
32
+ # @param options [Options]
33
+ # @return [void]
34
+ def assign_global_utils(options)
35
+ Pdfh.instance_variable_set(:@options, options)
36
+ Pdfh.instance_variable_set(:@console, Console.new(options.verbose?))
37
+ end
38
+
32
39
  # @param [String] file_name
33
- # @return [DocumentType]
40
+ # @return [DocumentType, nil]
34
41
  def match_doc_type(file_name)
35
42
  settings.document_types.each do |type|
36
43
  match = type.re_file.match(file_name)
@@ -63,31 +70,74 @@ module Pdfh
63
70
 
64
71
  # @param [String] work_directory
65
72
  # @return [void]
73
+ def process_zip_files(work_directory)
74
+ @settings.zip_types&.each do |zip_type|
75
+ find_files(work_directory, :zip).each do |file|
76
+ next unless zip_type.re_file.match?(File.basename(file))
77
+
78
+ Pdfh.info " > Processing zip file: #{file.green}"
79
+ password_opt = "-P #{zip_type.password}" if zip_type.password?
80
+ `unzip -o #{password_opt} #{file} -d #{work_directory}`
81
+ end
82
+ end
83
+ end
84
+
85
+ # @param directory [String]
86
+ # @param type [String, Symbol]
87
+ # @return [Array<String>]
88
+ def find_files(directory, type)
89
+ glob = File.join(directory, "*.#{type}")
90
+ Dir.glob(glob)
91
+ end
92
+
66
93
  def process_directory(work_directory)
67
94
  Pdfh.headline(work_directory)
68
- processed_count = 0
69
- ignored_files = []
70
- files = Dir["#{work_directory}/*.pdf"]
95
+ process_zip_files(work_directory) if @settings.zip_types?
96
+ processed_result = RunResult.new
97
+ files = find_files(work_directory, :pdf)
71
98
  files.each do |pdf_file|
72
99
  type = match_doc_type(pdf_file)
73
100
  if type
74
- processed_count += 1
75
101
  PdfFileHandler.new(pdf_file, type).process_document(settings.base_path)
102
+ processed_result.add_processed(pdf_file)
76
103
  else
77
- ignored_files << base_name_no_ext(pdf_file)
104
+ processed_result.add_ignored(pdf_file)
78
105
  end
79
106
  end
80
- puts " (No files processed)".colorize(:light_black) if processed_count.zero?
81
- return unless Pdfh.verbose?
82
-
83
- puts "\n No document type found for these PDF files:" if ignored_files.any?
84
- ignored_files.each.with_index(1) { |file, index| Pdfh.ident_print index, file, color: :magenta }
107
+ print_processing_results(processed_result)
85
108
  end
86
109
 
87
110
  # @return [String]
88
111
  def base_name_no_ext(file)
89
112
  File.basename(file, File.extname(file))
90
113
  end
114
+
115
+ def print_processing_results(result)
116
+ Pdfh.info " (No files processed)".colorize(:light_black) if result.processed.empty?
117
+ return unless Pdfh.verbose?
118
+
119
+ Pdfh.info "\n No document type found for these PDF files:" if result.ignored.any?
120
+ result.ignored.each.with_index(1) do |file, index|
121
+ Pdfh.ident_print index, base_name_no_ext(file), color: :magenta
122
+ end
123
+ end
124
+ end
125
+
126
+ # keeps track of the processed and ignored files
127
+ class RunResult
128
+ attr_reader :processed, :ignored
129
+
130
+ # @return [self]
131
+ def initialize
132
+ @processed = []
133
+ @ignored = []
134
+ end
135
+
136
+ # @return [void]
137
+ def add_ignored(file) = @ignored << file
138
+
139
+ # @return [void]
140
+ def add_processed(file) = @processed << file
91
141
  end
92
142
  end
93
143
  end
@@ -12,14 +12,18 @@ module Pdfh
12
12
  def initialize(file, type, text)
13
13
  @file = file
14
14
  @type = type
15
- Pdfh.debug "=== Document Type: #{type.name} =============================="
16
15
  @text = text
16
+ end
17
+
18
+ # @return [void]
19
+ def process
20
+ Pdfh.debug "=== Document Type: #{type.name} =============================="
17
21
  Pdfh.debug "~~~~~~~~~~~~~~~~~~ Finding a subtype"
18
22
  @sub_type = type.sub_type(@text)
19
23
  Pdfh.debug " SubType: #{@sub_type}"
20
24
  @companion = search_companion_files
21
25
 
22
- month, year, @extra = match_data
26
+ month, year, @extra = match_date(@sub_type&.re_date || @type.re_date)
23
27
  @period = DocumentPeriod.new(day: extra, month: month, month_offset: @sub_type&.month_offset, year: year)
24
28
  Pdfh.debug " Period: #{@period.inspect}"
25
29
  end
@@ -32,7 +36,6 @@ module Pdfh
32
36
  print_info_line "New Name", new_name
33
37
  print_info_line "Store Path", store_path
34
38
  print_info_line "Extra files", companion_files(join: true)
35
- print_info_line "Print CMD", print_cmd
36
39
  print_info_line "Processed?", "No (in Dry mode)" if Pdfh.dry?
37
40
  end
38
41
 
@@ -95,14 +98,6 @@ module Pdfh
95
98
  type.generate_path(rename_data)
96
99
  end
97
100
 
98
- # @return [String]
99
- def print_cmd
100
- return "N/A" if type.print_cmd.nil? || type.print_cmd.empty?
101
-
102
- relative_path = File.join(store_path, new_name)
103
- "#{type.print_cmd} #{relative_path}"
104
- end
105
-
106
101
  # @return [String (frozen)]
107
102
  def companion_files(join: false)
108
103
  return @companion unless join
@@ -125,16 +120,17 @@ module Pdfh
125
120
  # named matches can appear in any order with names 'd', 'm' and 'y'
126
121
  # unnamed matches needs to be in order month, year
127
122
  # @return [Array] - format [month, year, day]
128
- def match_data
123
+ # @param regex [RegularExpression]
124
+ def match_date(regex)
129
125
  Pdfh.debug "~~~~~~~~~~~~~~~~~~ Match Data RegEx"
130
- Pdfh.debug " Using regex: #{@type.re_date}"
131
- Pdfh.debug " named: #{@type.re_date.named_captures}"
132
- matched = @type.re_date.match(@text)
126
+ Pdfh.debug " Using regex: #{regex}"
127
+ Pdfh.debug " named: #{regex.named_captures}"
128
+ matched = regex.match(@text)
133
129
  raise ReDateError unless matched
134
130
 
135
131
  Pdfh.debug " captured: #{matched.captures}"
136
132
 
137
- return matched.captures.map(&:downcase) if @type.re_date.named_captures.empty?
133
+ return matched.captures.map(&:downcase) if regex.named_captures.empty?
138
134
 
139
135
  extra = matched.captures.size > 2 ? matched[:d] : nil
140
136
  [matched[:m].downcase, matched[:y], extra]
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Pdfh
4
4
  # Provides a way to divide document type by subtypes, for different name, and month adjustments
5
- DocumentSubType = Struct.new(:name, :month_offset, keyword_init: true)
5
+ DocumentSubType = Struct.new(:name, :month_offset, :re_date, keyword_init: true)
6
6
  end
@@ -2,15 +2,33 @@
2
2
 
3
3
  module Pdfh
4
4
  # Represents a type of document that can be processed by pdfh
5
- DocumentType = Struct.new(:name, :re_file, :re_date, :pwd, :store_path, :name_template, :sub_types, :print_cmd,
6
- keyword_init: true) do
5
+ class DocumentType
6
+ include Concerns::PasswordDecodable
7
+
8
+ # @!attribute [r] name
9
+ # @return [String] The name of the document type.
10
+ # @!attribute [r] re_file
11
+ # @return [Regexp] The regular expression to match file names.
12
+ # @!attribute [r] re_date
13
+ # @return [Regexp] The regular expression to extract dates and its information.
14
+ # @!attribute [r] pwd
15
+ # @return [String, nil] The base64 password for the document type, if any.
16
+ # @!attribute [r] store_path
17
+ # @return [String] The path where the document will be stored.
18
+ # @!attribute [r] name_template
19
+ # @return [String] The template for generating document names.
20
+ # @!attribute [r] sub_types
21
+ # @return [Array<DocumentSubType>, nil] The subtypes of the document, if any.
22
+ attr_reader :name, :re_file, :re_date, :pwd, :store_path, :name_template, :sub_types
23
+
24
+ # @param args [Hash]
7
25
  # @return [self]
8
26
  def initialize(args)
9
- super
10
- self.name_template ||= "{original}"
11
- self.re_file = Regexp.new(re_file)
12
- self.re_date = Regexp.new(re_date)
13
- self.sub_types = extract_subtype(sub_types) if sub_types
27
+ args.each { |k, v| instance_variable_set(:"@#{k}", v) }
28
+ @name_template ||= "{original}"
29
+ @re_file = Regexp.new(re_file)
30
+ @re_date = Regexp.new(re_date)
31
+ @sub_types = extract_subtypes(sub_types) if sub_types&.any?
14
32
  @path_validator = RenameValidator.new(store_path)
15
33
  @name_validator = RenameValidator.new(name_template)
16
34
  return if @path_validator.valid? && @name_validator.valid?
@@ -18,6 +36,11 @@ module Pdfh
18
36
  raise_validators_error
19
37
  end
20
38
 
39
+ # @return [Hash{Symbol->any}]
40
+ def to_h
41
+ instance_variables.to_h { |var| [var.to_s.delete_prefix("@"), instance_variable_get(var)] }
42
+ end
43
+
21
44
  # removes special characters from string and replaces spaces with dashes
22
45
  # @example usage
23
46
  # "Test This?%&".gid
@@ -27,19 +50,13 @@ module Pdfh
27
50
  name.downcase.gsub(/[^0-9A-Za-z\s]/, "").tr(" ", "-")
28
51
  end
29
52
 
53
+ # search the subtype name in the pdf document
30
54
  # @return [DocumentSubType]
31
55
  def sub_type(text)
32
56
  # Regexp.new(st.name).match?(name)
33
57
  sub_types&.find { |st| /#{st.name}/i.match?(text) }
34
58
  end
35
59
 
36
- # @return [String]
37
- def password
38
- return Base64.decode64(pwd) if base64?
39
-
40
- pwd
41
- end
42
-
43
60
  # @param values [Hash{Symbol->String}
44
61
  # @return [String]
45
62
  def generate_new_name(values)
@@ -54,28 +71,29 @@ module Pdfh
54
71
 
55
72
  private
56
73
 
57
- # @return [boolean]
58
- def base64?
59
- pwd.is_a?(String) && Base64.strict_encode64(Base64.decode64(pwd)) == pwd
60
- end
74
+ attr_accessor :path_validator, :name_validator
61
75
 
62
- # @param sub_types [Array]
63
- # @return [DocumentSubType]
64
- def extract_subtype(sub_types)
76
+ # @param sub_types [Array<Hash{Symbol->String}>]
77
+ # @return [Array<DocumentSubType>]
78
+ def extract_subtypes(sub_types)
65
79
  sub_types.map do |st|
66
- name = st[:name]
67
- offset = st[:month_offset].to_i
68
- DocumentSubType.new(name: name, month_offset: offset)
80
+ data = {
81
+ name: st[:name],
82
+ month_offset: st[:month_offset].to_i,
83
+ re_date: st[:re_date] && Regexp.new(st[:re_date])
84
+ }.compact
85
+ DocumentSubType.new(data)
69
86
  end
70
87
  end
71
88
 
72
89
  # @raise [ArgumentError] when called
73
90
  # @return [void]
74
91
  def raise_validators_error
75
- template = "has invalid %<1>s. Unknown tokens: %<2>s"
76
- path_errors = format(template, :store_path, @path_validator.unknown_list) unless @path_validator.valid?
77
- name_errors = format(template, :name_template, @name_validator.unknown_list) unless @name_validator.valid?
78
- raise ArgumentError, "Document type #{name.inspect} #{path_errors} #{name_errors}"
92
+ template = "has invalid %<field>s[Unknown tokens=%<error>s]"
93
+ errors = []
94
+ errors << format(template, field: :store_path, error: path_validator.unknown_list) unless path_validator.valid?
95
+ errors << format(template, field: :name_template, error: name_validator.unknown_list) unless name_validator.valid?
96
+ raise ArgumentError, "Document type #{name.inspect} #{errors.join(", ")}"
79
97
  end
80
98
  end
81
99
  end
@@ -3,7 +3,13 @@
3
3
  module Pdfh
4
4
  # Handles the config yaml data mapping, and associates a file name with a doc type
5
5
  class Settings
6
- attr_reader :lookup_dirs, :base_path
6
+ # @!attribute [r] lookup_dirs
7
+ # @return [Array<String>] List of directories to look up for processing.
8
+ # @!attribute [r] base_path
9
+ # @return [String] The base directory path for storing processed files.
10
+ # @!attribute [r] zip_types
11
+ # @return [Array<ZipType>, nil] List of zip types to process, or nil if none.
12
+ attr_reader :lookup_dirs, :base_path, :zip_types
7
13
 
8
14
  # @param config_data [Hash]
9
15
  # @return [self]
@@ -15,7 +21,8 @@ module Pdfh
15
21
  lookup_dirs.each.with_index(1) { |dir, idx| Pdfh.debug " #{idx}. #{dir}" }
16
22
  Pdfh.debug
17
23
 
18
- load_doc_types(config_data[:document_types])
24
+ build_doc_types(config_data[:document_types])
25
+ build_zip_types(config_data[:zip_types]) if config_data.key?(:zip_types)
19
26
  end
20
27
 
21
28
  # @return [Array<DocumentType>]
@@ -28,8 +35,14 @@ module Pdfh
28
35
  @document_types[id]
29
36
  end
30
37
 
38
+ # @return [Boolean]
39
+ def zip_types?
40
+ !!zip_types&.any?
41
+ end
42
+
31
43
  private
32
44
 
45
+ # @param lookup_dirs_list [Array[String]]
33
46
  # @return [void]
34
47
  def process_lookup_dirs(lookup_dirs_list)
35
48
  @lookup_dirs = lookup_dirs_list.filter_map do |dir|
@@ -44,20 +57,31 @@ module Pdfh
44
57
  end
45
58
 
46
59
  # @return [void]
60
+ # @param dir [String]
47
61
  def process_destination_base(dir)
48
62
  @base_path = File.expand_path(dir)
49
63
  raise ArgumentError, "Destination base directory is not configured." if @base_path.nil?
50
64
  raise ArgumentError, "Destination base directory #{@base_path} does not exist." unless File.directory?(@base_path)
51
65
  end
52
66
 
53
- # @return [Array<DocumentType>]
54
- def load_doc_types(doc_types)
67
+ # @param doc_types [Array<Hash>]
68
+ # @return [void]
69
+ def build_doc_types(doc_types)
55
70
  @document_types = doc_types.each_with_object({}) do |data, result|
56
71
  doc_type = DocumentType.new(data)
57
72
  result.store(doc_type.gid, doc_type)
58
73
  rescue ArgumentError => e
59
74
  Pdfh.error_print e.message, exit_app: false
75
+ Pdfh.backtrace_print e if Pdfh.verbose?
60
76
  end
61
77
  end
78
+
79
+ # @param zip_types [Array<Hash>]
80
+ # @return [void]
81
+ def build_zip_types(zip_types)
82
+ exit(1) if Pdfh::Utils::DependencyValidator.missing?(:unzip)
83
+
84
+ @zip_types = zip_types.compact.map { ZipType.new(_1) }
85
+ end
62
86
  end
63
87
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfh
4
+ # Zip files which contains PDF files that need pre-processing
5
+ class ZipType
6
+ include Concerns::PasswordDecodable
7
+
8
+ attr_reader :name, :re_file, :pwd
9
+
10
+ # @param args [Hash]
11
+ # @return [self]
12
+ def initialize(args)
13
+ args.each { |k, v| instance_variable_set(:"@#{k}", v) }
14
+ @re_file = Regexp.new(re_file)
15
+ end
16
+ end
17
+ end
@@ -41,6 +41,14 @@ module Pdfh
41
41
  exit 1 if exit_app
42
42
  end
43
43
 
44
+ # @param e [StandardError]
45
+ # @return [void]
46
+ def backtrace_print(e)
47
+ e.backtrace&.each do |line|
48
+ output " ↳ #{line.sub("#{Dir.pwd}/", "")}".colorize(:light_black)
49
+ end
50
+ end
51
+
44
52
  # @param message [String]
45
53
  # @return [void]
46
54
  def warn_print(message)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ module Pdfh
6
+ module Utils
7
+ # Provides methods to validate external dependencies
8
+ module DependencyValidator
9
+ module_function
10
+
11
+ # Validates if the required command-line applications are installed
12
+ # @param apps [Array<String>] names of required command-line applications
13
+ # @return [Boolean] true if all applications are installed, false otherwise
14
+ def installed?(*apps)
15
+ missing = apps.filter_map do |app|
16
+ _stdout, _stderr, status = Open3.capture3("which #{app}")
17
+
18
+ app.to_s unless status.success?
19
+ end
20
+
21
+ if missing.any?
22
+ errors = missing.map(&:red)
23
+ puts "Required dependency #{errors.join(", ")} not found. Please install it before continuing."
24
+ end
25
+ missing.empty?
26
+ end
27
+
28
+ # @param apps [Array<String>]
29
+ # @return [Boolean] true if any application is missing, false if all are installed
30
+ def missing?(*apps)
31
+ !installed?(*apps)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -5,58 +5,73 @@ require "optparse"
5
5
  module Pdfh
6
6
  # Handles Argument options
7
7
  class OptParser
8
- OPT_PARSER = OptionParser.new do |opts|
9
- opts.default_argv
10
- # Process ARGV
11
- opts.banner = "Usage: #{opts.program_name} [options] [file1 ...]"
12
- opts.separator ""
13
- opts.separator "Specific options:"
14
-
15
- opts.on("-tID", "--type=ID", "Document type id (requires a trailing file list)")
16
- opts.on_tail("-T", "--list-types", "List document types in configuration") { list_types || exit }
17
- opts.on_tail("-V", "--version", "Show version") { version || exit }
18
- opts.on_tail("-h", "--help", "help (this dialog)") { help || exit }
19
-
20
- opts.on("-v", "--verbose", "Show more output. Useful for debug")
21
- opts.on("-d", "--dry", "Dry run, does not write new pdf")
8
+ # @param argv [Array<String>] command line arguments (ie. ARGV)
9
+ # @param console [Pdfh::Console, nil]
10
+ # @return [self]
11
+ def initialize(argv:, console: nil)
12
+ @argv = argv
13
+ @console = console || Console.new(false)
14
+ @options = {
15
+ verbose: false,
16
+ dry: false,
17
+ type: nil,
18
+ files: []
19
+ }
22
20
  end
23
21
 
24
- class << self
25
- # @return [Hash]
26
- def parse_argv
27
- Pdfh.instance_variable_set(:@console, Console.new(false))
28
-
29
- options = { dry: false, verbose: false }
30
- OPT_PARSER.parse!(into: options)
31
- options[:files] = ARGV if ARGV.any?
32
- options.transform_keys { |key| key.to_s.tr("-", "_").to_sym }
33
- rescue OptionParser::InvalidOption => e
34
- Pdfh.error_print(e.message, exit_app: false)
35
- puts OPT_PARSER.help
36
- exit 1
37
- end
22
+ # @return [Hash] Parsed options including flags and file arguments
23
+ def parse_argv
24
+ option_parser = build_option_parser
25
+ non_option_args = option_parser.parse!(@argv)
26
+ @options[:files] = non_option_args
27
+ @options.transform_keys { |key| key.to_s.tr("-", "_").to_sym }
28
+ rescue OptionParser::InvalidOption => e
29
+ @console.error_print(e.message, exit_app: false)
30
+ puts option_parser.help
31
+ exit 1
32
+ end
38
33
 
39
- # @return [nil]
40
- def version
41
- puts "#{OPT_PARSER.program_name} v#{Pdfh::VERSION}"
42
- end
34
+ private
43
35
 
44
- # @return [nil]
45
- def help
46
- puts OPT_PARSER
36
+ # @return [OptionParser] Configured OptionParser instance
37
+ def build_option_parser
38
+ OptionParser.new do |opts|
39
+ opts.banner = "Usage: #{opts.program_name} [options] [file1.pdf, ...]"
40
+ opts.separator ""
41
+ opts.separator "Specific options:"
42
+
43
+ opts.on("-tID", "--type=ID", "Document type id (requires a trailing file list)") { @options[:type] = _1 }
44
+ opts.on("-v", "--verbose", "Show more output. Useful for debug") { @options[:verbose] = true }
45
+ opts.on("-d", "--dry", "Dry run, does not write new pdf") { @options[:dry] = true }
46
+ opts.on_tail("-T", "--list-types", "List document types in configuration") { list_types && exit }
47
+ opts.on_tail("-V", "--version", "Show version") { version || exit }
48
+ opts.on_tail("-h", "--help", "help (this dialog)") { help || exit }
47
49
  end
50
+ end
51
+
52
+ # @return [nil]
53
+ def version
54
+ @console.info "#{build_option_parser.program_name} v#{Pdfh::VERSION}"
55
+ end
56
+
57
+ # @return [nil]
58
+ def help
59
+ @console.info build_option_parser
60
+ end
61
+
62
+ # Lists the available document types
63
+ # @return [nil]
64
+ def list_types
65
+ Pdfh.instance_variable_set(:@options, Options.new(@options))
66
+ Pdfh.instance_variable_set(:@console, @console)
48
67
 
49
- # @return [nil]
50
- def list_types
51
- settings = SettingsBuilder.build
52
- ident = 2
53
- max_width = settings.document_types.map { |t| t.gid.size }.max
54
- puts "#{" " * ident}#{"ID".ljust(max_width)} Type Name"
55
- puts "#{" " * ident}#{"—" * max_width} #{"—" * 23}"
56
- settings.document_types.each do |type|
57
- puts "#{" " * ident}#{type.gid.ljust(max_width).yellow} #{type.name}"
58
- end
59
- nil
68
+ settings = SettingsBuilder.build
69
+ spacing = " " * 2
70
+ max_width = settings.document_types.map { |t| t.gid.size }.max
71
+ @console.info "#{spacing}#{"ID".ljust(max_width)} Type Name"
72
+ @console.info "#{spacing}#{"—" * max_width} #{"—" * 23}"
73
+ settings.document_types.each do |type|
74
+ @console.info "#{spacing}#{type.gid.ljust(max_width).yellow} #{type.name}"
60
75
  end
61
76
  end
62
77
  end
@@ -25,6 +25,7 @@ module Pdfh
25
25
  raise IOError, "File #{file} not found" unless File.exist?(file)
26
26
 
27
27
  @document = Document.new(file, type, extract_text)
28
+ document.process
28
29
  document.print_info
29
30
  write_pdf(base_path)
30
31
 
@@ -86,7 +87,7 @@ module Pdfh
86
87
  end
87
88
 
88
89
  # Gets the text from the pdf in order to execute
89
- # the regular expresion matches
90
+ # the regular expression matches
90
91
  # @return [String]
91
92
  def extract_text
92
93
  temp = Tempfile.new("pdfh")
@@ -3,13 +3,17 @@
3
3
  module Pdfh
4
4
  # Loads or creates a default settings yaml file
5
5
  class SettingsBuilder
6
- CONFIG_FILE_LOCATIONS = [Dir.pwd, File.expand_path("~")].freeze
6
+ CONFIG_FILE_LOCATIONS = [Dir.pwd, ENV.fetch("XDG_CONFIG_HOME", "~/.config"), "~"].freeze
7
7
  SUPPORTED_EXTENSIONS = %w[yml yaml].freeze
8
+ ENV_VAR = "PDFH_CONFIG_FILE"
8
9
 
9
10
  class << self
10
11
  # @return [Pdfh::Settings]
11
12
  def build
12
- config_file = search_config_file
13
+ env_config_file = ENV.fetch(ENV_VAR, nil)
14
+ raise "File path in #{ENV_VAR} not found" if env_config_file && !File.exist?(env_config_file)
15
+
16
+ config_file = env_config_file || search_config_file
13
17
  file_hash = YAML.load_file(config_file, symbolize_names: true)
14
18
  Pdfh.debug "Loaded configuration file: #{config_file}"
15
19
 
@@ -42,7 +46,8 @@ module Pdfh
42
46
  # Gets the first settings file found, or creates a new one
43
47
  # @return [String]
44
48
  def search_config_file
45
- CONFIG_FILE_LOCATIONS.each do |dir|
49
+ CONFIG_FILE_LOCATIONS.each do |dir_string|
50
+ dir = File.expand_path(dir_string)
46
51
  SUPPORTED_EXTENSIONS.each do |ext|
47
52
  path = File.join(dir, "#{config_file_name}.#{ext}")
48
53
  return path if File.exist?(path)
data/lib/pdfh/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pdfh
4
- VERSION = "3.1.0"
4
+ VERSION = "3.3.0"
5
5
  end