@@ -7,6 +7,7 @@ module Breadkit
77 module Render
88 class CLI
99 def run ( argv )
10+ original_args = argv . dup
1011 options = { scale : 2.0 , theme : "light" , orientation : "portrait" , color_by : "wire" , crop : "auto" , backend : "auto" , quality : 90 ,
1112 view : "breadboard" , label_density : "full" }
1213 parser = OptionParser . new do |opts |
@@ -33,6 +34,7 @@ def run(argv)
3334 opts . on ( "--backend NAME" , %w[ auto rsvg vips magick ] ) { |value | options [ :backend ] = value }
3435 opts . on ( "--background COLOR" ) { |value | options [ :background ] = value }
3536 opts . on ( "--static" ) { options [ :static ] = true }
37+ opts . on ( "--watch" ) { options [ :watch ] = true }
3638 opts . on ( "--quality N" , Integer ) { |value | options [ :quality ] = value }
3739 opts . on ( "--print-template" ) { options [ :print_template ] = true }
3840 opts . on ( "--render-timeout SECONDS" , Float ) { |value | options [ :render_timeout ] = value }
@@ -55,6 +57,11 @@ def run(argv)
5557 end
5658 raise ArgumentError , "--background is only supported for JPEG" if options [ :background ] && format != "jpeg"
5759 raise ArgumentError , "cannot write binary image data to a terminal; use -o PATH" if !%w[ svg html ] . include? ( format ) && !options [ :output ] && $stdout. tty?
60+ if options [ :watch ]
61+ raise ArgumentError , "--watch requires -o PATH" unless options [ :output ]
62+ original_args . delete_at ( original_args . index ( "--watch" ) )
63+ return watch ( input , second_input , options [ :annotations ] , options [ :output ] , original_args )
64+ end
5865 return render_diff ( input , second_input , options , format ) if options [ :diff ]
5966 circuit = Breadkit . load ( input )
6067 circuit . diagnostics . each do |item |
@@ -103,6 +110,35 @@ def run(argv)
103110
104111 private
105112
113+ def watch ( input , second_input , annotations , output , args )
114+ root = File . dirname ( File . expand_path ( input ) )
115+ paths = [ input , second_input , annotations ] . compact . map { |path | File . expand_path ( path ) }
116+ snapshot = watch_snapshot ( root , paths , output )
117+ warn "bkrender: watching #{ root } ; press Ctrl-C to stop"
118+ loop do
119+ warn "bkrender: rendered #{ output } " if run ( args . dup ) . zero?
120+ loop do
121+ sleep 0.5
122+ updated = watch_snapshot ( root , paths , output )
123+ next if updated == snapshot
124+
125+ snapshot = updated
126+ break
127+ end
128+ end
129+ end
130+
131+ def watch_snapshot ( root , paths , output )
132+ # ponytail: watch nearby circuit and part files; add dependency tracking if broad projects make scanning costly.
133+ files = paths + Dir . glob ( File . join ( root , "**" , "*.{bk.rb,yml,yaml,toml,json}" ) )
134+ files . map { |path | File . expand_path ( path ) } . uniq . sort . reject { |path | path == File . expand_path ( output ) } . to_h do |path |
135+ stat = File . stat ( path )
136+ [ path , [ stat . mtime . to_r , stat . size ] ]
137+ rescue Errno ::ENOENT
138+ [ path , nil ]
139+ end
140+ end
141+
106142 def validate_step_options ( options , format )
107143 raise ArgumentError , "--step must be a positive integer" unless options [ :step ] . positive?
108144 raise ArgumentError , "--step is unavailable in #{ options [ :view ] } view" unless options [ :view ] == "breadboard"
0 commit comments