pdfh 3.0.3 → 3.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae203433b71f3129de5d62505e63d8d1435b0463c82a22820b76e8ea8536de1c
4
- data.tar.gz: 61ac5f4219b353778a0e9bc3b749050e0f535926583ad8d6e74325b5cecfe51b
3
+ metadata.gz: 2cc0c0f6ba735b3d69c9f5bf32e6acc94b185b3606574834504634acad34f1e8
4
+ data.tar.gz: fd4bf05918b2631d2cb6335341704be2540d50cdcf5a395e7e85dd2206c865ca
5
5
  SHA512:
6
- metadata.gz: f5559496bf4652bbd0f63d3d8f056c9e39e248b7a18daae0669b5c3323f288f52ecf5bd15466de0025d948095ad04e46f1896ca367facdafe7a4c4eae48335a9
7
- data.tar.gz: c7fdff58c2c3c42a550e9bd8a3acf376ac958fa60de2588c5e212f67199799f47724b75d0a540317069944bd881f99d857fd3a6880e480e75c66abad75704c7b
6
+ metadata.gz: c58687eba046fb229b713a70650554a93473b22c9fe39c6d5427adde475187ec64a91031fb9b6ef6f22de9e516a5b5f75e7bdd6276657541127247395d53cec4
7
+ data.tar.gz: 0bc6756a6c83335f4afaad5708da797bd5d4e052542b12fa0ee030e23e66a779fe6303aa21eb6f63b6bba849291bf3a2f08a0a32ea1ea4b4f05ab14f2c3b976d
data/Gemfile.lock CHANGED
@@ -1,128 +1,148 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pdfh (3.0.3)
4
+ pdfh (3.2.0)
5
5
  colorize (~> 1.1.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activesupport (7.1.3.2)
10
+ activesupport (8.0.1)
11
11
  base64
12
+ benchmark (>= 0.3)
12
13
  bigdecimal
13
- concurrent-ruby (~> 1.0, >= 1.0.2)
14
+ concurrent-ruby (~> 1.0, >= 1.3.1)
14
15
  connection_pool (>= 2.2.5)
15
16
  drb
16
17
  i18n (>= 1.6, < 2)
18
+ logger (>= 1.4.2)
17
19
  minitest (>= 5.1)
18
- mutex_m
19
- tzinfo (~> 2.0)
20
+ securerandom (>= 0.3)
21
+ tzinfo (~> 2.0, >= 2.0.5)
22
+ uri (>= 0.13.1)
20
23
  ansi (1.5.0)
21
24
  ast (2.4.2)
22
25
  base64 (0.2.0)
23
- bigdecimal (3.1.6)
26
+ benchmark (0.4.0)
27
+ bigdecimal (3.1.9)
24
28
  blockenspiel (0.5.0)
25
29
  code-scanning-rubocop (0.6.1)
26
30
  rubocop (~> 1.0)
27
31
  coderay (1.1.3)
28
32
  colorize (1.1.0)
29
- concurrent-ruby (1.2.3)
30
- connection_pool (2.4.1)
31
- debug (1.9.1)
33
+ concurrent-ruby (1.3.5)
34
+ connection_pool (2.5.0)
35
+ date (3.4.1)
36
+ debug (1.10.0)
32
37
  irb (~> 1.10)
33
38
  reline (>= 0.3.8)
34
- diff-lcs (1.5.1)
35
- docile (1.4.0)
39
+ diff-lcs (1.6.0)
40
+ docile (1.4.1)
36
41
  drb (2.2.1)
37
- factory_bot (6.4.6)
38
- activesupport (>= 5.0.0)
39
- i18n (1.14.4)
42
+ factory_bot (6.5.1)
43
+ activesupport (>= 6.1.0)
44
+ i18n (1.14.7)
40
45
  concurrent-ruby (~> 1.0)
41
- io-console (0.7.2)
42
- irb (1.12.0)
43
- rdoc
46
+ io-console (0.8.0)
47
+ irb (1.15.1)
48
+ pp (>= 0.6.0)
49
+ rdoc (>= 4.0.0)
44
50
  reline (>= 0.4.2)
45
- json (2.7.1)
46
- language_server-protocol (3.17.0.3)
47
- method_source (1.0.0)
48
- minitest (5.22.2)
49
- mutex_m (0.2.0)
50
- parallel (1.24.0)
51
- parser (3.3.0.5)
51
+ json (2.10.1)
52
+ language_server-protocol (3.17.0.4)
53
+ lint_roller (1.1.0)
54
+ logger (1.6.6)
55
+ method_source (1.1.0)
56
+ minitest (5.25.4)
57
+ parallel (1.26.3)
58
+ parser (3.3.7.1)
52
59
  ast (~> 2.4.1)
53
60
  racc
54
- pry (0.14.2)
61
+ pp (0.6.2)
62
+ prettyprint
63
+ prettyprint (0.2.0)
64
+ pry (0.15.2)
55
65
  coderay (~> 1.1)
56
66
  method_source (~> 1.0)
57
- psych (5.1.2)
67
+ psych (5.2.3)
68
+ date
58
69
  stringio
59
- racc (1.7.3)
70
+ racc (1.8.1)
60
71
  rainbow (3.1.1)
61
- rake (13.1.0)
62
- rdoc (6.6.2)
72
+ rake (13.2.1)
73
+ rdoc (6.12.0)
63
74
  psych (>= 4.0.0)
64
- regexp_parser (2.9.0)
65
- reline (0.4.3)
75
+ regexp_parser (2.10.0)
76
+ reline (0.6.0)
66
77
  io-console (~> 0.5)
67
- rexml (3.2.6)
68
78
  rspec (3.13.0)
69
79
  rspec-core (~> 3.13.0)
70
80
  rspec-expectations (~> 3.13.0)
71
81
  rspec-mocks (~> 3.13.0)
72
- rspec-core (3.13.0)
82
+ rspec-core (3.13.3)
73
83
  rspec-support (~> 3.13.0)
74
- rspec-expectations (3.13.0)
84
+ rspec-expectations (3.13.3)
75
85
  diff-lcs (>= 1.2.0, < 2.0)
76
86
  rspec-support (~> 3.13.0)
77
- rspec-mocks (3.13.0)
87
+ rspec-mocks (3.13.2)
78
88
  diff-lcs (>= 1.2.0, < 2.0)
79
89
  rspec-support (~> 3.13.0)
80
- rspec-support (3.13.1)
90
+ rspec-support (3.13.2)
81
91
  rspec_junit_formatter (0.6.0)
82
92
  rspec-core (>= 2, < 4, != 2.12.0)
83
- rubocop (1.62.1)
93
+ rubocop (1.73.2)
84
94
  json (~> 2.3)
85
- language_server-protocol (>= 3.17.0)
95
+ language_server-protocol (~> 3.17.0.2)
96
+ lint_roller (~> 1.1.0)
86
97
  parallel (~> 1.10)
87
98
  parser (>= 3.3.0.2)
88
99
  rainbow (>= 2.2.2, < 4.0)
89
- regexp_parser (>= 1.8, < 3.0)
90
- rexml (>= 3.2.5, < 4.0)
91
- rubocop-ast (>= 1.31.1, < 2.0)
100
+ regexp_parser (>= 2.9.3, < 3.0)
101
+ rubocop-ast (>= 1.38.0, < 2.0)
92
102
  ruby-progressbar (~> 1.7)
93
- unicode-display_width (>= 2.4.0, < 3.0)
94
- rubocop-ast (1.31.2)
95
- parser (>= 3.3.0.4)
96
- rubocop-capybara (2.20.0)
103
+ unicode-display_width (>= 2.4.0, < 4.0)
104
+ rubocop-ast (1.38.1)
105
+ parser (>= 3.3.1.0)
106
+ rubocop-capybara (2.21.0)
97
107
  rubocop (~> 1.41)
98
- rubocop-factory_bot (2.25.1)
99
- rubocop (~> 1.41)
100
- rubocop-performance (1.20.2)
101
- rubocop (>= 1.48.1, < 2.0)
102
- rubocop-ast (>= 1.30.0, < 2.0)
103
- rubocop-rake (0.6.0)
104
- rubocop (~> 1.0)
105
- rubocop-rspec (2.27.1)
108
+ rubocop-factory_bot (2.27.0)
109
+ lint_roller (~> 1.1)
110
+ rubocop (~> 1.72, >= 1.72.1)
111
+ rubocop-performance (1.24.0)
112
+ lint_roller (~> 1.1)
113
+ rubocop (>= 1.72.1, < 2.0)
114
+ rubocop-ast (>= 1.38.0, < 2.0)
115
+ rubocop-rake (0.7.1)
116
+ lint_roller (~> 1.1)
117
+ rubocop (>= 1.72.1)
118
+ rubocop-rspec (2.31.0)
106
119
  rubocop (~> 1.40)
107
120
  rubocop-capybara (~> 2.17)
108
121
  rubocop-factory_bot (~> 2.22)
122
+ rubocop-rspec_rails (~> 2.28)
123
+ rubocop-rspec_rails (2.29.1)
124
+ rubocop (~> 1.61)
109
125
  ruby-progressbar (1.13.0)
126
+ securerandom (0.4.1)
110
127
  simplecov (0.22.0)
111
128
  docile (~> 1.1)
112
129
  simplecov-html (~> 0.11)
113
130
  simplecov_json_formatter (~> 0.1)
114
- simplecov-console (0.9.1)
131
+ simplecov-console (0.9.3)
115
132
  ansi
116
133
  simplecov
117
134
  terminal-table
118
- simplecov-html (0.12.3)
135
+ simplecov-html (0.13.1)
119
136
  simplecov_json_formatter (0.1.4)
120
- stringio (3.1.0)
121
- terminal-table (3.0.2)
122
- unicode-display_width (>= 1.1.1, < 3)
137
+ stringio (3.1.5)
138
+ terminal-table (4.0.0)
139
+ unicode-display_width (>= 1.1.1, < 4)
123
140
  tzinfo (2.0.6)
124
141
  concurrent-ruby (~> 1.0)
125
- unicode-display_width (2.5.0)
142
+ unicode-display_width (3.1.4)
143
+ unicode-emoji (~> 4.0, >= 4.0.4)
144
+ unicode-emoji (4.0.4)
145
+ uri (1.0.3)
126
146
  versionomy (0.5.0)
127
147
  blockenspiel (~> 0.5)
128
148
 
@@ -148,4 +168,4 @@ DEPENDENCIES
148
168
  versionomy (~> 0.5)
149
169
 
150
170
  BUNDLED WITH
151
- 2.5.6
171
+ 2.6.5
data/README.md CHANGED
@@ -18,20 +18,32 @@ gem install pdfh
18
18
  You need to install pdf handling dependencies in order to use this gem.
19
19
 
20
20
  #### macOS
21
+
21
22
  ```bash
22
23
  brew install qpdf # for qpdf
23
24
  brew install xpdf # for pdftotext
24
25
  ```
25
26
 
26
27
  #### Fedora
28
+
27
29
  ```bash
28
30
  sudo dnf install -y qpdf poppler-utils
29
31
  ```
30
32
 
33
+ #### Arch
34
+
35
+ ```bash
36
+ sudo pacman -S qpdf poppler
37
+ ```
38
+
31
39
  ## Usage
32
40
 
33
- After installing this gem you need to create your configuration file on your home folder.
34
- `pdfh.yml`
41
+ After installing this gem you need to create your configuration file on any of the following directories:
42
+
43
+ - `~/.config/pdfh.yml`
44
+ - `~/pdfh.yml`
45
+ - or configure `PDFH_CONFIG_FILE` environment variable
46
+
35
47
  ```yaml
36
48
  ---
37
49
  lookup_dirs: # Directories where all pdf's are going to be analyzed
@@ -42,25 +54,22 @@ document_types:
42
54
  re_file: '.*MyBankReg\.pdf' # Regular expression to match its filename
43
55
  re_date: 'al \d{1,2} de (\w+) del? (\d+)' # Date regular expresion
44
56
  pwd: base64string # [OPTIONAL] Password if the document is protected
45
- store_path: "{YEAR}/bank_docs" # Relative path to copy this document
57
+ store_path: "{year}/bank_docs" # Relative path to copy this document
46
58
  name_template: '{period} {subtype}' # Template for new filename when copied
47
59
  sub_types: # [OPTIONAL] In case your need an extra category
48
60
  - name: Account1 # Regular expresion to match this subtype
49
61
  month_offset: -1 # [OPTIONAL] Integer (signed) value to adjust month
50
62
  ```
51
63
 
52
- Store Path supported placeholders:
53
- * `{YEAR}` 2022
64
+ **Store Path** and **Name Template** supported placeholders:
54
65
 
55
- Name Template supported placeholders:
56
-
57
- * `{original}` Original filename
58
- * `{period}` 2022-01
59
- * `{year}` 2022
60
- * `{month}` 01
61
- * `{type}` document_type.name
62
- * `{subtype}` subtype.name if matched
63
- * `{extra}` day if provided/matched
66
+ - `{original}` Original filename
67
+ - `{period}` 2022-01
68
+ - `{year}` 2022
69
+ - `{month}` 01
70
+ - `{type}` document_type.name
71
+ - `{subtype}` subtype.name if matched
72
+ - `{extra}` day if provided/matched
64
73
 
65
74
  ## Development
66
75
 
@@ -77,6 +86,7 @@ gem install pdfh-*
77
86
  ```
78
87
 
79
88
  ### Conventional Commits
89
+
80
90
  ```bash
81
91
  npm install -g @commitlint/cli @commitlint/config-conventional
82
92
  commitlint --from origin --to @
@@ -84,7 +94,7 @@ commitlint --from origin --to @
84
94
 
85
95
  ## Contributing
86
96
 
87
- Bug reports and pull requests are welcome on GitHub at https://github.com/iax7/pdfh. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
97
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/iax7/pdfh>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
88
98
 
89
99
  ## License
90
100
 
@@ -97,7 +107,7 @@ Everyone interacting in the Pdfh project’s codebases, issue trackers, chat roo
97
107
  <!-- Links -->
98
108
  [rubocop-img]: https://github.com/iax7/pdfh/actions/workflows/rubocop-analysis.yml/badge.svg
99
109
  [rubocop-url]: https://github.com/iax7/pdfh/actions/workflows/rubocop-analysis.yml
100
- [ruby-img]: https://img.shields.io/badge/ruby-3.3-blue?style=flat&logo=ruby&logoColor=CC342D&labelColor=white
110
+ [ruby-img]: https://img.shields.io/badge/ruby-3.4-blue?style=flat&logo=ruby&logoColor=CC342D&labelColor=white
101
111
  [ruby-url]: https://www.ruby-lang.org/en/
102
112
  [cc-img]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=00&labelColor=fff
103
113
  [cc-url]: https://conventionalcommits.org
data/exe/pdfh CHANGED
@@ -9,7 +9,7 @@ require "pdfh"
9
9
  def validate_installed(*apps)
10
10
  found_app = []
11
11
  apps.each_with_object(found_app) do |app, result|
12
- _stdout, _stderr, status = Open3.capture3("command -v #{app}")
12
+ _stdout, _stderr, status = Open3.capture3("which #{app}")
13
13
  puts "Missing #{app} command." unless status.success?
14
14
  result << status.success?
15
15
  end
data/lib/pdfh/main.rb CHANGED
@@ -22,6 +22,7 @@ module Pdfh
22
22
  Pdfh.create_settings_file
23
23
  exit(1)
24
24
  rescue StandardError => e
25
+ Pdfh.backtrace_print e if Pdfh.verbose?
25
26
  Pdfh.error_print(e.message)
26
27
  end
27
28
 
@@ -3,8 +3,6 @@
3
3
  module Pdfh
4
4
  # Handles the PDF detected by the rules
5
5
  class Document
6
- IDENT = 12
7
-
8
6
  attr_reader :text, :type, :file, :extra, :period
9
7
 
10
8
  # @param file [String]
@@ -14,14 +12,18 @@ module Pdfh
14
12
  def initialize(file, type, text)
15
13
  @file = file
16
14
  @type = type
17
- Pdfh.debug "=== Document Type: #{type.name} =============================="
18
15
  @text = text
16
+ end
17
+
18
+ # @return [void]
19
+ def process
20
+ Pdfh.debug "=== Document Type: #{type.name} =============================="
19
21
  Pdfh.debug "~~~~~~~~~~~~~~~~~~ Finding a subtype"
20
22
  @sub_type = type.sub_type(@text)
21
23
  Pdfh.debug " SubType: #{@sub_type}"
22
24
  @companion = search_companion_files
23
25
 
24
- month, year, @extra = match_data
26
+ month, year, @extra = match_date(@sub_type&.re_date || @type.re_date)
25
27
  @period = DocumentPeriod.new(day: extra, month: month, month_offset: @sub_type&.month_offset, year: year)
26
28
  Pdfh.debug " Period: #{@period.inspect}"
27
29
  end
@@ -34,18 +36,22 @@ module Pdfh
34
36
  print_info_line "New Name", new_name
35
37
  print_info_line "Store Path", store_path
36
38
  print_info_line "Extra files", companion_files(join: true)
37
- print_info_line "Print CMD", print_cmd
38
39
  print_info_line "Processed?", "No (in Dry mode)" if Pdfh.dry?
39
40
  end
40
41
 
41
42
  # @return [void]
42
43
  def print_info_line(property, info)
43
- Pdfh.ident_print property, info.to_s, color: :light_blue, width: IDENT
44
+ Pdfh.ident_print property, info.to_s, color: :light_blue, width: 12
44
45
  end
45
46
 
46
47
  # @return [String]
47
48
  def file_name_only
48
- File.basename(@file, File.extname(@file))
49
+ File.basename(@file, file_extension)
50
+ end
51
+
52
+ # @return [String]
53
+ def file_extension
54
+ File.extname(@file)
49
55
  end
50
56
 
51
57
  # @return [String]
@@ -83,22 +89,16 @@ module Pdfh
83
89
 
84
90
  # @return [String]
85
91
  def new_name
86
- type.generate_new_name(rename_data)
92
+ new_name = type.generate_new_name(rename_data)
93
+ "#{new_name}#{file_extension}"
87
94
  end
88
95
 
89
96
  # @return [String]
90
97
  def store_path
91
- @type.store_path.gsub("{YEAR}", period.year.to_s)
92
- end
93
-
94
- # @return [String]
95
- def print_cmd
96
- return "N/A" if type.print_cmd.nil? || type.print_cmd.empty?
97
-
98
- relative_path = File.join(store_path, new_name)
99
- "#{type.print_cmd} #{relative_path}"
98
+ type.generate_path(rename_data)
100
99
  end
101
100
 
101
+ # @return [String (frozen)]
102
102
  def companion_files(join: false)
103
103
  return @companion unless join
104
104
 
@@ -120,16 +120,17 @@ module Pdfh
120
120
  # named matches can appear in any order with names 'd', 'm' and 'y'
121
121
  # unnamed matches needs to be in order month, year
122
122
  # @return [Array] - format [month, year, day]
123
- def match_data
123
+ # @param regex [RegularExpression]
124
+ def match_date(regex)
124
125
  Pdfh.debug "~~~~~~~~~~~~~~~~~~ Match Data RegEx"
125
- Pdfh.debug " Using regex: #{@type.re_date}"
126
- Pdfh.debug " named: #{@type.re_date.named_captures}"
127
- matched = @type.re_date.match(@text)
126
+ Pdfh.debug " Using regex: #{regex}"
127
+ Pdfh.debug " named: #{regex.named_captures}"
128
+ matched = regex.match(@text)
128
129
  raise ReDateError unless matched
129
130
 
130
131
  Pdfh.debug " captured: #{matched.captures}"
131
132
 
132
- return matched.captures.map(&:downcase) if @type.re_date.named_captures.empty?
133
+ return matched.captures.map(&:downcase) if regex.named_captures.empty?
133
134
 
134
135
  extra = matched.captures.size > 2 ? matched[:d] : nil
135
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,20 +2,27 @@
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
+ attr_reader :name, :re_file, :re_date, :pwd, :store_path, :name_template, :sub_types
7
+
8
+ # @param args [Hash]
7
9
  # @return [self]
8
10
  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
14
- @rename_validator = RenameValidator.new(name_template)
15
- return if @rename_validator.valid?
11
+ args.each { |k, v| instance_variable_set(:"@#{k}", v) }
12
+ @name_template ||= "{original}"
13
+ @re_file = Regexp.new(re_file)
14
+ @re_date = Regexp.new(re_date)
15
+ @sub_types = extract_subtypes(sub_types) if sub_types&.any?
16
+ @path_validator = RenameValidator.new(store_path)
17
+ @name_validator = RenameValidator.new(name_template)
18
+ return if @path_validator.valid? && @name_validator.valid?
19
+
20
+ raise_validators_error
21
+ end
16
22
 
17
- errors = @rename_validator.unknown.join(", ")
18
- raise ArgumentError, "Document type #{name.inspect} has invalid :name_template. Tokens not recognized: #{errors}"
23
+ # @return [Hash{Symbol->any}]
24
+ def to_h
25
+ instance_variables.to_h { |var| [var.to_s.delete_prefix("@"), instance_variable_get(var)] }
19
26
  end
20
27
 
21
28
  # removes special characters from string and replaces spaces with dashes
@@ -27,6 +34,7 @@ module Pdfh
27
34
  name.downcase.gsub(/[^0-9A-Za-z\s]/, "").tr(" ", "-")
28
35
  end
29
36
 
37
+ # search the subtype name in the pdf document
30
38
  # @return [DocumentSubType]
31
39
  def sub_type(text)
32
40
  # Regexp.new(st.name).match?(name)
@@ -43,24 +51,45 @@ module Pdfh
43
51
  # @param values [Hash{Symbol->String}
44
52
  # @return [String]
45
53
  def generate_new_name(values)
46
- @rename_validator.name(values)
54
+ @name_validator.gsub(values)
55
+ end
56
+
57
+ # @param values [Hash{Symbol->String}
58
+ # @return [String]
59
+ def generate_path(values)
60
+ @path_validator.gsub(values)
47
61
  end
48
62
 
49
63
  private
50
64
 
65
+ attr_accessor :path_validator, :name_validator
66
+
51
67
  # @return [boolean]
52
68
  def base64?
53
69
  pwd.is_a?(String) && Base64.strict_encode64(Base64.decode64(pwd)) == pwd
54
70
  end
55
71
 
56
- # @param sub_types [Array]
57
- # @return [DocumentSubType]
58
- def extract_subtype(sub_types)
72
+ # @param sub_types [Array<Hash{Symbol->String}>]
73
+ # @return [Array<DocumentSubType>]
74
+ def extract_subtypes(sub_types)
59
75
  sub_types.map do |st|
60
- name = st[:name]
61
- offset = st[:month_offset].to_i
62
- DocumentSubType.new(name: name, month_offset: offset)
76
+ data = {
77
+ name: st[:name],
78
+ month_offset: st[:month_offset].to_i,
79
+ re_date: st[:re_date] && Regexp.new(st[:re_date])
80
+ }.compact
81
+ DocumentSubType.new(data)
63
82
  end
64
83
  end
84
+
85
+ # @raise [ArgumentError] when called
86
+ # @return [void]
87
+ def raise_validators_error
88
+ template = "has invalid %<field>s[Unknown tokens=%<error>s]"
89
+ errors = []
90
+ errors << format(template, field: :store_path, error: path_validator.unknown_list) unless path_validator.valid?
91
+ errors << format(template, field: :name_template, error: name_validator.unknown_list) unless name_validator.valid?
92
+ raise ArgumentError, "Document type #{name.inspect} #{errors.join(", ")}"
93
+ end
65
94
  end
66
95
  end
@@ -57,6 +57,7 @@ module Pdfh
57
57
  result.store(doc_type.gid, doc_type)
58
58
  rescue ArgumentError => e
59
59
  Pdfh.error_print e.message, exit_app: false
60
+ Pdfh.backtrace_print e if Pdfh.verbose?
60
61
  end
61
62
  end
62
63
  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)
