spoonerize 0.0.5

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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +24 -0
  3. data/.gitignore +1 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +21 -0
  6. data/README.md +106 -0
  7. data/Rakefile +19 -0
  8. data/_config.yml +1 -0
  9. data/bin/spoonerize +5 -0
  10. data/doc/README_md.html +200 -0
  11. data/doc/Spoonerize/Bumper.html +287 -0
  12. data/doc/Spoonerize/Cli.html +544 -0
  13. data/doc/Spoonerize/Log.html +362 -0
  14. data/doc/Spoonerize/Spoonerism.html +590 -0
  15. data/doc/Spoonerize.html +125 -0
  16. data/doc/created.rid +8 -0
  17. data/doc/css/fonts.css +167 -0
  18. data/doc/css/rdoc.css +619 -0
  19. data/doc/fonts/Lato-Light.ttf +0 -0
  20. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  21. data/doc/fonts/Lato-Regular.ttf +0 -0
  22. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  23. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  24. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  25. data/doc/images/add.png +0 -0
  26. data/doc/images/arrow_up.png +0 -0
  27. data/doc/images/brick.png +0 -0
  28. data/doc/images/brick_link.png +0 -0
  29. data/doc/images/bug.png +0 -0
  30. data/doc/images/bullet_black.png +0 -0
  31. data/doc/images/bullet_toggle_minus.png +0 -0
  32. data/doc/images/bullet_toggle_plus.png +0 -0
  33. data/doc/images/date.png +0 -0
  34. data/doc/images/delete.png +0 -0
  35. data/doc/images/find.png +0 -0
  36. data/doc/images/loadingAnimation.gif +0 -0
  37. data/doc/images/macFFBgHack.png +0 -0
  38. data/doc/images/package.png +0 -0
  39. data/doc/images/page_green.png +0 -0
  40. data/doc/images/page_white_text.png +0 -0
  41. data/doc/images/page_white_width.png +0 -0
  42. data/doc/images/plugin.png +0 -0
  43. data/doc/images/ruby.png +0 -0
  44. data/doc/images/tag_blue.png +0 -0
  45. data/doc/images/tag_green.png +0 -0
  46. data/doc/images/transparent.png +0 -0
  47. data/doc/images/wrench.png +0 -0
  48. data/doc/images/wrench_orange.png +0 -0
  49. data/doc/images/zoom.png +0 -0
  50. data/doc/index.html +203 -0
  51. data/doc/js/darkfish.js +84 -0
  52. data/doc/js/navigation.js +105 -0
  53. data/doc/js/navigation.js.gz +0 -0
  54. data/doc/js/search.js +110 -0
  55. data/doc/js/search_index.js +1 -0
  56. data/doc/js/search_index.js.gz +0 -0
  57. data/doc/js/searcher.js +229 -0
  58. data/doc/js/searcher.js.gz +0 -0
  59. data/doc/table_of_contents.html +242 -0
  60. data/lib/config/lazy_words.yml +21 -0
  61. data/lib/spoonerize/bumper.rb +61 -0
  62. data/lib/spoonerize/cli.rb +158 -0
  63. data/lib/spoonerize/log.rb +68 -0
  64. data/lib/spoonerize/spoonerism.rb +166 -0
  65. data/lib/spoonerize/version.rb +5 -0
  66. data/lib/spoonerize.rb +21 -0
  67. data/pkg/spoonerize-0.0.7.gem +0 -0
  68. data/spoonerize.gemspec +38 -0
  69. metadata +154 -0
