skippy 0.1.0.a
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.vscode/settings.json +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +61 -0
- data/Rakefile +10 -0
- data/Skippy.sublime-project +25 -0
- data/app/boot.rb +43 -0
- data/app/commands/debug.rb +15 -0
- data/app/commands/new.rb +97 -0
- data/app/commands/template.rb +27 -0
- data/app/resources/commands/example.rb +14 -0
- data/app/templates/standard/%ext_name%.rb.tt +45 -0
- data/app/templates/standard/%ext_name%/main.rb.tt +21 -0
- data/app/templates/webdialog/extension.rb.erb +45 -0
- data/app/templates/webdialog/extension/html/dialog.html +6 -0
- data/app/templates/webdialog/extension/main.rb.erb +24 -0
- data/bin/bundler +17 -0
- data/bin/console +14 -0
- data/bin/rake +17 -0
- data/bin/setup +8 -0
- data/bin/skippy +17 -0
- data/bin/thor +17 -0
- data/exe/skippy +2 -0
- data/lib/skippy.rb +5 -0
- data/lib/skippy/app.rb +62 -0
- data/lib/skippy/cli.rb +191 -0
- data/lib/skippy/command.rb +15 -0
- data/lib/skippy/error.rb +4 -0
- data/lib/skippy/group.rb +17 -0
- data/lib/skippy/namespace.rb +55 -0
- data/lib/skippy/project.rb +90 -0
- data/lib/skippy/skippy.rb +9 -0
- data/lib/skippy/version.rb +3 -0
- data/skippy.gemspec +31 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6005a25ffc1f9757b4cf9656d97be15351463830
|
4
|
+
data.tar.gz: da9d85e6b9c72eeee60b18fed419722e13829a64
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fc7071ef383374ae27cc9fa15d15544dac943d07a53832f91712f8f8a44d9c1d7eeb0286babae6a3cfdb3b4d91b074a4693f2ab825d6f700961942d6fd5ec4c4
|
7
|
+
data.tar.gz: 0ce7d0c9935e0f607e1367062a297ccc83788efebea2330f282bd1d6f8608b4a72f5fb158a8f26a5f5b9e893c94ef9727e29c2b15039cc5cf7d835ebb81dd508
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Thomas Thomassen
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Skippy
|
2
|
+
|
3
|
+
Skippy is a Command Line Interface which aims to automate common developer tasks for SketchUp Ruby extension development.
|
4
|
+
|
5
|
+
It is currently in very early stage of development so many things are incomplete. Feedback and contributions are welcome.
|
6
|
+
|
7
|
+
Some of the main goals are:
|
8
|
+
|
9
|
+
* Automate common tasks
|
10
|
+
* Packaging the extension
|
11
|
+
* Running build scripts
|
12
|
+
* Easy interface to add per-project custom commands/tasks
|
13
|
+
* Quick initialization of new project with templates
|
14
|
+
* Library dependency management
|
15
|
+
* Pull in third-party modules into extension namespace
|
16
|
+
* Add/Remove/Update dependencies
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
$ gem install skippy
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
TODO: Write more detailed usage instructions here.
|
25
|
+
|
26
|
+
Install the gem on your system, afterwards the `skippy` command should become available.
|
27
|
+
|
28
|
+
### Quick-Reference
|
29
|
+
|
30
|
+
Type `skippy` to list available commands.
|
31
|
+
|
32
|
+
Type `skippy help [COMMAND]` for more information on how to use each command.
|
33
|
+
|
34
|
+
Use `skippy new` to create a new project in the current folder.
|
35
|
+
|
36
|
+
You can add custom per-project commands to a `skippy` folder in your project. Look at `skippy/example.rb` for an example of a simple custom command.
|
37
|
+
|
38
|
+
### Power of Thor
|
39
|
+
|
40
|
+
Skippy is built on [Thor](https://github.com/erikhuda/thor). Refer to [Thor's Website](http://whatisthor.com/) and [documentation](http://www.rubydoc.info/github/wycats/thor/index) for details on creating commands.
|
41
|
+
|
42
|
+
When creating Skippy command use the following replacements:
|
43
|
+
|
44
|
+
* Instead of class `Thor`, use `Skippy::Command`
|
45
|
+
* Instead of class `Thor::Group`, use `Skippy::Command::Group`
|
46
|
+
|
47
|
+
## Development
|
48
|
+
|
49
|
+
After checking out the repo, 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.
|
50
|
+
|
51
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/thomthom/skippy.
|
56
|
+
|
57
|
+
|
58
|
+
## License
|
59
|
+
|
60
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
61
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"folders":
|
3
|
+
[
|
4
|
+
{
|
5
|
+
"path": "."
|
6
|
+
},
|
7
|
+
{
|
8
|
+
"path": "C:\\Users\\tthomas2\\SourceTree\\thor"
|
9
|
+
}
|
10
|
+
],
|
11
|
+
"settings":
|
12
|
+
{
|
13
|
+
"default_encoding": "UTF-8",
|
14
|
+
"ensure_newline_at_eof_on_save": true,
|
15
|
+
"rulers":
|
16
|
+
[
|
17
|
+
80
|
18
|
+
],
|
19
|
+
"show_encoding": true,
|
20
|
+
"show_line_endings": true,
|
21
|
+
"tab_size": 2,
|
22
|
+
"translate_tabs_to_spaces": true,
|
23
|
+
"trim_trailing_white_space_on_save": true
|
24
|
+
}
|
25
|
+
}
|
data/app/boot.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Set the program name explicitly. Otherwise Thor will use the filename in the
|
4
|
+
# banner for the command help.
|
5
|
+
$PROGRAM_NAME = 'skippy'
|
6
|
+
|
7
|
+
# TODO(thomthom): Temporary set for development without having to set the ENV.
|
8
|
+
# Thor on Windows will by default not use colors. Using Cmder colors will work.
|
9
|
+
# Also in the latest Windows 10 colors appear to work. Not sure how older
|
10
|
+
# versions behave.
|
11
|
+
ENV['THOR_SHELL'] = 'Color' if $stdout.isatty
|
12
|
+
|
13
|
+
# Thor require DL which under Windows and Ruby 2.0 will yield a warning:
|
14
|
+
# DL is deprecated, please use Fiddle
|
15
|
+
#
|
16
|
+
# To avoid this appearing every time this tool is invoked, warnings are
|
17
|
+
# temporarily suppressed.
|
18
|
+
begin
|
19
|
+
original_verbose = $VERBOSE
|
20
|
+
$VERBOSE = nil
|
21
|
+
require 'thor'
|
22
|
+
# The Thor::Runner also needs to be loaded, as Skippy::CLI will call many of
|
23
|
+
# of the same methods - in many cases emulating what it do.
|
24
|
+
require "thor/runner"
|
25
|
+
# This is also needed to be set in order for Thor's utilities to output
|
26
|
+
# command names correctly.
|
27
|
+
$thor_runner = true
|
28
|
+
ensure
|
29
|
+
$VERBOSE = original_verbose
|
30
|
+
end
|
31
|
+
|
32
|
+
# Load skippy components the bootstrapper needs.
|
33
|
+
require 'skippy/app'
|
34
|
+
Skippy::App.boot(__FILE__)
|
35
|
+
|
36
|
+
# Everything is ready to start the CLI.
|
37
|
+
require 'skippy/cli'
|
38
|
+
require 'skippy/error'
|
39
|
+
begin
|
40
|
+
Skippy::CLI.start
|
41
|
+
rescue Skippy::Error => error
|
42
|
+
Skippy::CLI.display_error(error)
|
43
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'skippy/namespace'
|
2
|
+
|
3
|
+
class Debug < Skippy::Command
|
4
|
+
|
5
|
+
include Thor::Actions
|
6
|
+
|
7
|
+
desc 'clean', 'Cleans out project files'
|
8
|
+
def clean
|
9
|
+
say "Cleaning out project files..."
|
10
|
+
remove_file Skippy::Project::PROJECT_FILENAME
|
11
|
+
remove_dir 'src'
|
12
|
+
remove_dir 'skippy'
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
data/app/commands/new.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'skippy/app'
|
4
|
+
require 'skippy/group'
|
5
|
+
require 'skippy/project'
|
6
|
+
require 'skippy/template'
|
7
|
+
|
8
|
+
class New < Skippy::Command::Group
|
9
|
+
|
10
|
+
include Thor::Actions
|
11
|
+
|
12
|
+
argument :namespace,
|
13
|
+
:type => :string,
|
14
|
+
:desc => 'The namespace the extension will use'
|
15
|
+
|
16
|
+
class_option :template,
|
17
|
+
:type => :string,
|
18
|
+
:desc => 'The template used to generate the project files',
|
19
|
+
:default => 'standard'
|
20
|
+
|
21
|
+
source_paths << Skippy.app.resources
|
22
|
+
|
23
|
+
attr_reader :project
|
24
|
+
|
25
|
+
def initialize_project
|
26
|
+
@project = Skippy::Project.new(Dir.pwd)
|
27
|
+
if project.exist?
|
28
|
+
raise Skippy::Error, "A project already exist: #{project.filename}"
|
29
|
+
end
|
30
|
+
project.namespace = namespace
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_template
|
34
|
+
template_path = File.join(self.class.source_root, options[:template])
|
35
|
+
unless File.directory?(template_path)
|
36
|
+
raise Skippy::Error, %(Template "#{options[:template]}" not found)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_project_json
|
41
|
+
say ''
|
42
|
+
say 'Generating skippy.json...'
|
43
|
+
say ''
|
44
|
+
say project.filename
|
45
|
+
say project.to_json, :yellow
|
46
|
+
project.save
|
47
|
+
end
|
48
|
+
|
49
|
+
def compile_templates
|
50
|
+
say ''
|
51
|
+
say "Compiling template '#{options[:template]}'..."
|
52
|
+
say ''
|
53
|
+
directory(options[:template], 'src')
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_extension_json
|
57
|
+
extension_info = {
|
58
|
+
name: project.name,
|
59
|
+
description: project.description,
|
60
|
+
creator: project.author,
|
61
|
+
copyright: project.copyright,
|
62
|
+
license: project.license,
|
63
|
+
product_id: project.namespace.to_a.join('_'),
|
64
|
+
version: "0.1.0",
|
65
|
+
build: "1",
|
66
|
+
}
|
67
|
+
json = JSON.pretty_generate(extension_info)
|
68
|
+
json_filename = "src/#{project.namespace.to_underscore}/extension.json"
|
69
|
+
create_file(json_filename, json)
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_example_skippy_command
|
73
|
+
copy_file('commands/example.rb', 'skippy/example.rb')
|
74
|
+
end
|
75
|
+
|
76
|
+
def finalize
|
77
|
+
say ''
|
78
|
+
say "Project for #{namespace} created.", :green
|
79
|
+
end
|
80
|
+
|
81
|
+
# These are methods to be used by the template engine when it compiles the
|
82
|
+
# templates and expands the filenames.
|
83
|
+
no_commands do
|
84
|
+
|
85
|
+
# @return [String] The basename for the extension files.
|
86
|
+
def ext_name
|
87
|
+
project.namespace.to_underscore
|
88
|
+
end
|
89
|
+
|
90
|
+
end # no_commands
|
91
|
+
|
92
|
+
# Needed as base for Thor::Actions' file actions.
|
93
|
+
def self.source_root
|
94
|
+
Skippy.app.templates_source_path
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Template < Skippy::Command
|
2
|
+
|
3
|
+
desc 'list', 'List all known templates'
|
4
|
+
def list
|
5
|
+
say 'Available templates:', :yellow
|
6
|
+
templates = Skippy.app.templates
|
7
|
+
if templates.empty?
|
8
|
+
say ' No templates found'
|
9
|
+
else
|
10
|
+
templates.each { |template|
|
11
|
+
say " #{template.name}", :green
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
default_command(:list)
|
16
|
+
|
17
|
+
desc 'install', 'Install a new template'
|
18
|
+
def install(source)
|
19
|
+
raise Skippy::Error, 'Not implemented'
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'remove', 'Remove an installed template'
|
23
|
+
def remove(template_name)
|
24
|
+
raise Skippy::Error, 'Not implemented'
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -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(person)
|
11
|
+
say "DARK IN HERE, ISN'T IT?"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Author: <%= project.author %>
|
4
|
+
# Copyright: <%= project.copyright %>
|
5
|
+
# License: <%= project.license %>
|
6
|
+
#
|
7
|
+
#-------------------------------------------------------------------------------
|
8
|
+
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
require 'extensions.rb'
|
12
|
+
require 'sketchup.rb'
|
13
|
+
|
14
|
+
<%= project.namespace.open %>
|
15
|
+
|
16
|
+
file = __FILE__.dup
|
17
|
+
# Account for Ruby encoding bug under Windows.
|
18
|
+
file.force_encoding('UTF-8') if file.respond_to?(:force_encoding)
|
19
|
+
# Support folder should be named the same as the root .rb file.
|
20
|
+
folder_name = File.basename(file, '.*')
|
21
|
+
|
22
|
+
# Path to the root .rb file (this file).
|
23
|
+
PATH_ROOT = File.dirname(file).freeze
|
24
|
+
|
25
|
+
# Path to the support folder.
|
26
|
+
PATH = File.join(PATH_ROOT, folder_name).freeze
|
27
|
+
|
28
|
+
# Extension information.
|
29
|
+
extension_json_file = File.join(PATH, 'extension.json')
|
30
|
+
extension_json = File.read(extension_json_file)
|
31
|
+
EXTENSION = ::JSON.parse(extension_json, symbolize_names: true).freeze
|
32
|
+
|
33
|
+
unless file_loaded?(__FILE__)
|
34
|
+
loader = File.join(PATH, 'bootstrap')
|
35
|
+
@extension = SketchupExtension.new(EXTENSION[:name], loader)
|
36
|
+
@extension.description = EXTENSION[:description]
|
37
|
+
@extension.version = EXTENSION[:version]
|
38
|
+
@extension.copyright = EXTENSION[:copyright]
|
39
|
+
@extension.creator = EXTENSION[:creator]
|
40
|
+
Sketchup.register_extension(@extension, true)
|
41
|
+
end
|
42
|
+
|
43
|
+
<%= project.namespace.close %>
|
44
|
+
|
45
|
+
file_loaded(__FILE__)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'sketchup.rb'
|
2
|
+
|
3
|
+
module <%= project.namespace %>
|
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
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Author: <%= project.author %>
|
4
|
+
# Copyright: <%= project.copyright %>
|
5
|
+
# License: <%= project.license %>
|
6
|
+
#
|
7
|
+
#-------------------------------------------------------------------------------
|
8
|
+
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
require 'extensions.rb'
|
12
|
+
require 'sketchup.rb'
|
13
|
+
|
14
|
+
<%= project.namespace.open %>
|
15
|
+
|
16
|
+
file = __FILE__.dup
|
17
|
+
# Account for Ruby encoding bug under Windows.
|
18
|
+
file.force_encoding('UTF-8') if file.respond_to?(:force_encoding)
|
19
|
+
# Support folder should be named the same as the root .rb file.
|
20
|
+
folder_name = File.basename(file, '.*')
|
21
|
+
|
22
|
+
# Path to the root .rb file (this file).
|
23
|
+
PATH_ROOT = File.dirname(file).freeze
|
24
|
+
|
25
|
+
# Path to the support folder.
|
26
|
+
PATH = File.join(PATH_ROOT, folder_name).freeze
|
27
|
+
|
28
|
+
# Extension information.
|
29
|
+
extension_json_file = File.join(PATH, 'extension.json')
|
30
|
+
extension_json = File.read(extension_json_file)
|
31
|
+
EXTENSION = ::JSON.parse(extension_json, symbolize_names: true).freeze
|
32
|
+
|
33
|
+
unless file_loaded?(__FILE__)
|
34
|
+
loader = File.join(PATH, 'bootstrap')
|
35
|
+
@extension = SketchupExtension.new(EXTENSION[:name], loader)
|
36
|
+
@extension.description = EXTENSION[:description]
|
37
|
+
@extension.version = EXTENSION[:version]
|
38
|
+
@extension.copyright = EXTENSION[:copyright]
|
39
|
+
@extension.creator = EXTENSION[:creator]
|
40
|
+
Sketchup.register_extension(@extension, true)
|
41
|
+
end
|
42
|
+
|
43
|
+
<%= project.namespace.close %>
|
44
|
+
|
45
|
+
file_loaded(__FILE__)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'sketchup.rb'
|
2
|
+
|
3
|
+
module <%= project.namespace %>
|
4
|
+
|
5
|
+
unless file_loaded?(__FILE__)
|
6
|
+
menu = UI.menu('Plugins').add_submenu(EXTENSION[:name])
|
7
|
+
menu.add_item('Open Dialog') { self.open_dialog }
|
8
|
+
menu.add_separator
|
9
|
+
menu.add_item('Help...') { self.open_help }
|
10
|
+
file_loaded(__FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.open_dialog
|
14
|
+
file_path = File.join(PATH, 'html', 'dialog.html')
|
15
|
+
@dialog = UI::WebDialog.new
|
16
|
+
@dialog.set_file(file_path)
|
17
|
+
@dialog.show
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.open_help
|
21
|
+
UI.openURL(EXTENSION[:url])
|
22
|
+
end
|
23
|
+
|
24
|
+
end # module
|
data/bin/bundler
ADDED
@@ -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 'bundler' 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("bundler", "bundler")
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "skippy"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/rake
ADDED
@@ -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 'rake' 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("rake", "rake")
|
data/bin/setup
ADDED
data/bin/skippy
ADDED
@@ -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 'skippy' 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("skippy", "skippy")
|
data/bin/thor
ADDED
@@ -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 'thor' 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("thor", "thor")
|
data/exe/skippy
ADDED
data/lib/skippy.rb
ADDED
data/lib/skippy/app.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
require 'skippy/command'
|
4
|
+
require 'skippy/group'
|
5
|
+
require 'skippy/template'
|
6
|
+
require 'skippy/skippy'
|
7
|
+
|
8
|
+
class Skippy::App
|
9
|
+
|
10
|
+
# @param [String] boot_loader_path
|
11
|
+
# @return [Skippy::App]
|
12
|
+
def self.boot(boot_loader_path)
|
13
|
+
Skippy.app = Skippy::App.new(boot_loader_path)
|
14
|
+
Skippy.app.boot
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :path
|
18
|
+
|
19
|
+
# @param [String] boot_loader_path
|
20
|
+
def initialize(boot_loader_path)
|
21
|
+
@boot_loader_path = File.expand_path(boot_loader_path)
|
22
|
+
@path = File.dirname(@boot_loader_path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def boot
|
26
|
+
boot_commands
|
27
|
+
end
|
28
|
+
|
29
|
+
def resources(item = nil)
|
30
|
+
resource = Pathname.new(File.join(path, 'resources'))
|
31
|
+
item ? resource.join(item) : resource
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array<String>]
|
35
|
+
def templates_source_path
|
36
|
+
Pathname.new(File.join(path, 'templates'))
|
37
|
+
end
|
38
|
+
|
39
|
+
def templates
|
40
|
+
result = []
|
41
|
+
templates_source_path.entries.each { |entry|
|
42
|
+
template_path = templates_source_path.join(entry)
|
43
|
+
next unless template_path.directory?
|
44
|
+
next if %[. ..].include?(entry.basename.to_s)
|
45
|
+
result << Skippy::Template.new(entry)
|
46
|
+
}
|
47
|
+
result
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# @return [Array<String>] loaded files
|
53
|
+
def boot_commands
|
54
|
+
# Load the default skippy commands.
|
55
|
+
path_commands = File.join(path, 'commands')
|
56
|
+
commands_pattern = File.join(path_commands, '*.rb')
|
57
|
+
Dir.glob(commands_pattern) { |filename|
|
58
|
+
require filename
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/lib/skippy/cli.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'skippy/app'
|
2
|
+
require 'skippy/command'
|
3
|
+
require 'skippy/group'
|
4
|
+
require 'skippy/project'
|
5
|
+
require 'skippy/version'
|
6
|
+
|
7
|
+
# The Skippy::CLI class emulates much of what Thor::Runner do. It takes care of
|
8
|
+
# finding skippy projects and loading commands.
|
9
|
+
#
|
10
|
+
# The difference is mainly in how skippy vs thor present the commands.
|
11
|
+
#
|
12
|
+
# TODO(thomthom): ...or should it?
|
13
|
+
# Thor let you install commands globally, where as skippy does not.
|
14
|
+
#
|
15
|
+
# Skippy will list all known commands when invoked without any arguments.
|
16
|
+
#
|
17
|
+
# The code in this class will often refer to thor - when things have been copied
|
18
|
+
# verbatim. Makes it easier to update if needed.
|
19
|
+
class Skippy::CLI < Skippy::Command
|
20
|
+
|
21
|
+
class << self
|
22
|
+
|
23
|
+
# @param [Skippy::Error] error
|
24
|
+
def display_error(error)
|
25
|
+
shell = Thor::Base.shell.new
|
26
|
+
message = " #{error.message} "
|
27
|
+
message = shell.set_color(message, :white)
|
28
|
+
message = shell.set_color(message, :on_red)
|
29
|
+
shell.error message
|
30
|
+
end
|
31
|
+
|
32
|
+
end # Class methods
|
33
|
+
|
34
|
+
default_command :list
|
35
|
+
|
36
|
+
# Verbatim copy from Thor::Runner:
|
37
|
+
# Override Thor#help so it can give information about any class and any method.
|
38
|
+
#
|
39
|
+
def help(meth = nil)
|
40
|
+
if meth && !self.respond_to?(meth)
|
41
|
+
initialize_thorfiles(meth)
|
42
|
+
klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
|
43
|
+
self.class.handle_no_command_error(command, false) if klass.nil?
|
44
|
+
klass.start(["-h", command].compact, :shell => shell)
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Verbatim copy from Thor::Runner:
|
51
|
+
# If a command is not found on Thor::Runner, method missing is invoked and
|
52
|
+
# Thor::Runner is then responsible for finding the command in all classes.
|
53
|
+
#
|
54
|
+
def method_missing(meth, *args)
|
55
|
+
meth = meth.to_s
|
56
|
+
initialize_thorfiles(meth)
|
57
|
+
klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
|
58
|
+
self.class.handle_no_command_error(command, false) if klass.nil?
|
59
|
+
args.unshift(command) if command
|
60
|
+
klass.start(args, :shell => shell)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Verbatim copy from Thor::Runner:
|
64
|
+
desc "list [SEARCH]", "List the available #{$PROGRAM_NAME} commands (--substring means .*SEARCH)"
|
65
|
+
method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
|
66
|
+
def list(search = "")
|
67
|
+
initialize_thorfiles
|
68
|
+
|
69
|
+
search = ".*#{search}" if options["substring"]
|
70
|
+
search = /^#{search}.*/i
|
71
|
+
group = options[:group] || "standard"
|
72
|
+
|
73
|
+
klasses = Thor::Base.subclasses.select do |k|
|
74
|
+
(options[:all] || k.group == group) && k.namespace =~ search
|
75
|
+
end
|
76
|
+
|
77
|
+
display_klasses(false, false, klasses)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Based on Thor::Runner, with exception of program name.
|
83
|
+
def self.banner(command, all = false, subcommand = false)
|
84
|
+
"#{$PROGRAM_NAME} " + command.formatted_usage(self, all, subcommand)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Verbatim copy from Thor::Runner:
|
88
|
+
def self.exit_on_failure?
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
# This is one of the places this runner differ from Thor::Runner. It will
|
93
|
+
# instead load files for the current project.
|
94
|
+
#
|
95
|
+
# TODO(thomthom): Original arguments kept around for now, so avoid altering
|
96
|
+
# the methods that calls this. It might be that these arguments might be
|
97
|
+
# useful for optimizations later.
|
98
|
+
def initialize_thorfiles(_relevant_to = nil, _skip_lookup = false)
|
99
|
+
project = Skippy::Project.new(Dir.pwd)
|
100
|
+
return unless project.exist?
|
101
|
+
project.command_files { |filename|
|
102
|
+
unless Thor::Base.subclass_files.keys.include?(File.expand_path(filename))
|
103
|
+
Thor::Util.load_thorfile(filename, nil, options[:debug])
|
104
|
+
end
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def display_app_banner
|
109
|
+
program_name = shell.set_color($PROGRAM_NAME.capitalize, :green)
|
110
|
+
version = shell.set_color('version', :clear)
|
111
|
+
program_version = shell.set_color(Skippy::VERSION, :yellow)
|
112
|
+
say "#{program_name} #{version} #{program_version}"
|
113
|
+
end
|
114
|
+
|
115
|
+
# Based on Thor::Runner:
|
116
|
+
def display_klasses(with_modules = false, show_internal = false, klasses = Thor::Base.subclasses)
|
117
|
+
unless show_internal
|
118
|
+
klasses -= [
|
119
|
+
Thor, Thor::Runner, Thor::Group,
|
120
|
+
Skippy, Skippy::CLI, Skippy::Command, Skippy::Command::Group
|
121
|
+
]
|
122
|
+
end
|
123
|
+
|
124
|
+
fail Error, "No #{$PROGRAM_NAME.capitalize} commands available" if klasses.empty?
|
125
|
+
|
126
|
+
list = Hash.new { |h, k| h[k] = [] }
|
127
|
+
groups = klasses.select { |k| k.ancestors.include?(Thor::Group) }
|
128
|
+
|
129
|
+
# Get classes which inherit from Thor
|
130
|
+
(klasses - groups).each { |k|
|
131
|
+
list[k.namespace.split(":").first] += k.printable_commands(false)
|
132
|
+
}
|
133
|
+
|
134
|
+
# Get classes which inherit from Thor::Base
|
135
|
+
groups.map! { |k| k.printable_commands(false).first }
|
136
|
+
# Thor:Runner put these under 'root', but here we just avoid any name at
|
137
|
+
# all together.
|
138
|
+
list[''] = groups
|
139
|
+
|
140
|
+
display_app_banner
|
141
|
+
say
|
142
|
+
say 'Available commands:', :yellow
|
143
|
+
|
144
|
+
# Align all command descriptions. This means computing a fixed width for
|
145
|
+
# the first column.
|
146
|
+
col_width = list.map { |_, rows|
|
147
|
+
rows.map { |col| col.first.size }.max || 0
|
148
|
+
}.max
|
149
|
+
|
150
|
+
# Order namespaces with default coming first
|
151
|
+
list = list.sort { |a, b|
|
152
|
+
a[0].sub(/^default/, "") <=> b[0].sub(/^default/, "")
|
153
|
+
}
|
154
|
+
list.each { |n, commands|
|
155
|
+
display_commands(n, commands, col_width) unless commands.empty?
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
# Based on Thor::Runner:
|
160
|
+
def display_commands(namespace, list, col_width)
|
161
|
+
list.sort! { |a, b| a[0] <=> b[0] }
|
162
|
+
|
163
|
+
say shell.set_color(namespace, :yellow, true) unless namespace.empty?
|
164
|
+
|
165
|
+
list.each { |row|
|
166
|
+
row[0] = shell.set_color(row[0], :green) + shell.set_color('', :clear)
|
167
|
+
}
|
168
|
+
# TODO(thomthom): For some reason the column appear as half the width.
|
169
|
+
# Not sure why, so for now we apply this hack.
|
170
|
+
# TODO(thomthom): Because of the odd issue with col_width mentioned in
|
171
|
+
# `display_klasses` the table isn't truncated. Can probably re-enable if
|
172
|
+
# the col_width issue is fixed.
|
173
|
+
#print_table(list, :truncate => true, :indent => 2, :colwidth => col_width)
|
174
|
+
width = (col_width + 2) * 2
|
175
|
+
print_table(list, :indent => 2, :colwidth => width)
|
176
|
+
end
|
177
|
+
alias_method :display_tasks, :display_commands
|
178
|
+
|
179
|
+
# Based on Thor::Runner, skipping the yaml stuff:
|
180
|
+
def show_modules
|
181
|
+
info = []
|
182
|
+
labels = %w[Modules Namespaces]
|
183
|
+
|
184
|
+
info << labels
|
185
|
+
info << ["-" * labels[0].size, "-" * labels[1].size]
|
186
|
+
|
187
|
+
print_table info
|
188
|
+
say ""
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Skippy
|
4
|
+
class Command < Thor
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
# Customize the banner as we don't care for the 'skippy' prefix for each
|
9
|
+
# item in the list.
|
10
|
+
def self.banner(command, namespace = nil, subcommand = false)
|
11
|
+
"#{command.formatted_usage(self, true, subcommand)}"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
data/lib/skippy/error.rb
ADDED
data/lib/skippy/group.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'thor/group'
|
2
|
+
|
3
|
+
require 'skippy/command'
|
4
|
+
|
5
|
+
module Skippy
|
6
|
+
class Command::Group < Thor::Group
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
# Customize the banner as we don't care for the 'skippy' prefix for each
|
11
|
+
# item in the list.
|
12
|
+
def self.banner
|
13
|
+
"#{self_command.formatted_usage(self, false)}"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class Skippy::Namespace
|
2
|
+
|
3
|
+
def initialize(namespace)
|
4
|
+
unless valid?(namespace)
|
5
|
+
raise Skippy::Error, "'#{namespace}' is not a valid Ruby namespace"
|
6
|
+
end
|
7
|
+
@namespace = namespace
|
8
|
+
end
|
9
|
+
|
10
|
+
def basename
|
11
|
+
to_a.last
|
12
|
+
end
|
13
|
+
|
14
|
+
def open
|
15
|
+
@open ||= to_a.map { |part| "module #{part}" }.join("\n")
|
16
|
+
@open
|
17
|
+
end
|
18
|
+
|
19
|
+
def close
|
20
|
+
@close ||= to_a.reverse.map { |part| "end # module #{part}" }.join("\n")
|
21
|
+
@close
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_a
|
25
|
+
parts(@namespace)
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_name
|
29
|
+
basename_words(basename).join(' ')
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
@namespace.dup
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_underscore
|
37
|
+
basename_words(basename).map { |word| word.downcase }.join('_')
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def basename_words(namespace_basename)
|
43
|
+
result = namespace_basename.scan(/[[:upper:]]+[[:lower:][:digit:]]*/)
|
44
|
+
result.empty? ? [namespace_basename.dup] : result
|
45
|
+
end
|
46
|
+
|
47
|
+
def parts(namespace)
|
48
|
+
namespace.split('::')
|
49
|
+
end
|
50
|
+
|
51
|
+
def valid?(namespace)
|
52
|
+
parts(namespace).all? { |part| /^[[:upper:]]/.match(part) }
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
require 'skippy/namespace'
|
5
|
+
|
6
|
+
class Skippy::Project
|
7
|
+
|
8
|
+
PROJECT_FILENAME = 'skippy.json'.freeze
|
9
|
+
|
10
|
+
attr_reader :name, :namespace, :path, :author, :copyright, :license
|
11
|
+
attr_accessor :description
|
12
|
+
|
13
|
+
# Initialize a project for the provided path. If the path is within a project
|
14
|
+
# path the base path of the project will be found. Otherwise it's assumed that
|
15
|
+
# the path is the base for a new project.
|
16
|
+
#
|
17
|
+
# @param [Pathname, String] path
|
18
|
+
def initialize(path)
|
19
|
+
@path = find_project_path(path) || Pathname.new(path)
|
20
|
+
@namespace = Skippy::Namespace.new('Untitled')
|
21
|
+
@name = ''
|
22
|
+
@description = ''
|
23
|
+
@author = 'Unknown'
|
24
|
+
@copyright = "Copyright (c) #{Time.now.year}"
|
25
|
+
@license = 'None'
|
26
|
+
end
|
27
|
+
|
28
|
+
# @yield [filename]
|
29
|
+
# @yieldparam [String] filename the path to custom Skippy command
|
30
|
+
def command_files(&block)
|
31
|
+
files_pattern = File.join(path, 'skippy', '**', '*.rb')
|
32
|
+
Dir.glob(files_pattern) { |filename|
|
33
|
+
block.call(filename)
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Checks if a project exist on disk. If not it's just transient.
|
38
|
+
def exist?
|
39
|
+
File.exist?(filename)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Full path to the project's configuration file. This file may not exist.
|
43
|
+
# @return [String]
|
44
|
+
def filename
|
45
|
+
File.join(path, PROJECT_FILENAME)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [String]
|
49
|
+
def name
|
50
|
+
@name.empty? ? namespace.to_name : @name
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [String] namespace
|
54
|
+
def namespace=(namespace)
|
55
|
+
@namespace = Skippy::Namespace.new(namespace)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Commits the project to disk.
|
59
|
+
def save
|
60
|
+
File.write(filename, to_json)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [String]
|
64
|
+
def to_json
|
65
|
+
project_config = {
|
66
|
+
namespace: namespace,
|
67
|
+
name: name,
|
68
|
+
description: description
|
69
|
+
}
|
70
|
+
JSON.pretty_generate(project_config)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Finds the root of a project based on any path within the project.
|
76
|
+
#
|
77
|
+
# @param [String] path
|
78
|
+
# return [Pathname, nil]
|
79
|
+
def find_project_path(path)
|
80
|
+
pathname = Pathname.new(path)
|
81
|
+
loop do
|
82
|
+
project_file = pathname.join(PROJECT_FILENAME)
|
83
|
+
return pathname if project_file.exist?
|
84
|
+
break if pathname.root?
|
85
|
+
pathname = pathname.parent
|
86
|
+
end
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/skippy.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'skippy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "skippy"
|
8
|
+
spec.version = Skippy::VERSION
|
9
|
+
spec.authors = ["Thomas Thomassen"]
|
10
|
+
spec.email = ["thomas@thomthom.net"]
|
11
|
+
|
12
|
+
spec.summary = %q{CLI development tool for SketchUp extensions.}
|
13
|
+
spec.description = %q{Automate common tasks for SketchUp extension development, including managing library dependencies.}
|
14
|
+
spec.homepage = "https://github.com/thomthom/skippy"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.required_ruby_version = ">= 2.0"
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
|
+
f.match(%r{^(test|spec|features)/})
|
21
|
+
end
|
22
|
+
spec.bindir = "exe"
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
29
|
+
|
30
|
+
spec.add_dependency "thor"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: skippy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.a
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas Thomassen
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.13'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Automate common tasks for SketchUp extension development, including managing
|
70
|
+
library dependencies.
|
71
|
+
email:
|
72
|
+
- thomas@thomthom.net
|
73
|
+
executables:
|
74
|
+
- skippy
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- ".gitignore"
|
79
|
+
- ".vscode/settings.json"
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE.txt
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- Skippy.sublime-project
|
85
|
+
- app/boot.rb
|
86
|
+
- app/commands/debug.rb
|
87
|
+
- app/commands/new.rb
|
88
|
+
- app/commands/template.rb
|
89
|
+
- app/resources/commands/example.rb
|
90
|
+
- app/templates/standard/%ext_name%.rb.tt
|
91
|
+
- app/templates/standard/%ext_name%/main.rb.tt
|
92
|
+
- app/templates/webdialog/extension.rb.erb
|
93
|
+
- app/templates/webdialog/extension/html/dialog.html
|
94
|
+
- app/templates/webdialog/extension/main.rb.erb
|
95
|
+
- bin/bundler
|
96
|
+
- bin/console
|
97
|
+
- bin/rake
|
98
|
+
- bin/setup
|
99
|
+
- bin/skippy
|
100
|
+
- bin/thor
|
101
|
+
- exe/skippy
|
102
|
+
- lib/skippy.rb
|
103
|
+
- lib/skippy/app.rb
|
104
|
+
- lib/skippy/cli.rb
|
105
|
+
- lib/skippy/command.rb
|
106
|
+
- lib/skippy/error.rb
|
107
|
+
- lib/skippy/group.rb
|
108
|
+
- lib/skippy/namespace.rb
|
109
|
+
- lib/skippy/project.rb
|
110
|
+
- lib/skippy/skippy.rb
|
111
|
+
- lib/skippy/version.rb
|
112
|
+
- skippy.gemspec
|
113
|
+
homepage: https://github.com/thomthom/skippy
|
114
|
+
licenses:
|
115
|
+
- MIT
|
116
|
+
metadata: {}
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '2.0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 1.3.1
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 2.0.3
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: CLI development tool for SketchUp extensions.
|
137
|
+
test_files: []
|
138
|
+
has_rdoc:
|