@@ -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
 
@@ -13,13 +13,13 @@ module Pdfh
13
13
  "extra" => "Extra data extracted from date_re"
14
14
  }.freeze
15
15
 
16
- attr_reader :name_template, :all, :unknown, :valid
16
+ attr_reader :template, :all, :unknown, :valid
17
17
 
18
- # @param name_template [String]
18
+ # @param template [String]
19
19
  # @return [self]
20
- def initialize(name_template)
21
- @name_template = name_template
22
- @all = name_template.scan(/{(\w+)}/).flatten
20
+ def initialize(template)
21
+ @template = template
22
+ @all = template.scan(/{([^}]+)}/).flatten.map(&:downcase)
23
23
  @unknown = all - types
24
24
  @valid = all - unknown
25
25
  end
@@ -34,11 +34,17 @@ module Pdfh
34
34
  unknown.empty?
35
35
  end
36
36
 
37
+ # @return [String]
38
+ def unknown_list
39
+ unknown.join(", ")
40
+ end
41
+
37
42
  # @param values [Hash{Symbol->String}]
38
43
  # @return [String (frozen)]
39
- def name(values)
40
- new_name = name_template.gsub("{", "%{") % values
41
- "#{new_name}.pdf"
44
+ def gsub(values)
45
+ template
46
+ .gsub(/\{([^}]+)}/, &:downcase) # convert all text between {} to lowercase
47
+ .gsub("{", "%{") % values
42
48
  end
