glibrary 1.0.1 → 1.1.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: 55ce83446d6daacc5d6f6091297bb24052103e5069c82a99aa5d3bf99b48abfd
4
- data.tar.gz: a4f28c9a651a3bf86910810657828d850460682c602dcb37e13c1b6aee818776
3
+ metadata.gz: c6fe6f6ce56c501c33ad281b7d6acc4b2fc32d3a39e522a06d95044bdffb2212
4
+ data.tar.gz: 0106ee481b834da946078dca94cc28a3ae64705944b588005dfbe4930dadae5c
5
5
  SHA512:
6
- metadata.gz: bac4fc64f4a08fbe330471f501b0000662eba38886503c324404cf2caafe5e9bb6095d16a34e719755baab43d9ef05d333c3f5c845f52898c144d0777c94acf6
7
- data.tar.gz: 5293efc330c583482c989c904ab6adf70321e6f832cb10dacf2477624c38b8fb37f2a8fdb826aa28126b6531b1c84328ea4c0c15b3b4075fa692de703367cc10
6
+ metadata.gz: 6ddacb58256ab459b1028e76b81ce4d848a4cfefd6003f914780dd879f50fafbba025d1416dc353fe3ba8c1e4b472a4239af45bae72123723d46b0b539659383
7
+ data.tar.gz: 88bb81b0bf751f001f287474553fa76ff71cf3d97c7f87e129b709cf86bc5c506eb3151a15bf43537807755887d4f570912cc063faa313ebc8f8fddd2b8ebef9
@@ -3,51 +3,46 @@ require 'json'
3
3
  require 'io/console'
4
4
 
5
5
  require_relative '../modules/api_query'
6
- require_relative '../modules/command_line_parse'
7
- require_relative '../modules/errors'
8
- require_relative '../modules/error_handler'
9
- require_relative '../modules/exec_helper'
10
- require_relative '../modules/google_api_url'
11
- require_relative '../modules/user_prompt'
6
+ require_relative '../exec_helpers/command_line_parse'
7
+ require_relative '../globals/errors'
8
+ require_relative '../exec_helpers/error_handler'
9
+ require_relative '../exec_helpers/exec_helper'
10
+ require_relative '../globals/google_api_url'
11
+ require_relative '../exec_helpers/user_prompt'
12
12
 
13
13
  require_relative '../lib/book_search'
14
14
  require_relative '../lib/user_book'
15
15
  require_relative '../lib/user_library'
16
16
 
17
- include ExecHelper
18
- include UserPrompt
19
- include CommandLineParse
20
- include ErrorHandler
21
-
22
17
  CURRENT_DIR = File.join(File.dirname(__FILE__))
23
- DEFAULT_FILENAME = File.join File.expand_path("..", CURRENT_DIR), "saved_libraries", "library.json"
24
18
 
25
- process_args!
19
+ DEFAULT_FILENAME = File.join( File.expand_path("..", CURRENT_DIR),
20
+ "saved_libraries", "library.json" )
26
21
 
27
- @options = {}
28
- @filename = DEFAULT_FILENAME
29
- command_line_parse! #this function processes @filename and fills the @options hash.
22
+ process_args! # processes and modifies ARGV
23
+ filename = FileHelper.prepare(DEFAULT_FILENAME)
30
24
 
31
- prepare_filename_for_os!
25
+ options = get_cli_options
26
+ filename = options.delete(:filename) if options[:filename]
27
+ library_mode = options.delete(:library_mode)
32
28
 
33
- if library_mode?
29
+ if library_mode
34
30
 
35
31
  with_library_mode_error_handling do
36
- (@library = UserLibrary.new(filename: @filename)).pretty_print
37
- library_mode_user_prompt
32
+ user_library = UserLibrary.new(filename: filename)
33
+ library_mode_user_prompt(user_library)
38
34
  end
39
35
 
40
36
  else
41
37
 
42
38
  with_search_mode_error_handling do
43
- @persistent_library = UserLibrary.new(filename: @filename)
44
- @temp_booklist = UserLibrary.new(nonpersistent: true)
39
+ persistent_library = UserLibrary.new(filename: filename)
40
+ temp_booklist = UserLibrary.new(nonpersistent: true)
45
41
 
