1. seydar
  2. chitin
Issue #4 open

Request/suggestion: easier iterations / stdout processing

Misty De Meo
created an issue

So one of the most basic things you'd do in a shell is iterate over the output of something else, like the output of ls:

for file in $(ls)
do
    echo $file
done

Obviously bash has some gotchas, whitespace splitting is weird, etc. But it works.

So chitin is ruby! Awesome. So I tried this:

ls.each {|f| echo f}

...

ls: each: No such file or directory

Whoops, so that doesn't work. After I peeked at your readme I realized that what I really wanted to do was something like:

ls | split.map {|f| puts f}

or

ls | L {|f| echo f}

or even

Dir['*'].each {|f| puts f}

...at which point I might as well be using irb ;)

I guess my problem is that none of these feel especially shelly. They're surely shorter than the bash option, but somehow they actually feel longer!

One of the things I really expect from ruby is implicit return, which I feel like isn't quite happening yet with chitin. I need to take a step to transform the output from a command into "ruby-mode" and then operate on it, whereas it would feel more natural to me to be able to directly act on the output of a command (either as a string or split on newline/whitespace) without explicitly "piping" it into "ruby-mode".

tl;dr:

I'd like to be able to directly call methods on the output of a command. That output should be treated either as a string or split into an array as contextually appropriate, if at all possible. (Probably Enumerable methods should split into an array, and use a string otherwise.) Likely . for calling methods is too ambiguous, maybe another character is necessary?

Hopefully this is clear and makes some kind of sense, it is almost 1AM and I am tired!

Comments (4)

  1. seydar repo owner

    Good stuff! First, there's map_lines to make things easier. For instance:

    ls | map_lines {|l| l.size }

    which is more what you're looking for. This could be changed to each if you really wanted, but that would be a personal choice and I don't feel comfortable aliasing each_line to each, since it would behave differently than normal strings.

    Second, to do ls.each or ls.map_lines, it would mean giving up true piping since commands would have to be processed on the spot, giving no time for piping (since ruby is a Call-by-value language). It would also mean giving up the ability to do

    hg.stat

    as an equivalent for

    % hg stat

    I think

    ls | map_lines {}

    is more what you're looking for, and it really isn't any more characters than otherwise.

  2. Log in to comment