43
49
  end
44
50
  end
@@ -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.0.3"
4
+ VERSION = "3.2.0"
5
5
  end
data/lib/pdfh.rb CHANGED
@@ -45,6 +45,6 @@ module Pdfh
45
45
  class << self
46
46
  extend Forwardable
47
47
  def_delegators :@options, :verbose?, :dry?, :file_mode?
48
- def_delegators :@console, :ident_print, :warn_print, :error_print, :headline, :debug, :info, :print_options
48
+ def_delegators :@console, :ident_print, :warn_print, :error_print, :backtrace_print, :headline, :debug, :info, :print_options
49
49
  end
50
50
  end
data/mise.toml ADDED
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ ruby = "3.4.2"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdfh
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Isaias Piña
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-03-16 00:00:00.000000000 Z
10
+ date: 2025-04-01 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: colorize
@@ -37,7 +36,6 @@ files:
37
36
  - ".rspec"
38
37
  - ".rubocop.yml"
39
38
  - ".rubocop_todo.yml"
40
- - ".tool-versions"
41
39
  - CHANGELOG.md
42
40
  - CODE_OF_CONDUCT.md
43
41
  - Gemfile
@@ -67,6 +65,7 @@ files:
67
65
  - lib/pdfh/utils/rename_validator.rb
68
66
  - lib/pdfh/utils/settings_builder.rb
69
67
  - lib/pdfh/version.rb
68
+ - mise.toml
70
69
  - pdfh.gemspec
71
70
  homepage: https://github.com/iax7/pdfh
72
71
  licenses:
@@ -77,7 +76,6 @@ metadata:
77
76
  source_code_uri: https://github.com/iax7/pdfh
78
77
  changelog_uri: https://github.com/blob/master/CHANGELOG.md
79
78
  rubygems_mfa_required: 'true'
80
- post_install_message:
81
79
  rdoc_options: []
82
80
  require_paths:
83
81
  - lib
@@ -92,8 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
90
  - !ruby/object:Gem::Version
93
91
  version: '0'
94
92
  requirements: []
95
- rubygems_version: 3.5.6
96
- signing_key:
93
+ rubygems_version: 3.6.6
97
94
  specification_version: 4
98
95
  summary: Organize PDF files
99
96
  test_files: []
data/.tool-versions DELETED
@@ -1 +0,0 @@
1
- ruby 3.3.0