newline_hw 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +4 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +78 -0
- data/Rakefile +2 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/exe/newline_hw +5 -0
- data/exe/newline_hw_stream +20 -0
- data/exe/newline_hw_stream_shim +21 -0
- data/lib/newline_hw/chrome_manifest.rb +46 -0
- data/lib/newline_hw/cli.rb +60 -0
- data/lib/newline_hw/config.rb +52 -0
- data/lib/newline_hw/gui_trigger.rb +54 -0
- data/lib/newline_hw/shell/function.rb +52 -0
- data/lib/newline_hw/shell/run.rb +25 -0
- data/lib/newline_hw/shell/runners/base.rb +40 -0
- data/lib/newline_hw/shell/runners/javascript.rb +23 -0
- data/lib/newline_hw/shell/runners/ruby.rb +36 -0
- data/lib/newline_hw/shell/setup.rb +110 -0
- data/lib/newline_hw/stream_command_handler.rb +82 -0
- data/lib/newline_hw/stream_processor.rb +42 -0
- data/lib/newline_hw/version.rb +3 -0
- data/lib/newline_hw.rb +30 -0
- data/newline_hw.gemspec +37 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 39b29b562210b7192832f3072f93d105aebbe44b
|
4
|
+
data.tar.gz: 551d839f029426a9de65509f082f7ab84c826159
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bfd3d1bf736b1b47ae35a98e5e0e5fca04e7ad804207f2b08fddd8f611fc5db67d5310c9db7a7a68ad018c176decc6a1c40ac85f4b8b57315f27bdd425c2261d
|
7
|
+
data.tar.gz: 1ae5362a0162f34a7bd487b6d6ddcb3b42efcbbfc1dc27cac775694612e4952db6091474cb400ecb0c3c9e4a9819d4d48a860dd040c18472eb5b4231c669d733
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at russell@burningpony.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Russell Osborne
|
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,78 @@
|
|
1
|
+
# NewlineHw
|
2
|
+
|
3
|
+
Is a tool to rapidly clone and setup projects in a standard format, this is primarily
|
4
|
+
used to improving the speed to review homework turned in in a bootcamp like setting.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Install from rubygems:
|
9
|
+
|
10
|
+
$ gem install newline_hw
|
11
|
+
|
12
|
+
Run to install the config file and chrome integration.
|
13
|
+
|
14
|
+
$ newline_hw install
|
15
|
+
|
16
|
+
In your .bashrc / .bash_profile / .zshrc **THIS IS VERY REQUIRED**
|
17
|
+
|
18
|
+
$ eval "$(newline_hw init)"
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
Once the the eval code has been added to your bash or zsh profile you will have access to the `hw` command. This is where the majority of the tools use comes into play.
|
23
|
+
|
24
|
+
`hw GIT_REPO`
|
25
|
+
|
26
|
+
Example
|
27
|
+
|
28
|
+
`hw https://github.com/rposborne/countries`
|
29
|
+
|
30
|
+
### What it does
|
31
|
+
|
32
|
+
_All languages_
|
33
|
+
|
34
|
+
1. Clone a git-url/repo/gist/pull-request into ~/theironyard/homework by default using githubname-reponame
|
35
|
+
2. Trigger your editor to open.
|
36
|
+
3. `cd` current shell into new directory
|
37
|
+
|
38
|
+
_Ruby_
|
39
|
+
|
40
|
+
1. Run `bundle install` if `Gemfile` is present
|
41
|
+
|
42
|
+
_Rails_
|
43
|
+
|
44
|
+
1. `bin/rake db:setup`
|
45
|
+
2. Start a rails server / open it in default browser
|
46
|
+
3. `bin/rake test`
|
47
|
+
4. Reown rails server process so everything behaves as expected.
|
48
|
+
5. Tell spring die when it needs to die.
|
49
|
+
|
50
|
+
_Javascript_
|
51
|
+
|
52
|
+
1. Run `npm install` when `package.json` present and no yarn file
|
53
|
+
1. Run `yarn install` when `yarn.lock` present
|
54
|
+
|
55
|
+
## TIYO-Assistant Integration
|
56
|
+
|
57
|
+
This provides a message bus to allow TIYO assistant to send json to our local binary. This is used to open a terminal window (Apple Terminal or iTerm2) using appleScript and start a `hw <submission-id>` command. We use the NewlineCli to backfill data required to run the remainder of the commands.
|
58
|
+
|
59
|
+
1. You MUST be on a MAC (hope to drop this in the future)
|
60
|
+
1. You MUST have `newline_cli` installed
|
61
|
+
2. You MUST be running a ruby 2.3 or higher
|
62
|
+
3. You MUST have that ruby either in the system loadpath or use, rbenv, rvm, or chruby.
|
63
|
+
4. THIS IS ALPHA so please send logs.
|
64
|
+
|
65
|
+
## Development
|
66
|
+
|
67
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
68
|
+
|
69
|
+
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).
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/TIYDC/newline_hw. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
74
|
+
|
75
|
+
|
76
|
+
## License
|
77
|
+
|
78
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "newline_hw"
|
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
|
+
begin
|
11
|
+
require "pry"
|
12
|
+
Pry.start
|
13
|
+
rescue LoadError
|
14
|
+
require "irb"
|
15
|
+
IRB.start
|
16
|
+
end
|
data/bin/setup
ADDED
data/exe/newline_hw
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
require "logger"
|
4
|
+
require "json"
|
5
|
+
require_relative "../lib/newline_hw"
|
6
|
+
|
7
|
+
logger = Logger.new(File.new(File.expand_path(NewlineHw.config.log_file), "a+"))
|
8
|
+
|
9
|
+
begin
|
10
|
+
NewlineHw::StreamProcessor
|
11
|
+
.new($stdin, $stdout, logger: logger).on_message do |msg|
|
12
|
+
send_message(NewlineHw::StreamCommandHandler.new(msg).call)
|
13
|
+
end
|
14
|
+
rescue StandardError => e
|
15
|
+
logger.error e
|
16
|
+
exit 1
|
17
|
+
|
18
|
+
rescue SystemExit
|
19
|
+
exit 0
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
# Load binaries for rbenv
|
5
|
+
if [ -d "$HOME/.rbenv/shims" ]; then
|
6
|
+
export PATH=~/.rbenv/shims:$PATH
|
7
|
+
# Load RVM into a shell session *as a function*
|
8
|
+
elif [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
|
9
|
+
# First try to load from a user install
|
10
|
+
source "$HOME/.rvm/scripts/rvm"
|
11
|
+
|
12
|
+
elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
|
13
|
+
# Then try to load from a root install
|
14
|
+
source "/usr/local/rvm/scripts/rvm"
|
15
|
+
|
16
|
+
elif [ -f /usr/local/share/chruby/chruby.sh && [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]]; then
|
17
|
+
source /usr/local/share/chruby/chruby.sh
|
18
|
+
fi
|
19
|
+
|
20
|
+
exeDir=$(dirname -- "$BASH_SOURCE")
|
21
|
+
$exeDir/newline_hw_stream
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "json"
|
2
|
+
module NewlineHw
|
3
|
+
module ChromeManifest
|
4
|
+
NAME = "com.theironyard.newlinecli.hw".freeze
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def binary_path
|
9
|
+
File.expand_path File.join(__FILE__, "..", "..", "..", "exe", "newline_hw_stream_shim")
|
10
|
+
end
|
11
|
+
|
12
|
+
def native_messaging_manifest_path
|
13
|
+
File.expand_path("~/Library/Application Support/Google/Chrome/NativeMessagingHosts/#{NAME}.json")
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate
|
17
|
+
{
|
18
|
+
name: NAME,
|
19
|
+
description: spec.description,
|
20
|
+
path: binary_path,
|
21
|
+
type: "stdio",
|
22
|
+
allowed_origins: [
|
23
|
+
"chrome-extension://fnhanbdccpjnnoohoppkeejljjljihcc/",
|
24
|
+
"chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
|
25
|
+
]
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def write
|
30
|
+
create_native_messaging_manifest_directory
|
31
|
+
|
32
|
+
File.open(native_messaging_manifest_path, "w+") do |f|
|
33
|
+
f.write(JSON.pretty_generate(ChromeManifest.generate))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private def create_native_messaging_manifest_directory
|
38
|
+
return if Dir.exist?(File.dirname(native_messaging_manifest_path))
|
39
|
+
Dir.mkdir(File.dirname(native_messaging_manifest_path))
|
40
|
+
end
|
41
|
+
|
42
|
+
private def spec
|
43
|
+
@_gemspec ||= Gem::Specification.load("newline_hw.gemspec")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "thor"
|
2
|
+
module NewlineHw
|
3
|
+
class Cli < Thor
|
4
|
+
desc "init", "install the hw function into a current terminal session"
|
5
|
+
def init
|
6
|
+
puts Shell::Function.cmd
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "config", "edit your config file in your editor"
|
10
|
+
def config
|
11
|
+
`#{NewlineHw.config.editor} #{NewlineHw::Config::CONFIG_PATH}`
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "install newlinehw config file and chrome adapter",
|
15
|
+
"will setup a logging file and a chrome manifest to allow this app to be communicated to by the newline-assistant chrome extension."
|
16
|
+
def install
|
17
|
+
NewlineHw.make_log_directory
|
18
|
+
ChromeManifest.write
|
19
|
+
NewlineHw::Config.install_default
|
20
|
+
say "Installed a config file to `#{NewlineHw::Config::CONFIG_PATH}`"
|
21
|
+
say "Chrome Native Messaging Hook installed for Newline Assistant"
|
22
|
+
say ""
|
23
|
+
say ("*" * 30) + " YOU MUST!! Add this line to your shell profile " + ("*" * 30), :red
|
24
|
+
say '$ eval "$(newline_hw init)"'
|
25
|
+
say ("*" * 30), :red
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "setup SUBMISSION_ID",
|
29
|
+
"generate a shell command to clone and setup a given SUBMISSION_ID"
|
30
|
+
option :editor
|
31
|
+
def setup_command(submission_id)
|
32
|
+
puts Shell::Setup.new(submission_id, config).cmd
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "run WORKINGDIR", "generate a shell command to run language and project specfic tasks a given SUBMISSION_ID"
|
36
|
+
option :editor
|
37
|
+
def run_command(working_dir, _submission_id = nil)
|
38
|
+
puts Shell::Run.new(working_dir, config).cmd
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "", ""
|
42
|
+
option :editor
|
43
|
+
option :application
|
44
|
+
def gui_trigger(id)
|
45
|
+
GuiTrigger.new({ id: id }, config).call
|
46
|
+
end
|
47
|
+
|
48
|
+
no_commands do
|
49
|
+
def exit_on_failure?
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def config
|
54
|
+
config = Config.new
|
55
|
+
config.update(options)
|
56
|
+
config
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module NewlineHw
|
4
|
+
class Config
|
5
|
+
CONFIG_PATH = File.expand_path("~/.newline_hw.yaml").freeze
|
6
|
+
DEFAULTS = {
|
7
|
+
"editor" => "atom",
|
8
|
+
"terminal" => "Terminal",
|
9
|
+
"launch_editor" => true,
|
10
|
+
"homework_dir" => "~/theironyard/homework",
|
11
|
+
"log_file" => "~/Library/Logs/newline_hw/newlinehw.log"
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def update(options)
|
15
|
+
@config = config.merge(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def config
|
19
|
+
@config ||= DEFAULTS.merge(config_file)
|
20
|
+
end
|
21
|
+
|
22
|
+
def config_file
|
23
|
+
YAML.load_file(CONFIG_PATH) || {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def editor
|
27
|
+
config["editor"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def terminal
|
31
|
+
config["terminal"]
|
32
|
+
end
|
33
|
+
|
34
|
+
def log_file
|
35
|
+
config["log_file"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def homework_dir
|
39
|
+
config["homework_dir"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def launch_editor
|
43
|
+
config["launch_editor"]
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.install_default
|
47
|
+
File.open(CONFIG_PATH, "w+") do |f|
|
48
|
+
f.write DEFAULTS.to_yaml
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "net/http"
|
3
|
+
require "json"
|
4
|
+
require "openssl"
|
5
|
+
require "newline_cli/api"
|
6
|
+
|
7
|
+
module NewlineHw
|
8
|
+
class GuiTrigger
|
9
|
+
attr_reader :editor
|
10
|
+
def initialize(data, config)
|
11
|
+
@newline_submission_id = data["id"]
|
12
|
+
@application = config.terminal
|
13
|
+
end
|
14
|
+
|
15
|
+
def application
|
16
|
+
return "Terminal".freeze unless %w(iTerm2 Terminal).include?(@application)
|
17
|
+
@application
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
applescript = case application
|
22
|
+
when "iTerm2"
|
23
|
+
applescript_for_iterm
|
24
|
+
else
|
25
|
+
applescript_for_terminal
|
26
|
+
end
|
27
|
+
|
28
|
+
{ terminal_output: `osascript -e '#{applescript}'` }
|
29
|
+
end
|
30
|
+
|
31
|
+
private def command_to_run_in_tty
|
32
|
+
"hw #{@newline_submission_id}"
|
33
|
+
end
|
34
|
+
|
35
|
+
private def applescript_for_terminal
|
36
|
+
<<-APPLESCRIPT
|
37
|
+
tell application "#{application}" to do script "#{command_to_run_in_tty}"
|
38
|
+
tell application "#{application}" to activate
|
39
|
+
APPLESCRIPT
|
40
|
+
end
|
41
|
+
|
42
|
+
private def applescript_for_iterm
|
43
|
+
<<-APPLESCRIPT
|
44
|
+
tell application \"#{application}\"
|
45
|
+
set newWindow to (create window with default profile)
|
46
|
+
|
47
|
+
tell current session of newWindow
|
48
|
+
write text "#{command_to_run_in_tty}"
|
49
|
+
end tell
|
50
|
+
end tell
|
51
|
+
APPLESCRIPT
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# if [[ $# -eq 0 ]] ; then
|
2
|
+
# echo 'WARNING: You must provide a git url, pull-request url or a Newline Submission ID.'
|
3
|
+
# exit 0
|
4
|
+
# fi
|
5
|
+
# OUTPUT="$(#{path} run_command $PWD $*)"
|
6
|
+
# eval $OUTPUT
|
7
|
+
|
8
|
+
module NewlineHw
|
9
|
+
module Shell
|
10
|
+
##
|
11
|
+
# Produce a bash / zsh function to be called by a tty compatible shell
|
12
|
+
#
|
13
|
+
# WARNING: all bash lines below must be terminated in a semicolon, line
|
14
|
+
# endings do not survive being passed through the heredoc correctly for the
|
15
|
+
# shell to interpreter correctly.
|
16
|
+
module Function
|
17
|
+
HW_FUNCTION = "hw".freeze
|
18
|
+
module_function
|
19
|
+
def path
|
20
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "exe", "newline_hw"))
|
21
|
+
end
|
22
|
+
|
23
|
+
def cmd
|
24
|
+
<<-eos
|
25
|
+
function #{HW_FUNCTION}() {
|
26
|
+
|
27
|
+
setup_command=$(#{path} setup_command $*);
|
28
|
+
setup_es=$?;
|
29
|
+
|
30
|
+
if [ "$setup_es" = "0" ]; then
|
31
|
+
eval $setup_command;
|
32
|
+
setup_command_es=$?;
|
33
|
+
|
34
|
+
run_command=$(#{path} run_command $PWD $*);
|
35
|
+
run_es=$?;
|
36
|
+
|
37
|
+
if [ $run_es = "0" ] && [ $setup_command_es = "0" ]; then
|
38
|
+
eval $run_command;
|
39
|
+
else
|
40
|
+
echo "Could not run project run command";
|
41
|
+
echo $run_command;
|
42
|
+
fi
|
43
|
+
else
|
44
|
+
echo "Could not run project setup command";
|
45
|
+
echo $setup_command;
|
46
|
+
fi
|
47
|
+
}
|
48
|
+
eos
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "runners/base"
|
2
|
+
require_relative "runners/ruby"
|
3
|
+
require_relative "runners/javascript"
|
4
|
+
|
5
|
+
module NewlineHw
|
6
|
+
module Shell
|
7
|
+
##
|
8
|
+
# Generate a series of language specfic commands to start a project up
|
9
|
+
class Run
|
10
|
+
attr_reader :pwd, :config
|
11
|
+
def initialize(pwd, config)
|
12
|
+
@pwd = pwd
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
def cmd
|
17
|
+
commands = []
|
18
|
+
commands += Runners::Ruby.get_commands(pwd)
|
19
|
+
commands += Runners::Javascript.get_commands(pwd)
|
20
|
+
commands << "#{config.editor} ." if config.launch_editor
|
21
|
+
commands.join(" && ")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module NewlineHw
|
2
|
+
module Shell
|
3
|
+
module Runners
|
4
|
+
class Base
|
5
|
+
attr_reader :commands, :pwd
|
6
|
+
|
7
|
+
def initialize(pwd)
|
8
|
+
@commands = []
|
9
|
+
@pwd = pwd
|
10
|
+
prepare_commands
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_command(cmd)
|
14
|
+
@commands << cmd
|
15
|
+
end
|
16
|
+
|
17
|
+
def file_path(*args)
|
18
|
+
File.expand_path(File.join(pwd, *args))
|
19
|
+
end
|
20
|
+
|
21
|
+
def file?(*args)
|
22
|
+
File.exist?(file_path(*args))
|
23
|
+
end
|
24
|
+
|
25
|
+
def file_contents?(regex, *args)
|
26
|
+
return false unless file?(*args)
|
27
|
+
!File.readlines(file_path(*args)).grep(regex).empty?
|
28
|
+
end
|
29
|
+
|
30
|
+
def prepare_commands
|
31
|
+
raise NotImplementedError, "Subclases of Tiyo::Runners::Base must implement prepare_commands"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.get_commands(pwd)
|
35
|
+
new(pwd).commands
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module NewlineHw
|
2
|
+
module Shell
|
3
|
+
module Runners
|
4
|
+
##
|
5
|
+
# Build a shell command that is dependent on files of a project being
|
6
|
+
# present that are UNOPINIONATED about how to setup / start a JS project
|
7
|
+
class Javascript < Base
|
8
|
+
def npm?
|
9
|
+
file?("package.json")
|
10
|
+
end
|
11
|
+
|
12
|
+
def yarn?
|
13
|
+
file?("yarn.lock")
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepare_commands
|
17
|
+
add_command "yarn" if yarn?
|
18
|
+
add_command "npm install" if npm? && !yarn?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module NewlineHw
|
2
|
+
module Shell
|
3
|
+
module Runners
|
4
|
+
##
|
5
|
+
# Build a shell command that is dependent on files of a project being
|
6
|
+
# present that are UNOPINIONATED about how to setup / start a ruby related
|
7
|
+
# project
|
8
|
+
class Ruby < Base
|
9
|
+
def rails?
|
10
|
+
file?("bin", "rails")
|
11
|
+
end
|
12
|
+
|
13
|
+
def gemfile?
|
14
|
+
file?("Gemfile")
|
15
|
+
end
|
16
|
+
|
17
|
+
def spring?
|
18
|
+
file_contents?(/spring/, "Gemfile.lock")
|
19
|
+
end
|
20
|
+
|
21
|
+
def _rails_commands
|
22
|
+
add_command "spring stop" if spring?
|
23
|
+
add_command "bin/rake db:setup"
|
24
|
+
add_command "bin/rails s & sleep #{SLEEP_TIME} && open http://localhost:3000"
|
25
|
+
add_command "bin/rake test"
|
26
|
+
add_command "sleep 1 && %%" # Reown the rails s process
|
27
|
+
end
|
28
|
+
|
29
|
+
def prepare_commands
|
30
|
+
add_command "bundle install" if gemfile?
|
31
|
+
_rails_commands if rails?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "uri"
|
3
|
+
require "shellwords"
|
4
|
+
|
5
|
+
module NewlineHw
|
6
|
+
module Shell
|
7
|
+
##
|
8
|
+
# Generate a series of language **AGNOISIC** commands to download and
|
9
|
+
# organize a students homework.
|
10
|
+
class Setup
|
11
|
+
BRANCH_NAME = "submitted_assignment".freeze
|
12
|
+
attr_accessor :url, :newline_submission_id, :config
|
13
|
+
def initialize(id_or_url, config)
|
14
|
+
@config = config
|
15
|
+
@newline_submission_id = Integer(id_or_url)
|
16
|
+
@url = submission_info["url"]
|
17
|
+
rescue ArgumentError
|
18
|
+
@config = config
|
19
|
+
@url = id_or_url
|
20
|
+
end
|
21
|
+
|
22
|
+
def submission_info
|
23
|
+
@_submission_info ||= query_submission_info
|
24
|
+
end
|
25
|
+
|
26
|
+
def cloneable?
|
27
|
+
pr? || gist? || github_project_link? || git? || false
|
28
|
+
end
|
29
|
+
|
30
|
+
def sha
|
31
|
+
return submission_info["sha"] if @newline_submission_id
|
32
|
+
matches = /\b[0-9a-f]{40}\b/.match(url)
|
33
|
+
matches.to_s if matches && !gist?
|
34
|
+
end
|
35
|
+
|
36
|
+
def git_url
|
37
|
+
return infer_git_url_from_pr if pr?
|
38
|
+
final_url = url.split("/tree/").first
|
39
|
+
"#{final_url}#{'.git' unless final_url.end_with?('.git')}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def github_project_link?
|
43
|
+
url.starts_with?("https://github.com") && URI(url).path.split("/").reject{|l| l.empty?}.size == 2
|
44
|
+
end
|
45
|
+
|
46
|
+
def git?
|
47
|
+
url.starts_with?("git") || url.ends_with?(".git")
|
48
|
+
end
|
49
|
+
|
50
|
+
def gist?
|
51
|
+
/gist\.github\.com/.match(url)
|
52
|
+
end
|
53
|
+
|
54
|
+
def pr?
|
55
|
+
%r{\/\/github.com}.match(url) && %r{\/pull\/\d+}.match(url)
|
56
|
+
end
|
57
|
+
|
58
|
+
def dir_name
|
59
|
+
git_url.split(%r{[\/\.]})[-3..-2].join("-")
|
60
|
+
end
|
61
|
+
|
62
|
+
def clean_dir
|
63
|
+
FileUtils.rm_rf(File.join(homework_path, dir_name))
|
64
|
+
end
|
65
|
+
|
66
|
+
def homework_path
|
67
|
+
File.expand_path(config.homework_dir)
|
68
|
+
end
|
69
|
+
|
70
|
+
def setup
|
71
|
+
FileUtils.mkdir_p homework_path
|
72
|
+
end
|
73
|
+
|
74
|
+
def cmd
|
75
|
+
setup
|
76
|
+
clean_dir
|
77
|
+
cmds = []
|
78
|
+
cmds << "cd #{homework_path}"
|
79
|
+
cmds << "git clone #{git_url} #{dir_name}"
|
80
|
+
cmds << "cd #{dir_name}"
|
81
|
+
cmds << fetch_and_checkout_pr if pr?
|
82
|
+
cmds << "git checkout #{sha} -b #{BRANCH_NAME}" if sha
|
83
|
+
cmds << "echo #{Shellwords.escape JSON.pretty_generate submission_info} > .newline_submission_meta.json" if newline_submission_id
|
84
|
+
cmds.join(" && ")
|
85
|
+
end
|
86
|
+
|
87
|
+
private def fetch_and_checkout_pr
|
88
|
+
"git fetch origin pull/#{pr_id}/head:#{BRANCH_NAME} && git checkout #{BRANCH_NAME}"
|
89
|
+
end
|
90
|
+
|
91
|
+
private def infer_git_url_from_pr
|
92
|
+
url.split("/pull/").first + ".git"
|
93
|
+
end
|
94
|
+
|
95
|
+
private def pr_id
|
96
|
+
url.split("/pull/").last.to_i
|
97
|
+
end
|
98
|
+
|
99
|
+
private def query_submission_info
|
100
|
+
NewlineCli::Api.new.get("assignment_submissions/#{@newline_submission_id}")
|
101
|
+
rescue Excon::Error::Socket => e
|
102
|
+
puts "Error could not open a connection to newline #{e.message}"
|
103
|
+
exit 3
|
104
|
+
rescue Excon::Error::Forbidden => e
|
105
|
+
puts "You do not have access to this submission #{e.message}"
|
106
|
+
exit 3
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module NewlineHw
|
4
|
+
##
|
5
|
+
# A json message handler to trigger actions from chrome native messaging
|
6
|
+
class StreamCommandHandler
|
7
|
+
attr_reader :event, :data, :message_at
|
8
|
+
EVENTS = [
|
9
|
+
:heartbeat,
|
10
|
+
:clone_and_open_submission,
|
11
|
+
:check_if_cloneable
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
def initialize(event)
|
15
|
+
@event = event["event"].to_sym
|
16
|
+
@data = event["data"]
|
17
|
+
@message_at = event["message_at"].to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def known_event?
|
21
|
+
EVENTS.include?(event)
|
22
|
+
end
|
23
|
+
|
24
|
+
def call
|
25
|
+
return handle_unknown unless known_event?
|
26
|
+
send(event)
|
27
|
+
|
28
|
+
rescue StandardError => e
|
29
|
+
handle_fail(e)
|
30
|
+
end
|
31
|
+
|
32
|
+
def heartbeat
|
33
|
+
{
|
34
|
+
status: :ok,
|
35
|
+
message_at: message_at,
|
36
|
+
data: {
|
37
|
+
version: NewlineHw::VERSION,
|
38
|
+
newline_cli_version: NewlineCli::VERSION,
|
39
|
+
ruby_version: RUBY_VERSION,
|
40
|
+
config_path: Config::CONFIG_PATH
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_if_cloneable
|
46
|
+
{
|
47
|
+
status: :ok,
|
48
|
+
message_at: message_at,
|
49
|
+
data: {
|
50
|
+
cloneable:
|
51
|
+
Shell::Setup.new(data["id"], Config.new).cloneable?
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def clone_and_open_submission
|
57
|
+
{
|
58
|
+
status: :ok,
|
59
|
+
message_at: message_at,
|
60
|
+
data: GuiTrigger.new(data, Config.new).call
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def handle_unknown
|
65
|
+
{
|
66
|
+
status: :fail,
|
67
|
+
message_at: message_at,
|
68
|
+
message: \
|
69
|
+
"no event handler found in Stream Command Handler for #{@event}"
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def handle_fail(e)
|
74
|
+
{
|
75
|
+
status: :fail,
|
76
|
+
event: @event,
|
77
|
+
message_at: message_at,
|
78
|
+
message: e.message
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module NewlineHw
|
4
|
+
class StreamProcessor
|
5
|
+
# Don't instant shutdown wait for messages to clear, as chrome is much faster
|
6
|
+
# to trigger disconnect callback over wait for succesful messages.
|
7
|
+
SHUTDOWN_PAUSE = 0.5
|
8
|
+
attr_reader :logger
|
9
|
+
def initialize(stdin, stdout, opts = {})
|
10
|
+
@logger = opts[:logger]
|
11
|
+
@stdin = stdin
|
12
|
+
@stdout = stdout
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_message(&block)
|
16
|
+
loop do
|
17
|
+
msg = read_native_message
|
18
|
+
sleep(SHUTDOWN_PAUSE) && exit(0) unless msg
|
19
|
+
@logger.debug "Receiving Message #{msg} of size:#{msg.length}"
|
20
|
+
instance_exec(msg, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def read_native_message
|
25
|
+
# Read signed integer with a max length of 4 bytes.
|
26
|
+
text_length_bytes = @stdin.read(4)
|
27
|
+
return unless text_length_bytes
|
28
|
+
|
29
|
+
# Unpack bytes in a ruby int.
|
30
|
+
text_length = text_length_bytes.unpack("i")[0]
|
31
|
+
JSON.parse(@stdin.read(text_length))
|
32
|
+
end
|
33
|
+
|
34
|
+
def send_message(message)
|
35
|
+
m = message.to_json
|
36
|
+
@logger.debug "Sending Message: #{m.length} #{m}"
|
37
|
+
@stdout.write [m.length].pack("I")
|
38
|
+
@stdout.write(m)
|
39
|
+
@stdout.flush
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/newline_hw.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative "newline_hw/version"
|
2
|
+
require_relative "newline_hw/config"
|
3
|
+
require_relative "newline_hw/shell/run"
|
4
|
+
require_relative "newline_hw/shell/setup"
|
5
|
+
require_relative "newline_hw/shell/function"
|
6
|
+
require_relative "newline_hw/chrome_manifest"
|
7
|
+
require_relative "newline_hw/gui_trigger"
|
8
|
+
require_relative "newline_hw/stream_command_handler"
|
9
|
+
require_relative "newline_hw/stream_processor"
|
10
|
+
require "newline_cli"
|
11
|
+
require "active_support/core_ext/string"
|
12
|
+
|
13
|
+
module NewlineHw
|
14
|
+
SLEEP_TIME = 4
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def config
|
19
|
+
Config.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def logfile
|
23
|
+
File.expand_path config.log_file
|
24
|
+
end
|
25
|
+
|
26
|
+
def make_log_directory
|
27
|
+
return if Dir.exist?(File.dirname(NewlineHw.logfile))
|
28
|
+
Dir.mkdir(File.dirname(NewlineHw.logfile))
|
29
|
+
end
|
30
|
+
end
|
data/newline_hw.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "newline_hw/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "newline_hw"
|
8
|
+
spec.version = NewlineHw::VERSION
|
9
|
+
spec.authors = ["Russell Osborne"]
|
10
|
+
spec.email = ["russell@theironyard.com"]
|
11
|
+
|
12
|
+
spec.summary = "Quickly Clone and setup basic ruby and JS projects."
|
13
|
+
spec.description = "Quickly Clone and setup basic ruby and JS projects."
|
14
|
+
spec.homepage = "https://online.theironyard.com."
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org/"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
spec.add_dependency "activesupport"
|
30
|
+
spec.add_dependency "json"
|
31
|
+
spec.add_dependency "thor"
|
32
|
+
spec.add_dependency "newline_cli"
|
33
|
+
|
34
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
35
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
36
|
+
spec.add_development_dependency "webmock", "~> 2.3"
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: newline_hw
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Russell Osborne
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thor
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: newline_cli
|
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
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.11'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.11'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2.3'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2.3'
|
111
|
+
description: Quickly Clone and setup basic ruby and JS projects.
|
112
|
+
email:
|
113
|
+
- russell@theironyard.com
|
114
|
+
executables:
|
115
|
+
- newline_hw
|
116
|
+
- newline_hw_stream
|
117
|
+
- newline_hw_stream_shim
|
118
|
+
extensions: []
|
119
|
+
extra_rdoc_files: []
|
120
|
+
files:
|
121
|
+
- ".gitignore"
|
122
|
+
- ".rspec"
|
123
|
+
- ".rubocop.yml"
|
124
|
+
- CODE_OF_CONDUCT.md
|
125
|
+
- Gemfile
|
126
|
+
- LICENSE.txt
|
127
|
+
- README.md
|
128
|
+
- Rakefile
|
129
|
+
- bin/console
|
130
|
+
- bin/setup
|
131
|
+
- exe/newline_hw
|
132
|
+
- exe/newline_hw_stream
|
133
|
+
- exe/newline_hw_stream_shim
|
134
|
+
- lib/newline_hw.rb
|
135
|
+
- lib/newline_hw/chrome_manifest.rb
|
136
|
+
- lib/newline_hw/cli.rb
|
137
|
+
- lib/newline_hw/config.rb
|
138
|
+
- lib/newline_hw/gui_trigger.rb
|
139
|
+
- lib/newline_hw/shell/function.rb
|
140
|
+
- lib/newline_hw/shell/run.rb
|
141
|
+
- lib/newline_hw/shell/runners/base.rb
|
142
|
+
- lib/newline_hw/shell/runners/javascript.rb
|
143
|
+
- lib/newline_hw/shell/runners/ruby.rb
|
144
|
+
- lib/newline_hw/shell/setup.rb
|
145
|
+
- lib/newline_hw/stream_command_handler.rb
|
146
|
+
- lib/newline_hw/stream_processor.rb
|
147
|
+
- lib/newline_hw/version.rb
|
148
|
+
- newline_hw.gemspec
|
149
|
+
homepage: https://online.theironyard.com.
|
150
|
+
licenses:
|
151
|
+
- MIT
|
152
|
+
metadata:
|
153
|
+
allowed_push_host: https://rubygems.org/
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 2.5.1
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: Quickly Clone and setup basic ruby and JS projects.
|
174
|
+
test_files: []
|