andy 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/Gemfile +9 -0
  2. data/Gemfile.lock +48 -0
  3. data/README.md +46 -0
  4. data/Rakefile +72 -0
  5. data/TODO.md +4 -0
  6. data/VERSION +1 -0
  7. data/andy.gemspec +90 -0
  8. data/bin/andy +3 -3
  9. data/conf/andy.yaml +1 -0
  10. data/features/api/list.feature +16 -0
  11. data/features/api/step_definitions/api_steps.rb +10 -0
  12. data/features/api/support/env.rb +19 -0
  13. data/features/gem/create.feature +11 -0
  14. data/features/gem/info.feature +16 -0
  15. data/features/gem/support/env.rb +11 -0
  16. data/features/gem/support/gem.rb +81 -0
  17. data/install +7 -0
  18. data/lib/andy/api/install_api.rb +36 -0
  19. data/lib/andy/api/list.rb +15 -0
  20. data/lib/andy/cli/install_cli.rb +17 -0
  21. data/lib/andy/cli/list_cli.rb +21 -0
  22. data/lib/andy/config.rb +48 -0
  23. data/lib/andy/exceptions.rb +4 -0
  24. data/lib/andy/nested_ostruct.rb +10 -0
  25. data/lib/andy/pint.rb +75 -0
  26. data/lib/andy/pint_mug.rb +11 -0
  27. data/lib/andy.rb +4 -3
  28. data/lib/andy.yaml +5 -0
  29. data/lib/andy_thor.rb +38 -0
  30. data/spec/api/install_spec.rb +30 -0
  31. data/spec/api/list_api_spec.rb +16 -0
  32. data/spec/config_spec.rb +32 -0
  33. data/spec/pint_spec.rb +57 -0
  34. data/spec/spec_helper.rb +10 -0
  35. data/spec/support/user_home/andy_home/pints/basic_web/css/core.css.erb +5 -0
  36. data/spec/support/user_home/andy_home/pints/basic_web/img/favicon.ico +0 -0
  37. data/spec/support/user_home/andy_home/pints/basic_web/index.html.erb +11 -0
  38. data/spec/support/user_home/andy_home/pints/basic_web/js/app.js.erb +5 -0
  39. data/spec/support/user_home/andy_home/pints/basic_web/pint.yml +7 -0
  40. data/spec/support/user_home/andy_home/pints/jquery/css/core.css.erb +5 -0
  41. data/spec/support/user_home/andy_home/pints/jquery/img/favicon.ico +0 -0
  42. data/spec/support/user_home/andy_home/pints/jquery/index.html.erb +12 -0
  43. data/spec/support/user_home/andy_home/pints/jquery/js/app.js.erb +5 -0
  44. data/spec/support/user_home/andy_home/pints/jquery/pint.yml +7 -0
  45. data/spec/support/user_home/andy_home/pints/not-a-pint/css/core.css.erb +5 -0
  46. data/spec/support/user_home/andy_home/pints/not-a-pint/img/favicon.ico +0 -0
  47. data/spec/support/user_home/andy_home/pints/not-a-pint/index.html.erb +11 -0
  48. data/spec/support/user_home/andy_home/pints/not-a-pint/js/app.js.erb +5 -0
  49. metadata +112 -46
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'thor'
4
+ gem 'jeweler'
5
+
6
+ group :test do
7
+ gem 'aruba'
8
+ gem 'rspec'
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ aruba (0.5.3)
5
+ childprocess (>= 0.3.6)
6
+ cucumber (>= 1.1.1)
7
+ rspec-expectations (>= 2.7.0)
8
+ builder (3.2.2)
9
+ childprocess (0.3.9)
10
+ ffi (~> 1.0, >= 1.0.11)
11
+ cucumber (1.3.2)
12
+ builder (>= 2.1.2)
13
+ diff-lcs (>= 1.1.3)
14
+ gherkin (~> 2.12.0)
15
+ multi_json (~> 1.3)
16
+ diff-lcs (1.2.4)
17
+ ffi (1.9.0)
18
+ gherkin (2.12.0)
19
+ multi_json (~> 1.3)
20
+ git (1.2.5)
21
+ jeweler (1.8.4)
22
+ bundler (~> 1.0)
23
+ git (>= 1.2.5)
24
+ rake
25
+ rdoc
26
+ json (1.8.0)
27
+ multi_json (1.7.7)
28
+ rake (10.0.4)
29
+ rdoc (4.0.1)
30
+ json (~> 1.4)
31
+ rspec (2.13.0)
32
+ rspec-core (~> 2.13.0)
33
+ rspec-expectations (~> 2.13.0)
34
+ rspec-mocks (~> 2.13.0)
35
+ rspec-core (2.13.1)
36
+ rspec-expectations (2.13.0)
37
+ diff-lcs (>= 1.1.3, < 2.0)
38
+ rspec-mocks (2.13.1)
39
+ thor (0.15.4)
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ aruba
46
+ jeweler
47
+ rspec
48
+ thor
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ Andy - Quickly generate skeletons of websites
2
+ =============================================
3
+
4
+ There are endless tools around to generate web apps and projects. A lot of frameworks ship with their own,
5
+ like Rails, Grails, Django et al. Then there's Maven. Then there are tools like Middleman, or Monk. But what
6
+ if all I want to do is put a bit of a skeleton of a website in place, with the exact libraries I typically use?
7
+
8
+ This is where Andy comes in. Andy is a Ruby gem, but it's not a Ruby-centric project. It works by pouring pints.
9
+
10
+ What's a 'pint'?
11
+ ----------------
12
+
13
+ A 'pint' is the instructions for generating your starter site. At the most basic, it's a set of files to be copied in to your new project directory. In fact, at time of writing, that's **all** a pint is. Hooks to build
14
+ more complex pints will follow in time, but for now, a pint is a set of static files that get copied in to a new project dir for you.
15
+
16
+ How do I use it?
17
+ ----------------
18
+
19
+ You need git. Andy does everything with git. If you don't have git, go get [git](http://git-scm.com/).
20
+
21
+ Install using
22
+
23
+ ```gem install andy```
24
+
25
+ Now, navigate to a folder, and type
26
+ ```andy my_new_project```
27
+
28
+ You should see a bit of gumf, whilst Andy configures himself, and grabs the basic pint sources. Then you'll find
29
+ a folder called my_new_project, which has an index.html, a css directory with Eric Meyer's CSS reset in it, and a JS directory, with nothing in it.
30
+
31
+ You could also do
32
+
33
+ ```andy my_new_project basic```
34
+
35
+ Or, replace *basic* with the name of your chosen pint. Andy ships with the following pints:
36
+
37
+ * basic - uber-barebones
38
+ * skeleton - based on the [Skeleton](http://getskeleton) framework
39
+ * homer - based on my [Homer](http://homer-app.herokuapp.com) toolkit
40
+
41
+
42
+ Ok, I'll bite: why 'Andy', and why 'Pint'?
43
+ ------------------------------------------
44
+
45
+ [Andy Capp](http://en.wikipedia.org/wiki/Andy_Capp) is a cartoon character who drinks 'pints'. I had 'chef recipes' in mind when I was thkinking about what to call them.
46
+
data/Rakefile ADDED
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ require 'cucumber'
6
+ require 'cucumber/rake/task'
7
+ require 'rspec/core/rake_task'
8
+
9
+ begin
10
+ Bundler.setup(:default, :development)
11
+ rescue Bundler::BundlerError => e
12
+ $stderr.puts e.message
13
+ $stderr.puts "Run `bundle install` to install missing gems"
14
+ exit e.status_code
15
+ end
16
+ require 'rake'
17
+
18
+ require 'jeweler'
19
+ Jeweler::Tasks.new do |gem|
20
+ gem.name = "andy"
21
+ gem.homepage = "http://github.com/georgecodes/andy"
22
+ gem.license = "MIT"
23
+ gem.summary = "A utility for generating empty projects"
24
+ gem.description = "Generate a skeleton project to get you started"
25
+ gem.email = "george@georgemcintosh.com"
26
+ gem.authors = ["George McIntosh"]
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |test|
32
+ test.libs << 'lib' << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+
37
+ desc "Run all tests"
38
+ task :test => [:spec, :cucumber]
39
+
40
+ desc "Run RSpec tests"
41
+ RSpec::Core::RakeTask.new(:spec)
42
+
43
+
44
+ task :default => :test
45
+
46
+ require 'rdoc/task'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "buzz #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
55
+
56
+ desc "Run cucumber features"
57
+ Cucumber::Rake::Task.new(:cucumber) do |t|
58
+ ENV['RACK_ENV'] = 'test'
59
+ t.cucumber_opts = "features --format pretty"
60
+ end
61
+
62
+ desc "Run cucumber API features"
63
+ Cucumber::Rake::Task.new(:cucumber_api) do |t|
64
+ ENV['RACK_ENV'] = 'test'
65
+ t.cucumber_opts = "features/api --format pretty"
66
+ end
67
+
68
+ desc "Run cucumber gem features - against a built gem"
69
+ Cucumber::Rake::Task.new(:cucumber_gem) do |t|
70
+ ENV['RACK_ENV'] = 'test'
71
+ t.cucumber_opts = "features/gem --format pretty"
72
+ end
data/TODO.md ADDED
@@ -0,0 +1,4 @@
1
+ TODO
2
+ ====
3
+
4
+ * Decouple list of default pints from codebase
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/andy.gemspec ADDED
@@ -0,0 +1,90 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "andy"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["George McIntosh"]
12
+ s.date = "2013-06-16"
13
+ s.description = "Generate a skeleton project to get you started"
14
+ s.email = "george@georgemcintosh.com"
15
+ s.executables = ["andy"]
16
+ s.extra_rdoc_files = [
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "README.md",
23
+ "Rakefile",
24
+ "TODO.md",
25
+ "VERSION",
26
+ "andy.gemspec",
27
+ "bin/andy",
28
+ "conf/andy.yaml",
29
+ "features/api/list.feature",
30
+ "features/api/step_definitions/api_steps.rb",
31
+ "features/api/support/env.rb",
32
+ "features/gem/create.feature",
33
+ "features/gem/info.feature",
34
+ "features/gem/support/env.rb",
35
+ "features/gem/support/gem.rb",
36
+ "install",
37
+ "lib/andy.rb",
38
+ "lib/andy.yaml",
39
+ "lib/andy/api/install_api.rb",
40
+ "lib/andy/api/list.rb",
41
+ "lib/andy/cli/install_cli.rb",
42
+ "lib/andy/cli/list_cli.rb",
43
+ "lib/andy/config.rb",
44
+ "lib/andy/exceptions.rb",
45
+ "lib/andy/nested_ostruct.rb",
46
+ "lib/andy/pint.rb",
47
+ "lib/andy/pint_mug.rb",
48
+ "lib/andy_thor.rb",
49
+ "spec/api/install_spec.rb",
50
+ "spec/api/list_api_spec.rb",
51
+ "spec/config_spec.rb",
52
+ "spec/pint_spec.rb",
53
+ "spec/spec_helper.rb",
54
+ "spec/support/user_home/andy_home/pints/basic_web/css/core.css.erb",
55
+ "spec/support/user_home/andy_home/pints/basic_web/img/favicon.ico",
56
+ "spec/support/user_home/andy_home/pints/basic_web/index.html.erb",
57
+ "spec/support/user_home/andy_home/pints/basic_web/js/app.js.erb",
58
+ "spec/support/user_home/andy_home/pints/basic_web/pint.yml",
59
+ "spec/support/user_home/andy_home/pints/jquery/css/core.css.erb",
60
+ "spec/support/user_home/andy_home/pints/jquery/img/favicon.ico",
61
+ "spec/support/user_home/andy_home/pints/jquery/index.html.erb",
62
+ "spec/support/user_home/andy_home/pints/jquery/js/app.js.erb",
63
+ "spec/support/user_home/andy_home/pints/jquery/pint.yml",
64
+ "spec/support/user_home/andy_home/pints/not-a-pint/css/core.css.erb",
65
+ "spec/support/user_home/andy_home/pints/not-a-pint/img/favicon.ico",
66
+ "spec/support/user_home/andy_home/pints/not-a-pint/index.html.erb",
67
+ "spec/support/user_home/andy_home/pints/not-a-pint/js/app.js.erb"
68
+ ]
69
+ s.homepage = "http://github.com/georgecodes/andy"
70
+ s.licenses = ["MIT"]
71
+ s.require_paths = ["lib"]
72
+ s.rubygems_version = "1.8.25"
73
+ s.summary = "A utility for generating empty projects"
74
+
75
+ if s.respond_to? :specification_version then
76
+ s.specification_version = 3
77
+
78
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
79
+ s.add_runtime_dependency(%q<thor>, [">= 0"])
80
+ s.add_runtime_dependency(%q<jeweler>, [">= 0"])
81
+ else
82
+ s.add_dependency(%q<thor>, [">= 0"])
83
+ s.add_dependency(%q<jeweler>, [">= 0"])
84
+ end
85
+ else
86
+ s.add_dependency(%q<thor>, [">= 0"])
87
+ s.add_dependency(%q<jeweler>, [">= 0"])
88
+ end
89
+ end
90
+
data/bin/andy CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- require 'andy'
2
+ require 'andy_thor'
3
3
 
4
- andy = Andy.new
5
- andy.run
4
+ ENV['ANDY_HOME'] = "#{ENV['HOME']}/.andy"
5
+ Andy::CLI.start(ARGV)
data/conf/andy.yaml CHANGED
@@ -2,6 +2,7 @@ pints:
2
2
  basic: 'git://github.com/georgecodes/andy.git'
3
3
  skeleton: 'git://github.com/georgecodes/Skeleton.git'
4
4
  homer: 'git://github.com/georgecodes/homer.git'
5
+ nakedfrank: 'git://github.com/georgecodes/naked-frank.git'
5
6
 
6
7
  conf:
7
8
  favourite: 'basic'
@@ -0,0 +1,16 @@
1
+ Feature: The list api
2
+ In order to list info to the user
3
+ As the CLI
4
+ I want to use the List API
5
+
6
+ @list_cli
7
+ Scenario: List all pints
8
+ When I call "list_names"
9
+ Then the result should contain:
10
+ """
11
+ Installed pints:
12
+
13
+ basic
14
+ jquery-basic
15
+ """
16
+
@@ -0,0 +1,10 @@
1
+ When(/^I call "(.*?)"$/) do |argument|
2
+ @out = StringIO.new
3
+ $stdout = @out
4
+ @cli.send argument
5
+ $stdout = STDOUT
6
+ end
7
+
8
+ Then(/^the result should contain:$/) do |string|
9
+ assert_partial_output(string, @out.string)
10
+ end
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../../lib/')
2
+ require 'aruba/cucumber'
3
+ #require 'aruba/in_process'
4
+ require 'andy_thor'
5
+ require 'andy/api/list'
6
+ require 'andy/cli/list_cli'
7
+ require 'andy/config'
8
+ require 'pathname'
9
+
10
+ andy_home = Pathname.new(File.join(Dir.getwd, 'spec', 'support', 'user_home', 'andy_home')).cleanpath
11
+
12
+ ENV['ANDY_HOME'] = andy_home.to_s
13
+ puts "ANDY HOME #{ENV['ANDY_HOME']}"
14
+ Before('@list_cli') do
15
+ api = Andy::Api::List.new( Andy::Config.new )
16
+ @cli = Andy::Cli::List.new(api)
17
+ #Aruba::InProcess.main_class = Andy::Cli::Lis#t
18
+ #Aruba.process = Aruba::InProcess
19
+ end
@@ -0,0 +1,11 @@
1
+ Feature: Generate
2
+ In order to generate an empty project
3
+ As a user
4
+ I want to run Andy
5
+
6
+ @gem
7
+ Scenario: Layout
8
+ When I run `andy new test-app`
9
+ Then the following directories should exist:
10
+ | test-app |
11
+
@@ -0,0 +1,16 @@
1
+ Feature: Get info
2
+ In order to find out information
3
+ As a user
4
+ I want to run 'andy list'
5
+
6
+ @gem
7
+ Scenario: List all pints
8
+ When I run `andy list`
9
+ Then the output should contain:
10
+ """
11
+ Installed pints:
12
+
13
+ basic
14
+ jquery-basic
15
+ """
16
+
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../../lib/')
2
+ require 'aruba/cucumber'
3
+ require 'andy_thor'
4
+
5
+ Before('@gem') do
6
+ CukeGem.setup(File.dirname(__FILE__) + '/../../../andy.gemspec')
7
+ end
8
+
9
+ After('@gem') do
10
+ CukeGem.teardown
11
+ end
@@ -0,0 +1,81 @@
1
+ require 'aruba'
2
+ require 'aruba/api'
3
+
4
+ class CukeGem
5
+ @setup_done = false
6
+
7
+ class << self
8
+ include Aruba::Api
9
+
10
+ attr_reader :setup_done
11
+
12
+ def setup(gemspec, once=true)
13
+ gem_home = setup_env
14
+ if !@setup_done || !once then
15
+ @setup_done = true
16
+ mkgemdir(gem_home)
17
+ gem_install(gemspec)
18
+ end
19
+ end
20
+
21
+ def teardown
22
+ restore_env
23
+ end
24
+
25
+ def setup_env
26
+ tid = ENV['TDDIUM_TID'] || ''
27
+ gem_home = File.join('tmp', 'aruba-gem')
28
+ gem_home = File.expand_path(gem_home)
29
+
30
+ set_env('GEM_HOME', gem_home)
31
+ set_env('GEM_PATH', gem_home)
32
+ set_env('BUNDLE_PATH', gem_home)
33
+ unset_bundler_env_vars
34
+
35
+ paths = (ENV['PATH'] || "").split(File::PATH_SEPARATOR)
36
+ paths.unshift(File.join(gem_home, 'bin'))
37
+ set_env('PATH', paths.uniq.join(File::PATH_SEPARATOR))
38
+
39
+ return gem_home
40
+ end
41
+
42
+ def mkgemdir(gem_home)
43
+ FileUtils::rm_rf(gem_home)
44
+ FileUtils::mkdir_p(gem_home)
45
+
46
+ output = `gem install bundler`
47
+ if $?.exitstatus != 0 then
48
+ raise "unable to install bundler into #{gem_home}: #{output}"
49
+ end
50
+ end
51
+
52
+ def gem_install(gemspec)
53
+ gem_file = nil
54
+ begin
55
+ pwd = Dir.pwd
56
+ gemspec_dir = File.dirname(gemspec)
57
+ Dir.chdir(gemspec_dir)
58
+ output = `gem build #{File.basename(gemspec)}`
59
+ Dir.chdir(pwd)
60
+
61
+ if $?.exitstatus != 0 then
62
+ raise "unable to build gem: #{output}"
63
+ end
64
+
65
+ if output =~ /File:\s+([A-Za-z0-9_.-]+[.]gem)/ then
66
+ gem_file = $1
67
+ output = `gem install #{File.join(gemspec_dir, gem_file)}`
68
+ if $?.exitstatus != 0 then
69
+ raise "unable to install gem: #{output}"
70
+ end
71
+ else
72
+ raise "garbled gem build output: #{output}"
73
+ end
74
+ ensure
75
+ if gem_file then
76
+ FileUtils.rm_f(File.join(gemspec_dir, gem_file))
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
data/install ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ # This script builds the andy gem, then installs it locally
3
+ # it might not work, depending on whether you're using rvm, or other factors
4
+ # let me know!
5
+
6
+ gem build andy.gemspec
7
+ sudo gem install ./andy-0.0.1.gem
@@ -0,0 +1,36 @@
1
+ require 'erb'
2
+
3
+ module Andy
4
+ module Api
5
+ class Install
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def install(pint_name, project_name, dir_name, project_parent_location)
12
+ project_path = File.join(project_parent_location, dir_name)
13
+ Dir::mkdir(project_path)
14
+ pint = @config.get_pint(pint_name)
15
+ pint.source_files.each do |relative_source_file|
16
+ source_file = File.join(pint.location, relative_source_file)
17
+ destination_file = File.join(project_path, relative_source_file)
18
+ is_template = relative_source_file.end_with?('.erb')
19
+ destination_file = destination_file[0..-5] unless !is_template
20
+ body = File.open(source_file).read
21
+ if ( relative_source_file.end_with?('.erb') )
22
+ erb = ERB.new(body)
23
+ body = erb.result(binding)
24
+ end
25
+ destination_dir = Pathname.new(destination_file).dirname
26
+ Dir::mkdir(destination_dir) unless File.directory?(destination_dir)
27
+ output = File.open(destination_file, 'w')
28
+ output.puts body
29
+ output.close
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ module Andy
2
+ module Api
3
+ class List
4
+
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def pint_names
10
+ @config.pints.collect { |pint| pint.name }
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Andy
2
+
3
+ module Cli
4
+ class Install
5
+
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def install(pint_name, project_name, dir_name, project_parent_location)
11
+ @api.install(pint_name, project_name, dir_name, project_parent_location)
12
+ end
13
+
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,21 @@
1
+ module Andy
2
+
3
+ module Cli
4
+ class List
5
+
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def list_names
11
+ known_pints = @api.pint_names
12
+ puts "Installed pints:\n\n"
13
+ known_pints.each do |pint|
14
+ puts " #{pint}"
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,48 @@
1
+ require 'ostruct'
2
+ require 'yaml'
3
+ require 'andy/exceptions'
4
+ require 'andy/pint'
5
+
6
+ module Andy
7
+ class Config
8
+
9
+ def initialize(andy_home = ENV['ANDY_HOME'])
10
+ @home = andy_home
11
+ @pint_home = "#{@home}/pints"
12
+ @pints = load_pints
13
+ end
14
+
15
+ def home
16
+ @home
17
+ end
18
+
19
+ def pint_home
20
+ @pint_home
21
+ end
22
+
23
+ def pints
24
+ @pints.values
25
+ end
26
+
27
+ def get_pint(pint_name)
28
+ @pints[pint_name]
29
+ end
30
+
31
+ private
32
+ def load_pints
33
+ pints = {}
34
+ Dir.foreach(@pint_home) do |pint_location|
35
+ next if pint_location == '.' or pint_location == '..'
36
+ pint_location = File.join(@pint_home, pint_location)
37
+ begin
38
+ pint = Andy::Pint.new(pint_location)
39
+ pints [pint.name] = pint
40
+ rescue Exception => e #Andy::UknkownPintException
41
+ #puts "E => #{e}"
42
+ #puts "Failed to load pint from #{pint_location}"
43
+ end
44
+ end
45
+ pints
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,4 @@
1
+ module Andy
2
+ class UnknownPintException < StandardError
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ require 'ostruct'
2
+
3
+ module Andy
4
+ class NestedOStruct
5
+ def self.new(hash)
6
+ OpenStruct.new(hash.inject({}){|r,p| r[p[0]] = p[1].kind_of?(Hash)?
7
+ Andy::NestedOStruct.new(p[1]) : p[1]; r })
8
+ end
9
+ end
10
+ end
data/lib/andy/pint.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'yaml'
2
+ require 'andy/nested_ostruct'
3
+ require 'fileutils'
4
+ require 'pathname'
5
+ require 'andy/exceptions'
6
+
7
+ module Andy
8
+ class Pint
9
+
10
+ def initialize(location)
11
+ @location = location
12
+ begin
13
+ config = YAML.load_file("#{location}/pint.yml")
14
+ rescue
15
+ raise UnknownPintException.new
16
+ end
17
+ pint_config = Andy::NestedOStruct.new config
18
+ @my_config = pint_config.pint
19
+ end
20
+
21
+ def name
22
+ @my_config.name
23
+ end
24
+
25
+ def long_name
26
+ @my_config.long_name
27
+ end
28
+
29
+ def description
30
+ @my_config.description
31
+ end
32
+
33
+ def version
34
+ @my_config.version
35
+ end
36
+
37
+ def author
38
+ @my_config.author
39
+ end
40
+
41
+ def remote
42
+ @my_config.remote
43
+ end
44
+
45
+ def location
46
+ @location
47
+ end
48
+
49
+ def generated_files
50
+ my_files = []
51
+ Dir.glob("#{@location}/**/*").each do |file_name|
52
+ file = File.new(file_name)
53
+ if (! File.directory?(file_name))
54
+ path_name = Pathname.new(file_name).relative_path_from(Pathname.new(@location)).to_s
55
+ generated_file_name = path_name.end_with?('.erb') ? path_name[0..-5] : path_name
56
+ my_files << generated_file_name unless generated_file_name == 'pint.yml'
57
+ end
58
+ end
59
+ my_files
60
+ end
61
+
62
+ def source_files
63
+ my_files = []
64
+ Dir.glob("#{@location}/**/*").each do |file_name|
65
+ file = File.new(file_name)
66
+ if (! File.directory?(file_name))
67
+ path_name = Pathname.new(file_name).relative_path_from(Pathname.new(@location)).to_s
68
+ my_files << path_name unless path_name == 'pint.yml'
69
+ end
70
+ end
71
+ my_files
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,11 @@
1
+ module Andy
2
+ class PintMug
3
+
4
+ def fetch_local_pints
5
+ [
6
+ { :name => 'Static web', :description => 'HTML, CSS, JavaScript', :url => 'git@github.com:georgecodes/static-web-pint'},
7
+ { :name => 'Twitter Bootstrap', :description => 'Static web with Bootstrap', :url => 'git@github.com:georgecodes/bootstrap-ping'}
8
+ ]
9
+ end
10
+ end
11
+ end
data/lib/andy.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'fileutils'
2
2
  require 'git'
3
+ require 'yaml'
3
4
 
4
5
  class Andy
5
6
 
@@ -56,10 +57,10 @@ class Andy
56
57
  end
57
58
 
58
59
  def ensure_local_repo_built
59
- if FileTest::directory?ANDY_HOME
60
- return
60
+ if !FileTest::directory?ANDY_HOME
61
+ Dir::mkdir(ANDY_HOME)
61
62
  end
62
- Dir::mkdir(ANDY_HOME)
63
+
63
64
  $LOAD_PATH.each do | dir |
64
65
  if dir =~ /andy.*\/conf$/
65
66
  FileUtils.cp(dir + "/andy.yaml", ANDY_HOME )
data/lib/andy.yaml ADDED
@@ -0,0 +1,5 @@
1
+ repos:
2
+ - basic: '/Users/george/dev/andy-pints/basic'
3
+
4
+ conf:
5
+ default: 'basic'
data/lib/andy_thor.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'thor'
2
+ require 'andy/config'
3
+ require 'andy/api/list'
4
+ require 'andy/api/install_api'
5
+
6
+ module Andy
7
+ class CLI < Thor
8
+
9
+ def initialize(args=[], options={}, config={})
10
+ super(args, options, config)
11
+ @config = Andy::Config.new
12
+ @list = Andy::Api::List.new @config
13
+ @install = Andy::Api::Install.new @config
14
+ end
15
+
16
+ desc "new", "Generates an app directory and copies the appropriate files"
17
+ option :pint_name, :required => true, :aliases => ['-p']
18
+ option :app_name, :required => false, :aliases => ['-a']
19
+ def new(dir_name)
20
+ # def install(pint_name, project_name, dir_name, project_parent_location)
21
+ pint_name = options[:pint_name]
22
+ app_name = options[:app_name] || dir_name
23
+ project_parent_location = Dir.getwd
24
+ @install.install(pint_name, app_name, dir_name, project_parent_location)
25
+ puts "Created project #{app_name} in #{dir_name}"
26
+ end
27
+
28
+ desc "list", "Lists known pints"
29
+ def list
30
+ known_pints = @list.pint_names
31
+ puts "Installed pints:"
32
+ known_pints.each do |pint|
33
+ puts " #{pint}"
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Installs API" do
4
+
5
+ before :all do
6
+ @root = ENV['WORK_DIR']
7
+ Dir::mkdir @root
8
+ end
9
+
10
+ before :each do
11
+ config = Andy::Config.new
12
+ @install = Andy::Api::Install.new(config)
13
+ end
14
+
15
+ after :all do
16
+ FileUtils.rm_r ENV['WORK_DIR']
17
+ end
18
+
19
+ it "Should install a pint" do
20
+ @install.install('basic', 'My test project', 'test', @root)
21
+ project_dir = File.join(@root, 'test')
22
+ File.directory?(project_dir).should eq true
23
+ File.exist?(File.join(project_dir, 'index.html')).should be_true
24
+ File.exist?(File.join(project_dir, 'css', 'core.css')).should be_true
25
+ File.exist?(File.join(project_dir, 'js', 'app.js')).should be_true
26
+ File.exist?(File.join(project_dir, 'img', 'favicon.ico')).should be_true
27
+ end
28
+
29
+
30
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe "List API" do
4
+
5
+ before :each do
6
+ config = Andy::Config.new
7
+ @list = Andy::Api::List.new(config)
8
+ end
9
+
10
+ it "Should give a list of names of current installed pints" do
11
+ expected_names = ['basic', 'jquery-basic']
12
+ @list.pint_names.should eq expected_names
13
+ end
14
+
15
+
16
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Configuration" do
4
+
5
+ before :each do
6
+ @config = Andy::Config.new
7
+ end
8
+
9
+ it "should know where ANDY_HOME is" do
10
+ expected_andy_home = ENV['ANDY_HOME']
11
+ @config.home.should eq expected_andy_home
12
+ end
13
+
14
+ it "should know where it's pints are" do
15
+ expected_pint_home = File.join(ENV['ANDY_HOME'], 'pints')
16
+ @config.pint_home.should eq expected_pint_home
17
+ end
18
+
19
+ it "should load all pint metadata" do
20
+ pints = @config.pints.sort { |x,y| x.name <=> y.name }
21
+ pints.length.should be 2
22
+ pints[0].name.should eq 'basic'
23
+ pints[1].name.should eq 'jquery-basic'
24
+ end
25
+
26
+ it "should return the correct pint by name" do
27
+ pint = @config.get_pint 'basic'
28
+ pint.should_not be nil
29
+ pint.name.should eq 'basic'
30
+ end
31
+
32
+ end
data/spec/pint_spec.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe "The pint metadata object" do
4
+
5
+ before :each do
6
+ @pint_path = File.join(ENV['ANDY_HOME'], 'pints', 'basic_web')
7
+ @pint = Andy::Pint.new(@pint_path)
8
+ end
9
+
10
+ it "should tell me its name" do
11
+ @pint.name.should eq 'basic'
12
+ end
13
+
14
+ it "should tell me its long name" do
15
+ @pint.long_name.should eq 'Basic web site'
16
+ end
17
+
18
+ it "should tell me its description" do
19
+ @pint.description.should eq "Static HTML with CSS and JavaScript"
20
+ end
21
+
22
+ it "should tell me its version" do
23
+ @pint.version.should eq 1.0
24
+ end
25
+
26
+ it "should tell me its author" do
27
+ @pint.author.should eq "George McIntosh <george@georgemcintosh.com>"
28
+ end
29
+
30
+ it "should tell me its remote location" do
31
+ @pint.remote.should eq "git@github.com:georgecodes/basic-web-pint.git"
32
+ end
33
+
34
+ it "should list all of the files in the pint" do
35
+ end
36
+
37
+ it "should tell me its location" do
38
+ @pint.location.should eq @pint_path
39
+ end
40
+
41
+ it "should list all of the generated files, as they will end up in the generated project" do
42
+ expected_files = ['index.html', 'css/core.css', 'js/app.js', 'img/favicon.ico'].sort
43
+ files = @pint.generated_files.sort
44
+ files.should eq expected_files
45
+ end
46
+
47
+ it "should list all of the source files, which will be used to generate the project" do
48
+ expected_files = ['index.html.erb', 'css/core.css.erb', 'js/app.js.erb', 'img/favicon.ico'].sort
49
+ files = @pint.source_files.sort
50
+ files.should eq expected_files
51
+ end
52
+
53
+ it "should raise an error if the pint doesn't exist" do
54
+ expect {Andy::Pint.new('does/not/exist') }.to raise_error Andy::UnknownPintException
55
+ end
56
+
57
+ end
@@ -0,0 +1,10 @@
1
+ require 'andy_thor'
2
+ require 'andy/pint_mug'
3
+ require 'andy/pint'
4
+ require 'andy/api/list'
5
+ require 'andy/api/install_api'
6
+ require 'andy/config'
7
+ require 'fileutils'
8
+
9
+ ENV['WORK_DIR'] = File.join(Dir.getwd, 'tmp', 'work')
10
+ ENV['ANDY_HOME'] = File.join(File.dirname(__FILE__), 'support', 'user_home', 'andy_home')
@@ -0,0 +1,5 @@
1
+ /* This is the core CSS file for the project <%= project_name %> */
2
+
3
+ body {
4
+ background-color: #fff;
5
+ }
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Welcome to <%= project_name %></title>
5
+ <link rel="stylesheet" type="text/css" href="/css/core.css"/>
6
+ <script type="text/javascript" src="/js/app.js"></script>
7
+ </head>
8
+ <body>
9
+ <h1>This is the <%= project_name %> front page</h1>
10
+ </body>
11
+ </html>
@@ -0,0 +1,5 @@
1
+ // Main JavaScript file for <%= project_name %>
2
+
3
+ function hello() {
4
+ alert('Hello from <%= project_name %>');
5
+ }
@@ -0,0 +1,7 @@
1
+ pint:
2
+ name: basic
3
+ long_name: Basic web site
4
+ description: Static HTML with CSS and JavaScript
5
+ version: 1.0
6
+ author: George McIntosh <george@georgemcintosh.com>
7
+ remote: git@github.com:georgecodes/basic-web-pint.git
@@ -0,0 +1,5 @@
1
+ /* This is the core CSS file for the project <%= project_name %> */
2
+
3
+ body {
4
+ background-color: #fff;
5
+ }
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Welcome to <%= project_name %></title>
5
+ <link rel="stylesheet" type="text/css" href="/css/core.css"/>
6
+ <script type="text/javascript" src="/js/app.js"></script>
7
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
8
+ </head>
9
+ <body>
10
+ <h1>This is the <%= project_name %> front page</h1>
11
+ </body>
12
+ </html>
@@ -0,0 +1,5 @@
1
+ // Main JavaScript file for <%= project_name %>
2
+
3
+ function hello() {
4
+ alert('Hello from <%= project_name %>');
5
+ }
@@ -0,0 +1,7 @@
1
+ pint:
2
+ name: jquery-basic
3
+ long_name: JQuery Web site
4
+ description: Static HTML with CSS, JavaScript and CDN-hosted JQuery
5
+ version: 1.0
6
+ author: George McIntosh <george@georgemcintosh.com>
7
+ remote: git@github.com:georgecodes/jquerybasic-web-pint.git
@@ -0,0 +1,5 @@
1
+ /* This is the core CSS file for the project <%= project_name %> */
2
+
3
+ body {
4
+ background-color: #fff;
5
+ }
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Welcome to <%= title %></title>
5
+ <link rel="stylesheet" type="text/css" href="/css/core.css"/>
6
+ <script type="text/javascript" src="/js/app.js"></script>
7
+ </head>
8
+ <body>
9
+ <h1>This is the <%= app_name %> front page</h1>
10
+ </body>
11
+ </html>
@@ -0,0 +1,5 @@
1
+ // Main JavaScript file for <%= project_name %>
2
+
3
+ function hello() {
4
+ alert('Hello from <%= project_name %>');
5
+ }
metadata CHANGED
@@ -1,64 +1,130 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: andy
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 1
9
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - George McIntosh
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2012-11-21 00:00:00 +00:00
18
- default_executable:
19
- dependencies: []
20
-
21
- description: A simple site generator gem
22
- email: george@georgecodes.com
23
- executables:
12
+ date: 2013-06-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: jeweler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Generate a skeleton project to get you started
47
+ email: george@georgemcintosh.com
48
+ executables:
24
49
  - andy
25
50
  extensions: []
26
-
27
- extra_rdoc_files: []
28
-
29
- files:
30
- - lib/andy.rb
51
+ extra_rdoc_files:
52
+ - README.md
53
+ files:
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - README.md
57
+ - Rakefile
58
+ - TODO.md
59
+ - VERSION
60
+ - andy.gemspec
61
+ - bin/andy
31
62
  - conf/andy.yaml
32
- has_rdoc: true
33
- homepage: http://rubygems.org/gems/gen
34
- licenses: []
35
-
63
+ - features/api/list.feature
64
+ - features/api/step_definitions/api_steps.rb
65
+ - features/api/support/env.rb
66
+ - features/gem/create.feature
67
+ - features/gem/info.feature
68
+ - features/gem/support/env.rb
69
+ - features/gem/support/gem.rb
70
+ - install
71
+ - lib/andy.rb
72
+ - lib/andy.yaml
73
+ - lib/andy/api/install_api.rb
74
+ - lib/andy/api/list.rb
75
+ - lib/andy/cli/install_cli.rb
76
+ - lib/andy/cli/list_cli.rb
77
+ - lib/andy/config.rb
78
+ - lib/andy/exceptions.rb
79
+ - lib/andy/nested_ostruct.rb
80
+ - lib/andy/pint.rb
81
+ - lib/andy/pint_mug.rb
82
+ - lib/andy_thor.rb
83
+ - spec/api/install_spec.rb
84
+ - spec/api/list_api_spec.rb
85
+ - spec/config_spec.rb
86
+ - spec/pint_spec.rb
87
+ - spec/spec_helper.rb
88
+ - spec/support/user_home/andy_home/pints/basic_web/css/core.css.erb
89
+ - spec/support/user_home/andy_home/pints/basic_web/img/favicon.ico
90
+ - spec/support/user_home/andy_home/pints/basic_web/index.html.erb
91
+ - spec/support/user_home/andy_home/pints/basic_web/js/app.js.erb
92
+ - spec/support/user_home/andy_home/pints/basic_web/pint.yml
93
+ - spec/support/user_home/andy_home/pints/jquery/css/core.css.erb
94
+ - spec/support/user_home/andy_home/pints/jquery/img/favicon.ico
95
+ - spec/support/user_home/andy_home/pints/jquery/index.html.erb
96
+ - spec/support/user_home/andy_home/pints/jquery/js/app.js.erb
97
+ - spec/support/user_home/andy_home/pints/jquery/pint.yml
98
+ - spec/support/user_home/andy_home/pints/not-a-pint/css/core.css.erb
99
+ - spec/support/user_home/andy_home/pints/not-a-pint/img/favicon.ico
100
+ - spec/support/user_home/andy_home/pints/not-a-pint/index.html.erb
101
+ - spec/support/user_home/andy_home/pints/not-a-pint/js/app.js.erb
102
+ homepage: http://github.com/georgecodes/andy
103
+ licenses:
104
+ - MIT
36
105
  post_install_message:
37
106
  rdoc_options: []
38
-
39
- require_paths:
107
+ require_paths:
40
108
  - lib
41
- - conf
42
- required_ruby_version: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- segments:
47
- - 0
48
- version: "0"
49
- required_rubygems_version: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- segments:
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ segments:
54
116
  - 0
55
- version: "0"
117
+ hash: -128580633999570231
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
56
124
  requirements: []
57
-
58
125
  rubyforge_project:
59
- rubygems_version: 1.3.6
126
+ rubygems_version: 1.8.25
60
127
  signing_key:
61
128
  specification_version: 3
62
- summary: Site generator
129
+ summary: A utility for generating empty projects
63
130
  test_files: []
64
-