rs 0.1 released!
Posted by rue, Sat Oct 14 00:54:00 UTC 2006
The preliminary release of rs is out! You can view the documentation for more information.
Using rs
rs uses Readline which means that you can use the arrow keys to go up and down in history and back and forth in the current line.
Executing Ruby code
You should be able to execute any Ruby code on the line:1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
rs> 5 + 6 => 11 rs> rs> class Foo ..> def bar ..> puts 'Baz' ..> end ..> end => nil rs> Foo.new.bar Baz => nil rs> |
Output and environment control
You can affect the output using $config values of ruby_return, prompt and continuation_prompt. $config (and $env) behave like OpenStructs with the distinction that a method ending with ? returns a boolean and one ending with ! will set the attribute to true.
The prompts are #evaled so you can put arbitrary code in there. Be mindful that a static string has to be enclosed in quotes for it to work properly.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
rs> 1 + 1 => 2 rs> $config.ruby_return = false rs> 1 + 1 rs> $config.ruby_return! => true rs> rs> $config.prompt => "'rs> '" rs> $config.prompt = '"#{Dir.pwd}> "' => '"#{Dir.pwd}> "' /tmp> '/home/me'.to_fso.cd /home/me> '/tmp'.to_fso.cd /tmp> class Foo ..> end /tmp> $config.continuation_prompt = $config.prompt => '"#{Dir.pwd}> "' /tmp> class Foo /tmp> end /tmp> $config.prompt = "'rs> '"; $config.continuation_prompt = "'..> '" |
FileSystemObjects
FSOs give a relatively object-like interface to files and paths and incorporate several File, FileUtils, Dir etc. methods.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
rs> '/tmp'.to_fso.methods.sort => ["/", "<", "<<", "==", "===", "=~", ">", ">>", "__id__", "__send__", "append_to", "args", "basename", "blockdev?", "cat", "cd", "chardev?", "chmod", "chmod_R", "chown", "chown_R", "class", "clone", "compare", "cp", "cp_r", "directory?", "dirname", "display", "dup", "eql?", "equal?", "exec", "executable?", "executable_real?", "exist?", "exists?", "extend", "extname", "file?", "find", "freeze", "frozen?", "ftype", "glob", "grpowned?", "hash", "id", "inspect", "install", "instance_eval", "instance_of?", "instance_variable_get", "instance_variable_set", "instance_variables", "is_a?", "kind_of?", "ln", "ln_s", "ln_sf", "lstat", "method", "methods", "mkdir", "mkdir_p", "mv", "nil?", "object_id", "owned?", "path", "pipe", "pipe?", "private_methods", "protected_methods", "public_methods", "readable?", "readable_real?", "readlink", "relative_path", "respond_to?", "rm", "rm_r", "rm_rf", "rmdir", "run", "send", "setgid?", "setuid?", "singleton_methods", "size", "size?", "socket?", "split", "stat", "sticky?", "symlink", "symlink?", "taint", "tainted?", "to_a", "to_os", "to_s", "touch", "truncate", "type", "umask", "unlink", "untaint", "writable?", "writable_real?", "write_to", "zero?", "|"] rs> |
1 2 3 4 5 6 7 8 9 10 11 12 |
rs> '/tmp'.to_fso.directory? => true rs> '/tmp/quux'.to_fso.exist? => false rs> '/tmp'.to_fso.cd {'./quux'.to_fso.touch} => nil rs> '/tmp/quux'.to_fso.exist? => true rs> '/tmp/quux'.to_fso.rm => ['/tmp/quux'] rs> '/tmp/quux'.to_fso.exist? => false |
Executing programs
FSOs containing executable files may (unsurprisingly) be executed. One thing to know about the processing of FSOs is that currently any filename that does not start with ./, ../, / or ~/ is considered to be ‘unqualified’ and must exist in $PATH. In addition to this, unknown methods at the top-level are first treated as unqualified files (falling back on normal if not found). The UI provides special handling and will automatically run executables. Arguments may also be given.1 2 3 4 5 6 7 8 9 10 11 12 13 |
rs> 'ls'.to_fso.run ... => nil rs> ls ... => nil rs> ls '-la' ... => nil rs> 'ls'.to_fso.args('-l') ... => nil rs> |
Input redirection
More or less arbitrary objects can be ‘redirected’, > indicating overwriting and >> appending. In both cases, the file will be created if it does not exist.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
rs> '/tmp/foo'.to_fso.touch => ["/tmp/foo"] rs> '/tmp/foo'.to_fso.cat => nil rs> '/tmp/foo'.to_fso < "Foo" => 3 rs> '/tmp/foo'.to_fso.cat Foo => nil rs> '/tmp/foo'.to_fso << 45 => 2 rs> '/tmp/foo'.to_fso.cat Foo45 => nil rs> '/tmp/nonexist'.to_fso < '/tmp/foo'.to_fso.read => 5 rs> '/tmp/nonexist'.to_fso.cat Foo45 => nil rs> |
1 2 3 4 5 6 7 8 9 |
rs> '/tmp/nonexist'.to_fso.cat Foo45 => nil rs> 78 >> '/tmp/nonexist'.to_fso => 2 rs> '/tmp/nonexist'.to_fso.cat Foo4578 => nil rs> |
Pipes
Executable programs (and/or static input) can be chained together to an arbitrary degree using ObjectStreams, also known as pipes.
The result of a piping operation can be queried with #result (this is done automatically by the UI if the value of the expression is an OS).
Alternatively, an iterator interface is exposed with #each (an other Enumerable methods).
A few modifications take place on a Ruby object being piped: Arrays are newline-joined, #to_proc objects are #called and everything else is set to its #to_s representation.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
rs> ls | wc
8 8 46
=> nil
rs> (ls | wc).result
=> [" 8 8 46"]
rs> "foo\nbar" | wc('-l')
2
=> nil
rs> "foo\nbar" | wc('-l')
2
=> nil
rs> (ls | tr('a-z A-Z')).each {|f| p f.reverse}
"ELIFEKAR"
"SCRAD_"
"NIB"
"OOB"
"COD"
"BIL"
"BR.PUTES"
"TSET"
=> #<IO:0x65be40>
rs> lambda {"foo\nbar"} | wc
2 2 8
=> nil
rs>
|