utilikilt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ vendor/bundle/
3
+ pkg/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "http://rubygems.org"
3
+
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # Get Going!
2
+ install the dependencies you need with:
3
+ ```
4
+ bundle install --path vendor/bundle --binstubs
5
+ ```
6
+
7
+ Install pow, your friendly static server)
8
+ ```
9
+ curl get.pow.cx | sh
10
+ ```
11
+
12
+ Use powder to ask pow to serve up the files in the *public* subdirectory:
13
+ ```
14
+ bin/powder link
15
+ ```
16
+
17
+ Fire up **Guard** which will magically generate HTML and CSS whenever you change your HAML and SASS:
18
+ ```
19
+ bin/guard
20
+ ```
21
+
22
+ Open up your content in a web browser:
23
+ ```
24
+ bin/powder open
25
+ ```
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/uk ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'utilikilt'
4
+ require 'utilikilt/cli'
5
+
6
+ Utilikilt::CLI.start
@@ -0,0 +1,56 @@
1
+ # tricks rubygems into believeing that the extension compiled and worked out.
2
+ # This function lifted straight out of the zerg_support gem https://rubygems.org/gems/zerg_support
3
+ def emulate_extension_install
4
+ extension_name = "utilikilt"
5
+ File.open('Makefile', 'w') { |f| f.write "all:\n\ninstall:\n\n" }
6
+ File.open('make', 'w') do |f|
7
+ f.write '#!/bin/sh'
8
+ f.chmod f.stat.mode | 0111
9
+ end
10
+ File.open(extension_name + '.so', 'w') {}
11
+ File.open(extension_name + '.dll', 'w') {}
12
+ File.open('nmake.bat', 'w') { |f| }
13
+ end
14
+
15
+
16
+ def executable?( exe )
17
+ system "command -v #{exe} >/dev/null 2>&1"
18
+ end
19
+
20
+ def check_prereqs_and_advise
21
+ return nil if executable? 'node'
22
+
23
+ generic_advice = "\nUtilikilt uses node.js to serve up your files, but you don't appear to have it installed.\n"
24
+ if executable? 'brew'
25
+ return [generic_advice,"However it does look like you have homebrew available.","To install node simply run `brew install node`, then try to install the utilikilt gem again."].join("\n")
26
+ elsif `uname` =~ /Darwin/
27
+ return [generic_advice,%Q{The easiest way to install node is using a package manager called homebrew. You can get started with homebrew by visting http://bit.ly/getbrew, or just run the following from the command line:},%Q{/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"},"",%Q{Once homebrew is installed you can install node.js with a simple `brew install node` from the command line. After that, try installing the utilikilt gem again.}].join("\n")
28
+ else
29
+ return [generic_advice,"Please install node.js and then try to install the utilikilt gem again."].join("\n")
30
+ end
31
+ end
32
+
33
+
34
+ def install_node_package
35
+ puts 'installing utilikilt npm package...'
36
+ system *%w{npm install utilikilt}, {:chdir => "../../"}
37
+ puts '...utilikilt npm package installed'
38
+ end
39
+
40
+ # This is a big ol' hack to run a pre-install script for this gem, by pretending to compile a native extension. See http://blog.costan.us/2008/11/post-install-post-update-scripts-for.html for details.
41
+
42
+ emulate_extension_install()
43
+
44
+ prereq_errors = check_prereqs_and_advise()
45
+ if prereq_errors
46
+ puts "\n\n\n"
47
+ puts "*"*80
48
+ puts prereq_errors
49
+ puts "*"*80
50
+ puts "\n\n\n"
51
+ exit 1
52
+ end
53
+
54
+ install_node_package()
55
+
56
+
data/lib/utilikilt.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "utilikilt/version"
2
+
3
+ module Utilikilt
4
+ DEFAULT_INPUT_DIR_NAME = 'source'
5
+ DEFAULT_OUTPUT_DIR_NAME = 'public'
6
+ end
@@ -0,0 +1,86 @@
1
+ require 'thor'
2
+ require 'utilikilt/scanner'
3
+ require 'utilikilt/watcher'
4
+ require 'utilikilt/node_proxy'
5
+ require 'utilikilt/workspace'
6
+
7
+ module Utilikilt
8
+ class CLI < Thor
9
+
10
+ desc "watch", "watch for changes to source files and automatically create corresponding public files"
11
+ method_option :input_dir, :aliases => '-i', :type => 'string'
12
+ method_option :output_dir, :aliases => '-o', :type => 'string'
13
+ def watch( project_dir = nil )
14
+ opts = normalize_options(project_dir,options)
15
+ start_watcher(opts)
16
+ end
17
+
18
+ desc "build", "rebuild all input files"
19
+ method_option :input_dir, :aliases => '-i', :type => 'string'
20
+ method_option :output_dir, :aliases => '-o', :type => 'string'
21
+ def build( project_dir = nil )
22
+ opts = normalize_options(project_dir,options)
23
+ run_one_off_scan( opts )
24
+ end
25
+
26
+ desc "serve", "Start a little web server host whatever is in your public directory, with live refresh"
27
+ def serve( project_dir = nil )
28
+ opts = normalize_options(project_dir,options)
29
+ start_serve( opts )
30
+ end
31
+
32
+ desc "up", "live-compile the contents of source, and serve it up to your browser with live-refresh"
33
+ method_option :input_dir, :aliases => '-i', :type => 'string'
34
+ method_option :output_dir, :aliases => '-o', :type => 'string'
35
+ def up( project_dir=nil )
36
+ watch_thread = Thread.new{ watch(project_dir) }
37
+ serve_thread = Thread.new{ serve(project_dir) }
38
+
39
+ serve_thread.join # joining on serve rather than watch is arbitrary
40
+ end
41
+
42
+ desc "workspace", "create a new workspace directory"
43
+ def workspace( workspace_name )
44
+ workspace = Workspace.new( Dir.getwd, workspace_name )
45
+ problems = workspace.create_or_report_problems
46
+ if problems
47
+ puts
48
+ puts problems
49
+ exit 1
50
+ end
51
+ end
52
+ private
53
+
54
+ def run_one_off_scan(options)
55
+ scanner = Scanner.new( options )
56
+ scanner.scan
57
+ end
58
+
59
+ def start_watcher(options)
60
+ scanner = Scanner.new( options )
61
+ scanner.scan # do an initial build
62
+ Watcher.watch options['input_dir'] do
63
+ scanner.scan
64
+ end
65
+ end
66
+
67
+ def start_serve(options)
68
+ server = Utilikilt::NodeProxy.new( options['output_dir'] )
69
+ server.launch_server
70
+ end
71
+
72
+
73
+ def normalize_options( project_dir, opts )
74
+ normalized = {}
75
+ %w{input_dir output_dir}.each do |k|
76
+ normalized[k] = File.expand_path( opts[k] ) if opts.has_key?(k)
77
+ end
78
+ normalized['project_dir'] = File.expand_path( project_dir || Dir.getwd )
79
+
80
+ normalized['input_dir'] ||= File.join( normalized['project_dir'], Utilikilt::DEFAULT_INPUT_DIR_NAME )
81
+ normalized['output_dir'] ||= File.join( normalized['project_dir'], Utilikilt::DEFAULT_OUTPUT_DIR_NAME )
82
+
83
+ normalized
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,8 @@
1
+ module Utilikilt
2
+ module Loggable
3
+ def debug
4
+ puts yield if $DEBUG
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,13 @@
1
+ module Utilikilt
2
+ class NodeProxy
3
+ NODE_DIR = File.join( File.dirname(__FILE__), '..','..', 'node_modules', 'utilikilt' )
4
+
5
+ def initialize( serve_dir )
6
+ @serve_dir = File.expand_path(serve_dir)
7
+ end
8
+
9
+ def launch_server
10
+ system 'node_modules/.bin/coffee', 'lib/uk.coffee', @serve_dir, {:chdir => NODE_DIR}
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,76 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+
4
+ require 'utilikilt/loggable'
5
+
6
+ module Utilikilt
7
+ class Scanner
8
+ include Loggable
9
+
10
+ def initialize( opts )
11
+ @input_base = Pathname.new( opts['input_dir'] ).expand_path
12
+ @output_base = Pathname.new( opts['output_dir'] ).expand_path
13
+ @files_processed = 0
14
+ end
15
+
16
+ INPUT_TO_OUTPUT_EXT_MAP = {
17
+ 'md' => 'html',
18
+ 'markdown' => 'html',
19
+ 'haml' => 'html',
20
+ 'sass' => 'css',
21
+ 'scss' => 'css',
22
+ 'coffee' => 'js'
23
+ }
24
+
25
+ TILT_OPTIONS = {:cache => false}
26
+
27
+ def scan
28
+ @files_processed = 0
29
+ input_file_glob = '*.{'+INPUT_TO_OUTPUT_EXT_MAP.keys.join(',')+'}'
30
+ Pathname.glob(File.join( @input_base, "**", input_file_glob )).each do |input|
31
+ debug{"checking #{input}"}
32
+ output = output_for_input(input)
33
+ unless FileUtils.uptodate?( output, [input] )
34
+ filter( input, output )
35
+ end
36
+ end
37
+
38
+ log_files_processed
39
+ end
40
+
41
+ private
42
+
43
+ def log_files_processed
44
+ puts "#{@files_processed} files processed"
45
+ end
46
+
47
+ def filter input, output
48
+ require 'tilt'
49
+
50
+ output.dirname.mkpath
51
+
52
+ print "#{input} => #{output} ... "
53
+ template = Tilt.new( input.to_s, 1, TILT_OPTIONS )
54
+
55
+ output.dirname.mkpath
56
+ output.open('w') do |out_file|
57
+ out_file.write( template.render )
58
+ end
59
+ puts " done"
60
+
61
+ @files_processed += 1
62
+ end
63
+
64
+ def output_for_input input
65
+ relative = input.relative_path_from @input_base
66
+
67
+ # this is a bit fiddly because Pathname defines exts as including the leading dot while our map does not include it
68
+ output_ext = '.'+INPUT_TO_OUTPUT_EXT_MAP[input.extname[1..-1]]
69
+
70
+ raise ArgumentError, "unrecognized input file extension for #{input}" if output_ext.nil?
71
+
72
+ @output_base.join( relative.sub_ext(output_ext) )
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module Utilikilt
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,20 @@
1
+ require 'rb-fsevent'
2
+
3
+ module Utilikilt
4
+ class Watcher
5
+ def self.watch( dir_to_watch, &handler )
6
+ Watcher.new( dir_to_watch, handler ).start_watching
7
+ end
8
+
9
+ def initialize( dir_to_watch, on_change_handler )
10
+ @fsevent = FSEvent.new
11
+ @fsevent.watch dir_to_watch do |directories|
12
+ on_change_handler.call( directories )
13
+ end
14
+ end
15
+
16
+ def start_watching
17
+ @fsevent.run
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ require 'pathname'
2
+
3
+ module Utilikilt
4
+ class Workspace
5
+ def initialize base_dir, workspace_name
6
+ @workspace_name = workspace_name
7
+ @workspace_dir = Pathname.new(base_dir).join(@workspace_name).expand_path
8
+ end
9
+
10
+ def create_or_report_problems
11
+ if @workspace_dir.directory?
12
+ "There is already a directory called #{@workspace_name}. I don't want to mess with it. Please give me a new workspace name or delete that directory."
13
+ elsif @workspace_dir.exist?
14
+ "There is already a file called #{@workspace_name}, and I can't create a directory with the same name. Please give me a new workspace name or delete that file."
15
+ else
16
+ @workspace_dir.mkdir
17
+ @workspace_dir.join(Utilikilt::DEFAULT_INPUT_DIR_NAME).mkdir
18
+ @workspace_dir.join(Utilikilt::DEFAULT_OUTPUT_DIR_NAME).mkdir
19
+ @workspace_dir.join(Utilikilt::DEFAULT_INPUT_DIR_NAME, 'index.haml').open('w') do |f|
20
+ f.write CANNED_INDEX_HAML
21
+ end
22
+ nil
23
+ end
24
+ end
25
+
26
+
27
+ CANNED_INDEX_HAML = <<EOS
28
+ !!! 5
29
+ %html
30
+ %head
31
+ %title
32
+ Hello, world
33
+ %body
34
+ %p
35
+ Welcome to your new workspace. Edit #{Utilikilt::DEFAULT_INPUT_DIR_NAME}/index.haml to get started.
36
+ EOS
37
+ end
38
+ end
data/utilikilt.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "utilikilt/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "utilikilt"
7
+ s.version = Utilikilt::VERSION
8
+ s.authors = ["Pete Hodgson"]
9
+ s.email = ["github@thepete.net"]
10
+ s.homepage = "http://github.com/moredip/utilikilt"
11
+ s.summary = %q{Seriously simple prototyping}
12
+ s.description = %q{Prototype your UI development using tools like HAML and SASS with your changes showing up in the browser every time you save.}
13
+
14
+ s.rubyforge_project = "utilikilt"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.extensions << 'ext/check_for_node/extconf.rb'
22
+
23
+ s.add_runtime_dependency "thor"
24
+ s.add_runtime_dependency "rb-fsevent"
25
+ s.add_runtime_dependency "haml"
26
+ s.add_runtime_dependency "sass"
27
+ s.add_runtime_dependency "redcarpet"
28
+ s.add_runtime_dependency "tilt"
29
+ s.add_runtime_dependency "powder"
30
+ s.add_runtime_dependency "showoff-io"
31
+
32
+ # specify any dependencies here; for example:
33
+ # s.add_development_dependency "rspec"
34
+ # s.add_runtime_dependency "rest-client"
35
+ end
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/utilikilt/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in utilikilt.gemspec
4
+ gemspec
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: utilikilt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pete Hodgson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &70285499891220 !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: *70285499891220
25
+ - !ruby/object:Gem::Dependency
26
+ name: rb-fsevent
27
+ requirement: &70285499890800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70285499890800
36
+ - !ruby/object:Gem::Dependency
37
+ name: haml
38
+ requirement: &70285499890380 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70285499890380
47
+ - !ruby/object:Gem::Dependency
48
+ name: sass
49
+ requirement: &70285499889780 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70285499889780
58
+ - !ruby/object:Gem::Dependency
59
+ name: redcarpet
60
+ requirement: &70285499889160 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70285499889160
69
+ - !ruby/object:Gem::Dependency
70
+ name: tilt
71
+ requirement: &70285499888560 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70285499888560
80
+ - !ruby/object:Gem::Dependency
81
+ name: powder
82
+ requirement: &70285499887880 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: *70285499887880
91
+ - !ruby/object:Gem::Dependency
92
+ name: showoff-io
93
+ requirement: &70285499887200 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *70285499887200
102
+ description: Prototype your UI development using tools like HAML and SASS with your
103
+ changes showing up in the browser every time you save.
104
+ email:
105
+ - github@thepete.net
106
+ executables:
107
+ - uk
108
+ extensions:
109
+ - ext/check_for_node/extconf.rb
110
+ extra_rdoc_files: []
111
+ files:
112
+ - .gitignore
113
+ - Gemfile
114
+ - README.md
115
+ - Rakefile
116
+ - bin/uk
117
+ - ext/check_for_node/extconf.rb
118
+ - lib/utilikilt.rb
119
+ - lib/utilikilt/cli.rb
120
+ - lib/utilikilt/loggable.rb
121
+ - lib/utilikilt/node_proxy.rb
122
+ - lib/utilikilt/scanner.rb
123
+ - lib/utilikilt/version.rb
124
+ - lib/utilikilt/watcher.rb
125
+ - lib/utilikilt/workspace.rb
126
+ - utilikilt.gemspec
127
+ - utilikilt/.gitignore
128
+ - utilikilt/Gemfile
129
+ homepage: http://github.com/moredip/utilikilt
130
+ licenses: []
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project: utilikilt
149
+ rubygems_version: 1.8.10
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: Seriously simple prototyping
153
+ test_files: []