46
- search_results = perform_search
47
- search_results.selected_results.each { |info| @temp_booklist.add(UserBook.new(info)) }
48
- @temp_booklist.pretty_print
42
+ search_results = BookSearch.new(options)
43
+ search_results.selected.each { |info| temp_booklist.add(UserBook.new(info)) }
49
44
 
50
- search_mode_user_prompt
45
+ search_mode_user_prompt(temp_booklist, persistent_library)
51
46
  end
52
47
 
53
48
  end
@@ -0,0 +1,52 @@
1
+ require 'optparse'
2
+
3
+ def abort_library_mode
4
+ puts "Library file not found, cannot display."
5
+ exit
6
+ end
7
+
8
+ def print_help_message(opts)
9
+ puts ""
10
+ puts opts
11
+ puts "[query]: all other arguments will be treated as general search keywords"
12
+ puts ""
13
+ end
14
+
15
+ def get_cli_options
16
+ options = {}
17
+ OptionParser.new do |opts|
18
+ opts.banner = "Usage: glibrary [options...] [query]"
19
+
20
+ opts.on("-t", "--title=TITLE", "Specify a title keyword") do |t|
21
+ options[:title] = t
22
+ end
23
+
24
+ opts.on("-a", "--author=AUTHOR", "Specify an author keyword") do |a|
25
+ options[:author] = a
26
+ end
27
+
28
+ opts.on("-p", "--publisher=PUBLISHER", "Specify a publisher keyword") do |p|
29
+ options[:publisher] = p
30
+ end
31
+
32
+ opts.on("-f", "--lib-file=LIBFILE",
33
+ "Select a library save file. Otherwise, a default save file will be used.") do |libfile|
34
+ abort_library_mode if ARGV.include?("-l") && !File.exist?(libfile)
35
+ options[:filename] = libfile
36
+ end
37
+
38
+ opts.on("-l", "--library", "See your reading list; ignores all search options") do
39
+ return { filename: options[:filename], library_mode: true }
40
+ end
41
+
42
+ opts.on("-h", "--help", "Prints this help") do
43
+ print_help_message(opts)
44
+ exit
45
+ end
46
+ end.parse!
47
+
48
+ options[:search] = ARGV.join('+')
49
+
50
+ options
51
+ end
52
+
@@ -0,0 +1,35 @@
1
+ require_relative '../globals/errors'
2
+
3
+ def with_library_mode_error_handling
4
+ begin
5
+ yield
6
+ rescue UserQuits
7
+ puts "\nEnjoy your day."
8
+ rescue Errno::EACCES
9
+ puts "\nYou don't have permission to write to the file you specified. Quitting immediately"
10
+ puts ""
11
+ end
12
+ exit
13
+ end
14
+
15
+ def with_search_mode_error_handling
16
+ begin
17
+ yield
18
+ rescue UserQuits
19
+ puts "\nThanks for browsing. Library file saved"
20
+ puts ""
21
+ rescue Errno::EACCES
22
+ puts "\nYou don't have permission to write to the file you specified. Quitting immediately"
23
+ puts ""
24
+ rescue NoInternetError
25
+ puts "\nNo internet connection. Please connect to the internet and try again."
26
+ puts ""
27
+ rescue SearchError
28
+ puts "\nThere was an error with your query; be careful to format it well"
29
+ puts ""
30
+ rescue NoResults
31
+ puts "\nNo results."
32
+ puts ""
33
+ end
34
+ exit
35
+ end
@@ -0,0 +1,4 @@
1
+ def process_args!(args = ARGV)
2
+ args << '-h' if args.empty?
3
+ args << args.delete("-l") if args.include?("-l")
4
+ end
@@ -0,0 +1,78 @@
1
+ require_relative '../globals/errors'
2
+
3
+ def verify_selection(selection, regexp)
4
+ raise SelectionError unless selection =~ regexp
5
+ raise UserQuits if selection =~ /\A[Qq]\Z/
6
+ end
7
+
8
+ def process_selection(selection)
9
+ return selection.to_i - 1
10
+ end
11
+
12
+ def handle_successful_prompt_completion(selected_book)
13
+ puts ""
14
+ puts "The book \"#{selected_book['title']}\" has been added to your reading list."
15
+ end
16
+
17
+ def prompt(prompt, regexp, library, suppress = nil)
18
+ print prompt
19
+ s = suppress || STDIN.gets.strip
20
+ verify_selection(s, regexp)
21
+ s = process_selection(s)
22
+ raise NotABook unless s <= library.size
23
+ return s
24
+ end
25
+
26
+ def library_mode_user_prompt(lib)
27
+ while true
28
+ begin
29
+ lib.pretty_print
30
+
31
+ i = prompt( "Select a book number to delete, or type \"q\" to quit: ", /\A([0-9]+|[qQ])\Z/,
32
+ lib)
33
+
34
+ lib.delete(i)
35
+ lib.save
36
+
37
+ puts "Your library now looks like this."
38
+ puts ""
39
+ rescue SelectionError
40
+ puts "\nSorry, your selection was invalid. Please try again."
41
+ rescue NotABook
42
+ puts "\nSorry, your selection was invalid. Make sure your selection is in the provided range."
43
+ end
44
+ end
45
+ end
46
+
47
+
48
+ def search_mode_user_prompt(temp_booklist, persistent_library)
49
+
50
+ temp_booklist.pretty_print
51
+
52
+ while true
53
+ begin
54
+
55
+ i = prompt( "Enter a number (1-5) to add a book to your reading list (or q to quit): ",
56
+ /\A[1-5]|[qQ]\Z/, temp_booklist )
57
+ selected_book = temp_booklist[i]
58
+
59
+ persistent_library << selected_book
60
+ persistent_library.save
61
+
62
+ handle_successful_prompt_completion(selected_book)
63
+ puts "Would you like to add another?"
64
+ puts ""
65
+ rescue BookDuplicateError
66
+ puts "\nThat book is already in your reading list. Would you like to add another?"
67
+ puts ""
68
+ rescue SelectionError
69
+ puts "\nSorry, your selection was invalid. Please try again."
70
+ puts ""
71
+ rescue NotABook
72
+ puts "\nSorry, your selection was invalid. Make sure your selection is within the range of available options."
73
+ puts ""
74
+ end
75
+ end
76
+
77
+ end
78
+
@@ -0,0 +1,23 @@
1
+ class SearchError < StandardError
2
+ end
3
+
4
+ class BookDuplicateError < StandardError
5
+ end
6
+
7
+ class NoInternetError < StandardError
8
+ end
9
+
10
+ class NoResults < StandardError
11
+ end
12
+
13
+ class SelectionError < StandardError
14
+ end
15
+
16
+ class NotABook < StandardError
17
+ end
18
+
19
+ class UserQuits < StandardError
20
+ end
21
+
22
+ class PersistenceError < StandardError
23
+ end
File without changes
@@ -1,14 +1,14 @@
1
1
  require 'json'
