2012-04-15 11 views
8

मुझे पता है कि यह प्रश्न पहले से ही पूछा गया है, लेकिन मैं एक विशिष्ट कार्यक्षमता के साथ जावा क्ली पार्सर की तलाश में हूं। मैं चाहता हूं कि यह कमांड लाइन पेड़ को परिभाषित करने में सक्षम हो, इस प्रकार उप-सामग्रियों (और एक से अधिक स्तर की गहराई) का उपयोग कर। इस प्रकार मैं विकल्पों में आने से पहले 3-4 स्तर के कमांड प्राप्त कर सकता हूं। और ये उपसमूह पारस्परिक रूप से अनन्य हैं। धन्यवादजावा सीएलआई पार्सर

+0

क्या आप उन आदेशों के कुछ उदाहरण पोस्ट कर सकते हैं जिन्हें आप पार्स करना चाहते हैं? – dash1e

+1

कमांड उप-आदेश उप-उप-आदेश-विकल्प 1 तर्क-विकल्प 2 तर्क – Sophie

उत्तर

0

यदि आपका आदेश अभिव्यक्ति जटिल है तो आप, वाक्य रचना को परिभाषित अपनी खुद की पार्सर बनाने के लिए JavaCC या AntLR की तरह अपने BNF और उपयोग पुस्तकालयों लिखने के बारे में सोच सकते हैं।

12

JCommander के साथ किया जा सकता है। प्रत्येक JCommander ऑब्जेक्ट, इसके सार में, पैरामीटर की मनमानी संख्या और/या नेस्टेड उप-आदेशों की मनमानी संख्या के साथ एक आदेश है, जहां शीर्ष JCommander ऑब्जेक्ट रूट कमांड है। कमांड पैरामीटर हमेशा कमांड के लिए विशिष्ट होते हैं जिनके लिए उन्हें घोषित किया गया है और अन्य कमांड के पैरामीटर में हस्तक्षेप नहीं करते हैं। एक उप आदेश जोड़ने के लिए इंटरफ़ेस बहुत सहज ज्ञान युक्त नहीं है, लेकिन संभव है (देखें addCommand विधि())

यहाँ एक-का-प्रमाण अवधारणा परीक्षण वर्ग है:

public class Test{ 

@Test 
public void nestedSubCommandTest() { 
    GeneralOptions generalOpts = new GeneralOptions(); 
    JCommander jc = new JCommander(generalOpts); 

    Command command = new Command(); 
    JCommander jc_command = addCommand(jc, "command", command); 

    SubCommand1 subcommand1 = new SubCommand1(); 
    JCommander jc_subcommand1 = addCommand(jc_command, "subcommand1", 
      subcommand1); 

    SubCommand2 subcommand2 = new SubCommand2(); 
    JCommander jc_subcommand2 = addCommand(jc_subcommand1, "subcommand2", 
      subcommand2); 

    SubCommand3 subcommand3 = new SubCommand3(); 
    addCommand(jc_subcommand2, "subcommand3", subcommand3); 

    jc.parse("--general-opt", 
     "command", "--opt", 
     "subcommand1", 
     "subcommand2", "--sub-opt2", 
     "subcommand3", "--sub-opt3"); 

    assertTrue(generalOpts.opt);// --general-opt was set 
    assertTrue(command.opt);// command --opt was set 
    assertFalse(subcommand1.opt);// subcommand1 --sub-opt1 was not set 
    assertTrue(subcommand2.opt);// subcommand2 --sub-opt2 was set 
    assertTrue(subcommand3.opt);// subcommand3 --sub-opt3 was set 
} 

private static JCommander addCommand(JCommander parentCommand, 
     String commandName, Object commandObject) { 
    parentCommand.addCommand(commandName, commandObject); 
    return parentCommand.getCommands().get(commandName); 
} 

public static class GeneralOptions { 
    @Parameter(names = "--general-opt") 
    public boolean opt; 
} 

@Parameters 
public static class Command { 
    @Parameter(names = "--opt") 
    public boolean opt; 
} 

@Parameters 
public static class SubCommand1 { 
    @Parameter(names = "--sub-opt1") 
    public boolean opt; 
} 

@Parameters 
public static class SubCommand2 { 
    @Parameter(names = "--sub-opt2") 
    public boolean opt; 
} 

@Parameters 
public static class SubCommand3 { 
    @Parameter(names = "--sub-opt3") 
    public boolean opt; 
} 
} 

संपादित करें: कैसे आदेशों का पुन: उपयोग करने के लिए।

समाधान 1, उपयोग विरासत:

public class CommonArgs{ 
    @Parameter(names="--common-opt") 
    public boolean isCommonOpt; 
    } 

    @Parameters(description = "my command 1") 
    public class MyCommand1 extends CommonArgs{} 

    @Parameters(description = "my command 2") 
    public class MyCommand2 extends CommonArgs{} 

मुझे लगता है कि उपयोग और व्यवहार इस एक के लिए faily स्पष्ट है। एक दोष यह है कि आप केवल एक वर्ग से विस्तार कर सकते हैं, जो भविष्य में पुन: प्रयोज्यता को सीमित कर सकता है।

समाधान 2, रचना पद्धति का उपयोग कर (देखें doc here):

