skippy 0.1.1.a → 0.2.0.a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +14 -0
  3. data/.gitignore +5 -0
  4. data/.idea/.rakeTasks +7 -0
  5. data/.idea/codeStyleSettings.xml +9 -0
  6. data/.idea/encodings.xml +6 -0
  7. data/.idea/inspectionProfiles/Project_Default.xml +8 -0
  8. data/.idea/misc.xml +4 -0
  9. data/.idea/modules.xml +8 -0
  10. data/.idea/runConfigurations/All_Features.xml +32 -0
  11. data/.idea/runConfigurations/test__skippy.xml +21 -0
  12. data/.idea/skippy.iml +83 -0
  13. data/.idea/vcs.xml +6 -0
  14. data/.vscode/launch.json +61 -0
  15. data/.vscode/settings.json +3 -2
  16. data/.vscode/tasks.json +16 -0
  17. data/Gemfile +5 -0
  18. data/Rakefile +4 -4
  19. data/app/boot.rb +1 -1
  20. data/app/commands/debug.rb +2 -1
  21. data/app/commands/lib.rb +46 -0
  22. data/app/commands/new.rb +4 -3
  23. data/app/commands/template.rb +3 -3
  24. data/app/resources/commands/example.rb +1 -1
  25. data/app/templates/standard/%ext_name%.rb.tt +1 -1
  26. data/app/templates/webdialog/{extension.rb.erb → %ext_name%.rb.tt} +1 -1
  27. data/app/templates/webdialog/{extension → %ext_name%}/html/dialog.html +0 -0
  28. data/app/templates/webdialog/{extension/main.rb.erb → %ext_name%/main.rb.tt} +0 -0
  29. data/bin/aruba +17 -0
  30. data/bin/cucumber +17 -0
  31. data/bin/htmldiff +17 -0
  32. data/bin/ldiff +17 -0
  33. data/cSpell.json +18 -0
  34. data/fixtures/my_lib/skippy.json +5 -0
  35. data/fixtures/my_lib/src/command.rb +4 -0
  36. data/fixtures/my_lib/src/geometry.rb +4 -0
  37. data/fixtures/my_lib/src/tool.rb +4 -0
  38. data/fixtures/my_project/skippy.json +8 -0
  39. data/fixtures/my_project/skippy/commands/example.rb +14 -0
  40. data/fixtures/my_project/src/hello_world.rb +47 -0
  41. data/fixtures/my_project/src/hello_world/extension.json +10 -0
  42. data/fixtures/my_project/src/hello_world/main.rb +21 -0
  43. data/lib/skippy.rb +7 -3
  44. data/lib/skippy/app.rb +7 -5
  45. data/lib/skippy/cli.rb +12 -12
  46. data/lib/skippy/config.rb +135 -0
  47. data/lib/skippy/config_accessors.rb +43 -0
  48. data/lib/skippy/error.rb +1 -1
  49. data/lib/skippy/helpers/file.rb +14 -0
  50. data/lib/skippy/lib_module.rb +47 -0
  51. data/lib/skippy/library.rb +57 -0
  52. data/lib/skippy/library_manager.rb +75 -0
  53. data/lib/skippy/module_manager.rb +103 -0
  54. data/lib/skippy/namespace.rb +7 -3
  55. data/lib/skippy/project.rb +55 -26
  56. data/lib/skippy/version.rb +1 -1
  57. data/skippy.gemspec +14 -12
  58. metadata +69 -8
  59. data/lib/skippy/skippy.rb +0 -9
@@ -8,18 +8,18 @@ class Template < Skippy::Command
8
8
  say ' No templates found'
9
9
  else
10
10
  templates.each { |template|
11
- say " #{template}", :green
11
+ say " #{template.basename}", :green
12
12
  }
13
13
  end
14
14
  end
15
15
  default_command(:list)
16
16
 
17
- desc 'install', 'Install a new template'
17
+ desc 'install SOURCE', 'Install a new template'
18
18
  def install(source)
19
19
  raise Skippy::Error, 'Not implemented'
