Help MiniGit: need opinion on syntax

MiniGit is a small Ruby gem to talk with Git command line in a straightforward way. You can write, say, git.commit(:amend => true, :reuse_message => true), and have it do the right thing. No fancy model objects for repos, commits, and branches. No magic. Well, a little bit of magic, just to make it simple and comfortable to use.

One of the quirks is capturing Git’s output. As of now, MiniGit either lets git use the original console, or captures its whole stdout and returns it as a string. Without stripping the trailing newline, or any logic. Simple and straightforward – but pretty uncomfortable: to, say, make sure there are no changes to the work tree, you write git.capturing.diff.strip.empty?. It’s a handful, and don’t get me started on splitting the output into lines.

I want it to be simple. I want to be able to get the output as string – stripped or not, as I prefer at the moment. I want to be able to iterate over the lines, and don’t have the lines include the trailing newline. I want to be able to discard the output, or to display it only when there’s an error. And I don’t want to type too much to achieve that. But I have no good concept of how to write it.

A custom magic method (such as MiniGit#capturing) for each case would clutter the namespace and be hard to maintain. And it would involve a lot of output. The next idea – a custom MiniGit#[] method to get a customized instance – this syntax is reserved for git config integration: git[''] is too pretty and intuitive to waste it on anything else.

Next thing I thought of was overloading unary operators: -git could discard output (like prefixing Make lines), ~git could capture stdout, etc. Two issues here: one is that there’s still a very limited number of these operators. Still, there’s a limited number of things I may want to do with Git’s output, so this may not even be a problem. Second issue is that method call binds closer than any operator: -git.push would mean -(git.push), and I’d need to add extra parentheses to say (-git).push – ugly! Not to mention it would require users to memorize what each of the symbols means.

The idea I’m thinking of right now may be short enough, but it requires a bit of magic, and I’m not sure if it’s nice & convenient magic, or testrocket flashy & useless magic. If I’d need to use parentheses anyway, I may override binary operators to mimic shell redirection syntax. Instead of magic capturing method, one could write:

Each of these expressions would create a new, specialized instance (in most cases cached in the parent instance to avoid allocating too many short lived instances, at cost of sometimes storing a few too many) just the way MiniGit#capturing and #noncapturing. Other modifiers could make it e.g. return a boolean variable to indicate success rather than always raising exception on error and requiring user to rescue when they need to check status.

Update: a more straightforward option would be a method that would be quicker to type, and accept either a known keyword, or any MiniGit subclass; something like this:

Write me what you think

What do you think: nice? uselessly convoluted? confusing? stupid? Or maybe you have any better ideas for that? I’ll happy to hear any input. You can also help by upvoting on Hacker News to get more people here.

Just use the poll here – it’s not directly published as a comment, but sent directly to me. I will update the article to include the results after a few days. If you’d like me to be able to reply, include your e-mail – but it’s not required in any way.


Waiting to hear from you!