module Filmrolls::Cli

Public Class Methods

run() click to toggle source
    # File lib/filmrolls/cli.rb
  8 def self.run
  9   program :version,     Filmrolls::VERSION
 10   program :description, 'Tag TIFF files with EXIF data extracted from XML.'
 11   program :help_formatter, :compact
 12 
 13   global_option '-r', '--rolls FILE', 'Film Rolls XML file (default: stdin)' do |r|
 14     $rolls_file = r
 15   end
 16   global_option '-m', '--meta FILE', 'Author metadata YAML file' do |r|
 17     $yaml_file = r
 18   end
 19 
 20   command 'list-rolls' do |c|
 21     c.syntax      = 'filmrolls list-rolls [--rolls FILE]'
 22     c.summary     = 'List film rolls'
 23     c.description = 'List ID and additional data for all film rolls ' \
 24                     'in input.'
 25 
 26     c.action do |_args, _options|
 27       rolls = get_rolls($rolls_file).map do |roll|
 28         roll.merge(
 29           frames: roll[:frames].length,
 30           unload: roll[:unload].to_date,
 31           load: roll[:load].to_date
 32         )
 33       end
 34 
 35       unless rolls.empty?
 36         require 'terminal-table'
 37         head = rolls.first.keys.map(&:capitalize)
 38         rows = rolls.map(&:values)
 39         say Terminal::Table.new(headings: head, rows: rows)
 40       end
 41     end
 42   end
 43 
 44   command 'list-frames' do |c|
 45     c.syntax      = 'filmrolls list-frames [--rolls FILE] --id ID'
 46     c.summary     = 'List frames'
 47     c.description = 'List frames from film roll with ID in input.'
 48     c.option '-i', '--id ID',   'Use data from roll with id ID'
 49 
 50     c.action do |_args, options|
 51       abort "A film roll ID must be supplied" if options.id.nil?
 52 
 53       roll = get_rolls($rolls_file).detect do |r|
 54         r[:id] == options.id
 55       end
 56 
 57       abort "Could not find film roll with ID #{options.id}" if roll.nil?
 58 
 59       unless roll.nil?
 60         require 'terminal-table'
 61         head = roll[:frames].first.keys.map(&:capitalize)
 62         rows = roll[:frames].map(&:values)
 63         say Terminal::Table.new(headings: head, rows: rows)
 64       end
 65     end
 66   end
 67 
 68   command :tag do |c|
 69     c.syntax      = 'filmrolls tag [--dry-run] [--meta FILE] [--rolls FILE] --id ID IMAGE...'
 70     c.summary     = 'Write EXIF tags'
 71     c.description = 'Write EXIF tags to a set of images using data from ' \
 72                     'film roll with ID in input.'
 73     c.option '-i', '--id ID',   'Use data from roll with id ID'
 74     c.option '-n', '--dry-run', "Don't actually modify any files"
 75 
 76     c.action do |args, options|
 77       abort "A film roll ID must be supplied" if options.id.nil?
 78 
 79       roll = get_rolls($rolls_file).detect do |r|
 80         r[:id] == options.id
 81       end
 82 
 83       abort "Could not find film roll with ID #{options.id}" if roll.nil?
 84 
 85       unless args.length == roll[:frames].length
 86         abort "Expected #{roll[:frames].length} images, got #{args.length}"
 87       end
 88 
 89       meta = get_metadata($yaml_file)
 90       meta.each { |k, v| log k.to_s.gsub('_',' ').capitalize, v }
 91 
 92       roll[:frames].zip(args).each do |frame, file|
 93         log 'Path', file
 94         negative = Filmrolls::Negative.new(file)
 95         log 'Date', frame[:date]
 96         negative.date = frame[:date]
 97         log 'Camera', roll[:camera]
 98         negative.camera = roll[:camera]
 99         log 'Lens', frame[:lens]
100         negative.lens = frame[:lens]
101         log 'Film', roll[:film]
102         negative.film = roll[:film]
103         log 'ISO', roll[:speed]
104         negative.speed = roll[:speed]
105         if frame[:shutter_speed] != 0 and frame[:aperture] != 0
106           log 'Shutter speed', "#{frame[:shutter_speed]}s"
107           negative.shutter_speed = frame[:shutter_speed]
108           log 'Aperture', "ƒ/#{frame[:aperture]}"
109           negative.aperture = frame[:aperture]
110         end
111         if frame[:compensation] != 0
112           log 'Compensation', frame[:compensation]
113           negative.compensation = frame[:compensation]
114         end
115         if frame[:position] != Geokit::LatLng.new(0.0, 0.0)
116           log 'Position', frame[:position]
117           negative.position = frame[:position]
118         end
119         negative.merge(meta)
120         negative.save! unless options.dry_run
121       end
122     end
123   end
124 
125   command 'apply-metadata' do |c|
126     c.syntax      = 'filmrolls apply-metadata [--dry-run] --meta FILE IMAGE...'
127     c.summary     = 'Write author metadata'
128     c.description = 'Write author metadata to a set of images using YAML data from FILE.'
129     c.option '-n', '--dry-run', "Don't actually modify any files"
130 
131     c.action do |args, options|
132       abort "A YAML file must be supplied" if $yaml_file.nil?
133 
134       meta = get_metadata($yaml_file)
135       meta.each { |k, v| log k.to_s.gsub('_',' ').capitalize, v }
136 
137       args.each do |file|
138         log 'Path', file
139         negative = Filmrolls::Negative.new(file)
140         negative.merge(meta)
141         negative.save! unless options.dry_run
142       end
143     end
144   end
145 end

Private Class Methods

get_metadata(file) click to toggle source
    # File lib/filmrolls/cli.rb
158 def get_metadata(file)
159   begin
160     file.nil? ? Hash.new : Filmrolls::Metadata.load(File.read(file))
161   rescue SystemCallError => err
162     abort "Could not read input YAML: #{err.message}"
163   end
164 end
get_rolls(file) click to toggle source
    # File lib/filmrolls/cli.rb
150 def get_rolls(file)
151   begin
152     Filmrolls::XMLFormat.load(file.nil? ? $stdin.read : File.read(file))[:rolls]
153   rescue SystemCallError => err
154     abort "Could not read input XML: #{err.message}"
155   end
156 end