20
20
  end
21
21
 
22
- desc 'remove', 'Remove an installed template'
22
+ desc 'remove TEMPLATE', 'Remove an installed template'
23
23
  def remove(template_name)
24
24
  raise Skippy::Error, 'Not implemented'
25
25
  end
@@ -7,7 +7,7 @@ class Hello < Skippy::Command
7
7
  default_command(:world)
8
8
 
9
9
  desc 'universe', 'Greets the universe in general'
10
- def universe(person)
10
+ def universe
11
11
  say "DARK IN HERE, ISN'T IT?"
12
12
  end
13
13
 
@@ -31,7 +31,7 @@ require 'sketchup.rb'
31
31
  EXTENSION = ::JSON.parse(extension_json, symbolize_names: true).freeze
32
32
 
33
33
  unless file_loaded?(__FILE__)
34
- loader = File.join(PATH, 'bootstrap')
34
+ loader = File.join(PATH, 'main')
35
35
  @extension = SketchupExtension.new(EXTENSION[:name], loader)
36
36
  @extension.description = EXTENSION[:description]
37
37
  @extension.version = EXTENSION[:version]
@@ -31,7 +31,7 @@ require 'sketchup.rb'
31
31
  EXTENSION = ::JSON.parse(extension_json, symbolize_names: true).freeze
32
32
 
33
33
  unless file_loaded?(__FILE__)
34
- loader = File.join(PATH, 'bootstrap')
34
+ loader = File.join(PATH, 'main')
35
35
  @extension = SketchupExtension.new(EXTENSION[:name], loader)
36
36
  @extension.description = EXTENSION[:description]
