coltrane 1.0.11 → 1.0.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +19 -0
- data/Gemfile +5 -2
- data/Gemfile.lock +3 -3
- data/coltrane.gemspec +1 -1
- data/exe/coltrane +27 -21
- data/lib/{coltrane-cli.rb → cli.rb} +4 -2
- data/lib/cli/bass_guitar.rb +4 -1
- data/lib/cli/chord.rb +10 -3
- data/lib/cli/errors.rb +10 -4
- data/lib/cli/guitar.rb +12 -10
- data/lib/cli/notes.rb +7 -4
- data/lib/cli/piano.rb +11 -8
- data/lib/cli/representation.rb +14 -14
- data/lib/cli/scale.rb +15 -11
- data/lib/cli/text.rb +6 -3
- data/lib/cli/ukulele.rb +5 -2
- data/lib/coltrane.rb +4 -1
- data/lib/coltrane/cache.rb +10 -9
- data/lib/coltrane/cadence.rb +3 -1
- data/lib/coltrane/chord.rb +16 -8
- data/lib/coltrane/chord_quality.rb +7 -8
- data/lib/coltrane/classic_progressions.rb +10 -7
- data/lib/coltrane/classic_scales.rb +30 -43
- data/lib/coltrane/errors.rb +17 -10
- data/lib/coltrane/interval.rb +24 -23
- data/lib/coltrane/interval_sequence.rb +8 -7
- data/lib/coltrane/interval_set.rb +1 -0
- data/lib/coltrane/note.rb +23 -46
- data/lib/coltrane/note_set.rb +12 -14
- data/lib/coltrane/pitch.rb +5 -4
- data/lib/coltrane/progression.rb +9 -20
- data/lib/coltrane/qualities.rb +114 -112
- data/lib/coltrane/roman_chord.rb +8 -5
- data/lib/coltrane/scale.rb +25 -33
- data/lib/coltrane/version.rb +3 -1
- data/lib/core_ext.rb +7 -4
- metadata +7 -10
- data/db/schema.rb +0 -30
- data/lib/coltrane/chord_cache.rb +0 -4
- data/lib/coltrane/scale_chord.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5a4151938ea91678a02db7c78b3023923c9d9e68e8581e6ba632f4f1bb59536
|
4
|
+
data.tar.gz: 96f4375279f73a49d47f9bfbf8e8f36aa8a74bba168c3dea1484df15875c580a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0650ebfe175fffd885c6bf2d4545014fad8a0d061a488e469fb450eec8ba81833f70cc8951f31735517e4475d687e0ccd251a16809e612947dd20c3b9860bbc8
|
7
|
+
data.tar.gz: d99eb17b252b86dae5a62da524490b48ad37288c7a36e90c24d7017aee66204cb1127a520227a79383500368303e1ae62c39c996845428c2483052cec2bf5a2f
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
AllCops:
|
2
|
+
Include:
|
3
|
+
- 'lib/**/*'
|
4
|
+
Exclude:
|
5
|
+
- 'bin/**/*'
|
6
|
+
- '*'
|
7
|
+
|
8
|
+
Metrics/AbcSize:
|
9
|
+
Enabled: false
|
10
|
+
Metrics/ClassLength:
|
11
|
+
Enabled: false
|
12
|
+
Metrics/MethodLength:
|
13
|
+
Enabled: false
|
14
|
+
Metrics/ModuleLength:
|
15
|
+
Enabled: false
|
16
|
+
Lint/UnneededSplatExpansion:
|
17
|
+
Enabled: false
|
18
|
+
Security/MarshalLoad:
|
19
|
+
Enabled: false
|
data/Gemfile
CHANGED
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
source 'https://rubygems.org'
|
4
4
|
|
5
|
-
group :test do
|
6
|
-
gem 'rspec'
|
5
|
+
group :test, :development do
|
7
6
|
gem 'pry'
|
8
7
|
gem 'pry-byebug'
|
9
8
|
gem 'pry-rescue'
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'rspec'
|
10
13
|
gem 'simplecov', require: false
|
11
14
|
gem 'rubocop', require: false
|
12
15
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
coltrane (1.0.
|
5
|
-
|
4
|
+
coltrane (1.0.11)
|
5
|
+
color (~> 1.8)
|
6
6
|
facets (~> 3.1)
|
7
7
|
mercenary (~> 0.3)
|
8
8
|
paint (~> 2.0)
|
@@ -12,8 +12,8 @@ GEM
|
|
12
12
|
specs:
|
13
13
|
ast (2.3.0)
|
14
14
|
byebug (9.1.0)
|
15
|
-
chroma (0.2.0)
|
16
15
|
coderay (1.1.2)
|
16
|
+
color (1.8)
|
17
17
|
diff-lcs (1.3)
|
18
18
|
docile (1.1.5)
|
19
19
|
facets (3.1.0)
|
data/coltrane.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
|
33
33
|
spec.add_runtime_dependency 'facets', '~> 3.1'
|
34
34
|
spec.add_runtime_dependency 'paint', '~> 2.0'
|
35
|
-
spec.add_runtime_dependency '
|
35
|
+
spec.add_runtime_dependency 'color', '~> 1.8'
|
36
36
|
spec.add_runtime_dependency 'mercenary', '~> 0.3'
|
37
37
|
spec.add_development_dependency "bundler", '~> 1.14'
|
38
38
|
spec.add_development_dependency "rake", '~> 10.0'
|
data/exe/coltrane
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# rubocop:disable Metrics/BlockLength
|
2
5
|
|
3
6
|
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
4
7
|
|
5
8
|
require 'core_ext'
|
6
9
|
require 'coltrane'
|
7
|
-
require '
|
10
|
+
require 'cli'
|
8
11
|
|
9
12
|
full_color_terminals = %w[iTerm.app]
|
10
13
|
safe_mode_terminals = %w[Unsupported]
|
@@ -71,9 +74,9 @@ Mercenary.program(:Coltrane) do |p|
|
|
71
74
|
c.option :pentads, '--pentads', 'Outputs pentad chords from the scale'
|
72
75
|
c.option :tertians, '--tertians SIZE', 'Outputs all tertian chords from the given size from the scale'
|
73
76
|
c.option :chords, '--chords [SIZE]', 'Outputs all chords from given size from the scale. Leave size empty to retrieve all'
|
74
|
-
c.action do |(scale_str), flavor:'degrees', on:'text', **options|
|
77
|
+
c.action do |(scale_str), flavor: 'degrees', on: 'text', **options|
|
75
78
|
scale = Coltrane::Cli::Scale.parse(scale_str)
|
76
|
-
keyword_args = {flavor: flavor, on: on }
|
79
|
+
keyword_args = { flavor: flavor, on: on }
|
77
80
|
if options.include?(:triads)
|
78
81
|
chords = scale.triads
|
79
82
|
Coltrane::Cli::Chord.new(*chords, **keyword_args)
|
@@ -87,11 +90,11 @@ Mercenary.program(:Coltrane) do |p|
|
|
87
90
|
chords = scale.tertians(options[:tertians].to_i)
|
88
91
|
Coltrane::Cli::Chord.new(*chords, **keyword_args)
|
89
92
|
elsif options.include?(:chords)
|
90
|
-
if options[:chords].nil?
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
93
|
+
chords = if options[:chords].nil?
|
94
|
+
scale.all_chords
|
95
|
+
else
|
96
|
+
scale.chords(options[:chords])
|
97
|
+
end
|
95
98
|
Coltrane::Cli::Chord.new(*chords, **keyword_args)
|
96
99
|
else
|
97
100
|
Coltrane::Cli::Scale.new(scale, **keyword_args)
|
@@ -104,11 +107,11 @@ Mercenary.program(:Coltrane) do |p|
|
|
104
107
|
list.description 'List information.'
|
105
108
|
list.action do |(arg)|
|
106
109
|
puts case arg
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
110
|
+
when 'scales' then Coltrane::Scale.known_scales
|
111
|
+
when 'flavors' then %w[marks notes intervals degrees]
|
112
|
+
when 'instruments' then %w[guitar bass ukulele piano text]
|
113
|
+
when 'chords', 'chord-qualities' then Coltrane::Qualities::CHORD_QUALITIES.keys.sort.join(' ')
|
114
|
+
end
|
112
115
|
end
|
113
116
|
end
|
114
117
|
|
@@ -117,9 +120,9 @@ Mercenary.program(:Coltrane) do |p|
|
|
117
120
|
c.description 'finds scales with the provided --notes or --chord'
|
118
121
|
c.option :notes, '--notes C-D-E', 'Find scales with those notes'
|
119
122
|
c.option :chords, '--chords Cmaj7-D11', 'find scales with those chords'
|
120
|
-
c.action do |(
|
121
|
-
options[:notes] =
|
122
|
-
options[:chords] =
|
123
|
+
c.action do |(_arg), options|
|
124
|
+
options[:notes] = (options[:notes]).to_s.split('-')
|
125
|
+
options[:chords] = (options[:chords]).to_s.split('-')
|
123
126
|
Coltrane::Cli::Scale.find(**options)
|
124
127
|
end
|
125
128
|
end
|
@@ -145,14 +148,15 @@ Mercenary.program(:Coltrane) do |p|
|
|
145
148
|
p.command(:help) do |c|
|
146
149
|
c.description 'May give you some help.'
|
147
150
|
c.syntax 'help <command> [subcommand, sub-subcommand, ...]'
|
148
|
-
c.action do |(*command_path),
|
151
|
+
c.action do |(*command_path), _options|
|
149
152
|
if command_path.empty?
|
150
153
|
puts p
|
151
|
-
return
|
152
154
|
else
|
153
|
-
puts
|
154
|
-
|
155
|
-
|
155
|
+
puts begin
|
156
|
+
command_path.reduce(p) do |memo, key|
|
157
|
+
memo.commands.delete(key.to_sym)
|
158
|
+
end || "\n Sorry, command found."
|
159
|
+
end
|
156
160
|
end
|
157
161
|
end
|
158
162
|
end
|
@@ -166,3 +170,5 @@ Mercenary.program(:Coltrane) do |p|
|
|
166
170
|
|
167
171
|
p.default_command(:about)
|
168
172
|
end
|
173
|
+
|
174
|
+
# rubocop:enable Metrics/BlockLength
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'mercenary'
|
2
4
|
require 'paint'
|
3
|
-
require '
|
5
|
+
require 'color'
|
4
6
|
|
5
7
|
require 'cli/errors'
|
6
8
|
|
@@ -13,4 +15,4 @@ require 'cli/ukulele'
|
|
13
15
|
|
14
16
|
require 'cli/notes'
|
15
17
|
require 'cli/chord'
|
16
|
-
require 'cli/scale'
|
18
|
+
require 'cli/scale'
|
data/lib/cli/bass_guitar.rb
CHANGED
data/lib/cli/chord.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coltrane
|
2
4
|
module Cli
|
5
|
+
# Interfaces chord functionality with the lib
|
3
6
|
class Chord
|
4
7
|
def initialize(*chords, on: :text, flavor: 'intervals', notes: nil)
|
5
8
|
@chords =
|
@@ -10,15 +13,19 @@ module Coltrane
|
|
10
13
|
chords
|
11
14
|
end
|
12
15
|
elsif !notes.nil?
|
13
|
-
|
16
|
+
[Coltrane::Chord.new(notes: notes)]
|
14
17
|
end
|
15
18
|
|
16
19
|
@chords.each do |chord|
|
17
20
|
raise ChordNotFoundError unless chord.named?
|
18
21
|
desc = "#{chord.name} chord:"
|
19
|
-
Coltrane::Cli::Notes.new
|
22
|
+
Coltrane::Cli::Notes.new chord.notes, on: on,
|
23
|
+
desc: desc,
|
24
|
+
flavor: flavor
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
24
|
-
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# rubocop:enable Metrics/MethodLength
|
data/lib/cli/errors.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/Documentation
|
4
|
+
|
1
5
|
module Coltrane
|
2
6
|
module Cli
|
3
7
|
class ColtraneCliError < StandardError
|
@@ -7,13 +11,13 @@ module Coltrane
|
|
7
11
|
end
|
8
12
|
|
9
13
|
class WrongFlavorError < ColtraneCliError
|
10
|
-
def initialize(msg=nil)
|
14
|
+
def initialize(msg = nil)
|
11
15
|
super msg || 'Wrong flavor. Check possible flavors with `coltrane list flavors`.'
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
15
19
|
class BadFindScales < ColtraneCliError
|
16
|
-
def initialize(msg=nil)
|
20
|
+
def initialize(msg = nil)
|
17
21
|
super msg || 'Provide --notes or --chords. Ex: `coltrane find-scale --notes C E G`.'
|
18
22
|
end
|
19
23
|
end
|
@@ -21,8 +25,10 @@ module Coltrane
|
|
21
25
|
class WrongRepresentationTypeError < ColtraneCliError
|
22
26
|
def initialize(type)
|
23
27
|
super "The provided representation type (#{type}) "\
|
24
|
-
|
28
|
+
'is not available at the moment.'
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
28
|
-
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# rubocop:enable Style/Documentation
|
data/lib/cli/guitar.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coltrane
|
2
4
|
module Cli
|
3
|
-
SPECIAL_FRETS = [3, 5, 7, 9, 12, 15, 17, 19]
|
5
|
+
SPECIAL_FRETS = [3, 5, 7, 9, 12, 15, 17, 19].freeze
|
4
6
|
|
7
|
+
# Renders notes in a common most popular ukulele scheme
|
5
8
|
class Guitar < Representation
|
6
9
|
def initialize(notes, flavor, tuning: %w[E A D G B E], frets: 22)
|
7
10
|
@notes = notes
|
@@ -12,34 +15,33 @@ module Coltrane
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def render
|
15
|
-
[render_notes, render_special_frets, hint].join("\n"*2)
|
18
|
+
[render_notes, render_special_frets, hint].join("\n" * 2)
|
16
19
|
end
|
17
20
|
|
18
21
|
def render_notes
|
19
22
|
@tuning.map do |string|
|
20
23
|
string_note = Note[string]
|
21
|
-
(@frets+2)
|
24
|
+
Array.new(@frets + 2) do |i|
|
22
25
|
if i.zero?
|
23
26
|
string
|
24
27
|
else
|
25
28
|
fret = i - 1
|
26
29
|
note = string_note + fret
|
27
|
-
m = (@notes.include?(note) ? place_mark(note) :
|
28
|
-
fret.zero? ? (m +
|
30
|
+
m = (@notes.include?(note) ? place_mark(note) : '--')
|
31
|
+
fret.zero? ? (m + ' |') : m
|
29
32
|
end
|
30
33
|
end.join(' ')
|
31
34
|
end.join("\n")
|
32
35
|
end
|
33
36
|
|
34
37
|
def render_special_frets
|
35
|
-
(@frets+1)
|
38
|
+
Array.new(@frets + 1) do |fret|
|
36
39
|
m = SPECIAL_FRETS.include?(fret) ? fret.to_s.rjust(2, 0.to_s) : ' '
|
37
40
|
"#{m}#{' ' if fret.zero?}"
|
38
41
|
end.join(' ')
|
39
42
|
end
|
40
43
|
|
41
|
-
def render_dotted_frets
|
42
|
-
end
|
44
|
+
def render_dotted_frets; end
|
43
45
|
|
44
46
|
def place_mark(note)
|
45
47
|
case @flavor
|
@@ -47,9 +49,9 @@ module Coltrane
|
|
47
49
|
when :intervals then (@ref_note - note).name.ljust(2, '-')
|
48
50
|
when :degrees then @notes.degree(note).to_s.rjust(2, '0')
|
49
51
|
when :marks then '◼◼'
|
50
|
-
else raise WrongFlavorError
|
52
|
+
else raise WrongFlavorError
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
55
|
-
end
|
57
|
+
end
|
data/lib/cli/notes.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coltrane
|
2
4
|
module Cli
|
5
|
+
# Interfaces notes outputting functionality with the lib
|
3
6
|
class Notes
|
4
|
-
def initialize(notes, on: 'text', desc:
|
5
|
-
@desc = desc
|
7
|
+
def initialize(notes, on: 'text', desc: nil, flavor: 'notes')
|
8
|
+
@desc = desc || 'The notes you supplied:'
|
6
9
|
flavor = flavor.underscore.to_sym
|
7
10
|
on = on.to_sym
|
8
11
|
notes = Coltrane::NoteSet.new(notes)
|
@@ -11,8 +14,8 @@ module Coltrane
|
|
11
14
|
end
|
12
15
|
|
13
16
|
def render
|
14
|
-
puts "\n"+[@desc, @representation.render].join("\n"*2)
|
17
|
+
puts "\n" + [@desc, @representation.render].join("\n" * 2)
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
18
|
-
end
|
21
|
+
end
|
data/lib/cli/piano.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coltrane
|
2
4
|
module Cli
|
5
|
+
# It allows rendering notes in an ASCII piano
|
3
6
|
class Piano < Representation
|
4
7
|
PIANO_TEMPLATE = <<~ASCII
|
5
8
|
┌─┬─┬┬─┬─╥─┬─┬┬─┬┬─┬─╥─┬─┬┬─┬─╥─┬─┬┬─┬┬─┬─┐
|
@@ -24,11 +27,11 @@ module Coltrane
|
|
24
27
|
|
25
28
|
private
|
26
29
|
|
27
|
-
def replace_x(line, notes, size, index=0)
|
28
|
-
line.gsub('X'*size).with_index do |
|
29
|
-
note = notes[i%notes.size]
|
30
|
-
next ' '*size unless @notes.include?(note)
|
31
|
-
Paint[replacer(note)[size == 2 ? 0..2 : index
|
30
|
+
def replace_x(line, notes, size, index = 0)
|
31
|
+
line.gsub('X' * size).with_index do |_match, i|
|
32
|
+
note = notes[i % notes.size]
|
33
|
+
next ' ' * size unless @notes.include?(note)
|
34
|
+
Paint[replacer(note)[size == 2 ? 0..2 : index], 'red']
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
@@ -37,7 +40,7 @@ module Coltrane
|
|
37
40
|
case @flavor
|
38
41
|
when :intervals then (@ref_note - note).name
|
39
42
|
when :marks then '◼ '
|
40
|
-
when :degrees then @notes.degree(note).to_s.rjust(2,'0')
|
43
|
+
when :degrees then @notes.degree(note).to_s.rjust(2, '0')
|
41
44
|
when :notes then note.pretty_name.to_s.ljust(2, "\u266E")
|
42
45
|
end
|
43
46
|
end
|
@@ -47,8 +50,8 @@ module Coltrane
|
|
47
50
|
end
|
48
51
|
|
49
52
|
def black_notes
|
50
|
-
Coltrane::Scale.pentatonic_major('C#',4).notes
|
53
|
+
Coltrane::Scale.pentatonic_major('C#', 4).notes
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
54
|
-
end
|
57
|
+
end
|
data/lib/cli/representation.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coltrane
|
2
4
|
module Cli
|
5
|
+
# It manages notes representations, most of times instruments
|
3
6
|
class Representation
|
4
|
-
ACCEPTED_FLAVORS = %i[marks notes intervals degrees]
|
7
|
+
ACCEPTED_FLAVORS = %i[marks notes intervals degrees].freeze
|
5
8
|
|
6
9
|
def self.inherited(subclass)
|
7
10
|
@@types ||= {}
|
@@ -9,18 +12,15 @@ module Coltrane
|
|
9
12
|
end
|
10
13
|
|
11
14
|
def self.build(type, notes, flavor)
|
12
|
-
raise WrongFlavorError
|
15
|
+
raise WrongFlavorError unless ACCEPTED_FLAVORS.include?(flavor)
|
13
16
|
type = case type
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
when :ukelele then :ukulele
|
18
|
+
when :bass then :bass_guitar
|
19
|
+
else type
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
else
|
22
|
-
raise WrongRepresentationTypeError.new(type)
|
23
|
-
end
|
22
|
+
raise(WrongRepresentationTypeError, type) unless @@types.include?(type)
|
23
|
+
@@types[type].new(notes, flavor)
|
24
24
|
end
|
25
25
|
|
26
26
|
def initialize(notes, flavor)
|
@@ -31,7 +31,7 @@ module Coltrane
|
|
31
31
|
|
32
32
|
def hint
|
33
33
|
case @flavor
|
34
|
-
when :marks then
|
34
|
+
when :marks then ''
|
35
35
|
when :notes then "(\u266E means the note is natural, not flat nor sharp)"
|
36
36
|
when :intervals
|
37
37
|
<<~DESC
|
@@ -39,9 +39,9 @@ module Coltrane
|
|
39
39
|
Ex: 1P = Perfect First / 3m = Minor Third / 4A = Augmented Fourth
|
40
40
|
DESC
|
41
41
|
|
42
|
-
when :degrees then
|
42
|
+
when :degrees then '(The numbers represent the degree of the note in the scale)'
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|