public class CommonArgs{ 
    @Parameter(names="--common-opt") 
    public boolean isCommonOpt; 
    } 

    @Parameters(description = "my command 1") 
    public class MyCommand1{ 
    @ParametersDelegate 
    public CommonArgs commonArgs = new CommonArgs(); 
    } 

    @Parameters(description = "my command 2") 
    public class MyCommand2{ 
    @ParametersDelegate 
    public CommonArgs commonArgs = new CommonArgs(); 
    } 

यहाँ, नेस्टेड commonArgs वर्गों 'मानकों अगर वे आदेश वर्ग के प्रत्यक्ष मापदंडों थे के रूप में माना जाएगा। आप जितनी चाहें उतने प्रतिनिधियों को जोड़ सकते हैं, या यहां तक ​​कि अन्य प्रतिनिधियों के अंदर घोंसला प्रतिनिधि भी शामिल कर सकते हैं। पार्सिंग के बाद प्रतिनिधि विकल्प का मूल्य प्राप्त करने के लिए, बस myCommand1.commonArgs.isCommonOpt, आदि

+0

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

+2

जेकॉमेंडर शायद उप-आदेशों के साथ शीर्ष प्राथमिकता के रूप में डिज़ाइन नहीं किया गया था, यदि आप करेंगे तो यह एक * छुपा * सुविधा है। ऐसे कई असाधारण मामले नहीं हैं, इसलिए आप उन्हें कुछ और सहायक में लपेट सकते हैं। 'उपयोग() 'के रूप में ऐसा लगता है कि उप-आदेशों का कोई आधिकारिक समर्थन नहीं है, इसलिए आपको कुछ हैकिंग करना होगा, या बस इसे लिखना होगा। मैं पुन: उपयोग के बारे में सहमत नहीं हो सकता, हालांकि, पुन: प्रयोज्यता एक चीज है जिसे मैं जेकॉमैंडर के बारे में पसंद करता हूं। यदि आप मुझे एक ठोस उदाहरण देते हैं तो मैं उस पर मदद कर सकता हूं। – rodion

+0

ठीक है। धन्यवाद! तो उदाहरण के लिए मेरे पास 2 कमांड हैं जिनमें अलग-अलग नामकरण और अलग-अलग विवरण हैं लेकिन वे दोनों एक ही पैरामीटर प्राप्त करते हैं। इसलिए विवरण सेट करने के लिए, मेरे पास कमांड क्लास के अलग-अलग उदाहरण होना चाहिए हालांकि कक्षा के अंदर के पैरारेटर समान होंगे। – Sophie

0

मुझे लगता है कि यह बहु-स्तर के आदेशों को कई सीएलआई-टूल्स में विभाजित करना बेहतर होगा।

बजाय:
program cmd sub-cmd sub-sub-cmd -option1 argument -option2 argument

संलग्न एक या दो स्तरों कार्यक्रम के नाम:
program-cmd-sub-cmd sub-sub-cmd -option1 argument -option2 argument

रियल शब्द उदाहरण:
svn-add -q -N foo.c

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

1

picocli मनमाने ढंग से गहराई के लिए नेस्टेड उप-सामग्रियों का समर्थन करता है।

CommandLine commandLine = new CommandLine(new MainCommand()) 
     .addSubcommand("cmd1", new ChildCommand1()) // 1st level 
     .addSubcommand("cmd2", new ChildCommand2()) 
     .addSubcommand("cmd3", new CommandLine(new ChildCommand3()) // 2nd level 
       .addSubcommand("cmd3sub1", new GrandChild3Command1()) 
       .addSubcommand("cmd3sub2", new GrandChild3Command2()) 
       .addSubcommand("cmd3sub3", new CommandLine(new GrandChild3Command3()) // 3rd 
         .addSubcommand("cmd3sub3sub1", new GreatGrandChild3Command3_1()) 
         .addSubcommand("cmd3sub3sub2", new GreatGrandChild3Command3_2()) 
           // etc 
       ) 
     ); 

आप एएनएसआई शैलियों और रंगों के साथ इसकी उपयोग सहायता भी पसंद कर सकते हैं।

ध्यान दें कि उपयोग सहायता विकल्प और स्थितित्मक पैरामीटर के अलावा पंजीकृत उप-सामग्रियों को सूचीबद्ध करती है।

enter image description here

उपयोग मदद आसानी से एनोटेशन के साथ अनुकूलित है।

enter image description here

  • एनोटेशन आधारित
  • Git शैली subcommands
  • नेस्टेड सब-subcommands
  • प्रबलता से टाइप किये विकल्प मापदंडों
  • दृढ़ता से टाइप किया स्थितीय मापदंडों
  • अनुकूलन जैसे रूपांतरण
  • बहु मूल्य विकल्पों
  • कितने तर्क एक क्षेत्र
  • धाराप्रवाह एपीआई
  • POSIX शैली क्लस्टर कम विकल्प
  • जीएनयू शैली लंबी विकल्पों
  • की खपत के लिए सहज ज्ञान युक्त मॉडल में किसी भी विकल्प उपसर्ग
  • एएनएसआई रंग की अनुमति देता है उपयोग सहायता
  • अनुकूलन उपयोग सहायता
  • एकल स्रोत फ़ाइल: अपने एप्लिकेशन को एक एकल जार
  • रखने के लिए स्रोत के रूप में शामिल करें
संबंधित मुद्दे