coltrane 3.4.2 → 4.0.3

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile.lock +15 -4
  6. data/bin/old-coltrane +29 -0
  7. data/coltrane.gemspec +4 -4
  8. data/exe/coltrane +77 -47
  9. data/lib/.DS_Store +0 -0
  10. data/lib/coltrane/.DS_Store +0 -0
  11. data/lib/coltrane/commands.rb +4 -9
  12. data/lib/coltrane/commands/available_chord_representations.rb +9 -0
  13. data/lib/coltrane/commands/available_classic_scales.rb +9 -0
  14. data/lib/coltrane/commands/available_notable_progressions.rb +9 -0
  15. data/lib/coltrane/commands/available_representations.rb +9 -0
  16. data/lib/coltrane/commands/command.rb +3 -54
  17. data/lib/coltrane/commands/find_chord_by_notes.rb +9 -0
  18. data/lib/coltrane/commands/find_common_chords.rb +9 -0
  19. data/lib/coltrane/commands/find_progressions_from_chords.rb +9 -0
  20. data/lib/coltrane/commands/find_scale_by_chords.rb +9 -0
  21. data/lib/coltrane/commands/find_scale_by_notes.rb +9 -0
  22. data/lib/coltrane/commands/get_chords_from_notable_progression.rb +9 -0
  23. data/lib/coltrane/commands/get_chords_from_progression.rb +9 -0
  24. data/lib/coltrane/commands/get_chords_from_scale.rb +9 -0
  25. data/lib/coltrane/commands/get_chords_from_string.rb +11 -0
  26. data/lib/coltrane/commands/get_classic_scale.rb +9 -0
  27. data/lib/coltrane/commands/get_notes.rb +9 -0
  28. data/lib/coltrane/commands/get_notes_from_string.rb +9 -0
  29. data/lib/coltrane/commands/get_representation_chords.rb +18 -0
  30. data/lib/coltrane/commands/get_representation_notes.rb +12 -0
  31. data/lib/coltrane/commands/render.rb +9 -0
  32. data/lib/coltrane/renderers/text_renderer/hash_drawer.rb +1 -0
  33. data/lib/coltrane/renderers/text_renderer/theory_chord_drawer.rb +1 -2
  34. data/lib/coltrane/theory/classic_scales.rb +1 -1
  35. data/lib/coltrane/ui.rb +9 -0
  36. data/lib/coltrane/ui/.DS_Store +0 -0
  37. data/lib/coltrane/ui/router.rb +87 -0
  38. data/lib/coltrane/ui/views.rb +4 -0
  39. data/lib/coltrane/ui/views/chords.rb +19 -0
  40. data/lib/coltrane/ui/views/custom_progression.rb +27 -0
  41. data/lib/coltrane/ui/views/find_chord_by_notes.rb +16 -0
  42. data/lib/coltrane/ui/views/find_chords_in_scale.rb +34 -0
  43. data/lib/coltrane/ui/views/find_common_chords_in_scales.rb +40 -0
  44. data/lib/coltrane/ui/views/find_progressions_from_chords.rb +14 -0
  45. data/lib/coltrane/ui/views/find_scale.rb +14 -0
  46. data/lib/coltrane/ui/views/find_scale_by_chords.rb +16 -0
  47. data/lib/coltrane/ui/views/find_scale_by_notes.rb +16 -0
  48. data/lib/coltrane/ui/views/index.rb +14 -0
  49. data/lib/coltrane/ui/views/notes.rb +20 -0
  50. data/lib/coltrane/ui/views/progressions.rb +18 -0
  51. data/lib/coltrane/ui/views/scales.rb +17 -0
  52. data/lib/coltrane/ui/views/show_chord.rb +21 -0
  53. data/lib/coltrane/ui/views/show_progression.rb +26 -0
  54. data/lib/coltrane/ui/views/show_scale.rb +26 -0
  55. data/lib/coltrane/ui/views/view.rb +47 -0
  56. data/lib/coltrane/version.rb +1 -1
  57. metadata +64 -28
  58. data/lib/coltrane/commands/chords.rb +0 -93
  59. data/lib/coltrane/commands/common_chords.rb +0 -33
  60. data/lib/coltrane/commands/errors.rb +0 -44
  61. data/lib/coltrane/commands/find_guitar_chord.rb +0 -25
  62. data/lib/coltrane/commands/find_progression.rb +0 -28
  63. data/lib/coltrane/commands/find_scale.rb +0 -39
  64. data/lib/coltrane/commands/notes.rb +0 -50
  65. data/lib/coltrane/commands/progression.rb +0 -28
  66. data/lib/coltrane/commands/scale.rb +0 -46
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class FindScaleByNotes < Command
4
+ def run(notes)
5
+ Theory::Scale.having_notes(*notes)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetChordsFromNotableProgression < Command
4
+ def run(progression, key)
5
+ Theory::Progression.send(progression.underscore, key).chords
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetChordsFromProgression < Command
4
+ def run(notation, key)
5
+ Theory::Progression.new(notation, key: key).chords
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetChordsFromScale < Command
4
+ def run(scale, type, size)
5
+ scale.send(type == 'tertians' ? :tertians : :chords)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetChordsFromString < Command
4
+ def run(string)
5
+ string.split(' ').map do |chord|
6
+ Theory::Chord.new(name: chord)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetClassicScale < Command
4
+ def run(scale, tone)
5
+ Theory::Scale.fetch(scale, tone)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetNotes < Command
4
+ def run(*notes)
5
+ Theory::NoteSet[*notes]
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetNotesFromString < Command
4
+ def run(string)
5
+ GetNotes.run(*string.split(' '))
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetRepresentationChords < Command
4
+ def run(representation, chords)
5
+ chords.map do |chord|
6
+ if representation == 'GuitarChordChart'
7
+ {
8
+ chord.name => Representation::Guitar.find_chords(chord).first(4),
9
+ options: { layout: :horizontal, per_row: 4 }
10
+ }
11
+ else
12
+ { chord.name => GetRepresentationNotes.run(representation, chord.notes) }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Coltrane
2
+ module Commands
3
+ class GetRepresentationNotes < Command
4
+ def run(representation, notes)
5
+ return notes if representation == 'Text'
6
+ Object
7
+ .const_get("Coltrane::Representation::#{representation}")
8
+ .find_notes(notes)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Coltrane
2
+ module Commands
3
+ class Render < Command
4
+ def run(object)
5
+ Renderers::TextRenderer.render(object)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -5,6 +5,7 @@ module Coltrane
5
5
  alias hash model