2
2
  require_relative '../modules/api_query'
3
- require_relative '../modules/google_api_url'
4
- require_relative '../modules/errors'
3
+ require_relative '../globals/google_api_url'
4
+ require_relative '../globals/errors'
5
5
 
6
6
  class BookSearch
7
7
  include ApiQuery
8
8
  include Enumerable
9
- include Errors
9
+
10
10
 
11
- attr_reader :selected_results, :full_results, :url
11
+ attr_reader :selected, :full_results, :url
12
12
 
13
13
  def initialize(args)
14
14
  @args = args.dup
@@ -30,61 +30,61 @@ class BookSearch
30
30
  num = full_results['totalItems']
31
31
  raise NoResults unless num > 0
32
32
 
33
- @selected_results = full_results['items'].first(num_results)
34
- @selected_results.map! { |res| self.class.format_hash res }
33
+ @selected = full_results['items'].first(num_results)
34
+ @selected.map! { |res| self.class.format_hash res }
35
35
 
36
36
  end
37
37
 
38
38
  def each
39
39
  return to_enum :each unless block_given?
40
- selected_results.each { |r| yield(r) }
40
+ selected.each { |r| yield(r) }
41
41
  end
42
42
 
43
43
  def [](index)
44
- selected_results[index]
44
+ selected[index]
45
45
  end
