2016-10-08 4 views
5

이름이 지정된 프로그램 옵션 (예 : --files)을 허용하지 않는 위치 지정 목록 프로그램 옵션을 boost_program_options으로 만들고 싶습니다.boost :: program_options의 위치 옵션에 설명을 추가하는 방법은 무엇입니까?

I가 다음 코드 조각 다음과 같이 내가 파일을 위치 인수 목록으로 목록을 읽을 수

#include <boost/program_options.hpp> 
#include <iostream> 
#include <string> 
#include <vector> 

namespace po = boost::program_options; 

int main(int argc, const char* argv[]) { 
    po::options_description desc("Allowed options"); 
    desc.add_options()("help", "produce help message") 
    ("files", po::value<std::vector<std::string>>()->required(), "list of files"); 

    po::positional_options_description pos; 
    pos.add("files", -1); 

    po::variables_map vm; 
    try { 
    po::store(po::command_line_parser(argc, argv).options(desc).positional(pos).run(), vm); 
    po::notify(vm); 
    } catch(const po::error& e) { 
    std::cerr << "Couldn't parse command line arguments properly:\n"; 
    std::cerr << e.what() << '\n' << '\n'; 
    std::cerr << desc << '\n'; 
    return 1; 
    } 

    if(vm.count("help") || !vm.count("files")) { 
    std::cout << desc << "\n"; 
    return 1; 
    } 
} 

문제는 다음과 같습니다 불행하게도이 같은뿐만 아니라

./a.out file1 file2 file3 

을하지만 (이 해제하고 싶습니다.)

./a.out --files file1 file2 file3 

문제는 도움이되는 것입니다. 신분증 :

./a.out 
Couldn't parse command line arguments properly: 
the option '--files' is required but missing 

Allowed options: 
    --help    produce help message 
    --files arg   list of files 

그래서 내 원하는 시나리오는 이상 (유사한 OS)와 같은 것 :

./a.out 
Couldn't parse command line arguments properly: 
[FILES ...] is required but missing 

Allowed options: 
    --help    produce help message 
    --optionx    some random option used in future 
    [FILE ...]   list of files 

I 작동이 중지 desc.add_option()(...)에서 files 옵션을 제거한 후에는 그래서 내가 거기에 필요 믿습니다.

+0

왜 명명 된 매개 변수로 입력 파일을 지정하는 기능을 제거해야합니까? 그것은 무엇이든 해가되지 않으므로 왜 그걸 사용하지 못하게합니까? –

+0

@ DanMašek 이것은 사용자에게 분명하지 않습니다. 두 입력 모두 유효한 입력 전략이 될 수 있기 때문입니다. (특별히 하나만 원하면 도움을받을 수 있습니다.) – Patryk

+0

OK. 저에게 가장 침략적이지 않은 해결책이 있습니다. 인수 옵션 목록 전체에 위치 옵션이 계속 흩어져 있지만 더 쉽게 유효성 검사를 추가하여 제한 할 수 있습니다. –

답변

5

"boost :: program_options의 위치 옵션에 설명을 추가하는 방법"이라는 제목의 질문에 대해서는 no functionality이 라이브러리에 제공됩니다. 그 부분을 스스로 처리해야합니다.

질문의 몸은 ... 가능하지만 약간 둥근 방식입니다.

위치 옵션은 각 위치를 이름으로 매핑하고 이름이 존재해야합니다. 코드 (cmdline.cpp)에서 알 수 있듯이 unregistered 플래그는 위치 지정 인수에 설정되지 않습니다. [1], [2]

그래서, 당신이하고 싶은 일을하기 위해, 우리는 다음과 같은 작업을 수행 할 수

  • 는 도움에 표시에서 --files 옵션을 숨 깁니다. 위치 옵션에 대한 적절한 도움말을 표시해야하지만 이전과 다를 바 없습니다.
  • 구문 분석 된 옵션을 구문 분석하고 variables_map에 저장하는 사이에 자체 검증을 추가하십시오.

다음

우리는 우리가 add(...) 멤버 함수를 사용하여 복합 options_description을 만들 수 있다는 사실을 활용 도움에서 --files 숨기기 :

po::options_description desc_1; 
// ... 
po::options_description desc_2; 
// ... 
po::options_description desc_composite; 
desc_composite.add(desc_1).add(desc_2); 

우리는 따라서에 우리 files 옵션을 배치 할 수 있습니다 options_description을 숨기고 파싱 단계에서만 사용할 합성을 만듭니다. 우리는 구문 분석과 variables_map로 저장 사이의 옵션 목록을 차단해야 할

명시 적 --files

방지 (아래 코드 참조).

command_line_parserrun()있어서 그 부재 optionsbasic_option s의 벡터를 보유 basic_parsed_options의 인스턴스를 리턴한다. 구문 분석 된 각 인수에 대한 요소가 있으며 위치 옵션은 0부터 시작하며 위치 지정되지 않은 옵션은 위치가 -1입니다. 명시 적 (위치가 지정되지 않은) 인수로 --files이 표시되면이 방법을 사용하여 자체 유효성 검사를 수행하고 오류를 발생시킬 수 있습니다.

예제 소스 코드

See on Coliru

#include <boost/program_options.hpp> 
#include <iostream> 
#include <string> 
#include <vector> 

namespace po = boost::program_options; 

int main(int argc, const char* argv[]) 
{ 
    std::vector<std::string> file_names; 

    po::options_description desc("Allowed options"); 
    desc.add_options() 
     ("help", "produce help message") 
     ("test", "test option"); 

    std::string const FILES_KEY("files"); 

    // Hide the `files` options in a separate description 
    po::options_description desc_hidden("Hidden options"); 
    desc_hidden.add_options() 
     (FILES_KEY.c_str(), po::value(&file_names)->required(), "list of files"); 

    // This description is used for parsing and validation 
    po::options_description cmdline_options; 
    cmdline_options.add(desc).add(desc_hidden); 

    // And this one to display help 
    po::options_description visible_options; 
    visible_options.add(desc); 

    po::positional_options_description pos; 
    pos.add(FILES_KEY.c_str(), -1); 

    po::variables_map vm; 
    try { 
     // Only parse the options, so we can catch the explicit `--files` 
     auto parsed = po::command_line_parser(argc, argv) 
      .options(cmdline_options) 
      .positional(pos) 
      .run(); 

     // Make sure there were no non-positional `files` options 
     for (auto const& opt : parsed.options) { 
      if ((opt.position_key == -1) && (opt.string_key == FILES_KEY)) { 
       throw po::unknown_option(FILES_KEY); 
      } 
     } 

     po::store(parsed, vm); 
     po::notify(vm); 
    } catch(const po::error& e) { 
     std::cerr << "Couldn't parse command line arguments properly:\n"; 
     std::cerr << e.what() << '\n' << '\n'; 
     std::cerr << visible_options << '\n'; 
     return 1; 
    } 

    if (vm.count("help") || !vm.count("files")) { 
     std::cout << desc << "\n"; 
     return 1; 
    } 

    if (!file_names.empty()) { 
     std::cout << "Files: \n"; 
     for (auto const& file_name : file_names) { 
      std::cout << " * " << file_name << "\n"; 
     } 
    } 
} 

테스트 출력

유효한 옵션 :

>example a b c --test d e 
Files: 
* a 
* b 
* c 
* d 
* e 

잘못된 옵션 :

,132 10