@@ -0,0 +1,158 @@
1
+ require 'optparse'
2
+ require 'yaml'
3
+
4
+ module Spoonerize
5
+ ##
6
+ # The class for handling the command-line interface.
7
+ class Cli
8
+
9
+ ##
10
+ # The preferences file the user can create to change runtime options.
11
+ #
12
+ # @return [String]
13
+ PREFERENCE_FILE =
14
+ File.expand_path(File.join(ENV['HOME'], '.spoonerize.yml')).freeze
15
+
16
+ ##
17
+ # Creates an instance of +StandupMD+ and runs what the user requested.
18
+ #
19
+ # @param [Array] options
20
+ def self.execute(options = [])
21
+ exe = new(options)
22
+
23
+ if exe.print?
24
+ exe.print_log
25
+ return
26
+ end
27
+
28
+ puts exe.spoonerism.to_s
29
+ exe.print_mappings if exe.map?
30
+
31
+ if exe.save?
32
+ puts "Saving..."
33
+ exe.spoonerism.save
34
+ end
35
+ end
36
+
37
+ ##
38
+ # Arguments passed at runtime.
39
+ #
40
+ # @return [Array] ARGV
41
+ attr_reader :options
42
+
43
+ ##
44
+ # Preferences after reading config file and parsing ARGV.
45
+ #
46
+ # @return [Array]
47
+ attr_reader :preferences
48
+
49
+ ##
50
+ # Create instance of +Cli+
51
+ #
52
+ # @param [Array] options
53
+ #
54
+ # @return [self]
55
+ def initialize(options)
56
+ @map = false
57
+ @save = false
58
+ @print = false
59
+ @options = options
60
+ @preferences = get_preferences
61
+ end
62
+
63
+ ##
64
+ # Sets up an instance of +Spoonerize::Spoonerism+ and passes all user
65
+ # preferences.
66
+ #
67
+ # @return [Spoonerize::Spoonerism]
68
+ def spoonerism
69
+ @spoonerism ||= ::Spoonerize::Spoonerism.new(options) do |s|
70
+ preferences.each { |k, v| s.send("#{k}=", v) }
71
+ end
72
+ end
73
+
74
+ ##
75
+ # Should we save to the log file?
76
+ #
77
+ # @return [Boolean]
78
+ def save?
79
+ @save
80
+ end
81
+
82
+ ##
83
+ # Should we print the mappings to the command line?
84
+ #
85
+ # @return [Boolean]
86
+ def map?
87
+ @map
88
+ end
89
+
90
+ ##
91
+ # Should we print to the command line?
92
+ #
93
+ # @return [Boolean]
94
+ def print?
95
+ @print
96
+ end
97
+
98
+ ##
99
+ # The length of the longest word in the phrase.
100
+ #
101
+ # @return [Integer]
102
+ def longest_word_length
103
+ @longest_word_length ||=
104
+ spoonerism.spoonerize.group_by(&:size).max.first.size
105
+ end
106
+
107
+ ##
108
+ # Print the log file contents to the command line.
109
+ #
110
+ # @return [nil]
111
+ def print_log
112
+ s = Spoonerize::Log.new(spoonerism.logfile_name)
113
+ s.each { |row| print row.join(' | ') + "\n" }
114
+ end
115
+
116
+ ##
117
+ # Print the hash of mappings to the command line.
118
+ #
119
+ # @return [nil]
120
+ def print_mappings
121
+ spoonerism.to_h.each do |k, v|
122
+ puts "%-#{longest_word_length}s => %s" % [k, v]
123
+ end
124
+ end
125
+
126
+ private
127
+
128
+ ##
129
+ # Read in args and set options
130
+ def get_preferences # :nodoc:
131
+ prefs = {}
132
+ OptionParser.new do |o|
133
+ o.version = ::Spoonerize::VERSION
134
+ o.on('-r', '--[no-]reverse', 'Reverse flipping') do |v|
135
+ prefs['reverse'] = v
136
+ end
137
+ o.on('-l', '--[no-]lazy', 'Skip small words') do |v|
138
+ prefs['lazy'] = v
139
+ end
140
+ o.on('-m', '--[no-]map', 'Print words mapping') do |v|
141
+ @map = v
142
+ end
143
+ o.on('-p', '--[no-]print', 'Print all entries in the log') do |v|
144
+ @print = v
145
+ end
146
+ o.on('-s', '--[no-]save', 'Save results in log') do |v|
147
+ @save = v
148
+ end
149
+ o.on('--exclude=WORDS', Array, 'Words to skip') do |v|
150
+ prefs['exclude'] = v
151
+ end
152
+ end.parse!(options)
153
+
154
+ (File.file?(PREFERENCE_FILE) ? YAML.load_file(PREFERENCE_FILE) : {})
155
+ .merge(prefs)
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,68 @@
1
+ require 'csv'
2
+ require 'fileutils'
3
+
4
+ module Spoonerize
5
+ ##
6
+ # Class that handles reading/writing logs.
7
+ class Log
8
+
9
+ ##
10
+ # The file name to use.
11
+ #
12
+ # @return [String]
13
+ attr_reader :file
14
+
15
+ ##
16
+ # The directory the file is located.
17
+ #
18
+ # @return [String]
19
+ attr_reader :directory
20
+
21
+ ##
22
+ # Constructor for Log.
23
+ #
24
+ # @param [String] file
25
+ #
26
+ # @return [Spoonerize::Log]
27
+ def initialize(file)
28
+ @file = File.expand_path(file)
29
+ @directory = File.dirname(file)
30
+ FileUtils.mkdir_p(directory) unless File.directory?(directory)
31
+ FileUtils.touch(file) unless File.file?(file)
32
+ end
33
+
34
+ ##
35
+ # The contents of the log file.
36
+ #
37
+ # @return [Array]
38
+ def contents
39
+ ::CSV.read(file)
40
+ end
41
+
42
+ ##
43
+ # Writes a line to the log.
44
+ #
45
+ # @param [Array] row
46
+ #
47
+ # @return [Array]
48
+ def write(row)
49
+ ::CSV.open(file, 'a') { |csv| csv << row }
50
+ end
51
+
52
+ ##
53
+ # Iterate through each line of the file.
54
+ #
55
+ # @return [Array]
56
+ def each
57
+ contents.each { |row| yield row }
58
+ end
59
+
60
+ ##
61
+ # Number of entries in the file.
62
+ #
63
+ # @return [Integer]
64
+ def size
65
+ contents.size
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,166 @@
1
+ module Spoonerize
2
+ ##
3
+ # The main word-flipper.
4
+ class Spoonerism
5
+
6
+ ##
7
+ # The words originally passed at initialization.
8
+ #
9
+ # @return [Array]
10
+ attr_reader :words
11
+
12
+ ##
13
+ # This boolean determines if flipping should be performed lazily.
14
+ #
15
+ # @param [Boolean] true if should be lazy.
16
+ #
17
+ # @return [Boolean]
18
+ attr_writer :lazy
19
+
20
+ ##
21
+ # This boolean determines if flipping should be reversed.
22
+ #
23
+ # @param [Boolean] true if should be reversed.
24
+ #
25
+ # @return [Boolean]
26
+ attr_writer :reverse
27
+
28
+ ##
29
+ # The full path to the log file.
30
+ #
31
+ # @param [String] file
32
+ #
33
+ # @return [String]
34
+ attr_accessor :logfile_name
35
+
36
+ ##
37
+ # The words that are to be excluded.
38
+ #
39
+ # @param [Array] words
40
+ #
41
+ # @return [Array]
42
+ attr_accessor :excluded_words
43
+
44
+ ##
45
+ # Initialize instance and raise if there aren't enough words to flip.
46
+ #
47
+ # @param [Array] words
48
+ def initialize(words)
49
+ @excluded_words = []
50
+ @words = words.map(&:downcase)
51
+ @lazy = false
52
+ @reverse = false
53
+ @logfile_name = File.expand_path(
54
+ File.join(ENV['HOME'], '.cache', 'spoonerize', 'spoonerize.csv')
55
+ )
56
+ yield self if block_given?
57
+ end
58
+
59
+ ##
60
+ # Iterates through words array, and maps its elements to the output of
61
+ # flip_words. Returns results as an array.
62
+ def spoonerize
63
+ raise JakPibError, 'Not enough words to flip' unless enough_flippable_words?
64
+ words.map.with_index { |word, idx| flip_words(word, idx) }
65
+ end
66
+
67
+ ##
68
+ # Returns spoonerize array as a joined string.
69
+ def to_s
70
+ spoonerize.join(' ')
71
+ end
72
+
73
+ ##
74
+ # Returns hash of the original words mapped to their flipped counterparts.
75
+ def to_h
76
+ Hash[words.zip(spoonerize)]
77
+ end
78
+
79
+ ##
80
+ # Same as to_h, but as json.
81
+ def to_json
82
+ to_h.to_json
83
+ end
84
+
85
+ ##
86
+ # Returns true if there are more than one non-excluded word to flip
87
+ def enough_flippable_words?
88
+ (words - all_excluded_words).size > 1
89
+ end
90
+
91
+ ##
92
+ # Should the lazy words be excluded?
93
+ def lazy?
94
+ @lazy
95
+ end
96
+
97
+ ##
98
+ # Should the words flip the other direction?
99
+ def reverse?
100
+ @reverse
101
+ end
102
+
103
+ ##
104
+ # Saves the flipped words to the log file, along with the options
105
+ def save
106
+ log.write([words.join(' '), to_s, options.join(', ')])
107
+ end
108
+
109
+ ##
110
+ # Returns an array of words to exclude by combining three arrays:
111
+ # * Any word in the passed arguments that's only one character
112
+ # * Any user-passed words, stored in +excluded_words+
113
+ # * If lazy-mode, the LAZY_WORDS from yaml file are added
114
+ def all_excluded_words
115
+ (excluded_words + (lazy? ? LAZY_WORDS : [])).map(&:downcase)
116
+ end
117
+
118
+ private
119
+
120
+ ##
121
+ # Main flipping method. Creates the replacement word from the next
122
+ # non-excluded word's leading syllables, and the current word's first vowels
123
+ # through the end of the word.
124
+ def flip_words(word, idx) # :nodoc:
125
+ return word if excluded?(idx)
126
+ bumper = Bumper.new(idx, words.size, reverse?)
127
+ bumper.bump until !excluded?(bumper.value)
128
+ words[bumper.value].match(consonants).to_s + word.match(vowels).to_s
129
+ end
130
+
131
+ ##
132
+ # Returns true if word[index] is in the excluded_words array
133
+ def excluded?(index) # :nodoc:
134
+ all_excluded_words.include?(words[index])
135
+ end
136
+
137
+ ##
138
+ # Returns regex to match first vowels through the rest of the word
139
+ def vowels # :nodoc:
140
+ /((?<!q)u|[aeio]|(?<=[bcdfghjklmnprstvwxz])y).*$/
141
+ end
142
+
143
+ ##
144
+ # Returns regex to match leading consonants
145
+ def consonants # :nodoc:
146
+ /^(y|[bcdfghjklmnprstvwxz]+|qu)/
147
+ end
148
+
149
+ ##
150
+ # Creates and memoizes instance of the log file.
151
+ def log # :nodoc:
152
+ @log ||= Spoonerize::Log.new(logfile_name)
153
+ end
154
+
155
+ ##
156
+ # the options as a string
157
+ def options # :nodoc:
158
+ o = []
159
+ o << 'Lazy' if lazy?
160
+ o << 'Reverse' if reverse?
161
+ o << 'Exclude [%s]' % [all_excluded_words.join(', ')] if excluded_words.any?
162
+ o << 'No Options' if o.empty?
163
+ o
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,5 @@
1
+ module Spoonerize
2
+ ##
3
+ # The version of the gem.
4
+ VERSION = '0.0.5'
5
+ end
data/lib/spoonerize.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'yaml'
2
+ require_relative 'spoonerize/spoonerism'
3
+ require_relative 'spoonerize/bumper'
4
+ require_relative 'spoonerize/version'
5
+ require_relative 'spoonerize/log'
6
+ require_relative 'spoonerize/cli'
7
+
8
+ ##
9
+ # The main namespace for the gem.
10
+ module Spoonerize
11
+ ##
12
+ # The error exception raised when there are not enough flippable words.
13
+ JakPibError = Class.new(StandardError)
14
+
15
+ ##
16
+ # Excluded words from config files.
17
+ LAZY_WORDS = YAML.load_file(
18
+ File.join(File.dirname(__FILE__), 'config', 'lazy_words.yml')
19
+ ).freeze
20
+ end
21
+
Binary file
@@ -0,0 +1,38 @@
1
+ require_relative 'lib/spoonerize/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'spoonerize'
5
+ spec.version = Spoonerize::VERSION
6
+ spec.authors = ['Evan Gray']
7
+ spec.email = 'evanthegrayt@vivaldi.net'
8
+ spec.license = 'MIT'
9
+ spec.date = Time.now.strftime('%Y-%m-%d')
10
+
11
+ spec.summary = %q{Spoonerize phrases from the command line.}
12
+ spec.description = %q{Spoonerize phrases from the command line. Comes with an API}
13
+ spec.homepage = 'https://evanthegrayt.github.io/spoonerize/'
14
+
15
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
17
+ if spec.respond_to?(:metadata)
18
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
19
+
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = 'https://github.com/evanthegrayt/spoonerize'
22
+ spec.metadata['documentation_uri'] = 'https://evanthegrayt.github.io/spoonerize/doc/index.html'
23
+ else
24
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
25
+ end
26
+
27
+ # Specify which files should be added to the gem when it is released.
28
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
29
+ # spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
30
+ # `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
31
+ # end
32
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
33
+ spec.bindir = 'bin'
34
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
35
+ spec.require_paths = ['lib']
36
+ spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
37
+ spec.add_development_dependency 'test-unit', '~> 3.3', '>= 3.3.5'
38
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spoonerize
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Evan Gray
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 13.0.1
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '13.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 13.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: test-unit
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.3'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.3.5
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.3'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.3.5
53
+ description: Spoonerize phrases from the command line. Comes with an API
54
+ email: evanthegrayt@vivaldi.net
55
+ executables:
56
+ - spoonerize
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - ".github/workflows/ruby.yml"
61
+ - ".gitignore"
62
+ - Gemfile
63
+ - LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - _config.yml
67
+ - bin/spoonerize
68
+ - doc/README_md.html
69
+ - doc/Spoonerize.html
70
+ - doc/Spoonerize/Bumper.html
71
+ - doc/Spoonerize/Cli.html
72
+ - doc/Spoonerize/Log.html
73
+ - doc/Spoonerize/Spoonerism.html
74
+ - doc/created.rid
75
+ - doc/css/fonts.css
76
+ - doc/css/rdoc.css
77
+ - doc/fonts/Lato-Light.ttf
78
+ - doc/fonts/Lato-LightItalic.ttf
79
+ - doc/fonts/Lato-Regular.ttf
80
+ - doc/fonts/Lato-RegularItalic.ttf
81
+ - doc/fonts/SourceCodePro-Bold.ttf
82
+ - doc/fonts/SourceCodePro-Regular.ttf
83
+ - doc/images/add.png
84
+ - doc/images/arrow_up.png
85
+ - doc/images/brick.png
86
+ - doc/images/brick_link.png
87
+ - doc/images/bug.png
88
+ - doc/images/bullet_black.png
89
+ - doc/images/bullet_toggle_minus.png
90
+ - doc/images/bullet_toggle_plus.png
91
+ - doc/images/date.png
92
+ - doc/images/delete.png
93
+ - doc/images/find.png
94
+ - doc/images/loadingAnimation.gif
95
+ - doc/images/macFFBgHack.png
96
+ - doc/images/package.png
97
+ - doc/images/page_green.png
98
+ - doc/images/page_white_text.png
99
+ - doc/images/page_white_width.png
100
+ - doc/images/plugin.png
101
+ - doc/images/ruby.png
102
+ - doc/images/tag_blue.png
103
+ - doc/images/tag_green.png
104
+ - doc/images/transparent.png
105
+ - doc/images/wrench.png
106
+ - doc/images/wrench_orange.png
107
+ - doc/images/zoom.png
108
+ - doc/index.html
109
+ - doc/js/darkfish.js
110
+ - doc/js/navigation.js
111
+ - doc/js/navigation.js.gz
112
+ - doc/js/search.js
113
+ - doc/js/search_index.js
114
+ - doc/js/search_index.js.gz
115
+ - doc/js/searcher.js
116
+ - doc/js/searcher.js.gz
117
+ - doc/table_of_contents.html
118
+ - lib/config/lazy_words.yml
119
+ - lib/spoonerize.rb
120
+ - lib/spoonerize/bumper.rb
121
+ - lib/spoonerize/cli.rb
122
+ - lib/spoonerize/log.rb
123
+ - lib/spoonerize/spoonerism.rb
124
+ - lib/spoonerize/version.rb
125
+ - pkg/spoonerize-0.0.7.gem
126
+ - spoonerize.gemspec
127
+ homepage: https://evanthegrayt.github.io/spoonerize/
128
+ licenses:
129
+ - MIT
130
+ metadata:
131
+ allowed_push_host: https://rubygems.org
132
+ homepage_uri: https://evanthegrayt.github.io/spoonerize/
133
+ source_code_uri: https://github.com/evanthegrayt/spoonerize
134
+ documentation_uri: https://evanthegrayt.github.io/spoonerize/doc/index.html
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubygems_version: 3.1.2
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: Spoonerize phrases from the command line.
154
+ test_files: []