Class: Selector

Inherits:
Object
  • Object
show all
Defined in:
lib/selector.rb

Overview

Class for choosing and displaying the information from the pdf.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(c = "Test\nPDF\nContent", opts = { format: 0, auto: true, no_lookup: false }, lookup = nil) ⇒ Selector

Returns a new instance of Selector.



11
12
13
14
15
16
17
18
# File 'lib/selector.rb', line 11

def initialize(c = "Test\nPDF\nContent", opts = { format: 0, auto: true, no_lookup: false }, lookup = nil)
  self.content = c
  @options = opts
  @lookup = lookup || ScholarLookup.new
  return unless opts[:test]

  def puts(*x) = x
end

Instance Attribute Details

#contentObject

Returns the value of attribute content.



8
9
10
# File 'lib/selector.rb', line 8

def content
  @content
end

#metadataObject (readonly)

Returns the value of attribute metadata.



8
9
10
# File 'lib/selector.rb', line 8

def 
  @metadata
end

#optionsObject

Returns the value of attribute options.



9
10
11
# File 'lib/selector.rb', line 9

def options
  @options
end

#titleObject (readonly)

Returns the value of attribute title.



8
9
10
# File 'lib/selector.rb', line 8

def title
  @title
end

Instance Method Details

#choose(list, print: true) ⇒ Object

Pass in an array to list and be selected, and return the element that the user selects back to the calling method. this is a way to interpret the users input as a range (e.g., 0..2) or an integer (1).



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/selector.rb', line 109

def choose(list, print: true)
  raise 'List is empty.' if list.empty?

  if @options[:auto]
    line = 0
  else
    # Never print when --auto.
    if print
      list.each_with_index { |l, i| puts "#{i}\t#{l}" }
      printf "[0 - #{options.length - 1}]: "
    end
    line = $stdin.gets&.chomp || 0
  end

  meta = "list[#{line}]"
  mout = eval meta # rubocop:disable Security/Eval -- `line` is local interactive/--auto input only, never external
  mout = mout.join ' ' if mout.is_a?(Array)
  mout
end

#gen_authors(aline) ⇒ Object

Generate different forms for author selection, enumerating the different author that you want to save the file as. Split based on a comma.



131
132
133
134
135
136
137
138
139
# File 'lib/selector.rb', line 131

def gen_authors(aline)
  lines = aline.split(', ').map { |a| a.sub(/\d$/, '') } # delete ref number.
  if lines.is_a?(String)
    aline
  else # its an array, augment w/ lname and choose
    alines = lines.map { |a| a.split.last } + lines
    choose alines
  end
end

#gen_forms(y, t, a) ⇒ Object

based on the collected information, generate different forms of the title.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/selector.rb', line 80

def gen_forms(y, t, a)
  y = sanitize_path_component(y)
  t = sanitize_path_component(t)
  a = sanitize_path_component(a)
  ad = a.downcase
  au = a.upcase
  [
    "#{y} - #{a} - #{t}.pdf",
    "#{y} #{a} #{t}.pdf",
    "#{a}_#{y}_#{t}.pdf".gsub(' ', '_'),
    "#{au}_#{y}_#{t}.pdf".gsub(' ', '_'),
    "#{ad}_#{y}_#{t}.pdf".gsub(' ', '_'),
    "#{a} #{y} #{t}.pdf",
    "#{au} #{y} #{t}.pdf",
    "#{ad} #{y} #{t}.pdf"
  ]
end

#gen_yearObject

Parse out a year from a string, for each line of the document until found. Then clean it up and return it.



143
144
145
146
147
148
149
150
# File 'lib/selector.rb', line 143

def gen_year
  @full_text.each do |l| # find year
    lm = l.match(/(19|20)\d\d/)
    return lm[0] unless lm.nil?
  end

  Time.now.year.to_s # not matched, just return current year
end

#lookup_metadataObject

Query the lookup source with our best title guess, and let the user accept or reject the match (--auto always accepts, matching how #choose behaves elsewhere). Returns a [title, author, year] triple, or nil if there was no match or it was rejected.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/selector.rb', line 40

def 
  match = @lookup.lookup(@content.first)
  return nil unless match

  summary = "#{match[:title]} -- #{match[:author]}"
  summary += " (#{match[:year]})" if match[:year]
  summary += " [#{match[:venue]}]" if match[:venue]
  puts "Found match via #{@lookup.source_name}: #{summary}"

  if @options[:auto]
    puts '(auto-accepted)'
  else
    printf 'Use this? [Y/n]: '
    resp = $stdin.gets.to_s.strip.downcase
    return nil unless resp.empty? || resp == 'y' || resp == 'yes'
  end

  [match[:title], match[:author], match[:year] || gen_year]
end

#manual_metadataObject

Ask the user to pick the title/author lines by hand. Returns a [title, author, year] triple.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/selector.rb', line 62

def 
  unless @options[:auto]
    puts 'Options:'
    @content.each_with_index { |l, i| puts "#{i}\t#{l}" }
  end
  printf 'Select title line number:' unless @options[:auto]
  title = choose(@content, print: false)

  printf 'Select author line number:' unless @options[:auto]
  authors = choose(@content, print: false)

  puts 'Select author form:' unless @options[:auto]
  author = gen_authors(authors)

  [title, author, gen_year]
end

#puts(*x) ⇒ Object



17
# File 'lib/selector.rb', line 17

def puts(*x) = x

#sanitize_path_component(s) ⇒ Object

Filenames are built by combining year/title/author into a single path segment -- strip path separators so a "/" in a title (manually picked or fetched from an external source) can't turn File.rename into a move into a different (likely non-existent) directory.



102
103
104
# File 'lib/selector.rb', line 102

def sanitize_path_component(s)
  s.to_s.gsub(%r{[/\\]}, '-')
end

#select_allObject



27
28
29
30
31
32
33
34
# File 'lib/selector.rb', line 27

def select_all
  title, author, year =  unless @options[:no_lookup]
  title, author, year =  if title.nil?

  forms = gen_forms(year, title, author)
  @metadata = { year: year, title: title, author: author }
  @title = forms[@options[:format]]
end