37
37
  @extension.version = EXTENSION[:version]
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'aruba' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("aruba", "aruba")
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'cucumber' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("cucumber", "cucumber")
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'htmldiff' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("diff-lcs", "htmldiff")
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'ldiff' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("diff-lcs", "ldiff")
@@ -0,0 +1,18 @@
1
+ // cSpell Settings
2
+ {
3
+ // Version of the setting file. Always 0.1
4
+ "version": "0.1",
5
+ // language - current active spelling language
6
+ "language": "en",
7
+ // words - list of words to be always considered correct
8
+ "words": [
9
+ "namespace",
10
+ "yieldparam"
11
+ ],
12
+ // flagWords - list of words to be always considered incorrect
13
+ // This is useful for offensive words and common spelling errors.
14
+ // For example "hte" should be "the"
15
+ "flagWords": [
16
+ "hte"
17
+ ]
18
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "library": true,
3
+ "name": "My Shiny Library",
4
+ "version": "1.2.3"
5
+ }
@@ -0,0 +1,4 @@
1
+ module SkippyLib
2
+ class Command
3
+ end
4
+ end # module
@@ -0,0 +1,4 @@
1
+ module SkippyLib
2
+ class Geometry
3
+ end
4
+ end # module
@@ -0,0 +1,4 @@
1
+ module SkippyLib
2
+ class Tool
3
+ end
4
+ end # module
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "Hello World",
3
+ "description": "",
4
+ "namespace": "Example::HelloWorld",
5
+ "author": "Unknown",
6
+ "copyright": "Copyright (c) 2017",
7
+ "license": "None"
8
+ }
@@ -0,0 +1,14 @@
1
+ class Hello < Skippy::Command
2
+
3
+ desc 'world PERSON', 'Oh, hi there!'
4
+ def world(person)
5
+ say "Hello #{person}"
6
+ end
7
+ default_command(:world)
8
+
9
+ desc 'universe', 'Greets the universe in general'
10
+ def universe
11
+ say "DARK IN HERE, ISN'T IT?"
12
+ end
13
+
14
+ end
@@ -0,0 +1,47 @@
1
+ #-------------------------------------------------------------------------------
2
+ #
3
+ # Author: Unknown
4
+ # Copyright: Copyright (c) 2017
5
+ # License: None
6
+ #
7
+ #-------------------------------------------------------------------------------
8
+
9
+ require 'json'
10
+
11
+ require 'extensions.rb'
12
+ require 'sketchup.rb'
13
+
14
+ module Example
15
+ module HelloWorld
16
+
17
+ file = __FILE__.dup
18
+ # Account for Ruby encoding bug under Windows.
19
+ file.force_encoding('UTF-8') if file.respond_to?(:force_encoding)
20
+ # Support folder should be named the same as the root .rb file.
21
+ folder_name = File.basename(file, '.*')
22
+
23
+ # Path to the root .rb file (this file).
24
+ PATH_ROOT = File.dirname(file).freeze
25
+
26
+ # Path to the support folder.
27
+ PATH = File.join(PATH_ROOT, folder_name).freeze
28
+
29
+ # Extension information.
30
+ extension_json_file = File.join(PATH, 'extension.json')
31
+ extension_json = File.read(extension_json_file)
32
+ EXTENSION = ::JSON.parse(extension_json, symbolize_names: true).freeze
33
+
34
+ unless file_loaded?(__FILE__)
35
+ loader = File.join(PATH, 'main')
36
+ @extension = SketchupExtension.new(EXTENSION[:name], loader)
37
+ @extension.description = EXTENSION[:description]
38
+ @extension.version = EXTENSION[:version]
39
+ @extension.copyright = EXTENSION[:copyright]
40
+ @extension.creator = EXTENSION[:creator]
41
+ Sketchup.register_extension(@extension, true)
42
+ end
43
+
44
+ end # module HelloWorld
45
+ end # module Example
46
+
47
+ file_loaded(__FILE__)
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "Hello World",
3
+ "description": "",
4
+ "creator": "Unknown",
5
+ "copyright": "Copyright (c) 2017",
6
+ "license": "None",
7
+ "product_id": "Example_HelloWorld",
8
+ "version": "0.1.0",
9
+ "build": "1"
10
+ }
@@ -0,0 +1,21 @@
1
+ require 'sketchup.rb'
2
+
3
+ module Example::HelloWorld
4
+
5
+ unless file_loaded?(__FILE__)
6
+ menu = UI.menu('Plugins').add_submenu(EXTENSION[:name])
7
+ menu.add_item('Make Magic') { self.make_magic }
8
+ menu.add_separator
9
+ menu.add_item('Help...') { self.open_help }
10
+ file_loaded(__FILE__)
11
+ end
12
+
13
+ def self.make_magic
14
+ # Do magic here...
15
+ end
16
+
17
+ def self.open_help
18
+ UI.openURL(EXTENSION[:url])
19
+ end
20
+
21
+ end # module
@@ -1,5 +1,9 @@
1
- require "skippy/version"
1
+ require 'skippy/version'
2
2
 
3
3
  module Skippy
4
- # Your code goes here...
5
- end
4
+
5
+ class << self
6
+ attr_accessor :app
7
+ end
8
+
9
+ end # module
@@ -1,8 +1,8 @@
1
1
  require 'pathname'
2
2
 
3
+ require 'skippy'
3
4
  require 'skippy/command'
4
5
  require 'skippy/group'
5
- require 'skippy/skippy'
6
6
 
7
7
  class Skippy::App
8
8
 
@@ -11,6 +11,7 @@ class Skippy::App
11
11
  def self.boot(boot_loader_path)
12
12
  Skippy.app = Skippy::App.new(boot_loader_path)
13
13
  Skippy.app.boot
14
+ Skippy.app
14
15
  end
15
16
 
16
17
  attr_reader :path
@@ -35,27 +36,28 @@ class Skippy::App
35
36
  Pathname.new(File.join(path, 'templates'))
36
37
  end
37
38
 
39
+ # @return [Array<Pathname>]
38
40
  def templates
39
41
  result = []
40
42
  templates_source_path.entries.each { |entry|
41
43
  template_path = templates_source_path.join(entry)
42
44
  next unless template_path.directory?
43
- next if %[. ..].include?(entry.basename.to_s)
44
- result << entry
45
+ next if %w[. ..].include?(entry.basename.to_s)
46
+ result << entry.expand_path(templates_source_path)
45
47
  }