6
6
 
7
7
  def render
8
+ options = hash.delete(:options) || {}
8
9
  hash.map { |k, v|
9
10
  "#{k}: \n\n" +
10
11
  TextRenderer.render(v, **options)
@@ -5,8 +5,7 @@ module Coltrane
5
5
  alias chord model
6
6
 
7
7
  def render
8
- "#{chord.name}: ".ljust(5) +
9
- TextRenderer.render(chord.notes, **options)
8
+ "#{chord.name}: ".ljust(5) + TextRenderer.render(chord.notes)
10
9
  end
11
10
  end
12
11
  end
@@ -45,7 +45,7 @@ module Coltrane
45
45
  alias blues blues_major
46
46
 
47
47
  def known_scales
48
- SCALES.keys + ['Major', 'Natural Minor']
48
+ ['Major', 'Natural Minor'] + SCALES.keys
49
49
  end
50
50
 
51
51
  # List of scales appropriate for search
@@ -0,0 +1,9 @@
1
+ require 'active_support/inflector'
2
+ require 'paint'
3
+ require 'color'
4
+ require 'cli/ui' # shopify cli
5
+
6
+ require 'coltrane'
7
+ require 'coltrane/commands'
8
+ require 'coltrane/ui/views'
9
+ require 'coltrane/ui/router'
Binary file
@@ -0,0 +1,87 @@
1
+ module Coltrane
2
+ module UI
3
+ class Router
4
+
5
+ class Route
6
+ attr_reader :path, :view, :last
7
+ attr_accessor :params
8
+
9
+ def initialize(path, to:, with: {})
10
+ @path = path
11
+ @view = to
12
+ @params = with
13
+ end
14
+
15
+ def render(**other_params)
16
+ view.render(**params, **other_params)
17
+ end
18
+ end
19
+
20
+ class History
21
+ attr_reader :routes
22
+
23
+ def initialize
24
+ @routes = []
25
+ end
26
+
27
+ def add(route)
28
+ @routes << route
29
+ end
30
+
31
+ def previous
32
+ routes[-2]&.path || ''
33
+ end
34
+
35
+ def current_route
36
+ routes[-1]
37
+ end
38
+
39
+ def back
40
+ routes.pop.render
41
+ end
42
+
43
+ def refresh(params={})
44
+ current_route.render(params)
45
+ end
46
+ end
47
+
48
+ attr_reader :path, :params, :routes, :history, :url
49
+
50
+ def initialize
51
+ @routes = []
52
+ @history = History.new
53
+
54
+ draw_route '', to: Coltrane::UI::Views::Index
55
+ Views.constants.each do |view|
56
+ draw_route view.to_s.underscore.humanize.downcase, to: "Coltrane::UI::Views::#{view}".constantize
57
+ end
58
+ end
59
+
60
+ def get(**params)
61
+ path = params.delete(:path)
62
+ @url = build_url(path || history.current_route.path, **params)
63
+ route = @routes.detect { |route| route.path == path }
64
+ return history.refresh(params) unless route
65
+ history.add(route)
66
+ route.render(**params)
67
+ end
68
+
69
+ def build_url(path, params)
70
+ [
71
+ path,
72
+ (params || {}).map do |k,v|
73
+ [k,v.gsub(' ', '-')].join(':')
74
+ end
75
+ ].compact.join(' ')
76
+ end
77
+
78
+ def previous_path
79
+ history.previous
80
+ end
81
+
82
+ def draw_route(*args, **keyword_args, &block)
83
+ @routes << Route.new(*args, **keyword_args, &block)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,4 @@
1
+ require 'coltrane/ui/views/view'
2
+ Dir[File.expand_path('../views/*', __FILE__)].map do |f|
3
+ require(f)
4
+ end
@@ -0,0 +1,19 @@
1
+ module Coltrane
2
+ module UI
3
+ module Views
4
+ class Chords < View
5
+ questions({
6
+ path: {
7
+ statement: 'What do you need',
8
+ options: [
9
+ 'show chord',
10
+ 'find chord by notes',
11
+ 'find chords in scale',
12
+ 'find common chords in scales'
13
+ ]
14
+ }
15
+ })
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module Coltrane
2
+ module UI
3
+ module Views
4
+ class CustomProgression < View
5
+ questions({
6
+ progression_notation: {
7
+ statement: 'What is the progression? (Ex: I-vi-IV-V)'
8
+ },
9
+
10
+ representation: {
11
+ statement: 'How do you wanna see the chords?',
12
+ options: Commands::AvailableChordRepresentations.run
13
+ },
14
+
15
+ key: {
16
+ statement: 'What is the key?'
17
+ },
18
+ })
19
+
20
+ def render
21
+ chords = Commands::GetChordsFromProgression.run(*params.values_at(:progression_notation, :key))
22
+ Commands::GetRepresentationChords.run(params[:representation], chords)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ module Coltrane
2
+ module UI
3
+ module Views
4
+ class FindChordByNotes < View
5
+ questions({
6
+ notes: { statement: 'Which Notes?' }
7
+ })
8
+
9
+ def render
10
+ notes = Commands::GetNotesFromString.run(params[:notes])
11
+ Commands::FindChordByNotes.run(*notes)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ require 'coltrane/ui/views/show_scale'
2
+
3
+ module Coltrane
4
+ module UI
5
+ module Views
6
+ class FindChordsInScale < ShowScale
7
+ questions({
8
+ chord_type: {
9
+ statement: 'Which kind of chords?',
10
+ options: ['tertian', 'all']
11
+ },
12
+
13
+ chord_size: {
14
+ statement: 'What is the size of the chords',
15
+ options: (3..7).to_a.map(&:to_s)
16
+ },
17
+
18
+ chord_representation: {
19
+ statement: 'How do you wanna see this',
20
+ options: Commands::AvailableChordRepresentations.run
21
+ }
22
+ })
23
+ def render
24
+ scale = Commands::GetClassicScale.run(*params.values_at(:scale, :tone))
25
+ chords = Commands::GetChordsFromScale.run(
26
+ scale,
27
+ *params.values_at(:chord_type, :chord_size)
28
+ )
29
+ Commands::GetRepresentationChords.run(params[:chord_representation], chords)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ module Coltrane
2
+ module UI
3
+ module Views
4
+ class FindCommonChordsInScales < View
5
+ questions({
6
+ first_scale: {
7
+ statement: 'Choose the first scale',
8
+ options: Commands::AvailableClassicScales.run
9
+ },
10
+
11
+ first_scale_root: {
12
+ statement: 'Type the tone (note)'
13
+ },
14
+
15
+ second_scale: {
16
+ statement: 'Choose the second scale',
17
+ options: Commands::AvailableClassicScales.run
18
+ },
19
+
20
+ second_scale_root: {
21
+ statement: 'Type the tone (note)'
22
+ },
23
+
24
+ representation: {
25
+ statement: 'How do you wanna see the results?',
26
+ options: Commands::AvailableChordRepresentations.run
27
+ }
28
+ })
29
+
30
+ def render
31
+ scale_a = Commands::GetClassicScale.run(*params.values_at(:first_scale, :first_scale_root))
32
+ scale_b = Commands::GetClassicScale.run(*params.values_at(:second_scale, :second_scale_root))
33
+ chords = Commands::FindCommonChords.run(scale_a, scale_b)
34
+ rep_chords = Commands::GetRepresentationChords.run(params[:representation], chords)
35
+ { "Chords that exist in #{scale_a.full_name} and #{scale_b.full_name}" => rep_chords }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,14 @@
1
+ module Coltrane
2
+ module UI
3
+ module Views
4
+ class FindProgressionsFromChords < View
5
+ questions chords: { statement: 'Type the chords? (Ex: CM EM GM)' }
6
+
7
+ def render
8
+ chords = Commands::GetChordsFromString.run(params[:chords])
9
+ Commands::FindProgressionsFromChords.run(*chords)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Coltrane
2
+ module UI
3
+ module Views
4
+ class FindScale < View
5
+ questions({
6
+ path: {
7
+ statement: 'How do you wanna search',
8
+ options: ['find scale by chords', 'find scale by notes']
9
+ },
10
+ })
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Coltrane
2
+ module UI
3
+ module Views
4
+ class FindScaleByChords < View
5
+ questions({
6
+ chords: { statement: 'Which Chords?' }
7
+ })
8
+
9
+ def render
10
+ chords = Commands::GetChordsFromString.run(params[:chords])
11
+ Commands::FindScaleByChords.run(*chords)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end