quik 0.1.1 → 1.0.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.
data/bin/qk CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'quik'
4
-
5
- Quik.main
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'quik'
4
+
5
+ Quik.main
data/bin/quik CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'quik'
4
-
5
- Quik.main
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'quik'
4
+
5
+ Quik.main
@@ -1,43 +1,55 @@
1
- # encoding: utf-8
2
-
3
- # stdlibs
4
- require 'pp'
5
- require 'fileutils'
6
- require 'yaml'
7
- require 'uri'
8
-
9
- # 3rd party libs/gems
10
- require 'fetcher'
11
- require 'textutils' ## used for File.read_utf8
12
-
13
- ## more 3rd party gems
14
- require 'zip' # use $ gem install rubyzip
15
- require 'gli'
16
-
17
-
18
- # our own code
19
- require 'quik/version' # let version always go first
20
- require 'quik/package'
21
- require 'quik/merger'
22
- require 'quik/config'
23
- require 'quik/wizard'
24
- require 'quik/builder'
25
-
26
-
27
-
28
- require 'quik/cli/opts'
29
- require 'quik/cli/main'
30
-
31
-
32
- module Quik
33
- def self.main
34
- exit Tool.new.run( ARGV )
35
- end
36
- end # module Quik
37
-
38
-
39
- ## say hello
40
- puts Quik.banner if defined?($RUBYLIBS_DEBUG) && $RUBYLIBS_DEBUG
41
-
42
-
43
- Quik.main if __FILE__ == $0
1
+ # encoding: utf-8
2
+
3
+ # stdlibs
4
+ require 'pp'
5
+ require 'fileutils'
6
+ require 'yaml'
7
+ require 'json'
8
+ require 'uri'
9
+ require 'time'
10
+ require 'date'
11
+
12
+
13
+ # 3rd party libs/gems
14
+ require 'fetcher'
15
+
16
+ ## more 3rd party gems
17
+ require 'zip' # use $ gem install rubyzip
18
+ require 'gli'
19
+
20
+
21
+ # our own code
22
+ require 'quik/version' # let version always go first
23
+
24
+
25
+ module Quik
26
+ ### builtin default urls
27
+ QUIK_SCRIPTS_URL = "https://github.com/quikstart/scripts/raw/master/scripts.yml"
28
+ end
29
+
30
+
31
+
32
+ require 'quik/catalog'
33
+ require 'quik/package'
34
+ require 'quik/merger'
35
+ require 'quik/config'
36
+ require 'quik/wizard'
37
+ require 'quik/builder'
38
+ require 'quik/colors'
39
+
40
+
41
+ require 'quik/cli/opts'
42
+ require 'quik/cli/main'
43
+
44
+
45
+ module Quik
46
+ def self.main( args=ARGV )
47
+ exit Tool.new.run( args )
48
+ end
49
+ end # module Quik
50
+
51
+
52
+
53
+
54
+ ## say hello
55
+ puts Quik.banner if defined?($RUBYLIBS_DEBUG) && $RUBYLIBS_DEBUG
@@ -1,94 +1,96 @@
1
- #encoding: utf-8
2
-
3
- module Quik
4
-
5
- class Builder
6
-
7
- def self.load_file( path, opts={} )
8
- code = File.read_utf8( path )
9
- self.load( code, opts )
10
- end
11
-
12
- def self.load( code, opts={} )
13
- builder = Builder.new( opts )
14
- builder.instance_eval( code )
15
- builder
16
- end
17
-
18
-
19
- include Wizard ## mixin helpers for say, ask, yes?, no?, select, etc.
20
-
21
- def initialize( opts={} )
22
- puts "starting new Quik script #{opts.inspect}; lets go"
23
-
24
- @test = opts[:dry_run] || opts[:test] || false
25
- @output_dir = opts[:o] || '.'
26
- @pak = nil ## for now reference last template pack (in future support many - why?? why not??)
27
- end
28
-
29
- ## "global" builder options
30
- def test?() @test; end ## dry_run option (defaults to false)
31
- def output_dir() @output_dir; end ## ouptput (root) dir (defaults to . e.g. working folder)
32
-
33
-
34
-
35
- def use( name, opts={} ) ## short alias for install_template
36
- install_template( name, opts )
37
- end
38
-
39
- def install_template( name, opts= {} )
40
- puts " handle install_template #{name}, #{opts.inspect}"
41
-
42
- ## note for now assume name is key
43
- ## e.g. always downcase (e.g. Gem => gem)
44
- key = name.downcase
45
-
46
- if test?
47
- # do nothing; dry run
48
- else
49
- @pak = Package.new( key )
50
- @pak.download
51
- ## pak.unzip( "#{@output_dir}/#{key}" )
52
- end
53
- end
54
-
55
-
56
- def config( opts={} )
57
- puts " handle config block"
58
- c = OpenConfig.new
59
- yield( c )
60
- ## pp c
61
- h = c.to_h
62
-
63
- pp h
64
-
65
- ##
66
- # check for name
67
- ## required for output
68
- ## if no name
69
- ## use ./ working folder for output!!!
70
-
71
- name = h['name']
72
-
73
- if name.nil? || name.empty?
74
- fail 'sorry; for now name is required for output folder'
75
- end
76
-
77
- if test?
78
- ## do nothing; dry run
79
- else
80
- if @pak
81
- unzip_dir = "./#{name}"
82
- ## step 1: unzip templates
83
- @pak.unzip( unzip_dir )
84
- ## step 2: merge templates (using hash/config settings)
85
- m = Quik::Merger.new
86
- m.merge( unzip_dir, h )
87
- end
88
- end
89
- end # method config
90
-
91
-
92
- end # class Builder
93
-
94
- end # module Quik
1
+ #encoding: utf-8
2
+
3
+ module Quik
4
+
5
+ class Builder
6
+
7
+ def self.load_file( path, opts={} )
8
+ code = File.open( path, 'r:utf-8' ) { |f| f.read }
9
+ self.load( code, opts )
10
+ end
11
+
12
+ def self.load( code, opts={} )
13
+ builder = Builder.new( opts )
14
+ builder.instance_eval( code )
15
+ builder
16
+ end
17
+
18
+
19
+ include Wizard ## mixin helpers for say, ask, yes?, no?, select, etc.
20
+
21
+ def initialize( opts={} )
22
+ puts "==> starting new Quik script with options #{opts.inspect}; lets go"
23
+
24
+ @test = opts[:dry_run] || opts[:test] || false
25
+ @output_dir = opts[:o] || '.'
26
+ @pak = nil ## for now reference last template pack (in future support many - why?? why not??)
27
+ end
28
+
29
+ ## "global" builder options
30
+ def test?() @test; end ## dry_run option (defaults to false)
31
+ def output_dir() @output_dir; end ## ouptput (root) dir (defaults to . e.g. working folder)
32
+
33
+
34
+
35
+ def use( name, opts={} ) ## short alias for install_template
36
+ install_template( name, opts )
37
+ end
38
+
39
+ def install_template( name, opts= {} )
40
+ puts "==> handle install_template >#{name}< with options #{opts.inspect}"
41
+
42
+ ## note for now assume name is key
43
+ ## e.g. always downcase (e.g. Gem => gem)
44
+ key = name.downcase
45
+
46
+ if test?
47
+ # do nothing; dry run
48
+ else
49
+ @pak = Package.new( key )
50
+
51
+ puts "GET #{@pak.remote_zip_url}".bold.green ## output network access in green bold
52
+ @pak.download
53
+ ## pak.unzip( "#{@output_dir}/#{key}" )
54
+ end
55
+ end
56
+
57
+
58
+ def config( opts={} )
59
+ puts "==> handle config block"
60
+ c = OpenConfig.new
61
+ yield( c )
62
+ ## pp c
63
+ h = c.to_h
64
+
65
+ pp h
66
+
67
+ ##
68
+ # check for name
69
+ ## required for output
70
+ ## if no name
71
+ ## use ./ working folder for output!!!
72
+
73
+ name = h['name']
74
+
75
+ if name.nil? || name.empty?
76
+ fail 'sorry; for now name is required for output folder'
77
+ end
78
+
79
+ if test?
80
+ ## do nothing; dry run
81
+ else
82
+ if @pak
83
+ unzip_dir = "./#{name}"
84
+ ## step 1: unzip templates
85
+ @pak.unzip( unzip_dir )
86
+ ## step 2: merge templates (using hash/config settings)
87
+ m = Quik::Merger.new
88
+ m.merge( unzip_dir, h )
89
+ end
90
+ end
91
+ end # method config
92
+
93
+
94
+ end # class Builder
95
+
96
+ end # module Quik
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+
3
+ module Quik
4
+
5
+ class Catalog
6
+
7
+ def self.from_url( src )
8
+ worker = Fetcher::Worker.new
9
+ text = worker.read_utf8!( src )
10
+ new( text )
11
+ end
12
+
13
+ def self.from_file( path )
14
+ ## read in themes catalog
15
+ text = File.open( path, 'r:utf-8' ) { |f| f.read }
16
+ new( text )
17
+ end
18
+
19
+ # def self.from_string( text )
20
+ # self.new( text )
21
+ # end
22
+
23
+
24
+ def initialize( text )
25
+ recs = YAML.load( text )
26
+ ## note: convert array to hash (lookup by name)
27
+ ## todo: check for missing name property? - why? why not?
28
+ @scripts = recs.reduce( {} ) { |h,rec| h[rec['name']] = rec; h }
29
+ end
30
+
31
+
32
+ def find( name )
33
+ @scripts[ name ]
34
+ end
35
+
36
+ def list( filter=nil )
37
+ ## pp filter
38
+
39
+ @scripts.each_with_index do |(_,rec),i|
40
+ name = rec['name']
41
+ summary = rec['summary']
42
+ script = rec['script']
43
+
44
+ if script && script.index( '//github.com/')
45
+ ## "beautify" / shorten github links - remove raw/master/
46
+ script = script.gsub('raw/master/', '' )
47
+ end
48
+
49
+ ## pp h
50
+
51
+ line = ''
52
+ line << " %3d" % (i+1)
53
+ line << "..%-10s" % name
54
+ line << " .:. #{summary}"
55
+ line << " @ (#{script})"
56
+
57
+ if filter
58
+ ## note: ignore case (upper/lower/downcase) for now
59
+ ## filter on name/title and
60
+ ## tags for now
61
+ if name.downcase.index(filter.downcase) != nil || ## note: 0 is match found on index 0; only nil is not found
62
+ summary.downcase.index(filter.downcase) != nil
63
+ puts line
64
+ end
65
+ else
66
+ puts line
67
+ end
68
+ end
69
+ end # method filter
70
+
71
+ end # class Catalog
72
+
73
+ end # module Quik
@@ -1,150 +1,213 @@
1
- # encoding: utf-8
2
-
3
- ### NOTE: wrap gli config into a class
4
- ## see github.com/davetron5000/gli/issues/153
5
-
6
- module Quik
7
-
8
- class Tool
9
- def initialize
10
- LogUtils::Logger.root.level = :info # set logging level to info
11
- end
12
-
13
- def run( args )
14
- puts Quik.banner
15
- Toolii.run( args )
16
- end
17
- end
18
-
19
- ## NOTE: gli added function are class methods (thus, wrap class Toolii in Tool for now)
20
-
21
- class Toolii
22
- extend GLI::App
23
-
24
- def self.logger=(value) @@logger=value; end
25
- def self.logger() @@logger; end
26
-
27
- ## todo: find a better name e.g. change to settings? config? safe_opts? why? why not?
28
- def self.opts=(value) @@opts = value; end
29
- def self.opts() @@opts; end
30
-
31
-
32
- logger = LogUtils::Logger.root
33
- opts = Opts.new
34
-
35
-
36
- program_desc 'ruby quick starter template script wizard .:. the missing code generator'
37
- version VERSION
38
-
39
-
40
- ## desc 'Use only local (offline) cached data; no (online) remote network access'
41
- ## switch [:l, :local], negatable: false
42
-
43
- desc '(Debug) Show debug messages'
44
- switch [:verbose], negatable: false ## todo: use -w for short form? check ruby interpreter if in use too?
45
-
46
- desc '(Debug) Dry run; run script in simulation for testing'
47
- switch [:test, :dry_run], negatable: false
48
-
49
-
50
- def self.fetch_script( name )
51
-
52
- ## first try local version in working folder
53
-
54
- text = ''
55
- local_script = "./#{name}.rb"
56
- if File.exist?( local_script )
57
- text = File.read_utf8( local_script )
58
- else ## fetch remote script
59
- url = "https://github.com/rubyref/scripts/raw/master/#{name}.rb"
60
- ## assume utf8 text encoding for now
61
- worker = Fetcher::Worker.new
62
- text = worker.read_utf8!( url )
63
- end
64
-
65
- text
66
- end
67
-
68
-
69
- desc "Run ruby quick starter script"
70
- arg_name 'NAME' # required theme name
71
- command [:new,:n] do |c|
72
-
73
- c.action do |g,o,args|
74
-
75
- name = args[0] || 'gem'
76
-
77
- script = fetch_script( name )
78
- if opts.test?
79
- puts "dry (test) run:"
80
- Builder.load( script, test: true )
81
- else
82
- Builder.load( script )
83
- end
84
-
85
- puts 'Done.'
86
- end # action
87
- end # command setup
88
-
89
-
90
-
91
- desc '(Debug) Test command suite'
92
- command :test do |c|
93
- c.action do |g,o,args|
94
-
95
- puts "hello from test command"
96
- puts "args (#{args.class.name}):"
97
- pp args
98
- puts "o (#{o.class.name}):"
99
- pp o
100
- puts "g (#{g.class.name}):"
101
- pp g
102
-
103
- LogUtils::Logger.root.debug 'test debug msg'
104
- LogUtils::Logger.root.info 'test info msg'
105
- LogUtils::Logger.root.warn 'test warn msg'
106
-
107
- puts 'Done.'
108
- end
109
- end
110
-
111
-
112
-
113
- pre do |g,c,o,args|
114
- opts.merge_gli_options!( g )
115
- opts.merge_gli_options!( o )
116
-
117
- puts Quik.banner
118
-
119
- if opts.verbose?
120
- LogUtils::Logger.root.level = :debug
121
- end
122
-
123
- logger.debug "Executing #{c.name}"
124
- true
125
- end
126
-
127
- post do |global,c,o,args|
128
- logger.debug "Executed #{c.name}"
129
- true
130
- end
131
-
132
-
133
- on_error do |e|
134
- puts
135
- puts "*** error: #{e.message}"
136
-
137
- if opts.verbose?
138
- puts e.backtrace
139
- end
140
-
141
- false # skip default error handling
142
- end
143
-
144
-
145
- ### exit run(ARGV) ## note: use Toolii.run( ARGV ) outside of class
146
-
147
- end # class Toolii
148
-
149
- end # module Quik
150
-
1
+ ################
2
+ ## NOTE: wrap gli config into a class
3
+ ## see github.com/davetron5000/gli/issues/153
4
+
5
+ module Quik
6
+
7
+ class Tool
8
+ def initialize
9
+ LogUtils::Logger.root.level = :info # set logging level to info
10
+ end
11
+
12
+ def run( args )
13
+ puts Quik.banner
14
+ Toolii.run( args )
15
+ end
16
+ end
17
+
18
+
19
+ ## NOTE: gli added function are class methods (thus, wrap class Toolii in Tool for now)
20
+
21
+ class Toolii
22
+ extend GLI::App
23
+
24
+ def self.logger=(value) @@logger=value; end
25
+ def self.logger() @@logger; end
26
+
27
+ ## todo: find a better name e.g. change to settings? config? safe_opts? why? why not?
28
+ def self.opts=(value) @@opts = value; end
29
+ def self.opts() @@opts; end
30
+
31
+
32
+ logger = LogUtils::Logger.root
33
+ opts = Opts.new
34
+
35
+
36
+ program_desc 'ruby quick starter template script wizard .:. the missing code generator'
37
+ version VERSION
38
+
39
+
40
+ ## desc 'Use only local (offline) cached data; no (online) remote network access'
41
+ ## switch [:l, :local], negatable: false
42
+
43
+ desc '(Debug) Show debug messages'
44
+ switch [:verbose], negatable: false ## todo: use -w for short form? check ruby interpreter if in use too?
45
+
46
+ desc '(Debug) Dry run; run script in simulation for testing'
47
+ switch [:test, :dry_run], negatable: false
48
+
49
+
50
+
51
+ def self.fetch_catalog
52
+ ## scripts_dir = "#{Quik.root}/test/data"
53
+ ## catalog = Catalog.new( "#{scripts_dir}/scripts.yml" )
54
+
55
+ url = QUIK_SCRIPTS_URL
56
+
57
+ puts "GET #{url}".bold.green ## output network access in green bold
58
+
59
+ catalog = Catalog.from_url( url )
60
+ catalog
61
+ end
62
+
63
+
64
+ def self.fetch_script( name_or_path )
65
+
66
+ ## first try local version in working folder
67
+
68
+ text = ''
69
+
70
+ extname = File.extname( name_or_path )
71
+
72
+
73
+ ## try local first
74
+ ## todo/fix: check in ~/.quik/ dir too?
75
+
76
+ path = if extname == '.rb' && File.exist?( name_or_path )
77
+ name_or_path
78
+ elsif extname == '' && File.exist?( "#{name_or_path}.rb" )
79
+ "#{name_or_path}.rb"
80
+ elsif extname == '' && File.exist?( "~/.quik/#{name_or_path}.rb" )
81
+ "~/.quik/#{name_or_path}.rb" ## todo/check - if (~) shortcut works in windows -too?
82
+ else
83
+ nil
84
+ end
85
+
86
+ if path
87
+ text = File.open( path, 'r:utf-8' ) { |f| f.read }
88
+ else ## try fetch remote script
89
+
90
+ url = nil
91
+
92
+ if name_or_path.index( '/' ).nil? ## assume short-cut name if no (/) in name
93
+ ## do a lookup from catalog!!!
94
+ catalog = fetch_catalog
95
+ rec = catalog.find( name_or_path )
96
+ url = rec['script'] if rec
97
+
98
+ if url.nil?
99
+ puts "!! ERROR - sorry no wizard script found / available for name >#{name_or_path}<"
100
+ exit 1
101
+ end
102
+ else
103
+ ## assume custom github url shortcut
104
+ url = "https://github.com/#{name_or_path}/raw/master/quik.rb"
105
+ end
106
+
107
+ ## assume utf8 text encoding for now
108
+ puts "GET #{url}".bold.green ## output network access in green bold
109
+
110
+ worker = Fetcher::Worker.new
111
+ text = worker.read_utf8!( url )
112
+ end
113
+
114
+ text
115
+ end
116
+
117
+
118
+
119
+ desc "List ruby quick starter scripts"
120
+ arg_name 'QUERY' # optional search query/filter
121
+ command [:list,:ls,:l] do |c|
122
+
123
+ c.action do |g,o,args|
124
+ ## read in scripts diretory
125
+ catalog = fetch_catalog
126
+ catalog.list( args[0] ) ## note: pass in filter e.g. args[0]; may be nil (no filter)
127
+ puts 'Done.'
128
+ end # action
129
+ end # command list
130
+
131
+
132
+ desc "Run ruby quick starter script"
133
+ arg_name 'NAME' # required theme name
134
+ command [:new,:n] do |c|
135
+
136
+ c.action do |g,o,args|
137
+
138
+ name = args[0] || 'gem'
139
+
140
+ script = fetch_script( name )
141
+ if opts.test?
142
+ puts "dry (test) run:"
143
+ Builder.load( script, test: true )
144
+ else
145
+ Builder.load( script )
146
+ end
147
+
148
+ puts 'Done.'
149
+ end # action
150
+ end # command setup
151
+
152
+
153
+
154
+ desc '(Debug) Test command suite'
155
+ command :test do |c|
156
+ c.action do |g,o,args|
157
+
158
+ puts "hello from test command"
159
+ puts "args (#{args.class.name}):"
160
+ pp args
161
+ puts "o (#{o.class.name}):"
162
+ pp o
163
+ puts "g (#{g.class.name}):"
164
+ pp g
165
+
166
+ LogUtils::Logger.root.debug 'test debug msg'
167
+ LogUtils::Logger.root.info 'test info msg'
168
+ LogUtils::Logger.root.warn 'test warn msg'
169
+
170
+ puts 'Done.'
171
+ end
172
+ end
173
+
174
+
175
+
176
+ pre do |g,c,o,args|
177
+ opts.merge_gli_options!( g )
178
+ opts.merge_gli_options!( o )
179
+
180
+ puts Quik.banner
181
+
182
+ if opts.verbose?
183
+ LogUtils::Logger.root.level = :debug
184
+ end
185
+
186
+ logger.debug "Executing #{c.name}"
187
+ true
188
+ end
189
+
190
+ post do |global,c,o,args|
191
+ logger.debug "Executed #{c.name}"
192
+ true
193
+ end
194
+
195
+
196
+ on_error do |e|
197
+ puts
198
+ puts "*** error: #{e.message}"
199
+
200
+ if opts.verbose?
201
+ puts e.backtrace
202
+ end
203
+
204
+ false # skip default error handling
205
+ end
206
+
207
+
208
+ ### exit run(ARGV) ## note: use Toolii.run( ARGV ) outside of class
209
+
210
+ end # class Toolii
211
+
212
+ end # module Quik
213
+