46
48
  result
47
49
  end
48
50
 
49
51
  private
50
52
 
51
- # @return [Array<String>] loaded files
52
53
  def boot_commands
53
54
  # Load the default skippy commands.
54
55
  path_commands = File.join(path, 'commands')
55
56
  commands_pattern = File.join(path_commands, '*.rb')
56
57
  Dir.glob(commands_pattern) { |filename|
58
+ # noinspection RubyResolve
57
59
  require filename
58
60
  }
59
61
  end
60
62
 
61
- end
63
+ end
@@ -31,11 +31,11 @@ class Skippy::CLI < Skippy::Command
31
31
 
32
32
  end # Class methods
33
33
 
34
- map "-v" => :version
34
+ map '-v' => :version
35
35
 
36
36
  default_command :list
37
37
 
38
- desc "version", "Show Skippy version"
38
+ desc 'version', 'Show Skippy version'
39
39
  def version
40
40
  display_app_banner
41
41
  end
@@ -48,7 +48,7 @@ class Skippy::CLI < Skippy::Command
48
48
  initialize_thorfiles(meth)
49
49
  klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
50
50
  self.class.handle_no_command_error(command, false) if klass.nil?
51
- klass.start(["-h", command].compact, :shell => shell)
51
+ klass.start(['-h', command].compact, :shell => shell)
52
52
  else
53
53
  super
54
54
  end
@@ -68,14 +68,14 @@ class Skippy::CLI < Skippy::Command
68
68
  end
69
69
 
70
70
  # Verbatim copy from Thor::Runner:
71
- desc "list [SEARCH]", "List the available #{$PROGRAM_NAME} commands (--substring means .*SEARCH)"
71
+ desc 'list [SEARCH]', "List the available #{$PROGRAM_NAME} commands (--substring means .*SEARCH)"
72
72
  method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
73
- def list(search = "")
73
+ def list(search = '')
74
74
  initialize_thorfiles
75
75
 
76
- search = ".*#{search}" if options["substring"]
76
+ search = ".*#{search}" if options['substring']
77
77
  search = /^#{search}.*/i
78
- group = options[:group] || "standard"
78
+ group = options[:group] || 'standard'
79
79
 
80
80
  klasses = Thor::Base.subclasses.select do |k|
81
81
  (options[:all] || k.group == group) && k.namespace =~ search
@@ -120,7 +120,7 @@ class Skippy::CLI < Skippy::Command
120
120
  end
121
121
 
122
122
  # Based on Thor::Runner:
123
- def display_klasses(with_modules = false, show_internal = false, klasses = Thor::Base.subclasses)
123
+ def display_klasses(_with_modules = false, show_internal = false, klasses = Thor::Base.subclasses)
124
124
  unless show_internal
125
125
  klasses -= [
126
126
  Thor, Thor::Runner, Thor::Group,
@@ -135,7 +135,7 @@ class Skippy::CLI < Skippy::Command
135
135
 
136
136
  # Get classes which inherit from Thor
137
137
  (klasses - groups).each { |k|
138
- list[k.namespace.split(":").first] += k.printable_commands(false)
138
+ list[k.namespace.split(':').first] += k.printable_commands(false)
139
139
  }
140
140
 
141
141
  # Get classes which inherit from Thor::Base
@@ -156,7 +156,7 @@ class Skippy::CLI < Skippy::Command
156
156
 
157
157
  # Order namespaces with default coming first
158
158
  list = list.sort { |a, b|
159
- a[0].sub(/^default/, "") <=> b[0].sub(/^default/, "")
159
+ a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '')
160
160
  }
