rhymera 0.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.
@@ -0,0 +1,37 @@
1
+ # Rhymera
2
+
3
+ Rhymera is a CLI gem to search the [RhymeBrain](https://rhymebrain.com) API for rhymes and portmanteaus of a given query. Menus give you the option to start a new search with the result, look through previous searches, or copy a result to the clipboard.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'rhymera'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rhymera
20
+
21
+ ## Usage
22
+
23
+ Execute `rhymera`. After searching a query and choosing which type of search to conduct, you can find more information about each result in the menus.
24
+
25
+ ## Development
26
+
27
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
28
+
29
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
30
+
31
+ ## Contributing
32
+
33
+ Bug reports and pull requests are welcome on GitHub at https://github.com/revarcline/rhymera.
34
+
35
+ ## License
36
+
37
+ Licensed under GPL 3.0, See LICENSE for details.
@@ -0,0 +1,101 @@
1
+ RHYMERA
2
+ ===
3
+ for api/scraper calls
4
+ [RhymeBrain](https://rhymebrain.com) for rhymes and portmanteaus
5
+ [clipboard](https://github.com/janlelis/clipboard) to copy result to clipboard
6
+
7
+ HEY OK DITCHING CLI/UI BECAUSE THEN YOU WON'T NEED THE DAMN HASH
8
+ like then you can just return objects
9
+ as cool as interactivity is it's not what they're looking for
10
+
11
+ make sure you go back to initializing list as array!
12
+
13
+ please research how to
14
+ a) take args from cli
15
+ b) paginate (should be easy) (also, its own method)
16
+
17
+
18
+ should probably review revision history of this document for blog post
19
+ of note:
20
+ initially wanted to add in scraper for OneLook but it was unscrapable (no js)
21
+ tried building with cli-ui gem from shopify so i could get a nice interactive prompt
22
+ however returning a string hobbled this - if i could understand the handlers better, maybe?
23
+
24
+ this way i can generate my list by iterating through each object enumerable
25
+
26
+ maybe switch to [TTY::Prompt](https://github.com/piotrmurach/tty-prompt)
27
+ i can keep my objects as arrays (clean, no redundancy)
28
+ and make my menus return the object value itself!
29
+ should be able to do this as a block!
30
+
31
+ ok! so blogpost about "picking the right depedencies"
32
+ - shopify's looked pretty fresh, liked the vi-keys functionality
33
+ - only returned string value though, meaning i would need to do some dumb iterations
34
+ - tty-prompt allowed me to more easily pass a hash
35
+
36
+ ## basic outline:
37
+
38
+ present with
39
+ "Enter a word"
40
+ or "quit"
41
+
42
+ then, choose
43
+ 1) rhyme
44
+ (type: getRhymes)
45
+ 2) portmanteaus
46
+ (type: getPortmanteaus)
47
+
48
+ get a list of results back (possibly limit or paginate?)
49
+
50
+
51
+ detail view, common (module?)
52
+ - copy to clipboard
53
+ - search using word as query
54
+ - search previous query
55
+ - search a new query
56
+ - back to list
57
+
58
+ detail view - rhyme
59
+ word
60
+ number of syllables
61
+
62
+ detail view - portmanteau
63
+ portmanteau (actually spelling[0])
64
+ root word 1
65
+ root word 2 (selectable with common menu)
66
+ alternative (spelling[1] if spelling[1])
67
+ - selectable and switches with portmanteau name on selection (incl searchability)
68
+
69
+ ## classes (and tests):
70
+
71
+ ### Rhymera
72
+ - creates menu
73
+ - do i make everything extend it so i can call it from other stuff?
74
+
75
+ ### Menu
76
+ - handles choices, relies on `TTY::Prompt`
77
+ - send word to clipboard with `Clipboard`
78
+ - displays `List` object as selectable menu
79
+ - also: search new word/previous search/search {other type}
80
+ - selecting `Rhyme` or `Portmanteau` entry shows relevant details, option to search
81
+
82
+ ### List
83
+ - init with type (rhyme or port) and query
84
+ - has many `Rhyme`, `Portmanteau`
85
+ - collects the prior for display from a rhymebrain call
86
+ - class instance variable with prior queries!
87
+
88
+ ### Rhyme
89
+ - contains each rhyme entry from json object
90
+ - syllables
91
+
92
+ ### Portmanteau
93
+ - contains each portmanteau entry from json object
94
+ - spelling (array of one or two)
95
+ - source 1
96
+ - source 2
97
+ test:
98
+ make sure it parses input correctly, and `:alternative` is conditional on original object
99
+
100
+ ### RhymeBrain
101
+ - uses input to structure api, scrapes rhymebrain results page, returns json
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ task default: :test
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'rhymera'
6
+ require_relative '../config/environment'
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+
11
+ # (If you use this, don't forget to add pry to your Gemfile!)
12
+ # require "pry"
13
+ # Pry.start
14
+
15
+ require 'irb'
16
+ IRB.start(__FILE__)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/rhymera'
4
+ Rhymera::Menu.new.call
data/bin/run ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'rhymera'
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'rhymera/version'
4
+ require_relative 'rhymera/menu'
5
+ require_relative 'rhymera/list'
6
+ require_relative 'rhymera/rhymebrain'
7
+ require_relative 'rhymera/rhyme'
8
+ require_relative 'rhymera/portmanteau'
9
+
10
+ module Rhymera
11
+ class Error < StandardError; end
12
+ end
@@ -0,0 +1,50 @@
1
+ module Rhymera
2
+ # container for lists of Rhyme and Portmanteau
3
+ class List
4
+ attr_reader :query, :type, :object
5
+ attr_accessor :entries
6
+
7
+ @all = []
8
+
9
+ # using class instance variable instead of class variable per rubocop
10
+ class << self
11
+ attr_accessor :all
12
+ end
13
+
14
+ def initialize(function:, word:)
15
+ @object = Rhymera::RhymeBrain.query(function: function, word: word)
16
+ @query = word
17
+ @type = function
18
+ @entries = []
19
+ build_correct_type
20
+
21
+ # add to all hash
22
+ self.class.all << self
23
+ end
24
+
25
+ def build_correct_type
26
+ case @type
27
+ when 'getRhymes'
28
+ create_rhymes
29
+ when 'getPortmanteaus'
30
+ create_portmanteaus
31
+ end
32
+ end
33
+
34
+ def create_portmanteaus
35
+ @object.each do |entry|
36
+ port = Rhymera::Portmanteau.new(source: entry['source'],
37
+ combined: entry['combined'])
38
+ entries << port
39
+ end
40
+ end
41
+
42
+ def create_rhymes
43
+ @object.each do |entry|
44
+ rhyme = Rhymera::Rhyme.new(word: entry['word'],
45
+ syllables: entry['syllables'])
46
+ entries << rhyme
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,82 @@
1
+ require 'clipboard'
2
+ require 'tty-prompt'
3
+
4
+ module Rhymera
5
+ # menu handler
6
+ class Menu
7
+ attr_accessor :list, :result, :word, :function
8
+ attr_reader :prompt
9
+
10
+ def initialize
11
+ @prompt = TTY::Prompt.new
12
+ # print once on intialization
13
+ puts 'Welcome to Rhymera.'
14
+ end
15
+
16
+ def call
17
+ @word = prompt.ask("Please enter a search term or :q to quit.\n>")
18
+ call if @word == ''
19
+ # vim-style quit, seems best
20
+ exit(0) if @word == ':q'
21
+ search(@word)
22
+ end
23
+
24
+ def search(term)
25
+ # can be called again and again!
26
+ @word = term
27
+ @function = search_type
28
+ @list = Rhymera::List.new(word: @word, function: "get#{@function}")
29
+ display_results
30
+ end
31
+
32
+ def search_type
33
+ prompt.select('Which type of result are you looking for?',
34
+ %w[Rhymes Portmanteaus])
35
+ end
36
+
37
+ def display_results
38
+ # can be called both by search and previous entries
39
+ results = extra_menu_entries
40
+ results << @list.entries.map { |ent| { ent.word.to_s => ent } }
41
+ result = prompt.select("#{@function} for '#{@word}' and other options:", results)
42
+
43
+ @word = result.word
44
+ detail_view(result)
45
+ end
46
+
47
+ def extra_menu_entries
48
+ # options leading to lambas! we love lambdas, don't we folks
49
+ [{ "Copy '#{@word}' to Clipboard" => -> { Clipboard.copy(@word) } },
50
+ { "Search '#{@word}'" => -> { search(@word) } },
51
+ { 'New Search' => -> { call } },
52
+ { 'Previous Searches' => -> { old_searches } },
53
+ { 'Quit Program' => -> { exit(0) } }]
54
+ end
55
+
56
+ def detail_view(object)
57
+ menu = extra_menu_entries
58
+ # iterate through attrs of a given Rhyme or Portmanteau for display
59
+ object.instance_variables.each do |var|
60
+ arg = var.to_s.gsub('@', '')
61
+ word = object.send(arg)
62
+ menu << { "#{arg.capitalize}: #{word}" => word }
63
+ end
64
+ opts = prompt.select("More details on #{@word}:", menu)
65
+
66
+ @word = opts
67
+ prompt.select("More details on #{@word}:", extra_menu_entries)
68
+ end
69
+
70
+ def old_searches
71
+ # here's one of the ol' class methods
72
+ lists = Rhymera::List.all.map do |list|
73
+ { "#{list.type[3..]} for #{list.query}" => list }
74
+ end
75
+ selection = prompt.select('Previous searches:', lists)
76
+ @list = selection
77
+ @function = selection.type[3..]
78
+ @word = selection.query
79
+ display_results
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,15 @@
1
+ module Rhymera
2
+ # converts RhymeBrain json data to object
3
+ class Portmanteau
4
+ attr_reader :prefix, :suffix, :word, :alternative
5
+
6
+ def initialize(source:, combined:)
7
+ source_words = source.split(',')
8
+ combined_words = combined.split(',')
9
+ @prefix = source_words[0]
10
+ @suffix = source_words[1]
11
+ @word = combined_words[0]
12
+ @alternative = combined_words[1] if combined_words[1]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Rhymera
2
+ # converts RhymeBrain json to object
3
+ class Rhyme
4
+ attr_reader :word, :syllables
5
+
6
+ def initialize(word:, syllables:)
7
+ @word = word
8
+ @syllables = syllables
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module Rhymera
5
+ # calls Rhymebrain API via URL, gets JSON object
6
+ class RhymeBrain
7
+ def self.query(function:, word:)
8
+ uri = URI.parse("https://rhymebrain.com/talk?function=#{function}&word=#{word}")
9
+ JSON.parse(Net::HTTP.get(uri))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rhymera
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/rhymera/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rhymera'
7
+ spec.version = Rhymera::VERSION
8
+ spec.authors = ['Alex Cline']
9
+ spec.email = ['rev.a.r.cline@gmail.com']
10
+
11
+ spec.summary = 'rhyme and portmanteau generator'
12
+ spec.description = 'uses RhymeBrain api to find rhymes and portmanteaus'
13
+ spec.homepage = 'https://github.com/revarcline/rhymera'
14
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.6.1')
15
+
16
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
+
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = 'https://github.com/revarcline/rhymera.git'
20
+ spec.metadata['changelog_uri'] = 'https://github.com/revarcline/rhymera/blob/main/CHANGELOG.md'
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
+ end
27
+ spec.bindir = 'bin'
28
+ spec.executables = %w[rhymera]
29
+ spec.require_paths = %w[lib bin]
30
+
31
+ # Uncomment to register a new dependency of your gem
32
+ # spec.add_dependency "example-gem", "~> 1.0"
33
+ spec.add_dependency 'clipboard', '~> 1.3'
34
+ spec.add_dependency 'tty-prompt', '~> 0.23'
35
+
36
+ spec.add_development_dependency 'bundler', '~> 2.2'
37
+ spec.add_development_dependency 'pry'
38
+ spec.add_development_dependency 'rake', '~> 13.0'
39
+ spec.add_development_dependency 'rspec', '~> 3.9'
40
+
41
+ # For more information and examples about making a new gem, checkout our
42
+ # guide at: https://bundler.io/guides/creating_gem.html
43
+ end
@@ -0,0 +1,31 @@
1
+ require 'tty-prompt'
2
+ require_relative 'lib/rhymera'
3
+ prompt = TTY::Prompt.new
4
+ port_list = Rhymera::List.new(function: 'getPortmanteaus', word: 'fancy')
5
+
6
+ prompt.yes?('is this working?')
7
+
8
+ prompt.select('Select a result for more info',
9
+ port_list.entries.map(&:word))
10
+
11
+ object = prompt.select('Select a result for more info',
12
+ port_list.entries.map { |entry| { entry.word.to_s => entry } })
13
+
14
+ object.instance_variables
15
+
16
+ object.instance_variables.first.to_s.gsub('@', '')
17
+
18
+ object.source_one
19
+
20
+ object.instance_variables.each do |var|
21
+ arg = var.to_s.gsub('@', '')
22
+ puts "#{arg.capitalize}: #{object.send(arg)}"
23
+ end
24
+
25
+ Rhymera::List.all
26
+
27
+ Rhymera::List.all.first.class.to_s.split('::')[1]
28
+ Rhymera::List.all.first.entries.first.word
29
+
30
+ Rhymera::List.all.first.query
31
+ Rhymera::List.all.first.type[3..]