46
46
 
47
47
  private
48
- class << self
49
- def make_url_arg_list(args)
50
- url = ["?q="]
48
+ class << self
51
49
 
52
- q = args.delete('search')
53
- url << q.to_s
54
-
55
- url << args.map do |k,v|
56
- k = ("in" + k) if %w[title author publisher].include?(k)
57
- "%s:%s" % [k, v]
50
+ def make_url(args)
51
+ (BASE_API_URL + make_url_arg_list(args)).gsub(/ /, "+")
58
52
  end
59
53
 
60
- url.reject!(&:empty?)
61
- url[0] + url[1, url.length-1].join("+")
62
- end
54
+ def make_url_arg_list(args)
55
+ url = ["?q="]
56
+
57
+ q = args.delete('search')
58
+ url << q.to_s
63
59
 
64
- def format_args(args)
65
- result = args.map { |k, v| [k,v].map(&:to_s) }.to_h
66
- result.reject! { |k, v| v.empty? }
67
- return result.to_h
68
- end
60
+ url << args.map do |k,v|
61
+ k = ("in" + k) if %w[title author publisher].include?(k)
62
+ "%s:%s" % [k, v]
63
+ end
69
64
 
70
- def searchable_arguments?(args)
71
- args.keys.any? do |k|
72
- %i[search title author publisher subject isbn lccn oclc].include?(k)
65
+ url.reject!(&:empty?)
66
+ url[0] + url[1, url.length-1].join("+")
73
67
  end
74
- end
75
68
 
69
+ def format_args(args)
70
+ result = args.map { |k, v| [k,v].map(&:to_s) }.to_h
71
+ result.reject! { |k, v| v.empty? }
72
+ return result.to_h
73
+ end
76
74
 
77
- def format_hash(hash)
78
- hash['volumeInfo'].merge( { 'id' => hash['id'] } )
79
- end
75
+ def searchable_arguments?(args)
76
+ args.keys.any? do |k|
77
+ %i[search title author publisher subject isbn lccn oclc].include?(k)
78
+ end
79
+ end
80
80
 
81
- def make_url(args)
82
- (BASE_API_URL + make_url_arg_list(args)).gsub(/ /, "+")
83
- end
81
+ def format_hash(hash)
82
+ hash['volumeInfo'].merge( { 'id' => hash['id'] } )
83
+ end
84
84
 
85
- def args
86
- @args
87
- end
85
+ def args
86
+ @args
87
+ end
88
88
  end
89
89
 
90
90
  end
@@ -1,8 +1,8 @@
1
1
  require 'json'
2
- require_relative '../modules/errors'
2
+ require_relative '../globals/errors'
3
3
 
4
4
  class UserBook
5
- include Errors
5
+
6
6
 
7
7
  attr_accessor :title, :publisher, :info, :id
8
8
 
@@ -1,13 +1,12 @@
1
1
  require 'json'
2
- require_relative '../modules/errors'
3
- require_relative '../modules/exec_helper'
2
+ require_relative '../globals/errors'
3
+ require_relative '../modules/file_helper'
4
4
  require_relative 'user_book'
5
5
 
6
6
 
7
7
  class UserLibrary
8
8
  include Enumerable
9
- include ExecHelper
10
- include Errors
9
+
11
10
 
12
11
  attr_reader :books, :filename
13
12
 
@@ -96,13 +95,11 @@ class UserLibrary
96
95
 
97
96
  def set_filename(name)
98
97
  @nonpersistent = false
99
- @filename = name
100
- prepare_filename_for_os!
98
+ @filename = FileHelper.prepare(name)
101
99
  end
102
100
 
103
101
  def determine_filename!
104
- @filename = File.absolute_path(@filename)
105
- prepare_filename_for_os!
102
+ @filename = FileHelper.prepare(@filename)
106
103
  end
107
104
 
108
105
  def get_raw_JSON_data