161
161
  list.each { |n, commands|
162
162
  display_commands(n, commands, col_width) unless commands.empty?
@@ -189,10 +189,10 @@ class Skippy::CLI < Skippy::Command
189
189
  labels = %w[Modules Namespaces]
190
190
 
191
191
  info << labels
192
- info << ["-" * labels[0].size, "-" * labels[1].size]
192
+ info << ['-' * labels[0].size, '-' * labels[1].size]
193
193
 
194
194
  print_table info
195
- say ""
195
+ say ''
196
196
  end
197
197
 
198
198
  end
@@ -0,0 +1,135 @@
1
+ require 'json'
2
+ require 'pathname'
3
+
4
+ require 'skippy/error'
5
+
6
+ class Skippy::Config < Hash
7
+
8
+ attr_accessor :path
9
+
10
+ class MissingPathError < Skippy::Error; end
11
+
12
+ def self.load(path, defaults = {})
13
+ if path.exist?
14
+ json = File.read(path)
15
+ config = JSON.parse(json,
16
+ symbolize_names: true,
17
+ object_class: self
18
+ )
19
+ else
20
+ config = self.new
21
+ end
22
+ # Need to merge nested defaults.
23
+ config.merge!(defaults) { |_key, value, default|
24
+ if value.is_a?(Hash) && default.is_a?(Hash)
25
+ # Deep merge in order to merge nested hashes.
26
+ # Note: This currently doesn't merge arrays.
27
+ # http://stackoverflow.com/a/9381776/486990
28
+ merger = proc { |_k, v1, v2|
29
+ Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
30
+ }
31
+ default.merge(value, &merger)
32
+ else
33
+ value || default
34
+ end
35
+ }
36
+ config.path = path
37
+ config
38
+ end
39
+
40
+ def get(key_path, default = nil)
41
+ get_item(key_path) || default
42
+ end
43
+
44
+ def set(key_path, value)
45
+ set_item(key_path, value)
46
+ end
47
+
48
+ def push(key_path, value)
49
+ item = get_item(key_path)
50
+ item = set_item(key_path, []) if item.nil?
51
+ raise ArgumentError, 'key path is not an Array' unless item.is_a?(Array)
52
+ item << value
53
+ end
54
+
55
+ def export(target_path)
56
+ json = JSON.pretty_generate(self)
57
+ File.write(target_path, json)
58
+ nil
59
+ end
60
+
61
+ def save_as(target_path)
62
+ export(target_path)
63
+ @path = target_path
64
+ nil
65
+ end
66
+
67
+ def save
68
+ raise MissingPathError if path.nil?
69
+ export(path)
70
+ end
71
+
72
+ def path=(new_path)
73
+ @path = Pathname.new(new_path)
74
+ end
75
+
76
+ def update(hash)
77
+ if hash.keys.first.is_a?(String)
78
+ update_from_key_paths(hash)
79
+ else
80
+ update_from_hash(hash)
81
+ end
82
+ self
83
+ end
84
+
85
+ def inspect
86
+ "#{super}:#{self.class.name}"
87
+ end
88
+
89
+ private
90
+
91
+ def update_from_hash(hash)
92
+ merger = proc { |_key, v1, v2|
93
+ Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
94
+ }
95
+ merge!(hash, &merger)
96
+ end
97
+
98
+ def update_from_key_paths(key_paths)
99
+ key_paths.each { |key_path, value|
100
+ set(key_path, value)
101
+ }
102
+ end
103
+
104
+ def key_parts(key_path)
105
+ if key_path.is_a?(Symbol)
106
+ [key_path]
107
+ else
108
+ key_path.split('/').map { |key| key.intern }
109
+ end
110
+ end
111
+
112
+ def get_item(key_path)
113
+ parts = key_parts(key_path)
114
+ return nil if parts.empty?
115
+ item = self
116
+ parts.each { |key|
117
+ return nil if item.nil?
118
+ item = item[key]
119
+ }
120
+ item
121
+ end
122
+
123
+ def set_item(key_path, value)
124
+ item = self
125
+ parts = key_parts(key_path)
126
+ last_key = parts.pop
127
+ parts.each { |key|
128
+ item[key] ||= self.class.new
129
+ item = item[key]
130
+ }
131
+ item[last_key] = value
132
+ value
133
+ end
134
+
135
+ end