Coder Social home page Coder Social logo

Comments (9)

bobthecow avatar bobthecow commented on August 30, 2024

or mycommand.arguments.groups?

from cri.

denisdefreyne avatar denisdefreyne commented on August 30, 2024

I need a decent example of where this would be useful. I remember you mentioning a command similar to add-tags:

add-tags foo.md bar.md clojure scala

The foo.md and bar.md arguments clearly (to a human, at least) are filenames, while clojure and scala are tags. For the add-tags example, would you require users to separate filenames and tags with --?

add-tags foo.md bar.md -- clojure scala

The implementation of add-tags would then check the number of argument groups, and if it is not equal to 2, show an error message. Is that right?

from cri.

bobthecow avatar bobthecow commented on August 30, 2024

Okay, I've got a concrete example :)

Forematter has an "add" command, and it works like this:

forematter add <field> <value> [<value>...] <file> [<file>...]

Note that it accepts multiple values to add, and multiple files. Most of the time it's pretty easy to guess which are values and which are files...

$ forematter add tags bacon sausage ham content/articles/*

Because bacon, sausage and ham aren't files, we can fairly reliably guess the appropriate argument partition. But in some cases, it can be ambiguous. For example:

$ forematter add tags ruby Gemfile content/building-a-ruby-gem.md

In this case, I could be adding the tags ruby and Gemfile to my "building a ruby gem" post, or I could be adding the tag ruby to both my Gemfile and my "building a ruby gem" post. So in this case, the user could disambiguate:

$ forematter add tags ruby -- Gemfile content/building-a-ruby-gem.md

Good prior art for this is found in many of Git's subcommands. Because it has a deeply nested command API similar to this, and uses positional arguments with implied semantic meaning, it too usually guesses the appropriate partition. But it uses -- to disambiguate when there could be two potential interpretations. For example, if I have a file called HEAD in my project it requires me to add a --:

$ git checkout HEAD
# fatal: ambiguous argument 'HEAD': both revision and filename
# Use '--' to separate paths from revisions, like this:
# 'git <command> [<revision>...] -- [<file>...]'

But either of these work, because they're not ambiguous:

$ git checkout HEAD --
$ git checkout -- HEAD

from cri.

denisdefreyne avatar denisdefreyne commented on August 30, 2024

I find argument_groups a bit awkward to work with. Here’s a sample implementation of checkout I came up with:

class SampleGroupsRunner < Cri::CommandRunner

  def run
    if files.empty?
      puts "Checking out all files (revision #{revision})"
    else
      files.each do |file|
        puts "Checking out file #{file} (revision #{revision})"
      end
    end
  end

  private

  def files
    if argument_groups.size == 2
      argument_groups[1]
    else
      arguments.select do |a|
        File.file?(a)
      end
    end
  end

  def revision
    if argument_groups.size == 2
      potential_revisions = argument_groups[0]
    else
      potential_revisions = arguments.select do |a|
        !File.file?(a)
      end
    end

    if potential_revisions.size > 1
      $stderr.puts "Expected 0 or 1 revisions, got #{potential_revisions.size}"
      exit 1
    end

    potential_revisions[0] || 'HEAD'
  end

end

Sample output:

$ be ruby samples/sample_groups.rb HEAD
Checking out all files (revision HEAD)

$ be ruby samples/sample_groups.rb Gemfile
Checking out file Gemfile (revision HEAD)

$ be ruby samples/sample_groups.rb HEAD Gemfile NEWS.md
Checking out file Gemfile (revision HEAD)
Checking out file NEWS.md (revision HEAD)

$ be ruby samples/sample_groups.rb 0f3aa691 Gemfile
Checking out file Gemfile (revision 0f3aa691)

It’s a lot of code, and it doesn’t even detect ambiguous names like HEAD.

from cri.

denisdefreyne avatar denisdefreyne commented on August 30, 2024

Comparison between master and feature/argument-groups

from cri.

denisdefreyne avatar denisdefreyne commented on August 30, 2024

Updated sample to show how to detect ambiguous arguments.

from cri.

bobthecow avatar bobthecow commented on August 30, 2024

And here's Forematter updated to use argument_groups

from cri.

denisdefreyne avatar denisdefreyne commented on August 30, 2024

Nice! Are you satisfied with argument_groups?

from cri.

bobthecow avatar bobthecow commented on August 30, 2024

Yep. Works for me!

from cri.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.