2011-08-31 7 views
11

Ho il seguente Rakefile:Come posso utilizzare una virgola in un argomento stringa su un'attività rake?

task :test_commas, :arg1 do |t, args| 
    puts args[:arg1] 
end 

e si desidera consultare con un singolo argomento stringa contenente le virgole. Ecco quello che ottengo:

%rake 'test_commas[foo, bar]' 
foo 

%rake 'test_commas["foo, bar"]' 
"foo 

%rake "test_commas['foo, bar']" 
'foo 

%rake "test_commas['foo,bar']" 
'foo 

%rake "test_commas[foo\,bar]" 
foo\ 

Attualmente sto usando la soluzione proposta in questo pull request to rake, ma c'è un modo per ottenere questo risultato senza patch rake?

risposta

6

Non sono sicuro che sia possibile. Guardando lib/rake/application.rb, il metodo per l'analisi della stringa compito è:

def parse_task_string(string) 
    if string =~ /^([^\[]+)(\[(.*)\])$/ 
    name = $1 
    args = $3.split(/\s*,\s*/) 
    else 
    name = string 
    args = [] 
    end 
    [name, args] 
end 

Sembra che la stringa di argomenti è diviso da una virgola, quindi non si può avere un argomento che contiene una virgola, almeno non nel rake- corrente 0.9.2.

3

Hai provato a sfuggire allo , con un \?

+0

sì, e questo non funziona neanche per me (in nessuno dei casi sopra). Aggiornerò la domanda con un esempio. –

+0

Ha funzionato come un fascino! – Elmor

3

Eugen already answered, perché non funziona.

Ma forse la seguente soluzione può aiutare:

task :test_commas, :arg1, :arg2 do |t, args| 
    arg = args.to_hash.values.join(',') 
    puts "Argument is #{arg.inspect}" 
end 

Richiede due argomenti, ma si unisce a loro per ottenere la 'vera' uno.

Se si dispone di più di una virgola, sono necessari più argomenti.


Ho fatto una ricerca più approfondita e ho trovato una (o due) soluzione. Non penso che sia una soluzione perfetta, ma sembra che funzioni.

require 'rake' 
module Rake 
    class Application 
    #usage: 
    # rake test_commas[1\,2\,3] 
    def parse_task_string_masked_commas(string) 
     if string =~ /^([^\[]+)(\[(.*)\])$/ 
     name = $1 
     args = $3.split(/\s*(?<!\\),\s*/).map{|x|x.gsub(/\\,/,',')} 
     else 
     name = string 
     args = [] 
     end 
     [name, args] 
    end 

    #Usage: 
    # rake test_commas[\"1,2\",3] 
    #" and ' must be masked 
    def parse_task_string_combined(string) 
     if string =~ /^([^\[]+)(\[(.*)\])$/ 
     name = $1 
     args = $3.split(/(['"].+?["'])?,(["'].+?["'])?/).map{|ts| ts.gsub(/\A["']|["']\Z/,'') } 
     args.shift if args.first.empty? 
     else 
     name = string 
     args = [] 
     end 
     [name, args] 
    end 

    #~ alias :parse_task_string :parse_task_string_masked_commas 
    alias :parse_task_string :parse_task_string_combined 

    end 

end 
desc 'Test comma separated arguments' 
task :test_commas, :arg1 do |t, args| 
    puts '---' 
    puts "Argument is #{args.inspect}" 
end 

La versione parse_task_string_masked_commas consente le chiamate con virgole mascherati:

rake test_commas[1\,2\,3] 

La versione parse_task_string_combined permette:

rake test_commas[\"1,2,3\"] 

Almeno sotto le finestre, la "(o ') deve essere mascherato. In caso contrario, sono già eliminati fino a quando la stringa ha raggiunto Rake :: Aplication (probabilmente sostituzione shell)

+0

Questa è una buona soluzione se conosco il formato di input in precedenza, ma in tal caso potrei semplicemente denominare gli argomenti in modo che 'rake -T' sarebbe più descrittivo. –

+0

Ho aggiunto una nuova versione: è un po 'più vicino alle tue proposte. – knut

+0

Vale la pena di inviarlo come patch upstream, in modo da poter includere virgole nelle stringhe. Che dire dell'uso di un'espressione regolare con lookbehind negativo (corrispondente a una virgola non preceduta da una barra) anziché utilizzare MYSEP? –

8

Cambiare il rastrello è una soluzione piuttosto sporca. Prova a utilizzare OptionParser invece. La sintassi segue

$ rake mytask -- -s 'some,comma,sepparated,string' 

il -- è necessario ignorare il modo di spoglia del parsing argomenti

ed ecco il codice rubino:

task :mytask do 
    options = {} 

    optparse = OptionParser.new do |opts| 
    opts.on('-s', '--string ARG', 'desc of my argument') do |str| 
     options[:str] = str 
    end 

    opts.on('-h', '--help', 'Display this screen') do  
     puts opts               
     exit                  
    end 
    end 

    begin 
    optparse.parse! 
    mandatory = [:str] 
    missing = mandatory.select{ |param| options[param].nil? } 
    if not missing.empty? 
     puts "Missing options: #{missing.join(', ')}" 
     puts optparse 
     exit 
    end 

    rescue OptionParser::InvalidOption, OptionParser::MissingArgument 
    puts $!.to_s 
    puts optparse 
    exit 
    end 

    puts "Performing task with options: #{options.inspect}" 
    # @TODO add task's code 
end 
+1

Questo è un approccio veramente pulito dal punto di vista dell'implementazione. Dal punto di vista dell'usabilità, sono abituato ad usare - per separare le opzioni dagli argomenti, specialmente con git, quindi è strano da usare - e quindi trattare gli argomenti come opzioni, ma poi di nuovo se mi interessa l'usabilità, probabilmente andrei solo con una CLI personalizzata o usa thor :) –

+0

Molto pulito grazie! – Alagu

0

Un'altra soluzione semplice è quella di utilizzare un delimitatore diverso nei tuoi argomenti.

È piuttosto semplice passare a un tubo | carattere (o altro) invece degli argomenti separati da virgola. Rake analizza correttamente i tuoi argomenti in questo caso e ti consente di dividere il primo per un array.

desc 'Test pipe separated arguments' 
task :test_pipes, :arg1, :arg2 do |t, args| 
    puts ":arg1 is: #{ args[:arg1] }" 
    puts ":arg2 still works: #{ args[:arg2] }" 
    puts "Split :arg1 is: #{ args[:arg1].split('|') }" 
end 

chiamata con:

rake test_pipes["foo|bar",baz] 
3

variabili task rake non sono molto convenienti in generale, invece utilizzare le variabili di ambiente:

task :my_task do 
    ENV["MY_ARGUMENT"].split(",").each_with_index do |arg, i| 
    puts "Argument #{i}: #{arg}" 
    end 
end 

Poi si può richiamare con

MY_ARGUMENT=foo,bar rake my_task 

Oppure se preferisci

rake my_task MY_ARGUMENT=foo,bar 
+0

Grazie! Tutte le opzioni presentate qui sono un po 'sporche e/o brutte, ma questo è stato di gran lunga il più veloce. – naudster

0

Siamo in grado di convertire ogni stringa di simboli, Come,

task :create do 
ARGV.each { |a| task a.to_sym do ; end } 
puts ARGV[1] 
puts ARGV[2] 
puts ARGV[3] 
puts ARGV[4]  
end 
end 

Esegui come,

rastrello creare '1, s' '2' 'ww ww' 'w, w '

0

# rake -v 10.5

rake test_commas\['foo\,bar'\]

funziona come un fascino.