skippy 0.3.0.a → 0.4.3.a
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.
- checksums.yaml +4 -4
- data/.appveyor.yml +32 -0
- data/.rubocop.yml +31 -1
- data/.vscode/tasks.json +14 -12
- data/Gemfile +2 -1
- data/README.md +28 -3
- data/Rakefile +3 -0
- data/app/commands/install.rb +1 -1
- data/app/commands/lib.rb +2 -1
- data/app/commands/new.rb +1 -0
- data/app/commands/sketchup.rb +66 -0
- data/lib/skippy/app.rb +1 -0
- data/lib/skippy/cli.rb +8 -5
- data/lib/skippy/config.rb +4 -0
- data/lib/skippy/config_accessors.rb +2 -0
- data/lib/skippy/helpers/file.rb +1 -0
- data/lib/skippy/installer/git.rb +5 -2
- data/lib/skippy/lib_module.rb +1 -0
- data/lib/skippy/lib_source.rb +5 -1
- data/lib/skippy/library.rb +2 -0
- data/lib/skippy/library_manager.rb +8 -0
- data/lib/skippy/module_manager.rb +10 -2
- data/lib/skippy/namespace.rb +2 -0
- data/lib/skippy/os.rb +17 -0
- data/lib/skippy/os/common.rb +33 -0
- data/lib/skippy/os/mac.rb +34 -0
- data/lib/skippy/os/win.rb +58 -0
- data/lib/skippy/project.rb +4 -2
- data/lib/skippy/sketchup/app.rb +11 -0
- data/lib/skippy/version.rb +1 -1
- data/skippy.gemspec +2 -2
- metadata +25 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 991d733215aa26f37690ad9c68cd6d515e648c287584c1acaa91d54ddfb74544
|
4
|
+
data.tar.gz: c5da843a98f179df55787c15805b3e0ea7b614bad8dcd450d1b503b0295050f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d095d565fc66112b57b16ab89d807ce8b2d3f4a8dc0dd8edd27f5456224a37b906b5b023bf9937fdb8fd533ea18fac75af7fad9ef61f735f003854c225f1ade
|
7
|
+
data.tar.gz: 2cc778b7b6b08973447c1868944302c2debb5a3b6e7ba03474873997f45c6b1dcd7af32866aab776740035eb0a4b3050c07dcbb7fa5f41837ee09ce1301fc748
|
data/.appveyor.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
version: "{build}-{branch}"
|
2
|
+
|
3
|
+
branches:
|
4
|
+
only:
|
5
|
+
- master
|
6
|
+
- dev-appveyor
|
7
|
+
|
8
|
+
cache:
|
9
|
+
- vendor/bundle
|
10
|
+
|
11
|
+
environment:
|
12
|
+
matrix:
|
13
|
+
- RUBY_VERSION: 25
|
14
|
+
- RUBY_VERSION: 26
|
15
|
+
|
16
|
+
install:
|
17
|
+
- set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
|
18
|
+
- gem update --no-document --system 2.7.8
|
19
|
+
- gem install bundler --no-document --version="<2.0.0"
|
20
|
+
- bundle config --local path vendor/bundle
|
21
|
+
- bundle install
|
22
|
+
- git submodule update --init --recursive
|
23
|
+
|
24
|
+
build: off
|
25
|
+
|
26
|
+
before_test:
|
27
|
+
- ruby -v
|
28
|
+
- gem -v
|
29
|
+
- bundle -v
|
30
|
+
|
31
|
+
test_script:
|
32
|
+
- bundle exec rake
|
data/.rubocop.yml
CHANGED
@@ -9,6 +9,7 @@ AllCops:
|
|
9
9
|
- 'vendor/**/*'
|
10
10
|
DisplayCopNames: true
|
11
11
|
|
12
|
+
|
12
13
|
Layout/AlignParameters:
|
13
14
|
EnforcedStyle: with_fixed_indentation
|
14
15
|
|
@@ -36,6 +37,11 @@ Layout/EndOfLine:
|
|
36
37
|
Layout/EmptyLinesAroundBlockBody:
|
37
38
|
Enabled: false
|
38
39
|
|
40
|
+
|
41
|
+
Naming/RescuedExceptionsVariableName:
|
42
|
+
PreferredName: error
|
43
|
+
|
44
|
+
|
39
45
|
Metrics/AbcSize:
|
40
46
|
Enabled: false
|
41
47
|
Exclude:
|
@@ -45,6 +51,10 @@ Metrics/ClassLength:
|
|
45
51
|
Exclude:
|
46
52
|
- test/**/*
|
47
53
|
|
54
|
+
# Too noisy.
|
55
|
+
Metrics/CyclomaticComplexity:
|
56
|
+
Enabled: false
|
57
|
+
|
48
58
|
Metrics/LineLength:
|
49
59
|
Exclude:
|
50
60
|
- features/step_definitions/**/*
|
@@ -53,6 +63,11 @@ Metrics/MethodLength:
|
|
53
63
|
Exclude:
|
54
64
|
- test/**/*
|
55
65
|
|
66
|
+
# Too noisy.
|
67
|
+
Metrics/PerceivedComplexity:
|
68
|
+
Enabled: false
|
69
|
+
|
70
|
+
|
56
71
|
# Prefer { ... } over do ... end except for control flow and
|
57
72
|
# method defintions. Unfortunatly, no cop configuration for this.
|
58
73
|
# https://github.com/chneukirchen/styleguide/blob/e60de37b478d3f892f6985a58d573016f33f0269/RUBY-STYLE#L63-L67
|
@@ -82,6 +97,18 @@ Style/Documentation:
|
|
82
97
|
Style/GuardClause:
|
83
98
|
Enabled: false
|
84
99
|
|
100
|
+
# In the context of the Thor DLS the rocket arrow => reads better.
|
101
|
+
Style/HashSyntax:
|
102
|
+
Exclude:
|
103
|
+
- app/commands/**/*
|
104
|
+
|
105
|
+
# Some times it reads clearer to not trail if/unless at the end.
|
106
|
+
Style/IfUnlessModifier:
|
107
|
+
Enabled: false
|
108
|
+
|
109
|
+
Style/ModuleFunction:
|
110
|
+
Enabled: false
|
111
|
+
|
85
112
|
# %w and %i etc isn't really intuitive unless you are really familiar with the
|
86
113
|
# syntax. %w seems used often enough. But [:symbol, :foo] reads clearer than
|
87
114
|
# %i(symbol foo).
|
@@ -89,5 +116,8 @@ Style/SymbolArray:
|
|
89
116
|
Enabled: False
|
90
117
|
|
91
118
|
# Add trailing comma so it's easy to duplicate/add lines.
|
92
|
-
Style/
|
119
|
+
Style/TrailingCommaInArrayLiteral:
|
120
|
+
EnforcedStyleForMultiline: consistent_comma
|
121
|
+
|
122
|
+
Style/TrailingCommaInHashLiteral:
|
93
123
|
EnforcedStyleForMultiline: consistent_comma
|
data/.vscode/tasks.json
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
{
|
2
2
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
3
3
|
// for the documentation about the tasks.json format
|
4
|
-
"version": "0.
|
5
|
-
"
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
"version": "2.0.0",
|
5
|
+
"tasks": [
|
6
|
+
{
|
7
|
+
"label": "rake test FILE",
|
8
|
+
"type": "shell",
|
9
|
+
"command": "bundle",
|
10
|
+
"args": [
|
11
|
+
"exec",
|
12
|
+
"rake",
|
13
|
+
"TEST=${relativeFile}"
|
14
|
+
],
|
15
|
+
"group": "test"
|
16
|
+
}
|
17
|
+
]
|
16
18
|
}
|
data/Gemfile
CHANGED
@@ -13,6 +13,7 @@ group :development do
|
|
13
13
|
# gem 'aruba', git: 'https://github.com/rbld/aruba.git',
|
14
14
|
# branch: 'aruba-win-fix'
|
15
15
|
gem 'pry'
|
16
|
-
gem 'rubocop', '~> 0.
|
16
|
+
gem 'rubocop', '~> 0.67.2', require: false
|
17
|
+
gem 'rubocop-performance', '~> 1.1.0', require: false
|
17
18
|
gem 'webmock', '~> 3.1'
|
18
19
|
end
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Skippy
|
2
2
|
|
3
|
-
[](https://badge.fury.io/rb/skippy)
|
3
|
+
[](https://badge.fury.io/rb/skippy) [](https://ci.appveyor.com/project/thomthom/skippy/branch/master)
|
4
4
|
|
5
5
|
Skippy is a Command Line Interface which aims to automate common developer tasks for SketchUp Ruby extension development.
|
6
6
|
|
@@ -14,7 +14,8 @@ Some of the main goals are:
|
|
14
14
|
- [ ] Add/Remove/Update user templates
|
15
15
|
- [ ] Automate common tasks
|
16
16
|
- [ ] Packaging the extension
|
17
|
-
- [
|
17
|
+
- [x] Launch SketchUp
|
18
|
+
- [x] Launch SketchUp in debug mode
|
18
19
|
- [x] Easy interface to add per-project custom commands/tasks
|
19
20
|
- [x] Library dependency management
|
20
21
|
- [x] Pull in third-party modules into extension namespace
|
@@ -31,7 +32,7 @@ For Windows the easiest way to get Ruby running is using the [Ruby Installer for
|
|
31
32
|
## Installation
|
32
33
|
|
33
34
|
```bash
|
34
|
-
gem install skippy
|
35
|
+
gem install skippy --pre
|
35
36
|
```
|
36
37
|
|
37
38
|
## Usage
|
@@ -201,6 +202,30 @@ For more examples, refer to:
|
|
201
202
|
* [github.com/thomthom/tt-lib](https://github.com/thomthom/tt-lib)
|
202
203
|
* [github.com/thomthom/skippy-test-lib](https://github.com/thomthom/skippy-test-lib)
|
203
204
|
|
205
|
+
### Launching SketchUp
|
206
|
+
|
207
|
+
Skippy will attempt to locate your SketchUp installations and offer commands to launch them.
|
208
|
+
|
209
|
+
These commands provides a cross platform way of launching SketchUp which can be useful in build scripts or IDE automation tasks.
|
210
|
+
|
211
|
+
(**Note:** Currently Skippy assumes that SketchUp is installed to its default installation directory.)
|
212
|
+
|
213
|
+
`skippy sketchup:list` will display a list of all known SketchUp versions on the system.
|
214
|
+
|
215
|
+

|
216
|
+
|
217
|
+
To launch one, use `skippy sketchup:launch VERSION`, for instance:
|
218
|
+
|
219
|
+
```
|
220
|
+
skippy sketchup:launch 2018
|
221
|
+
```
|
222
|
+
|
223
|
+
You can also launch SketchUp in debug mode if the [SketchUp Ruby Debugger library](https://github.com/SketchUp/sketchup-ruby-debugger) is installed.
|
224
|
+
|
225
|
+
```
|
226
|
+
skippy sketchup:debug 2018
|
227
|
+
```
|
228
|
+
|
204
229
|
## Development
|
205
230
|
|
206
231
|
After checking out the repository, 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.
|
data/Rakefile
CHANGED
@@ -5,6 +5,9 @@ Rake::TestTask.new(:test) do |t|
|
|
5
5
|
t.libs << 'test'
|
6
6
|
t.libs << 'lib'
|
7
7
|
t.test_files = FileList['test/**/*_test.rb']
|
8
|
+
# Turning off because Rake 11 >= turns warning on by default.
|
9
|
+
# TODO: Clean up the warnings coming from this project and enable.
|
10
|
+
t.warning = false
|
8
11
|
end
|
9
12
|
|
10
13
|
task default: :test
|
data/app/commands/install.rb
CHANGED
@@ -22,7 +22,7 @@ class Install < Skippy::Command::Group
|
|
22
22
|
next if library[:version].nil? || library[:source].nil?
|
23
23
|
|
24
24
|
options = {
|
25
|
-
requirement: library[:version]
|
25
|
+
requirement: library[:version],
|
26
26
|
}
|
27
27
|
options[:branch] = library[:branch] unless library[:branch].nil?
|
28
28
|
lib = project.libraries.install(library[:source], options)
|
data/app/commands/lib.rb
CHANGED
@@ -39,7 +39,8 @@ class Lib < Skippy::Command
|
|
39
39
|
def install(source)
|
40
40
|
project = Skippy::Project.current_or_fail
|
41
41
|
libraries = project.libraries
|
42
|
-
|
42
|
+
installation_options = install_options(options)
|
43
|
+
library = libraries.install(source, installation_options) { |type, message|
|
43
44
|
color = type == :warning ? :red : :yellow
|
44
45
|
say message, color
|
45
46
|
}
|
data/app/commands/new.rb
CHANGED
@@ -38,6 +38,7 @@ class New < Skippy::Command::Group
|
|
38
38
|
if project.exist?
|
39
39
|
raise Skippy::Error, "A project already exist: #{project.filename}"
|
40
40
|
end
|
41
|
+
|
41
42
|
project.namespace = namespace
|
42
43
|
project.name = project.namespace.to_name
|
43
44
|
project.basename = options[:basename] || project.namespace.short_name
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
require 'skippy/error'
|
5
|
+
require 'skippy/os'
|
6
|
+
|
7
|
+
class Sketchup < Skippy::Command
|
8
|
+
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
option :port, :type => :numeric, :default => 7000
|
12
|
+
desc 'debug VERSION', 'Start SketchUp with Ruby Debugger'
|
13
|
+
def debug(version)
|
14
|
+
app = find_sketchup(version)
|
15
|
+
unless app.can_debug
|
16
|
+
raise Skippy::Error, "Debug library not installed for Sketchup #{version}"
|
17
|
+
end
|
18
|
+
|
19
|
+
arguments = ['-rdebug', %("ide port=#{options.port}")]
|
20
|
+
Skippy.os.launch_app(app.executable, *arguments)
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'launch VERSION', 'Start SketchUp'
|
24
|
+
def launch(version)
|
25
|
+
app = find_sketchup(version)
|
26
|
+
Skippy.os.launch_app(app.executable)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'list', 'List all known SketchUp versions'
|
30
|
+
def list
|
31
|
+
say shell.set_color('Known SketchUp versions:', :yellow, true)
|
32
|
+
Skippy.os.sketchup_apps.each { |sketchup|
|
33
|
+
version = sketchup.version.to_s.ljust(4)
|
34
|
+
sketchup_name = "SketchUp #{version}"
|
35
|
+
bitness = sketchup.is64bit ? '64bit' : '32bit'
|
36
|
+
debug = sketchup.can_debug ? '(debugger)' : ''
|
37
|
+
# TODO(thomthom): Use print_table ?
|
38
|
+
output = StringIO.new
|
39
|
+
output.write ' '
|
40
|
+
output.write shell.set_color(sketchup_name, :green, false)
|
41
|
+
output.write ' '
|
42
|
+
output.write bitness
|
43
|
+
output.write ' '
|
44
|
+
output.write shell.set_color(debug, :yellow, false)
|
45
|
+
say output.string
|
46
|
+
}
|
47
|
+
end
|
48
|
+
default_command(:list)
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# @param [Integer] version
|
53
|
+
# @return [Skippy::SketchUpApp, nil]
|
54
|
+
def find_sketchup(version)
|
55
|
+
# Allow shortcuts such as 18 to mean 2018.
|
56
|
+
full_version = version.to_i
|
57
|
+
full_version += 2000 if (13..99).cover?(full_version)
|
58
|
+
app = Skippy.os.sketchup_apps.find { |sketchup|
|
59
|
+
sketchup.version == full_version
|
60
|
+
}
|
61
|
+
raise Skippy::Error, "SketchUp #{version} not found." if app.nil?
|
62
|
+
|
63
|
+
app
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/skippy/app.rb
CHANGED
data/lib/skippy/cli.rb
CHANGED
@@ -57,11 +57,12 @@ class Skippy::CLI < Skippy::Command
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
# rubocop:disable Style/MethodMissingSuper,Style/MissingRespondToMissing
|
60
61
|
# Verbatim copy from Thor::Runner:
|
61
62
|
# If a command is not found on Thor::Runner, method missing is invoked and
|
62
63
|
# Thor::Runner is then responsible for finding the command in all classes.
|
63
64
|
#
|
64
|
-
def method_missing(meth, *args)
|
65
|
+
def method_missing(meth, *args)
|
65
66
|
meth = meth.to_s
|
66
67
|
initialize_thorfiles(meth)
|
67
68
|
klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
|
@@ -69,14 +70,15 @@ class Skippy::CLI < Skippy::Command
|
|
69
70
|
args.unshift(command) if command
|
70
71
|
klass.start(args, shell: shell)
|
71
72
|
end
|
73
|
+
# rubocop:enable Style/MethodMissingSuper,Style/MissingRespondToMissing
|
72
74
|
|
73
75
|
# Verbatim copy from Thor::Runner:
|
74
76
|
desc 'list [SEARCH]',
|
75
77
|
"List the available #{$PROGRAM_NAME} commands (--substring means .*SEARCH)"
|
76
78
|
method_options substring: :boolean,
|
77
|
-
group:
|
78
|
-
all:
|
79
|
-
debug:
|
79
|
+
group: :string,
|
80
|
+
all: :boolean,
|
81
|
+
debug: :boolean
|
80
82
|
def list(search = '')
|
81
83
|
initialize_thorfiles
|
82
84
|
|
@@ -112,8 +114,9 @@ class Skippy::CLI < Skippy::Command
|
|
112
114
|
def initialize_thorfiles(_relevant_to = nil, _skip_lookup = false)
|
113
115
|
project = Skippy::Project.new(Dir.pwd)
|
114
116
|
return unless project.exist?
|
117
|
+
|
115
118
|
project.command_files { |filename|
|
116
|
-
unless Thor::Base.subclass_files.
|
119
|
+
unless Thor::Base.subclass_files.key?(File.expand_path(filename))
|
117
120
|
begin
|
118
121
|
Thor::Util.load_thorfile(filename, nil, options[:debug])
|
119
122
|
rescue ScriptError, StandardError => error
|
data/lib/skippy/config.rb
CHANGED
@@ -35,6 +35,7 @@ class Skippy::Config < Hash
|
|
35
35
|
item = get_item(key_path)
|
36
36
|
item = set_item(key_path, []) if item.nil?
|
37
37
|
raise ArgumentError, 'key path is not an Array' unless item.is_a?(Array)
|
38
|
+
|
38
39
|
item << value
|
39
40
|
end
|
40
41
|
|
@@ -52,6 +53,7 @@ class Skippy::Config < Hash
|
|
52
53
|
|
53
54
|
def save
|
54
55
|
raise MissingPathError if path.nil?
|
56
|
+
|
55
57
|
export(path)
|
56
58
|
end
|
57
59
|
|
@@ -117,9 +119,11 @@ class Skippy::Config < Hash
|
|
117
119
|
def get_item(key_path)
|
118
120
|
parts = key_parts(key_path)
|
119
121
|
return nil if parts.empty?
|
122
|
+
|
120
123
|
item = self
|
121
124
|
parts.each { |key|
|
122
125
|
return nil if item.nil?
|
126
|
+
|
123
127
|
item = item[key]
|
124
128
|
}
|
125
129
|
item
|
@@ -15,6 +15,7 @@ module Skippy::ConfigAccessors
|
|
15
15
|
class_eval do
|
16
16
|
symbols.each { |symbol|
|
17
17
|
raise TypeError unless symbol.is_a?(Symbol)
|
18
|
+
|
18
19
|
define_method(symbol) do
|
19
20
|
value = @config.get(key || symbol, default)
|
20
21
|
value = type.new(value) if type && !value.is_a?(type)
|
@@ -29,6 +30,7 @@ module Skippy::ConfigAccessors
|
|
29
30
|
class_eval do
|
30
31
|
symbols.each { |symbol|
|
31
32
|
raise TypeError unless symbol.is_a?(Symbol)
|
33
|
+
|
32
34
|
symbol_set = "#{symbol}=".intern
|
33
35
|
define_method(symbol_set) do |value|
|
34
36
|
value = type.new(value) if type && !value.is_a?(type)
|
data/lib/skippy/helpers/file.rb
CHANGED
data/lib/skippy/installer/git.rb
CHANGED
@@ -27,7 +27,7 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
|
|
27
27
|
end
|
28
28
|
begin
|
29
29
|
checkout_branch(git, source.branch) if source.branch
|
30
|
-
checkout_tag(git, source.requirement) unless edge_version?(source.requirement)
|
30
|
+
checkout_tag(git, source.requirement) unless edge_version?(source.requirement) # rubocop:disable Metrics/LineLength
|
31
31
|
rescue Skippy::Error
|
32
32
|
git.checkout(previous_commit) if previous_commit
|
33
33
|
raise
|
@@ -62,11 +62,12 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
|
|
62
62
|
# @param [Git::Base]
|
63
63
|
# @param [String] branch
|
64
64
|
def checkout_branch(git, branch)
|
65
|
-
branches = git.
|
65
|
+
branches = git.branches.map(&:name)
|
66
66
|
info "Branches: #{branches.inspect}"
|
67
67
|
unless branches.include?(branch)
|
68
68
|
raise Skippy::BranchNotFound, "Found no branch named: '#{branch}'"
|
69
69
|
end
|
70
|
+
|
70
71
|
git.checkout(branch)
|
71
72
|
nil
|
72
73
|
end
|
@@ -77,6 +78,7 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
|
|
77
78
|
tags = Naturally.sort_by(git.tags, :name)
|
78
79
|
tag = latest_version?(version) ? tags.last : resolve_tag(tags, version)
|
79
80
|
raise Skippy::TagNotFound, "Found no version: '#{version}'" if tag.nil?
|
81
|
+
|
80
82
|
git.checkout(tag)
|
81
83
|
# Verify the library version with the tagged version.
|
82
84
|
target = path.join(source.lib_path)
|
@@ -97,6 +99,7 @@ class Skippy::GitLibraryInstaller < Skippy::LibraryInstaller
|
|
97
99
|
requirement = Gem::Requirement.new(version)
|
98
100
|
tags.reverse.find { |tag|
|
99
101
|
next false unless Gem::Version.correct?(tag.name)
|
102
|
+
|
100
103
|
tag_version = Gem::Version.new(tag.name)
|
101
104
|
requirement.satisfied_by?(tag_version)
|
102
105
|
}
|
data/lib/skippy/lib_module.rb
CHANGED
data/lib/skippy/lib_source.rb
CHANGED
@@ -40,6 +40,7 @@ class Skippy::LibrarySource
|
|
40
40
|
# @return [String, nil]
|
41
41
|
def requirement
|
42
42
|
return nil if @options[:requirement].nil?
|
43
|
+
|
43
44
|
# Normalize the version requirement pattern.
|
44
45
|
parts = Gem::Requirement.parse(@options[:requirement])
|
45
46
|
# .parse will from '1.2.3' return ['=', '1.2.3']. Don't need that.
|
@@ -117,7 +118,10 @@ class Skippy::LibrarySource
|
|
117
118
|
# @param [String] source
|
118
119
|
# @return [String]
|
119
120
|
def resolve_from_git_uri(source)
|
120
|
-
|
121
|
+
# This can be a local Windows path, normalize path separators to allow the
|
122
|
+
# path to be parsed.
|
123
|
+
normalized = source.tr('\\', '/')
|
124
|
+
uri = URI.parse(normalized)
|
121
125
|
# When logged in, BitBucket will display a URI with the user's username.
|
122
126
|
uri.user = ''
|
123
127
|
uri.to_s
|
data/lib/skippy/library.rb
CHANGED
@@ -28,8 +28,10 @@ class Skippy::Library
|
|
28
28
|
@path = Pathname.new(path)
|
29
29
|
raise LibraryNotFoundError, @path.to_s unless @path.directory?
|
30
30
|
raise LibraryNotFoundError, config_file.to_s unless config_file.exist?
|
31
|
+
|
31
32
|
@config = Skippy::Config.load(config_file)
|
32
33
|
raise LibraryNotFoundError, 'Not a Skippy Library' unless @config[:library]
|
34
|
+
|
33
35
|
@source = source
|
34
36
|
end
|
35
37
|
|
@@ -29,6 +29,7 @@ class Skippy::LibraryManager
|
|
29
29
|
# @param [Skippy::Project] project
|
30
30
|
def initialize(project)
|
31
31
|
raise TypeError, 'expected a Project' unless project.is_a?(Skippy::Project)
|
32
|
+
|
32
33
|
@project = project
|
33
34
|
@libraries = SortedSet.new(discover_libraries)
|
34
35
|
end
|
@@ -56,8 +57,10 @@ class Skippy::LibraryManager
|
|
56
57
|
if library_name.nil? || module_name.nil?
|
57
58
|
raise ArgumentError, 'expected a module path'
|
58
59
|
end
|
60
|
+
|
59
61
|
library = find_library(library_name)
|
60
62
|
return nil if library.nil?
|
63
|
+
|
61
64
|
library.modules.find { |mod| mod.basename.casecmp(module_name).zero? }
|
62
65
|
end
|
63
66
|
|
@@ -77,6 +80,7 @@ class Skippy::LibraryManager
|
|
77
80
|
# @return [Skippy::Library]
|
78
81
|
def install(source, options = {})
|
79
82
|
raise Skippy::Project::ProjectNotSavedError unless project.exist?
|
83
|
+
|
80
84
|
lib_source = Skippy::LibrarySource.new(project, source, options)
|
81
85
|
|
82
86
|
installer = get_installer(lib_source)
|
@@ -99,8 +103,10 @@ class Skippy::LibraryManager
|
|
99
103
|
# @return [Skippy::Library]
|
100
104
|
def uninstall(lib)
|
101
105
|
raise Skippy::Project::ProjectNotSavedError unless project.exist?
|
106
|
+
|
102
107
|
library = lib.is_a?(Skippy::Library) ? lib : find_library(lib)
|
103
108
|
raise Skippy::LibraryNotFound, 'Library not found' if library.nil?
|
109
|
+
|
104
110
|
# Uninstall modules first - using the module manager.
|
105
111
|
vendor_path = project.modules.vendor_path
|
106
112
|
vendor_module_path = vendor_path.join(library.name)
|
@@ -113,9 +119,11 @@ class Skippy::LibraryManager
|
|
113
119
|
vendor_path.rmdir
|
114
120
|
end
|
115
121
|
raise 'Unable to remove vendor modules' if vendor_module_path.exist?
|
122
|
+
|
116
123
|
# Now the library itself is safe to remove.
|
117
124
|
library.path.rmtree if library.path.exist?
|
118
125
|
raise 'Unable to remove library' if library.path.exist?
|
126
|
+
|
119
127
|
@libraries.delete(library)
|
120
128
|
library
|
121
129
|
end
|
@@ -17,6 +17,7 @@ class Skippy::ModuleManager
|
|
17
17
|
# @param [Skippy::Project] project
|
18
18
|
def initialize(project)
|
19
19
|
raise TypeError, 'expected a Project' unless project.is_a?(Skippy::Project)
|
20
|
+
|
20
21
|
@project = project
|
21
22
|
@modules = SortedSet.new(discover_modules)
|
22
23
|
end
|
@@ -48,6 +49,7 @@ class Skippy::ModuleManager
|
|
48
49
|
# @return [Skippy::LibModule]
|
49
50
|
def use(module_name)
|
50
51
|
raise Skippy::Project::ProjectNotSavedError unless project.exist?
|
52
|
+
|
51
53
|
lib_module = project.libraries.find_module_or_fail(module_name)
|
52
54
|
|
53
55
|
source = lib_module.path
|
@@ -63,6 +65,7 @@ class Skippy::ModuleManager
|
|
63
65
|
# @return [Array<Skippy::LibModule>]
|
64
66
|
def update(library)
|
65
67
|
raise Skippy::Project::ProjectNotSavedError unless project.exist?
|
68
|
+
|
66
69
|
installed = select { |mod| mod.library.name.casecmp(library.name).zero? }
|
67
70
|
installed.each { |mod| use(mod.name) }
|
68
71
|
installed
|
@@ -72,6 +75,7 @@ class Skippy::ModuleManager
|
|
72
75
|
# @return [Skippy::LibModule]
|
73
76
|
def remove(module_name)
|
74
77
|
raise Skippy::Project::ProjectNotSavedError unless project.exist?
|
78
|
+
|
75
79
|
lib_module = project.libraries.find_module_or_fail(module_name)
|
76
80
|
|
77
81
|
target = vendor_path.join(lib_module.library.name, lib_module.path.basename)
|
@@ -103,9 +107,11 @@ class Skippy::ModuleManager
|
|
103
107
|
project.libraries.each { |library|
|
104
108
|
library_vendor_path = vendor_path.join(library.name)
|
105
109
|
next unless library_vendor_path.directory?
|
110
|
+
|
106
111
|
library_vendor_path.each_child { |module_file|
|
107
112
|
next unless module_file.file?
|
108
113
|
next unless module_file.extname.casecmp('.rb').zero?
|
114
|
+
|
109
115
|
modules << Skippy::LibModule.new(library, module_file)
|
110
116
|
}
|
111
117
|
}
|
@@ -122,6 +128,7 @@ class Skippy::ModuleManager
|
|
122
128
|
basename = source.basename('.*')
|
123
129
|
source_support_folder = source.parent.join(basename)
|
124
130
|
return unless source_support_folder.directory?
|
131
|
+
|
125
132
|
target_support_folder = target.parent.join(basename)
|
126
133
|
copy_directory(lib_module, source_support_folder, target_support_folder)
|
127
134
|
end
|
@@ -133,6 +140,7 @@ class Skippy::ModuleManager
|
|
133
140
|
Dir.glob("#{source_path}/**/*") { |filename|
|
134
141
|
source = Pathname.new(filename)
|
135
142
|
next unless source.file?
|
143
|
+
|
136
144
|
relative_path = source.relative_path_from(source_path)
|
137
145
|
target = target_path.join(relative_path)
|
138
146
|
copy_file(lib_module, source, target)
|
@@ -150,7 +158,7 @@ class Skippy::ModuleManager
|
|
150
158
|
transform_module(content)
|
151
159
|
File.write(target, content)
|
152
160
|
else
|
153
|
-
|
161
|
+
FileUtils.copy(source, target)
|
154
162
|
end
|
155
163
|
end
|
156
164
|
|
@@ -164,7 +172,7 @@ class Skippy::ModuleManager
|
|
164
172
|
content
|
165
173
|
end
|
166
174
|
|
167
|
-
LIB_REQUIRE_PATTERN = %r{(\brequire ["'])(modules)(/[^"']*["'])}
|
175
|
+
LIB_REQUIRE_PATTERN = %r{(\brequire ["'])(modules)(/[^"']*["'])}.freeze
|
168
176
|
|
169
177
|
# Transform the require statements to the target destination.
|
170
178
|
#
|
data/lib/skippy/namespace.rb
CHANGED
@@ -6,6 +6,7 @@ class Skippy::Namespace
|
|
6
6
|
unless valid?(namespace)
|
7
7
|
raise Skippy::Error, "'#{namespace}' is not a valid Ruby namespace"
|
8
8
|
end
|
9
|
+
|
9
10
|
@namespace = namespace
|
10
11
|
end
|
11
12
|
|
@@ -24,6 +25,7 @@ class Skippy::Namespace
|
|
24
25
|
def short_name
|
25
26
|
items = to_a
|
26
27
|
return to_s unless items.size > 1
|
28
|
+
|
27
29
|
initials = items.first.scan(/[[:upper:]]/)
|
28
30
|
prefix = initials.size > 1 ? initials.join : items.first[0, 2]
|
29
31
|
"#{prefix}_#{items.last}"
|
data/lib/skippy/os.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class Skippy::OSCommon
|
2
|
+
|
3
|
+
# @param [String] command
|
4
|
+
def execute_command(command)
|
5
|
+
# Something with a Thor application like skippy get the 'RUBYLIB'
|
6
|
+
# environment set which prevents SketchUp from finding its StdLib
|
7
|
+
# directories. (At least under Windows.) This relates to child processes
|
8
|
+
# inheriting the environment variables of its parent.
|
9
|
+
# To work around this we unset RUBYLIB before launching SketchUp. This
|
10
|
+
# doesn't affect skippy as it's about to exit as soon as SketchUp starts
|
11
|
+
# any way.
|
12
|
+
ENV['RUBYLIB'] = nil if ENV['RUBYLIB']
|
13
|
+
id = spawn(command)
|
14
|
+
Process.detach(id)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [String] path
|
18
|
+
def launch_app(path, *args) # rubocop:disable Lint/UnusedMethodArgument
|
19
|
+
raise NotImplementedError
|
20
|
+
end
|
21
|
+
|
22
|
+
def sketchup_apps
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [String] path
|
27
|
+
# @return [Integer, nil]
|
28
|
+
def sketchup_version_from_path(path)
|
29
|
+
match = File.basename(path).match(/[0-9.]+/)
|
30
|
+
match ? match[0].to_i : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'skippy/os/common'
|
2
|
+
require 'skippy/sketchup/app'
|
3
|
+
|
4
|
+
class Skippy::OSMac < Skippy::OSCommon
|
5
|
+
|
6
|
+
# @param [String] executable_path
|
7
|
+
def launch_app(executable_path, *args)
|
8
|
+
command = %(open -a "#{executable_path}")
|
9
|
+
unless args.empty?
|
10
|
+
command << " --args #{args.join(' ')}"
|
11
|
+
end
|
12
|
+
execute_command(command)
|
13
|
+
end
|
14
|
+
|
15
|
+
def sketchup_apps
|
16
|
+
apps = []
|
17
|
+
pattern = '/Applications/SketchUp */'
|
18
|
+
Dir.glob(pattern) { |path|
|
19
|
+
app = File.join(path, 'SketchUp.app')
|
20
|
+
debug_lib = File.join(app, 'Contents/Frameworks/SURubyDebugger.dylib')
|
21
|
+
version = sketchup_version_from_path(path)
|
22
|
+
next unless version
|
23
|
+
|
24
|
+
apps << Skippy::SketchUpApp.from_hash(
|
25
|
+
executable: app,
|
26
|
+
version: version,
|
27
|
+
can_debug: File.exist?(debug_lib),
|
28
|
+
is64bit: version > 2015
|
29
|
+
)
|
30
|
+
}
|
31
|
+
apps.sort_by(&:version)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'skippy/os/common'
|
2
|
+
require 'skippy/sketchup/app'
|
3
|
+
|
4
|
+
class Skippy::OSWin < Skippy::OSCommon
|
5
|
+
|
6
|
+
# Note: This is not a good indication to 32bit bs 64bit. It's a naive
|
7
|
+
# assumption that will fail when SketchUp is installed to a
|
8
|
+
# non-standard location.
|
9
|
+
SYSTEM_32BIT = ENV['ProgramFiles(x86)'].nil? && ENV['ProgramW6432'].nil?
|
10
|
+
SYSTEM_64BIT = !SYSTEM_32BIT
|
11
|
+
|
12
|
+
PROGRAM_FILES_64BIT = File.expand_path(ENV['ProgramW6432'])
|
13
|
+
|
14
|
+
# @param [String] executable_path
|
15
|
+
def launch_app(executable_path, *args)
|
16
|
+
command = %("#{executable_path}")
|
17
|
+
unless args.empty?
|
18
|
+
command << " #{args.join(' ')}"
|
19
|
+
end
|
20
|
+
execute_command(command)
|
21
|
+
end
|
22
|
+
|
23
|
+
def sketchup_apps
|
24
|
+
# TODO(thomthom): Find by registry information.
|
25
|
+
apps = []
|
26
|
+
program_files_paths.each { |program_files|
|
27
|
+
pattern = "#{program_files}/{@Last Software,Google,SketchUp}/*SketchUp *"
|
28
|
+
Dir.glob(pattern) { |path|
|
29
|
+
exe = File.join(path, 'SketchUp.exe')
|
30
|
+
debug_dll = File.join(path, 'SURubyDebugger.dll')
|
31
|
+
version = sketchup_version_from_path(path)
|
32
|
+
next unless version
|
33
|
+
|
34
|
+
apps << Skippy::SketchUpApp.from_hash(
|
35
|
+
executable: exe,
|
36
|
+
version: version,
|
37
|
+
can_debug: File.exist?(debug_dll),
|
38
|
+
is64bit: SYSTEM_64BIT && path.start_with?("#{PROGRAM_FILES_64BIT}/")
|
39
|
+
)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
apps.sort_by(&:version)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def program_files_paths
|
48
|
+
paths = []
|
49
|
+
if SYSTEM_64BIT
|
50
|
+
paths << File.expand_path(ENV['ProgramFiles(x86)'])
|
51
|
+
paths << File.expand_path(ENV['ProgramW6432'])
|
52
|
+
else
|
53
|
+
paths << File.expand_path(ENV['ProgramFiles'])
|
54
|
+
end
|
55
|
+
paths
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/skippy/project.rb
CHANGED
@@ -36,6 +36,7 @@ class Skippy::Project
|
|
36
36
|
def self.current_or_fail
|
37
37
|
project = current
|
38
38
|
raise ProjectNotFoundError, project.filename unless project.exist?
|
39
|
+
|
39
40
|
project
|
40
41
|
end
|
41
42
|
|
@@ -108,8 +109,8 @@ class Skippy::Project
|
|
108
109
|
end
|
109
110
|
|
110
111
|
# @return [String]
|
111
|
-
def to_json
|
112
|
-
JSON.pretty_generate(@config)
|
112
|
+
def to_json(*args)
|
113
|
+
JSON.pretty_generate(@config, *args)
|
113
114
|
end
|
114
115
|
|
115
116
|
private
|
@@ -141,6 +142,7 @@ class Skippy::Project
|
|
141
142
|
project_file = pathname.join(PROJECT_FILENAME)
|
142
143
|
return pathname if project_file.exist?
|
143
144
|
break if pathname.root?
|
145
|
+
|
144
146
|
pathname = pathname.parent
|
145
147
|
end
|
146
148
|
nil
|
data/lib/skippy/version.rb
CHANGED
data/skippy.gemspec
CHANGED
@@ -28,8 +28,8 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_dependency 'naturally', '~> 2.1'
|
29
29
|
spec.add_dependency 'thor', '~> 0.19'
|
30
30
|
|
31
|
-
spec.add_development_dependency 'bundler', '
|
32
|
-
spec.add_development_dependency 'rake', '~>
|
31
|
+
spec.add_development_dependency 'bundler', '>= 1.15.0', '< 3.0'
|
32
|
+
spec.add_development_dependency 'rake', '~> 12.3.3'
|
33
33
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
34
34
|
# TODO(thomthom): Need to lock to 2.3 because 2.4 fails with the custom
|
35
35
|
# aruba build.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skippy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.4.3.a
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Thomassen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: git
|
@@ -56,30 +56,36 @@ dependencies:
|
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.15.0
|
62
|
+
- - "<"
|
60
63
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
64
|
+
version: '3.0'
|
62
65
|
type: :development
|
63
66
|
prerelease: false
|
64
67
|
version_requirements: !ruby/object:Gem::Requirement
|
65
68
|
requirements:
|
66
|
-
- - "
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.15.0
|
72
|
+
- - "<"
|
67
73
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
74
|
+
version: '3.0'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
76
|
name: rake
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
72
78
|
requirements:
|
73
79
|
- - "~>"
|
74
80
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
81
|
+
version: 12.3.3
|
76
82
|
type: :development
|
77
83
|
prerelease: false
|
78
84
|
version_requirements: !ruby/object:Gem::Requirement
|
79
85
|
requirements:
|
80
86
|
- - "~>"
|
81
87
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
88
|
+
version: 12.3.3
|
83
89
|
- !ruby/object:Gem::Dependency
|
84
90
|
name: minitest
|
85
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,6 +137,7 @@ executables:
|
|
131
137
|
extensions: []
|
132
138
|
extra_rdoc_files: []
|
133
139
|
files:
|
140
|
+
- ".appveyor.yml"
|
134
141
|
- ".editorconfig"
|
135
142
|
- ".gitignore"
|
136
143
|
- ".gitmodules"
|
@@ -159,6 +166,7 @@ files:
|
|
159
166
|
- app/commands/install.rb
|
160
167
|
- app/commands/lib.rb
|
161
168
|
- app/commands/new.rb
|
169
|
+
- app/commands/sketchup.rb
|
162
170
|
- app/commands/template.rb
|
163
171
|
- app/resources/commands/example.rb
|
164
172
|
- app/templates/standard/%ext_name%.rb.tt
|
@@ -226,14 +234,19 @@ files:
|
|
226
234
|
- lib/skippy/library_manager.rb
|
227
235
|
- lib/skippy/module_manager.rb
|
228
236
|
- lib/skippy/namespace.rb
|
237
|
+
- lib/skippy/os.rb
|
238
|
+
- lib/skippy/os/common.rb
|
239
|
+
- lib/skippy/os/mac.rb
|
240
|
+
- lib/skippy/os/win.rb
|
229
241
|
- lib/skippy/project.rb
|
242
|
+
- lib/skippy/sketchup/app.rb
|
230
243
|
- lib/skippy/version.rb
|
231
244
|
- skippy.gemspec
|
232
245
|
homepage: https://github.com/thomthom/skippy
|
233
246
|
licenses:
|
234
247
|
- MIT
|
235
248
|
metadata: {}
|
236
|
-
post_install_message:
|
249
|
+
post_install_message:
|
237
250
|
rdoc_options: []
|
238
251
|
require_paths:
|
239
252
|
- lib
|
@@ -248,9 +261,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
248
261
|
- !ruby/object:Gem::Version
|
249
262
|
version: 1.3.1
|
250
263
|
requirements: []
|
251
|
-
|
252
|
-
|
253
|
-
signing_key:
|
264
|
+
rubygems_version: 3.0.3
|
265
|
+
signing_key:
|
254
266
|
specification_version: 4
|
255
267
|
summary: CLI development tool for SketchUp extensions.
|
256
268
|
test_files: []
|