cultome_player 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +325 -0
- data/Rakefile +8 -0
- data/bin/cultome_player +39 -0
- data/config/environment.yml +28 -0
- data/cultome_player.gemspec +35 -0
- data/db/001_create_schema.rb +58 -0
- data/lib/cultome_player.rb +107 -0
- data/lib/cultome_player/command.rb +11 -0
- data/lib/cultome_player/command/language.rb +61 -0
- data/lib/cultome_player/command/processor.rb +165 -0
- data/lib/cultome_player/command/reader.rb +86 -0
- data/lib/cultome_player/environment.rb +130 -0
- data/lib/cultome_player/events.rb +29 -0
- data/lib/cultome_player/media.rb +47 -0
- data/lib/cultome_player/objects.rb +15 -0
- data/lib/cultome_player/objects/album.rb +21 -0
- data/lib/cultome_player/objects/artist.rb +18 -0
- data/lib/cultome_player/objects/command.rb +37 -0
- data/lib/cultome_player/objects/drive.rb +26 -0
- data/lib/cultome_player/objects/genre.rb +16 -0
- data/lib/cultome_player/objects/parameter.rb +37 -0
- data/lib/cultome_player/objects/response.rb +42 -0
- data/lib/cultome_player/objects/song.rb +38 -0
- data/lib/cultome_player/player.rb +13 -0
- data/lib/cultome_player/player/adapter.rb +14 -0
- data/lib/cultome_player/player/adapter/mpg123.rb +143 -0
- data/lib/cultome_player/player/interactive.rb +56 -0
- data/lib/cultome_player/player/interface.rb +13 -0
- data/lib/cultome_player/player/interface/basic.rb +96 -0
- data/lib/cultome_player/player/interface/builtin_help.rb +368 -0
- data/lib/cultome_player/player/interface/extended.rb +199 -0
- data/lib/cultome_player/player/interface/helper.rb +300 -0
- data/lib/cultome_player/player/playlist.rb +280 -0
- data/lib/cultome_player/plugins.rb +23 -0
- data/lib/cultome_player/plugins/help.rb +58 -0
- data/lib/cultome_player/state_checker.rb +74 -0
- data/lib/cultome_player/utils.rb +95 -0
- data/lib/cultome_player/version.rb +3 -0
- data/spec/config.yml +0 -0
- data/spec/cultome_player/command/processor_spec.rb +168 -0
- data/spec/cultome_player/command/reader_spec.rb +45 -0
- data/spec/cultome_player/cultome_player_spec.rb +17 -0
- data/spec/cultome_player/environment_spec.rb +65 -0
- data/spec/cultome_player/events_spec.rb +22 -0
- data/spec/cultome_player/media_spec.rb +41 -0
- data/spec/cultome_player/player/adapter/mpg123_spec.rb +82 -0
- data/spec/cultome_player/player/interface/basic_spec.rb +168 -0
- data/spec/cultome_player/player/interface/extended/connect_spec.rb +117 -0
- data/spec/cultome_player/player/interface/extended/search_spec.rb +90 -0
- data/spec/cultome_player/player/interface/extended/show_spec.rb +36 -0
- data/spec/cultome_player/player/interface/extended/shuffle_spec.rb +26 -0
- data/spec/cultome_player/player/interface/extended_spec.rb +136 -0
- data/spec/cultome_player/player/interface/helper_spec.rb +63 -0
- data/spec/cultome_player/player/interface_spec.rb +17 -0
- data/spec/cultome_player/player/playlist_spec.rb +301 -0
- data/spec/cultome_player/plugins/help_spec.rb +21 -0
- data/spec/cultome_player/plugins_spec.rb +19 -0
- data/spec/cultome_player/utils_spec.rb +15 -0
- data/spec/spec_helper.rb +108 -0
- data/spec/test/uno/dos/dos.mp3 +0 -0
- data/spec/test/uno/dos/tres/tres.mp3 +0 -0
- data/spec/test/uno/uno.mp3 +0 -0
- data/tasks/console.rake +19 -0
- data/tasks/db.rake +19 -0
- data/tasks/run.rake +7 -0
- metadata +322 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
user:
|
2
|
+
db_adapter: sqlite3
|
3
|
+
db_file: ~/.cultome/db.dat
|
4
|
+
db_log_file: ~/.cultome/db.log
|
5
|
+
file_types: mp3
|
6
|
+
mplayer_pipe: ~/.cultome/mpctr
|
7
|
+
config_file: ~/.cultome/config.yml
|
8
|
+
memory:
|
9
|
+
db_adapter: sqlite3
|
10
|
+
db_file: /tmp/db.dat
|
11
|
+
db_log_file: /tmp/db.log
|
12
|
+
file_types: mp3
|
13
|
+
mplayer_pipe: /tmp/mpctr
|
14
|
+
config_file: /tmp/config.yml
|
15
|
+
rspec:
|
16
|
+
db_adapter: sqlite3
|
17
|
+
db_file: spec/db.dat
|
18
|
+
db_log_file: spec/db.log
|
19
|
+
file_types: mp3
|
20
|
+
mplayer_pipe: spec/mpctr
|
21
|
+
config_file: spec/config.yml
|
22
|
+
test:
|
23
|
+
db_adapter: sqlite3
|
24
|
+
db_file: ~/tmp/db.dat
|
25
|
+
db_log_file: ~/tmp/db.log
|
26
|
+
file_types: mp3
|
27
|
+
mplayer_pipe: ~/tmp/mpctr
|
28
|
+
config_file: ~/tmp/config.yml
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cultome_player/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "cultome_player"
|
8
|
+
gem.version = CultomePlayer::VERSION
|
9
|
+
gem.summary = "CulToMe Player"
|
10
|
+
gem.description = "A console music library explorer and player"
|
11
|
+
gem.authors = ["Carlos Soria"]
|
12
|
+
gem.email = "cultome@gmail.com"
|
13
|
+
gem.homepage = "https://github.com/cultome/cultome_player"
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_runtime_dependency "activerecord"
|
22
|
+
gem.add_runtime_dependency "activesupport"
|
23
|
+
gem.add_runtime_dependency "taglib-ruby"
|
24
|
+
gem.add_runtime_dependency "rb-readline"
|
25
|
+
gem.add_runtime_dependency "sqlite3"
|
26
|
+
gem.add_runtime_dependency "colorize"
|
27
|
+
|
28
|
+
gem.add_development_dependency "rake"
|
29
|
+
gem.add_development_dependency "coveralls"
|
30
|
+
gem.add_development_dependency "rspec"
|
31
|
+
gem.add_development_dependency "bundler"
|
32
|
+
gem.add_development_dependency "database_cleaner"
|
33
|
+
gem.add_development_dependency "pry"
|
34
|
+
gem.add_development_dependency "yard"
|
35
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
class CreateSchema < ActiveRecord::Migration
|
3
|
+
def self.up
|
4
|
+
create_table :songs do |t|
|
5
|
+
t.string :name # If I Had A Gun
|
6
|
+
t.integer :artist_id, default: 0 # Noel Gallagher
|
7
|
+
t.integer :album_id, default: 0 # High Flying Birds
|
8
|
+
t.integer :year # 2011
|
9
|
+
t.integer :track # 3
|
10
|
+
t.integer :duration # 210 sec
|
11
|
+
t.integer :drive_id
|
12
|
+
t.string :relative_path
|
13
|
+
t.integer :points, default: 0
|
14
|
+
t.integer :plays, default: 0
|
15
|
+
t.datetime :last_played_at
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
|
19
|
+
create_table :albums do |t|
|
20
|
+
t.string :name
|
21
|
+
t.integer :points
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table :artists do |t|
|
26
|
+
t.string :name
|
27
|
+
t.integer :points
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :genres do |t|
|
32
|
+
t.integer :points
|
33
|
+
t.string :name
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :genres_songs, id: false do |t|
|
37
|
+
t.integer :song_id
|
38
|
+
t.integer :genre_id
|
39
|
+
end
|
40
|
+
|
41
|
+
create_table :drives do |t|
|
42
|
+
t.string :name
|
43
|
+
t.string :path
|
44
|
+
t.boolean :connected, default: true
|
45
|
+
t.timestamps
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.down
|
50
|
+
drop_table :songs
|
51
|
+
drop_table :albums
|
52
|
+
drop_table :artists
|
53
|
+
drop_table :genres
|
54
|
+
drop_table :genres_songs
|
55
|
+
drop_table :drives
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "cultome_player/version"
|
2
|
+
require "cultome_player/environment"
|
3
|
+
require "cultome_player/objects"
|
4
|
+
require "cultome_player/command"
|
5
|
+
require "cultome_player/player"
|
6
|
+
require "cultome_player/media"
|
7
|
+
require "cultome_player/utils"
|
8
|
+
require "cultome_player/events"
|
9
|
+
require "cultome_player/plugins"
|
10
|
+
require "cultome_player/state_checker"
|
11
|
+
|
12
|
+
module CultomePlayer
|
13
|
+
include Environment
|
14
|
+
include Utils
|
15
|
+
include Objects
|
16
|
+
include Command
|
17
|
+
include Player
|
18
|
+
include Media
|
19
|
+
include Events
|
20
|
+
include Plugins
|
21
|
+
include StateChecker
|
22
|
+
|
23
|
+
# Interpret a user input string as it would be typed in the console.
|
24
|
+
#
|
25
|
+
# @param user_input [String] The user input.
|
26
|
+
# @return [Response] Response object with information about command execution.
|
27
|
+
def execute(user_input)
|
28
|
+
cmd = parse user_input
|
29
|
+
# revisamos si es un built in command o un plugin
|
30
|
+
action = cmd.action
|
31
|
+
plugin_action = "command_#{cmd.action}".to_sym
|
32
|
+
action = plugin_action if respond_to?(plugin_action)
|
33
|
+
|
34
|
+
raise 'invalid command:action unknown' unless respond_to?(action)
|
35
|
+
with_connection do
|
36
|
+
begin
|
37
|
+
send(action, cmd)
|
38
|
+
rescue Exception => e
|
39
|
+
s = e.message.split(":")
|
40
|
+
failure(message: s[0], details: s[1])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Creates a generic response
|
46
|
+
#
|
47
|
+
# @param type [Symbol] The response type.
|
48
|
+
# @param data [Hash] The information that the response will contain.
|
49
|
+
# @return [Response] Response object with information in form of getter methods.
|
50
|
+
def create_response(type, data)
|
51
|
+
data[:response_type] = data.keys.first unless data.has_key?(:response_type)
|
52
|
+
return Response.new(type, data)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Creates a success response. Handy method for #create_response
|
56
|
+
#
|
57
|
+
# @param response [Hash] The information that the response will contain.
|
58
|
+
# @return [Response] Response object with information in form of getter methods.
|
59
|
+
def success(response)
|
60
|
+
create_response(:success, get_response_params(response))
|
61
|
+
end
|
62
|
+
|
63
|
+
# Creates a failure response. Handy method for #create_response
|
64
|
+
#
|
65
|
+
# @param response [Hash] The information that the response will contain.
|
66
|
+
# @return [Response] Response object with information in form of getter methods.
|
67
|
+
def failure(response)
|
68
|
+
create_response(:failure, get_response_params(response))
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
class DefaultPlayer
|
73
|
+
include CultomePlayer
|
74
|
+
|
75
|
+
def initialize(env)
|
76
|
+
prepare_environment(env)
|
77
|
+
playlists.register(:current)
|
78
|
+
playlists.register(:history)
|
79
|
+
playlists.register(:queue)
|
80
|
+
playlists.register(:focus)
|
81
|
+
playlists.register(:search)
|
82
|
+
|
83
|
+
register_listener(:playback_finish, self)
|
84
|
+
end
|
85
|
+
|
86
|
+
def on_playback_finish
|
87
|
+
r = execute("next no_history")
|
88
|
+
display_over("#{r.message}\n#{PROMPT}")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Get an instance of DefaultPlayer
|
93
|
+
#
|
94
|
+
# @param env [Symbol] The environment from which the configirations will be taken.
|
95
|
+
# @return [DefaultPlayer] A Cultome player ready to rock.
|
96
|
+
def get_player(env=:user)
|
97
|
+
DefaultPlayer.new(env)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def get_response_params(response)
|
104
|
+
return {message: response} if response.instance_of?(String)
|
105
|
+
return response
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module CultomePlayer::Command
|
2
|
+
module Language
|
3
|
+
|
4
|
+
# Define the sintaxis of the player language.
|
5
|
+
#
|
6
|
+
# @return [Hash] With the keys :command, :parameters, :actions, :param
|
7
|
+
def sintaxis
|
8
|
+
# <command> : <action> | <action> <parameters>
|
9
|
+
# <action> : literal
|
10
|
+
# <parameters> : <param> | <param> <parameters>
|
11
|
+
# <param> : literal | criteria | number | object | path | bubble
|
12
|
+
{
|
13
|
+
command: ["action", "action parameters"],
|
14
|
+
parameters: ["param", "param parameters"],
|
15
|
+
action: [:literal],
|
16
|
+
param: [:literal, :criteria, :number, :object, :path, :boolean, :bubble],
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the semantics of the builtin commands.
|
21
|
+
#
|
22
|
+
# @note The first literal in regex is the command itself.
|
23
|
+
# @return [Hash<String, Regex>] The key is the command name and the regex its format.
|
24
|
+
def semantics
|
25
|
+
{
|
26
|
+
"play" => /^literal(literal|number|criteria|object|[\s]+)*$/,
|
27
|
+
"show" => /^literal(number|object|[\s]+)*$/,
|
28
|
+
"search" => /^literal(literal|criteria|[\s]+)+$/,
|
29
|
+
"enqueue" => /^literal(literal|number|criteria|object|[\s]+)+$/,
|
30
|
+
"connect" => /^literal ((literal)|(path) bubble (literal))$/,
|
31
|
+
"disconnect" => /^literal (literal)$/,
|
32
|
+
"stop" => /^literal[\s]*$/,
|
33
|
+
"pause" => /^literal (boolean)$/,
|
34
|
+
"prev" => /^literal[\s]*$/,
|
35
|
+
"next" => /^literal[\s]*$/,
|
36
|
+
"quit" => /^literal[\s]*$/,
|
37
|
+
"ff" => /^literal(number|[\s]+)*$/,
|
38
|
+
"fb" => /^literal(number|[\s]+)*$/,
|
39
|
+
"shuffle" => /^literal[\s]+(boolean)$/,
|
40
|
+
"repeat" => /^literal[\s]*$/,
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return the token identities.
|
45
|
+
#
|
46
|
+
# @return [List<Hash>] The has contains the type of the token and their format.
|
47
|
+
def token_identities
|
48
|
+
[
|
49
|
+
{type: :bubble, identity: /^(=>|->)$/},
|
50
|
+
{type: :number, identity: /^([\d]+)$/},
|
51
|
+
{type: :object, identity: /^@([\w\d]+)$/},
|
52
|
+
{type: :path, identity: /^(['"]?(?:\/|~\/)[\/\w\d\s.]+)["']?$/},
|
53
|
+
{type: :criteria, identity: /^([\w]+):([\d\w\s]+)$/, captures: 2, labels: [:criteria, :value]},
|
54
|
+
{type: :boolean, identity: /^(on|off|yes|false|true|si|no|y|n|s|ok)$/},
|
55
|
+
{type: :ip, identity: /^([\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3})$/},
|
56
|
+
{type: :literal, identity: /^([\w\d\s]+)$/},
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module CultomePlayer::Command
|
2
|
+
module Processor
|
3
|
+
|
4
|
+
# Parse a user input into a command
|
5
|
+
#
|
6
|
+
# @param user_input [String] The user input to be parsed.
|
7
|
+
# @return [Command] The parsed command.
|
8
|
+
def parse(user_input)
|
9
|
+
tokens = identify_tokens(get_tokens(user_input))
|
10
|
+
validate_command(:command, tokens)
|
11
|
+
return CultomePlayer::Objects::Command.new(tokens.shift, tokens)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Split the user input into tokens.
|
15
|
+
#
|
16
|
+
# @param user_input [String] The user input.
|
17
|
+
# @return [List<String>] The detected tokens.
|
18
|
+
def get_tokens(user_input)
|
19
|
+
tokens = []
|
20
|
+
token = ""
|
21
|
+
capturing_string = false
|
22
|
+
|
23
|
+
user_input.each_char do |char|
|
24
|
+
case char
|
25
|
+
when /[\d\w\/:@]/
|
26
|
+
token << char
|
27
|
+
when /["']/
|
28
|
+
capturing_string = !capturing_string
|
29
|
+
when /[\s]/
|
30
|
+
if capturing_string
|
31
|
+
token << char
|
32
|
+
else
|
33
|
+
tokens << token
|
34
|
+
token = ""
|
35
|
+
end
|
36
|
+
else
|
37
|
+
token << char
|
38
|
+
end # case
|
39
|
+
end # each
|
40
|
+
|
41
|
+
tokens << token unless token.empty?
|
42
|
+
raise "invalid command:unclosed string" if capturing_string
|
43
|
+
|
44
|
+
return tokens
|
45
|
+
end
|
46
|
+
|
47
|
+
# Identify detected tokens.
|
48
|
+
#
|
49
|
+
# @param tokens [List<String>] The detected tokens.
|
50
|
+
# @return [List<Hash>] The hash contains keys :type and :value.
|
51
|
+
def identify_tokens(tokens)
|
52
|
+
tokens.map do |token|
|
53
|
+
id = guess_token_id(token)
|
54
|
+
id.nil? ? {type: :unknown, value: token} : get_token_value(token, id)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Check that a the tokens identifed correspond to a player command.
|
59
|
+
#
|
60
|
+
# @param type [Symbol] The language structure you try to match.
|
61
|
+
# @param tokens [List<Hash>] The list of tokens identified.
|
62
|
+
# @return [Boolean] True if the user command match with a player command format.
|
63
|
+
def validate_command(type, tokens)
|
64
|
+
current_format = get_command_format(type, tokens)
|
65
|
+
# extraemos el primer token, que debe ser el comando
|
66
|
+
cmd = tokens.first[:value]
|
67
|
+
|
68
|
+
valid_format = semantics[cmd]
|
69
|
+
if valid_format.nil?
|
70
|
+
if plugins_respond_to?(cmd)
|
71
|
+
valid_format = plugin_command_sintaxis(cmd)
|
72
|
+
else
|
73
|
+
raise 'invalid command:invalid action'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
return current_format =~ valid_format
|
77
|
+
end
|
78
|
+
|
79
|
+
# Creates a string representation of the command prototype.
|
80
|
+
#
|
81
|
+
# @param type [Symbol] The Language structure you try to match.
|
82
|
+
# @param tokens [List<Hash>] The Language structure you try to match.
|
83
|
+
# @return [String] The string representation of the command prototype.
|
84
|
+
def get_command_format(type, tokens)
|
85
|
+
format = guess_command_format(type, tokens)
|
86
|
+
|
87
|
+
return format if format.class == Symbol
|
88
|
+
|
89
|
+
langs = format.split
|
90
|
+
# partimos el formato y validamos cada pedazo
|
91
|
+
tks = tokens.clone
|
92
|
+
|
93
|
+
cmd_format = ""
|
94
|
+
while !langs.empty? do
|
95
|
+
# extraemos el primer elemento del formato
|
96
|
+
lang = langs.shift
|
97
|
+
|
98
|
+
if langs.empty?
|
99
|
+
# volvemos a validar con el nuevo elemento del lenguaje
|
100
|
+
cmd_format << " " << get_command_format(lang.to_sym, tks).to_s
|
101
|
+
else
|
102
|
+
tk = tks.shift
|
103
|
+
cmd_format << " " << get_command_format(lang.to_sym, tk).to_s
|
104
|
+
end
|
105
|
+
end
|
106
|
+
# limpiamos el formato final
|
107
|
+
return cmd_format.strip.gsub(" ", " ")
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def guess_token_id(token)
|
113
|
+
token_identities.find do |tok_id|
|
114
|
+
token =~ tok_id[:identity]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def get_token_value(token, id)
|
119
|
+
captures = id[:captures] || 1
|
120
|
+
labels = id[:labels] || [:value]
|
121
|
+
|
122
|
+
token_info = {type: id[:type]}
|
123
|
+
|
124
|
+
token =~ id[:identity]
|
125
|
+
(1..captures).to_a.zip(labels).each do |idx, label|
|
126
|
+
token_info[label] = eval("$#{idx}")
|
127
|
+
end
|
128
|
+
|
129
|
+
return token_info
|
130
|
+
end
|
131
|
+
|
132
|
+
def guess_command_format(type, tokens)
|
133
|
+
# buscamos el formato que tenga mas matches con los parametros
|
134
|
+
format = sintaxis[type].find do |stxs_elem| # ["action", "action parameters"]
|
135
|
+
if stxs_elem.is_a?(String)
|
136
|
+
# checamos si el numero de token en el comando corresponde
|
137
|
+
# con el numer de tokens en la sintaxis
|
138
|
+
stxs_elem.split.size >= tokens.size # ej. "play 1 2" === "action paramters"
|
139
|
+
elsif stxs_elem.is_a?(Symbol)
|
140
|
+
if tokens.is_a?(Hash)
|
141
|
+
tokens[:type] == stxs_elem
|
142
|
+
elsif tokens.is_a?(Array) && tokens.size == 1
|
143
|
+
tokens.first[:type] == stxs_elem
|
144
|
+
else
|
145
|
+
false
|
146
|
+
end
|
147
|
+
else
|
148
|
+
raise 'invalid command:invalid command format'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
if format.nil?
|
153
|
+
max = sintaxis[type].max{|tk| tk.class == String ? tk.split.size: 0}
|
154
|
+
if max.respond_to?(:split) && tokens.size > max.split.size
|
155
|
+
format = max
|
156
|
+
else
|
157
|
+
raise 'invalid command:invalid command'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
return format
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|