Class: OggAlbumTagger::CLI
- Inherits:
-
Object
- Object
- OggAlbumTagger::CLI
- Defined in:
- lib/ogg_album_tagger/cli.rb
Constant Summary collapse
- QUOTE_CHARACTERS =
"\"'"
- SIMPLE_SELECTOR =
/^[+-]?[1-9]\d*$/
- RANGE_SELECTOR =
/^[+-]?[1-9]\d*-[1-9]\d*$/
Instance Method Summary collapse
- #add_command(args) ⇒ Object
- #auto_command(args) ⇒ Object
- #autocomplete(buffer, point, input) ⇒ Object
- #configure_readline ⇒ Object
- #execute_command(command_line) ⇒ Object
- #handle_picture_args(args) ⇒ Object
-
#initialize(library) ⇒ CLI
constructor
A new instance of CLI.
- #ls_command ⇒ Object
- #move_command(args) ⇒ Object
- #parse_command(command_line) ⇒ Object
- #print_album_summary(summary) ⇒ Object
- #rm_command(args) ⇒ Object
- #select_command(args) ⇒ Object
- #selector?(arg) ⇒ Boolean
- #set_command(args) ⇒ Object
- #show_command(args) ⇒ Object
- #suggestions(context, input) ⇒ Object
Constructor Details
#initialize(library) ⇒ CLI
Returns a new instance of CLI.
13 14 15 |
# File 'lib/ogg_album_tagger/cli.rb', line 13 def initialize(library) @library = library end |
Instance Method Details
#add_command(args) ⇒ Object
183 184 185 186 187 188 189 190 191 |
# File 'lib/ogg_album_tagger/cli.rb', line 183 def add_command(args) if args.length < 2 m = "Usage: add <tag> [<value>+]" raise ArgumentError, m end handle_picture_args(args) @library.add_tag(*args) end |
#auto_command(args) ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/ogg_album_tagger/cli.rb', line 202 def auto_command(args) usage = "Usage: auto tracknumber|rename" if args.length < 1 raise ArgumentError, usage end case args[0] when 'tracknumber' @library.auto_tracknumber() when 'rename' @library.auto_rename ls_command() else raise ArgumentError, usage end end |
#autocomplete(buffer, point, input) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/ogg_album_tagger/cli.rb', line 29 def autocomplete(buffer, point, input) # Extract the context: everything before the word being completed. context = buffer.slice(0, point - input.length) begin # Let's try to split the context into its various arguments. context_args = Shellwords.shellwords(context) # If the last argument is quoted and the quote is the last character of the context, # no autocompletion, or we may end up with things like "something"somethingelse. return [] if context.size > 0 and QUOTE_CHARACTERS.include?(context[-1]) rescue ::ArgumentError => ex # The context couldn't be parsed because it ends with an opening quote. # Let's remove it to allow the context to be parsed. context.slice!(-1) if context.size > 0 and QUOTE_CHARACTERS.include?(context[-1]) begin context_args = Shellwords.shellwords(context) rescue ::ArgumentError => ex return [] end end # Remove leading selectors first_not_selector = context_args.find_index { |e| !selector?(e) } context_args.slice!(0, first_not_selector) unless first_not_selector.nil? || first_not_selector == 0 # Keep only suggestions starting with the input. sugg = suggestions(context_args, input).grep(/^#{Regexp.escape(input)}/i).map { |v| # Quote them if they contain spaces, otherwise a multiple word value # will appear unquoted on the command line. v.include?(' ') ? "\"#{v}\"" : v } sugg end |
#configure_readline ⇒ Object
17 18 19 20 |
# File 'lib/ogg_album_tagger/cli.rb', line 17 def configure_readline Readline.completer_quote_characters = QUOTE_CHARACTERS Readline.completion_append_character = " " end |
#execute_command(command_line) ⇒ Object
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/ogg_album_tagger/cli.rb', line 238 def execute_command(command_line) selectors, command, args = parse_command(command_line) return if command.nil? @library.with_selection(selectors) { case command when 'ls' then ls_command() when 'select' select_command(args) ls_command() when 'move' move_command(args) ls_command() when 'show' then show_command(args) when 'set' set_command(args) show_command([args[0]]) when 'add' add_command(args) show_command([args[0]]) when 'rm' rm_command(args) show_command([args[0]]) when 'auto' auto_command(args) when 'check' @library.check puts "OK" when 'write' @library.write when 'help' # TODO else puts "Unknown command \"#{command}\"" end } end |
#handle_picture_args(args) ⇒ Object
148 149 150 151 152 153 154 155 156 |
# File 'lib/ogg_album_tagger/cli.rb', line 148 def handle_picture_args args if %w{METADATA_BLOCK_PICTURE PICTURE}.include? args[0].upcase file = args[1] desc = args.length == 3 ? args[2] : '' args.clear args << 'METADATA_BLOCK_PICTURE' args << OggAlbumTagger::Picture::(file, desc) end end |
#ls_command ⇒ Object
142 143 144 145 146 |
# File 'lib/ogg_album_tagger/cli.rb', line 142 def ls_command @library.ls().each_with_index { |f, i| puts sprintf("%s %4d: %s", (f[:selected] ? '*' : ' '), i + 1, f[:file]) } end |
#move_command(args) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/ogg_album_tagger/cli.rb', line 158 def move_command(args) raise ArgumentError if args.length != 2 # Will raise ::ArgumentError if not integers from = Integer(args[0]) - 1 to = Integer(args[1]) - 1 @library.move(from, to) rescue ::StandardError m = "Usage: move <from_index> <to_index>\n\n" + "<from_index> must be in the [1; #{@library.size}] range.\n" + "<to_index> must be in the [1; #{@library.size + 1}] range." raise ArgumentError, m end |
#parse_command(command_line) ⇒ Object
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/ogg_album_tagger/cli.rb', line 219 def parse_command(command_line) begin arguments = Shellwords.shellwords(command_line) rescue ::StandardError raise OggAlbumTagger::ArgumentError, "Invalid command." end selectors = [] first_not_selector = arguments.find_index { |e| !selector?(e) } unless first_not_selector.nil? || first_not_selector == 0 selectors = arguments.slice!(0, first_not_selector) end command, *args = arguments return selectors, command, args end |
#print_album_summary(summary) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/ogg_album_tagger/cli.rb', line 106 def print_album_summary(summary) OggAlbumTagger::OggFile.(summary.keys) do |tag| puts tag if (summary[tag].size == @library.selected_files.size) && (summary[tag].values.uniq.length == 1) # If all tracks have only one common value puts "\t" + OggAlbumTagger::TagContainer::pp_tag(summary[tag].first[1]) else summary[tag].keys.sort.each do |i| values = summary[tag][i] puts sprintf("\t%4d: %s", i+1, OggAlbumTagger::TagContainer::pp_tag(values)) end end end end |
#rm_command(args) ⇒ Object
193 194 195 196 197 198 199 200 |
# File 'lib/ogg_album_tagger/cli.rb', line 193 def rm_command(args) if args.length < 1 m = "Usage: rm <tag> [<value>+]" raise ArgumentError, m end @library.rm_tag(*args) end |
#select_command(args) ⇒ Object
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/ogg_album_tagger/cli.rb', line 131 def select_command(args) if args.length == 0 m = "Usage: select <selector>+\n\n" + "A selector can either be \"all\", a single index or a range (e.g. 3-5).\n" + "Number and range based selectors can be made cumulative by adding a plus or minus sign in front of the selector (ex. \"-1-3\")." raise ArgumentError, m end @library.select(args) end |
#selector?(arg) ⇒ Boolean
25 26 27 |
# File 'lib/ogg_album_tagger/cli.rb', line 25 def selector?(arg) return arg == 'all' || arg.match(SIMPLE_SELECTOR) || arg.match(RANGE_SELECTOR) end |
#set_command(args) ⇒ Object
173 174 175 176 177 178 179 180 181 |
# File 'lib/ogg_album_tagger/cli.rb', line 173 def set_command(args) if args.length < 2 m = "Usage: set <tag> <value>+" raise ArgumentError, m end handle_picture_args(args) @library.set_tag(*args) end |
#show_command(args) ⇒ Object
122 123 124 125 126 127 128 129 |
# File 'lib/ogg_album_tagger/cli.rb', line 122 def show_command(args) case args.length when 0 print_album_summary(@library.summary) else print_album_summary @library.summary(args[0].upcase) end end |
#suggestions(context, input) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/ogg_album_tagger/cli.rb', line 64 def suggestions(context, input) if context.empty? # No args, suggest the supported commands. return %w{ls select move show set add rm auto check write help exit quit} elsif %w{ls select move check help exit quit}.include?(context[0]) # These commands don't take any argument or don't need autocomplete. elsif context[0] == 'show' # The "show" command can be followed by a tag return @library. if context.size == 1 elsif %w{add set}.include?(context[0]) case context.size when 1 # The "add" and "set" commands must be followed by a tag. # TODO Suggest usual ogg tags. return @library. when 2 if %w{METADATA_BLOCK_PICTURE PICTURE}.include? context[1].upcase # When a picture tag is edited, the tag must be followed by the path of a file. return Readline::FILENAME_COMPLETION_PROC.call(input) || [] else # Otherwise, propose values already used by the specified tag. return @library.tag_summary(context[1].upcase).values.flatten.uniq end end elsif context[0] == 'rm' if context.size == 1 return @library. else tag = context[1].upcase raise ArgumentError, "Autocompletion is not supported for pictures" if tag == 'METADATA_BLOCK_PICTURE' return @library.tag_summary(tag).values.flatten.uniq end elsif context[0] == 'auto' if context.length == 1 return %w{tracknumber rename} end end return [] end |