Slop ist ein einfacher Optionsparser mit einer leicht zu merkenden Syntax und einer benutzerfreundlichen API.
gem install slop
opts = Slop . parse do | o |
o . string '-h' , '--host' , 'a hostname'
o . integer '--port' , 'custom port' , default : 80
o . string '-l' , '--login' , required : true
o . symbol '-m' , '--method' , default : :get
o . bool '-v' , '--verbose' , 'enable verbose mode'
o . bool '-q' , '--quiet' , 'suppress output (quiet mode)'
o . bool '-c' , '--check-ssl-certificate' , 'check SSL certificate for host'
o . bool '-k' , '--use-keychain' , 'store passphrase in OS keychain'
o . on '--version' , 'print the version' do
puts Slop :: VERSION
exit
end
end
ARGV #=> -v --login alice --host 192.168.0.1 -m post --check-ssl-certificate --use-keychain false
opts [ :host ] #=> 192.168.0.1
opts [ :login ] #=> alice
opts [ :method ] #=> :post
opts [ :use_keychain ] #=> false
# We can also check if a flag was passed (this has no bearing on the options default value):
opts . use_keychain? #=> true
opts . verbose? #=> true
opts . quiet? #=> false
opts . check_ssl_certificate? #=> true
opts . to_hash #=> { host: "192.168.0.1", port: 80, login: "alice", method: :post, verbose: true, quiet: false, check_ssl_certificate: true }
Beachten Sie, dass der Block, den wir zum Flag --version
hinzugefügt haben, während der Analysezeit ausgeführt wird. Daher sollten diese Blöcke reserviert werden, um sofort auf das Vorhandensein eines Flags zu reagieren. Wenn Sie auf andere Optionen zugreifen oder Werte ändern möchten, sehen Sie sich den Abschnitt „Benutzerdefinierte Optionstypen“ unten an und implementieren Sie die #finish
-Methode.
Die integrierten Optionstypen sind wie folgt:
o . string #=> Slop::StringOption, expects an argument
o . bool #=> Slop::BoolOption, argument optional, aliased to BooleanOption
o . integer #=> Slop::IntegerOption, expects an argument, aliased to IntOption
o . float #=> Slop::FloatOption, expects an argument
o . array #=> Slop::ArrayOption, expects an argument
o . regexp #=> Slop::RegexpOption, expects an argument
o . symbol #=> Slop::SymbolOption, expects an argument
o . null #=> Slop::NullOption, no argument and ignored from `to_hash`
o . on #=> alias for o.null
Sie können alle eingebauten Typen in slop/types.rb
sehen. Vorschläge oder Pull-Requests für weitere Typen sind willkommen.
Dieses Beispiel dient eigentlich nur dazu, die Funktionsweise der zugrunde liegenden API zu beschreiben. Es ist nicht unbedingt der beste Weg, es zu tun.
opts = Slop :: Options . new
opts . banner = "usage: connect [options] ..."
opts . separator ""
opts . separator "Connection options:"
opts . string "-H" , "--hostname" , "a hostname"
opts . int "-p" , "--port" , "a port" , default : 80
opts . separator ""
opts . separator "Extra options:"
opts . array "--files" , "a list of files to import"
opts . bool "-v" , "--verbose" , "enable verbose mode" , default : true
parser = Slop :: Parser . new ( opts )
result = parser . parse ( [ "--hostname" , "192.168.0.1" , "--no-verbose" ] )
result . to_hash #=> { hostname: "192.168.0.1", port: 80,
# files: [], verbose: false }
puts opts # prints out help
Es ist üblich, ein Array von Argumenten abzurufen, die nicht vom Parser verarbeitet wurden (z. B. Optionen oder verbrauchte Argumente). Sie können dies mit der Methode Result#arguments
tun:
args = %w( connect --host google.com GET )
opts = Slop . parse args do | o |
o . string '--host'
end
p opts . arguments #=> ["connect", "GET"] # also aliased to `args`
Dies ist besonders nützlich, wenn Sie Skripte mit ARGF
schreiben:
opts = Slop . parse do | blah |
# ...
end
# make sure sloptions aren't consumed by ARGF
ARGV . replace opts . arguments
ARGF . each { | line |
# ...
}
Slop verfügt über eine integrierte ArrayOption
zur Verarbeitung von Array-Werten:
opts = Slop . parse do | o |
# the delimiter defaults to ','
o . array '--files' , 'a list of files' , delimiter : ','
end
# Both of these will return o[:files] as ["foo.txt", "bar.rb"]:
# --files foo.txt,bar.rb
# --files foo.txt --files bar.rb
# This will return o[:files] as []:
# --files ""
Wenn Sie die integrierte Zeichenfolgenaufteilung deaktivieren möchten, setzen Sie das Trennzeichen auf nil
.
Slop verwendet Optionstypklassen für jede neu hinzugefügte Option. Sie verwenden standardmäßig NullOption
. Wenn Sie o.array
eingeben, sucht Slop nach einer Option namens Slop::ArrayOption
. Diese Klasse muss mindestens eine Methode enthalten, call
. Diese Methode wird zur Analysezeit ausgeführt und der Rückgabewert dieser Methode wird als Optionswert verwendet. Wir können dies verwenden, um benutzerdefinierte Optionstypen zu erstellen:
module Slop
class PathOption < Option
def call ( value )
Pathname . new ( value )
end
end
end
opts = Slop . parse %w( --path ~/ ) do | o |
o . path '--path' , 'a custom path name'
end
p opts [ :path ] #=> #<Pathname:~/>
Benutzerdefinierte Optionen können auch eine finish
-Methode implementieren. Diese Methode führt standardmäßig nichts aus, wird jedoch ausgeführt, sobald alle Optionen analysiert wurden. Dadurch können wir zurückgehen und den Status ändern, ohne uns darauf verlassen zu müssen, dass Optionen in einer bestimmten Reihenfolge analysiert werden. Hier ist ein Beispiel:
module Slop
class FilesOption < ArrayOption
def finish ( opts )
if opts . expand?
self . value = value . map { | f | File . expand_path ( f ) }
end
end
end
end
opts = Slop . parse %w( --files foo.txt,bar.rb -e ) do | o |
o . files '--files' , 'an array of files'
o . bool '-e' , '--expand' , 'if used, list of files will be expanded'
end
p opts [ :files ] #=> ["/full/path/foo.txt", "/full/path/bar.rb"]
Slop wird Fehler für Folgendes auslösen:
Slop::MissingArgument
Slop::UnknownOption
required
markiert ist, wenn sie nicht bereitgestellt wird: Slop::MissingRequiredOption
validate_types
markierte Option mit einem Argument, das nicht mit ihrem Typ übereinstimmt (z. B. bla
für integer
): Slop::InvalidOptionValue
Diese Fehler erben von Slop::Error
, sodass Sie sie alle retten können. Alternativ können Sie diese Fehler mit der Konfigurationsoption suppress_errors
unterdrücken:
opts = Slop . parse suppress_errors : true do
o . string '-name'
end
# or per option:
opts = Slop . parse do
o . string '-host' , suppress_errors : true
o . int '-port'
end
Standardmäßig überprüft Slop nicht, ob ein Argument ein gültiger Wert für eine bestimmte Option ist; Wenn die Option stattdessen einen Standardwert hat, wird dieser anstelle des angegebenen ungültigen Arguments verwendet. Damit Typen (z. B. integer
und float
) validiert werden und anzeigen, dass der bereitgestellte Wert ungültig ist, kann entweder dem Argument selbst oder seinem Optionssatz eine zusätzliche Option bereitgestellt werden:
opts = Slop :: Options . new
opts . int "-p" , "--port" , "a port" , default : 80 , validate_types : true
parser = Slop :: Parser . new ( opts )
result = parser . parse ( [ "--port" , "bla" ] )
# invalid value for -p, --port (Slop::InvalidOptionValue)
# Or to the option set...
opts = Slop :: Options . new ( validate_types : true )
opts . int "-p" , "--port" , "a port" , default : 80
parser = Slop :: Parser . new ( opts )
result = parser . parse ( [ "--port" , "bla" ] )
# invalid value for -p, --port (Slop::InvalidOptionValue)
Der Rückgabewert von Slop.parse
ist ein Slop::Result
, das eine nette Hilfezeichenfolge zur Anzeige Ihrer Optionen bereitstellt. puts opts
oder ruft opts.to_s
auf:
opts = Slop . parse do | o |
o . string '-h' , '--host' , 'hostname'
o . int '-p' , '--port' , 'port (default: 80)' , default : 80
o . string '--username'
o . separator ''
o . separator 'other options:'
o . bool '--quiet' , 'suppress output'
o . on '-v' , '--version' do
puts "1.1.1"
end
end
puts opts
Ausgabe:
% ruby run.rb
usage: run.rb [options]
-h, --host hostname
-p, --port port (default: 80)
--username
other options:
--quiet suppress output
-v, --version
Diese Methode benötigt einen optionalen prefix
, der standardmäßig " " * 4
:
puts opts.to_s(prefix: " ")
Dabei geht es darum, Ihre Beschreibungen nach dem längsten Optionsflag auszurichten.
Hier ist ein Beispiel für das Hinzufügen einer eigenen Hilfeoption:
o . on '--help' do
puts o
exit
end
Slop verfügt nicht mehr über eine integrierte Unterstützung für Unterbefehle im Git-Stil.