2010-04-28 7 views
22

पार्स करने के लिए मैं रूबी के OptionParser उपयोग करने के लिए प्रपत्रमाणिक के OptionParser का उपयोग करते हुए उप-आदेशों

COMMAND [GLOBAL FLAGS] [SUB-COMMAND [SUB-COMMAND FLAGS]] 

तरह के उप-आदेशों को पार्स करने में सक्षम होना चाहते हैं एक अलग विकल्प पार्सर लाइब्रेरी (जैसे ट्रोलॉप) पर स्विच करें, लेकिन मुझे यह जानने में दिलचस्पी है कि इसे विकल्पपर्सर के भीतर से कैसे किया जाए, क्योंकि मैं लाइब्रेरी को बेहतर तरीके से सीखना चाहता हूं।

कोई सुझाव?

+0

कोई सुझाव नहीं, एक सुझाव से अलग दिशाओं को बदलने के लिए खुला रहता है। मेरे अनुभव में, 'OptionParser' कई कारणों से उपयोग करने में निराशाजनक रहा है, उनमें से एक खराब दस्तावेज है - इसलिए आपका प्रश्न। ट्रोलोप के लेखक विलियम मॉर्गन ने उनकी आलोचना में कोई दया नहीं दिखायी है (उदाहरण के लिए, http://stackoverflow.com/questions/897630/really-cheap-command-line-option-parsing-in-ruby और http://trollop.rubyforge.org)। मैं जो कहता हूं उससे विवाद नहीं कर सकता। – FMc

+1

@ एफएम: ठीक है, उस प्रश्न के लेखक की तरह, मैं एक मशीन पर फंस गया हूं जहां लाइब्रेरी आयात करना एक पिटा है, इसलिए मैं मानक libs के साथ ऐसा करने की कोशिश कर रहा हूं - जैसे 'optparse'। – rampion

उत्तर

35

यह पता लगाया। मुझे OptionParser#order! का उपयोग करने की आवश्यकता है। यह ARGV की शुरुआत से सभी विकल्पों को पार्स करेगा जब तक कि यह एक गैर-विकल्प (जो विकल्प विकल्प नहीं है) पाता है, ARGV से प्रक्रियाओं को हटाकर, और फिर यह छोड़ दिया जाएगा।

तो मैं बस की तरह कुछ करने की जरूरत है:

global = OptionParser.new do |opts| 
    # ... 
end 
subcommands = { 
    'foo' => OptionParser.new do |opts| 
    # ... 
    end, 
    # ... 
    'baz' => OptionParser.new do |opts| 
    # ... 
    end 
} 

global.order! 
subcommands[ARGV.shift].order! 
+2

संदर्भ के लिए, इस [Gist] (https://gist.github.com/rkumar/445735) में एक और पूर्ण उदाहरण है। – sschuberth

+0

क्या होगा यदि 'foo' और' baz' बहुत सारे सामान्य विकल्प साझा करते हैं? पुनरावृत्ति से कैसे बचें? –

+0

फर्नांडो ए: सरल, बस एक विधि के लिए आम विकल्पों को अमूर्त करें। 'def common_options (&blk) ; OptionParser.new {| opts | opts.on (...); ...; blk.call (opts)}; end', फिर बाद में subcommand-specific विकल्पों के लिए ब्लॉक के साथ उस विधि को कॉल करें - 'subcommands = {'foo' => common_options {| opts | ...}, 'baz' => common_options {| opts | ...}, ...}' – rampion

0

वहाँ भी अन्य रत्नों आप main रूप में इस तरह देख सकते हैं।

+0

क्या इसमें कोई दस्तावेज़ है? – rampion

+0

@ रैंपियन: आप नमूनों को देख सकते हैं, उदाहरण के लिए http://codeforpeople.com/lib/ruby/main/main-2.8.3/samples/f.rb –

1

ऐसा लगता है कि OptionParser वाक्यविन्यास कुछ बदल गया है। मुझे निम्नलिखित का उपयोग करना पड़ा ताकि तर्क सरणी में ऑप्शन ऑब्जेक्ट द्वारा पार्स किए गए सभी विकल्प नहीं थे।

begin 
    opts.order!(arguments) 
rescue OptionParser::InvalidOption => io 
    # Prepend the invalid option onto the arguments array 
    arguments = io.recover(arguments) 
rescue => e 
    raise "Argument parsing failed: #{e.to_s()}" 
end 
0

GLI जाने का रास्ता, https://github.com/davetron5000/gli है। एक ट्यूटोरियल से एक अंश:

#!/usr/bin/env ruby 
require 'gli' 
require 'hacer' 

include GLI::App 

program_desc 'A simple todo list' 

flag [:t,:tasklist], :default_value => File.join(ENV['HOME'],'.todolist') 

pre do |global_options,command,options,args| 
    $todo_list = Hacer::Todolist.new(global_options[:tasklist]) 
end 

command :add do |c| 
    c.action do |global_options,options,args| 
    $todo_list.create(args) 
    end 
end 

command :list do |c| 
    c.action do 
    $todo_list.list.each do |todo| 
     printf("%5d - %s\n",todo.todo_id,todo.text) 
    end 
    end 
end 

command :done do |c| 
    c.action do |global_options,options,args| 
    id = args.shift.to_i 
    $todo_list.list.each do |todo| 
     $todo_list.complete(todo) if todo.todo_id == id 
    end 
    end 
end 

exit run(ARGV) 

आप http://davetron5000.github.io/gli/ पर ट्यूटोरियल पा सकते हैं।

संबंधित मुद्दे