@@ -0,0 +1,14 @@
1
+ require_relative '../globals/errors'
2
+
3
+ module FileHelper
4
+ def self.prepare_for_os(filename)
5
+ ENV.values.any? { |v| v =~ /[A-Z]:\\Windows/i } ?
6
+ filename.gsub(/\//, '\\') : filename
7
+ end
8
+
9
+ def self.prepare(filename)
10
+ filename = File.absolute_path(filename)
11
+ FileHelper.prepare_for_os(filename)
12
+ end
13
+
14
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glibrary
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Engelbert
@@ -19,16 +19,17 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - bin/glibrary
22
+ - exec_helpers/command_line_parse.rb
23
+ - exec_helpers/error_handler.rb
24
+ - exec_helpers/exec_helper.rb
25
+ - exec_helpers/user_prompt.rb
26
+ - globals/errors.rb
27
+ - globals/google_api_url.rb
22
28
  - lib/book_search.rb
23
29
  - lib/user_book.rb
24
30
  - lib/user_library.rb
25
31
  - modules/api_query.rb
26
- - modules/command_line_parse.rb
27
- - modules/error_handler.rb
28
- - modules/errors.rb
29
- - modules/exec_helper.rb
30
- - modules/google_api_url.rb
31
- - modules/user_prompt.rb
32
+ - modules/file_helper.rb
32
33
  - saved_libraries/.gitkeep
33
34
  homepage: https://github.com/pmengelbert/g_library
34
35
  licenses:
@@ -38,6 +39,8 @@ post_install_message:
38
39
  rdoc_options: []
39
40
  require_paths:
40
41
  - modules
42
+ - exec_helpers
43
+ - globals
41
44
  - saved_libraries
42
45
  - lib
43
46
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -1,55 +0,0 @@
1
- require_relative 'errors'
2
-
3
- module CommandLineParse
4
- require 'optparse'
5
- include Errors
6
-
7
- def handle_nonexistent_file
8
- (puts "Library file not found, cannot display."; exit)
9
- puts "Creating new file"
10
- end
11
-
12
- def print_help_message(opts)
13
- puts ""
14
- puts opts
15
- puts "[query]: all other arguments will be treated as general search keywords"
16
- puts ""
17
- end
18
-
19
- def command_line_parse!
20
- OptionParser.new do |opts|
21
- opts.banner = "Usage: glibrary [options...] [query]"
22
-
23
- opts.on("-t", "--title=TITLE", "Specify a title keyword") do |t|
24
- @options[:title] = t
25
- end
26
-
27
- opts.on("-a", "--author=AUTHOR", "Specify an author keyword") do |a|
28
- @options[:author] = a
29
- end
30
-
31
- opts.on("-p", "--publisher=PUBLISHER", "Specify a publisher keyword") do |p|
32
- @options[:publisher] = p
33
- end
34
-
35
- opts.on("-f", "--lib-file=LIBFILE",
36
- "Select a library save file. Otherwise, a default save file will be used.") do |libfile|
37
- @filename = File.absolute_path(libfile)
38
- handle_nonexistent_file if ARGV.include?("-l") && !File.exist?(@filename)
39
- end
40
-
41
- opts.on("-l", "--library", "See your reading list; ignores all search options") do
42
- @options = nil
43
- return
44
- end
45
-
46
- opts.on("-h", "--help", "Prints this help") do
47
- print_help_message(opts)
48
- exit
49
- end
50
- end.parse!
51
-
52
- @options[:search] = ARGV.join('+')
53
-
54
- end
55
- end
@@ -1,38 +0,0 @@
1
- require_relative 'errors'
2
-
3
- module ErrorHandler
4
- def with_library_mode_error_handling
5
- begin
6
- yield
7
- rescue UserQuits
8
- puts "\nEnjoy your day."
9
- rescue Errno::EACCES
10
- puts "\nYou don't have permission to write to the file you specified. Quitting immediately"
11
- puts ""
12
- end
13
- exit
14
- end
15
-
16
- def with_search_mode_error_handling
17
- begin
18
- yield
19
- rescue UserQuits
20
- puts "\nThanks for browsing. Library file saved"
21
- puts ""
22
- rescue Errno::EACCES
23
- puts "\nYou don't have permission to write to the file you specified. Quitting immediately"
24
- puts ""
25
- rescue NoInternetError
26
- puts "\nNo internet connection. Please connect to the internet and try again."
27
- puts ""
28
- rescue SearchError
29
- puts "\nThere was an error with your query; be careful to format it well"
30
- puts ""
31
- rescue NoResults
32
- puts "\nNo results."
33
- puts ""
34
- end
35
- exit
36
- end
37
-
38
- end
@@ -1,25 +0,0 @@
1
- module Errors
2
- class SearchError < StandardError
3
- end
4
-
5
- class BookDuplicateError < StandardError
6
- end
7
-
8
- class NoInternetError < StandardError
9
- end
10
-
11
- class NoResults < StandardError
12
- end
13
-
14
- class SelectionError < StandardError
15
- end
16
-
17
- class NotABook < StandardError
18
- end
19
-
20
- class UserQuits < StandardError
21
- end
22
-
23
- class PersistenceError < StandardError
24
- end
25
- end
@@ -1,24 +0,0 @@
1
- require_relative 'errors'
2
-
3
- module ExecHelper
4
- include Errors
5
-
6
- def process_args!(args = ARGV)
7
- args << '-h' if args.empty?
8
- args << args.delete("-l") if args.include?("-l")
9
- end
10
-
11
- def library_mode?
12
- @options.nil?
13
- end
14
-
15
- def prepare_filename_for_os!
16
- @filename.gsub!(/\//, '\\') if ENV.values.any? { |v| v =~ /[A-Z]:\\Windows/i }
17
- end
18
-
19
- def perform_search
20
- search = @options[:search] || ARGV.join('+')
21
- s = BookSearch.new(search: search, title: @options[:title], author: @options[:author],
22
- publisher: @options[:publisher])
23
- end
24
- end
@@ -1,75 +0,0 @@
1
- require_relative 'errors'
2
-
3
- module UserPrompt
4
- include Errors
5
-
6
- def verify_selection(selection, regexp)
7
- raise SelectionError unless selection =~ regexp
8
- raise UserQuits if selection =~ /\A[Qq]\Z/
9
- end
10
-
11
- def process_selection(selection)
12
- return selection.to_i - 1
13
- end
14
-
15
- def handle_successful_prompt_completion(selected_book)
16
- puts ""
17
- puts "The book \"#{selected_book['title']}\" has been added to your reading list."
18
- end
19
-
20
- def prompt(prompt, regexp, library, suppress = nil)
21
- print prompt
22
- s = suppress || STDIN.gets.strip
23
- verify_selection(s, regexp)
24
- s = process_selection(s)
25
- raise NotABook unless s <= library.size
26
- return s
27
- end
28
-
29
- def library_mode_user_prompt
30
- while true
31
- begin
32
- i = prompt( "Select a book number to delete, or type \"q\" to quit: ", /\A([0-9]+|[qQ])\Z/,
33
- @library )
34
-
35
- @library.delete(i)
36
- @library.save
37
- @library.pretty_print
38
-
39
- puts "Your library now looks like this."
40
- puts ""
41
- rescue SelectionError
42
- puts "\nSorry, your selection was invalid. Please try again."
43
- rescue NotABook
44
- puts "\nSorry, your selection was invalid. Make sure your selection is in the provided range."
45
- end
46
- end
47
- end
48
-
49
-
50
- def search_mode_user_prompt
51
- while true
52
- begin
53
- i = prompt( "Enter a number (1-5) to add a book to your reading list (or q to quit): ",
54
- /\A[1-5]|[qQ]\Z/, @temp_booklist )
55
- selected_book = @temp_booklist[i]
56
-
57
- @persistent_library << selected_book
58
- @persistent_library.save
59
-
60
- handle_successful_prompt_completion(selected_book)
61
- puts "Would you like to add another?"
62
- puts ""
63
- rescue BookDuplicateError
64
- puts "\nThat book is already in your reading list. Would you like to add another?"
65
- puts ""
66
- rescue SelectionError
67
- puts "\nSorry, your selection was invalid. Please try again."
68
- puts ""
69
- rescue NotABook
70
- puts "\nSorry, your selection was invalid. Make sure your selection is within the range of available options."
71
- puts ""
72
- end
73
- end
74
- end
75
- end