Трета задача

  1. Не е голяма работа, но Този клас трябва да има методи #argument, #option и #option_with_argument, докато примерите и тестовете говорят за option_with_parameter.

    Имам и въпрос: Какви символи са позволени за имена на опции?

    EDIT: В единия пример за help-a има следния формат: parser.help #=> 'Usage: rspec [FIRST] [SECOND]', а малко по-надолу срещаме: 'Usage: rspec [SPEC FILE]. Кое да ползваме?

  2. В този пример

    parser = CommandParser.new('rspec')
    
    parser.option('v', 'version', 'show version number') do |runner, value|
      runner[:version] = value
    end
    
    command_runner = {}
    parser.parse(command_runner, ['--version'])
    
    command_runner #=> {version: true}

    Ако няма зададена такава опция, да връщаме ли само {} или

    command_runner #=> {version: false}
  3. @Михаил, #option_with_parameter е метода, който искаме за задачата.

    Късите имена на опциите ще са само една буква, докато дългите имена могат да имат произволна дължина, като няма да съдържат whitespace символи.

    За #help виж примера пак. В първия пример имаме 2 аргумента 'FIRST' и 'SECOND', във втория само един - 'SPEC FILE'.

  4. Имам въпрос как да форматирам крайния стринг на #help , по-точно как се слагат новите редове, тъй като ако сложа \n, като върна стринга стринга съдържа самия символ \n и тестовете не го отчитат като "properly formatted string "

  5. да направих всичко в Google , включително и изпозлвах "" вместо '' , но \n продължава да се връща като поредица от символи а не се интерпретира :(

    п.С. Всичко си е било наред аз не съм догледал нещо, съжалявам.

  6. Здравейте, в условието има следната забележка

    Забележка: За по-просто, няма да тестваме с различен брой позиционни аргументи в argv от броя на дефинираните в нашия парсер. За сметка на това, може да има опции (нещата, започващи с тире), които да направят argv с различна дължина от броя на извикванията на argument.
    

    Това означава ли, че случаи като по-долният ще бъдат изключени от тестовете?

    parser = CommandParser.new('rspec')
    
    parser.argument('FIRST') do |runner, value|
      runner[:first] = value
    end
    
    parser.argument('SECOND') do |runner, value|
      runner[:second] = value
    end
    
    command_runner = {}
    
    parser.parse(command_runner, ['foo', 'larodi'])
    
    command_runner #=> {first: 'foo', second: 'larodi'}
    
    parser.parse(command_runner, ['test'])
    

    Ако не съм разбрал правилно забележката, то тогава горният пример дали трябва да върне резултат {first: 'foo', second: 'larodi', third: 'test'} или резултатът трябва да е {first: 'test', second: 'larodi'} ?

  7. @Иван, никъде в кода няма :third. Откъде смяташ, че ще се появи? :)

    Забележката казва, че няма да подаваме parser.parse(command_runner, ['test']) ако сме извикали #argument два пъти. Тоест, няма да правим това в примера ти.

  8. Георги, благодаря за бързия отговор и се извинявам за предния пост, имам пропуск във кода.. Хем го редактирах този пост няколко пъти :D имах предвид

    
    parser = CommandParser.new('rspec')
    
    parser.argument('FIRST') do |runner, value|
      runner[:first] = value
    end
    
    parser.argument('SECOND') do |runner, value|
      runner[:second] = value
    end
    
    parser.argument('THIRD') do |runner, value|
      runner[:third] = value
    end
    
    command_runner = {}
    
    parser.parse(command_runner, ['foo', 'larodi'])
    
    command_runner #=> {first: 'foo', second: 'larodi'}
    
    parser.parse(command_runner, ['test'])
    

    Извинявам се за неразбирането. Тоест дали може да има случаи на незапълнени аргументи и дали ако #parse бъде извикан втори път ще пълни тези аргументи, които все още нямат стойност или първият, който има стойност? Това не ми е напълно ясно, и такива примери ли няма да има? Благодаря и съжалявам за няколкото поста

  9. @Иван

    Забележка: За по-просто, няма да тестваме с различен брой позиционни аргументи в argv от броя на дефинираните в нашия парсер. За сметка на това, може да има опции (нещата, започващи с тире), които да направят argv с различна дължина от броя на извикванията на argument. Тоест броя на позиционните аргументи в argv ще е равен на броя на тези, които сме дефинирали.(В твоя случай 3)

  10. @Иван каквото @Петко каза. Няма да тестваме с повече или по-малко позиционни аргументи от тези, които са дефинирани за парсъра. Също така повторното извикване не трябва да прави нищо специално. Имайте предвид, че на всяко извикване на #parse command_runner-а, които му се подава може да е различен.

  11. Благодаря за отговорите, това е хубава новина! Съжалявам, за следващия въпрос, но за да съм 100% сигурен все пак ще го задам.

    Възможно ли е #argument и #option_with_parameter да са дефинирани със един и същи параметър? Например следния случай:

    
         parser.argument('FILE') do |runner, value|
            runner[:file] = value
          end
    
          parser.option_with_parameter('r', 'require', 'require FILE in spec', 'FILE') do |runner, value|
            runner[:file] = value
          end
    

    Благодаря.

  12. @Марио, благодаря за бързият отговор. Значи в такъв случай, документацията ще включи 'FILE' като

     Usage: rspec
        -r, --require=FILE require FILE in spec
    

    а не като

     Usage: rspec [FILE]
        -r, --require=FILE require FILE in spec
    

    (в случая parser = CommandParser.new('rspec') )?

  13.   parser = CommandParser.new('rspec')
    
      parser.argument('FILE') do |runner, value|
        runner[:file] = value
      end
    
      parser.option_with_parameter('r', 'require', 'require FILE in spec', 'FILE') do |runner, value|
        runner[:file] = value
      end
    

    Ще ти върне това:

    Usage: rspec [FILE]
        -r, --require=FILE require FILE in spec
    

    И това, че имат еднакви имена няма никакво значение. Тези имена не са идентификатори под никаква форма.

  14. parser.option('v', 'version', 'show version number') do |runner, value|
      runner[:version] = value
    end
    

    Опциите винаги ли се задават по този начин, или е възможно първите 2 аргумента да са в разменен ред parser.option('version', 'v', 'show version number')

  15. Възможно ли е да имаме option и option_with_parameter с еднакво име (кратък или дълъг вариант)? Тоест ако направим следното:

    parser = CommandParser.new('rspec')
    parser.option('v', 'version', 'show version number') do |runner, value|
      runner[:version] = value
    end
    parser.option_with_parameter('v', 'version', 'do something else with version') do |runner, value|
      #something else
    end
    

    Трябва ли да се очаква parser.parse(runner, ['--version']) и parser.parse(runner, ['--version=larodi']) да работят по различен начин?

  16. Конструкцията на нашата команда всъщност от кое се задава, от методите #argument, #option и #option_with_parameter или #parse взема стойности от argv масива и ги подава като value на блоковете в трите метода; parse чете вече подадени аргументи и опции или ги генерира? Може би по-глобално въпросът ми е свързан с това как се генерира цялостната команда, защото по начало тя има само име и какво е точно взаимодействието между parse и другите методи. И последен, може би малко глупав въпрос, но каква е семантиката на блока { |_, _| } , подаван в тестовете?

  17. @Дарин, според мен, метода #parse просто се грижи за това да разбере дали нещата от масива са аргумент/опция или опция с аргмумент. Другите методи служат за генериране на документацията и изпълняване на блоковете, за да се пълни обекта command_runner. Що се отнася до семантиката на блока { |_, _| }, в тестовете го подават защото се очаква блок, а аргументите на блока (_,_) са просто placeholder-и, т.е. няма да се използват.

  18. 
    parser = CommandParser.new('rspec')
    
    parser.argument('FILE') do |runner, value|
      runner[:file] = value
    end
    
    parser.argument('FILE') do |runner, value|
      runner[:file2] = value
    end
    
    command_runner = {}
    
    parser.parse(command_runner, ['spec.rb'])
    parser.parse(command_runner, ['spec2.rb'])
    

    command_runner # => ?

    и

    
    parser = CommandParser.new('rspec')
    
    parser.argument('FILE') do |runner, value|
      runner[:file] = value
    end
    
    parser.argument('FILE2') do |runner, value|
      runner[:file2] = value
    end
    
    command_runner = {}
    
    parser.parse(command_runner, ['spec.rb'])
    parser.parse(command_runner, ['spec2.rb'])
    

    command_runner # => ?

  19. @Христо имената на аргументите имат значение само за генериране на документацията от #help. И 2та ти примера са невалидни защото викаш #parse с argv аргумент само с по един елемент докато си направил 2 #argument извиквания. Тези случей са невалидни. argv винаги ще има точно толкова аргумента в себе си колкото и са извикванията на #argument преди това.

Трябва да сте влезли в системата, за да може да отговаряте на теми.