From: Eero Saynatkari Date: 2006-10-13T13:26:27+09:00 Subject: Re: [ANN] rs 0.1 --vkEkAx9hr54EJ73W Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On 2006.10.12 12:38, Eero Saynatkari wrote: > rs is a project to implement a non-traditional object-oriented shell in R= uby. And of course I forget to enter the most important part. Examples! =3D Examples Using rs. =3D=3D General notes 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. =3D=3D Executing Ruby code You should be able to execute any Ruby code on the line: rs> 5 + 6 =3D> 11 rs> rs> class Foo ..> def bar ..> puts 'Baz' ..> end ..> end =3D> nil rs> Foo.new.bar Baz =3D> nil rs> =20 =3D=3D 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. rs> 1 + 1 =3D> 2 rs> $config.ruby_return =3D false rs> 1 + 1 rs> $config.ruby_return! =3D> true rs>=20 rs> $config.prompt =3D> "'rs> '" rs> $config.prompt =3D '"#{Dir.pwd}> "' =3D> '"#{Dir.pwd}> "' /tmp> class Foo ..> end /tmp> $config.continuation_prompt =3D $config.prompt =3D> '"#{Dir.pwd}> "' /tmp> class Foo /tmp> end /tmp> $config.prompt =3D "'rs> '"; $config.continuation_prompt =3D "'..> = '" =3D=3D FileSystemObjects FSOs give a relatively object-like interface to files and paths and incorporate several File, FileUtils, Dir etc. methods. rs> '/tmp'.to_fso.methods.sort =3D> ["/", "<", "<<", "=3D=3D", "=3D=3D=3D", "=3D~", ">", ">>", "__id__",= "__send__",=20 "append_to", "args", "basename", "blockdev?", "cat", "cd", "chardev?",= =20 "chmod", "chmod_R", "chown", "chown_R", "class", "clone", "compare",=20 "cp", "cp_r", "directory?", "dirname", "display", "dup", "eql?", "equal= ?",=20 "exec", "executable?", "executable_real?", "exist?", "exists?", "extend= ",=20 "extname", "file?", "find", "freeze", "frozen?", "ftype", "glob", "grpo= wned?",=20 "hash", "id", "inspect", "install", "instance_eval", "instance_of?",=20 "instance_variable_get", "instance_variable_set", "instance_variables",= =20 "is_a?", "kind_of?", "ln", "ln_s", "ln_sf", "lstat", "method", "methods= ",=20 "mkdir", "mkdir_p", "mv", "nil?", "object_id", "owned?", "path", "pipe"= ,=20 "pipe?", "private_methods", "protected_methods", "public_methods", "rea= dable?",=20 "readable_real?", "readlink", "relative_path", "respond_to?", "rm", "rm= _r",=20 "rm_rf", "rmdir", "run", "send", "setgid?", "setuid?", "singleton_metho= ds",=20 "size", "size?", "socket?", "split", "stat", "sticky?", "symlink", "sym= link?", "taint", "tainted?", "to_a", "to_os", "to_s", "touch", "truncate", "typ= e",=20 "umask", "unlink", "untaint", "writable?", "writable_real?", "write_to"= , "zero?", "|"] rs>=20 Generally, these methods behave exactly as their Ruby counterparts with the= path of the FSO given as the file to operate on. For example: rs> '/tmp'.to_fso.directory? =3D> true rs> '/tmp/quux'.to_fso.exist? =3D> false rs> '/tmp'.to_fso.cd {'./quux'.to_fso.touch} =3D> nil rs> '/tmp/quux'.to_fso.exist? =3D> true rs> '/tmp/quux'.to_fso.rm =3D> ['/tmp/quux'] rs> '/tmp/quux'.to_fso.exist? =3D> false You could of course put the FSO in a variable to avoid the repetition--also= , if you feel like metaprogramming a bit, you could put a String#method_missing = in your ~/.rsrc so that you can skip the #to_fso (which will eventually go away, of= course). =3D=3D Executing programs FSOs containing executable files may (unsurprisingly) be executed. One thin= g 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 exis= t in $PATH. In addition to this, unknown methods at the top-level are first trea= ted as unqualified files (falling back on normal if not found). The UI provides= =20 special handling and will automatically run executables. Arguments may also= be given. rs> 'ls'.to_fso.run ... =3D> nil rs> ls ... =3D> nil rs> ls '-la' ... =3D> nil rs> 'ls'.to_fso.args('-l') ... =3D> nil rs> =3D=3D 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 ex= ist. rs> '/tmp/foo'.to_fso.touch =3D> ["/tmp/foo"] rs> '/tmp/foo'.to_fso.cat =20 =3D> nil rs> '/tmp/foo'.to_fso < "Foo" =3D> 3 rs> '/tmp/foo'.to_fso.cat Foo =3D> nil rs> '/tmp/foo'.to_fso << 45 =20 =3D> 2 rs> '/tmp/foo'.to_fso.cat Foo45 =3D> nil rs> '/tmp/nonexist'.to_fso < '/tmp/foo'.to_fso.read =3D> 5 rs> '/tmp/nonexist'.to_fso.cat =20 Foo45 =3D> nil rs> The opposite should also work: rs> '/tmp/nonexist'.to_fso.cat =20 Foo45 =3D> nil rs> 78 >> '/tmp/nonexist'.to_fso =3D> 2 rs> '/tmp/nonexist'.to_fso.cat Foo4578 =3D> nil rs> There are a few exceptions. If the 'input' is an Array, it is recursively joined with newlines. If the input is an executable FSO, it will be run=20 and the result written as a String. Thirdly, if the file TO which the input is going is executable, it is converted to an ObjectStream instead. This brings us to our next topic. =3D=3D 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. rs> ls | wc 8 8 46 =3D> nil rs> (ls | wc).result =3D> [" 8 8 46"] rs> "foo\nbar" | wc('-l') 2 =3D> nil rs> "foo\nbar" | wc('-l') 2 =3D> nil rs> (ls | tr('a-z A-Z')).each {|f| p f.reverse} "ELIFEKAR" "SCRAD_" "NIB" "OOB" "COD" "BIL" "BR.PUTES" "TSET" =3D> # rs> lambda {"foo\nbar"} | wc 2 2 8 =3D> nil rs>=20 --vkEkAx9hr54EJ73W Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (FreeBSD) iD8DBQFFLxTi7Nh7RM4TrhIRAhnXAKDj4P4emWjLOrh3j43iLlz6+7GSGgCgtZ7p 2l/sjM0JZ+YoLzum3JneNTQ= =ymUB -----END PGP SIGNATURE----- --vkEkAx9hr54EJ73W--