Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Lazy fun: Make unary minus silence stderr for backticks

Reply
Thread Tools

Lazy fun: Make unary minus silence stderr for backticks

 
 
Sam Stephenson
Guest
Posts: n/a
 
      11-06-2005
I was reading about mentalguy's lazy.rb and thought it'd be fun to use
lazy evaluation as a vehicle for adding new syntactic sugar to Ruby.=20
Here's one such example, which lets you prefix backticks with a unary
minus to silence stderr:

| % irb -r lazy_backtick
| irb(main):001:0> `hello`
| /opt/local/lib/ruby/1.8/irb/workspace.rb:81: command not found: hello
| =3D> ""
| irb(main):002:0> -`hello`
| =3D> ""

lazy_backtick.rb:

| class LazyBacktick < String
| instance_methods.each {|m| undef_method(m) unless m =3D~ /^__/}
|
| def initialize(command)
| @command, @silence_stderr =3D command, false
| end
|
| def -@
| @swallow_stderr =3D true
| value
| end
|
| def method_missing(method, *arguments, &block)
| value.send(method, *arguments, &block)
| end
|
| private
| def value
| @value ||=3D evaluate
| end
|
| def evaluate
| real_backtick "#@command#{' 2>/dev/null' if @silence_stderr}"
| end
| end
|
| module Kernel
| alias_method :real_backtick, :'`'
|
| def `(command)
| LazyBacktick.new(command)
| end
| end

Note that I'm using the same approach as BlankSlate to remove
LazyBacktick's methods, but inheriting from String instead -- this is
so "String =3D=3D=3D `foo`" doesn't break. (It would be nice to have a mixi=
n
alternative to BlankSlate.)

The way I'm silencing stderr is a bit, um, agile. Can it be made to
work in Ruby on Windows without loading an external library (since
open3 doesn't work there)?

Sam


 
Reply With Quote
 
 
 
 
Sam Stephenson
Guest
Posts: n/a
 
      11-06-2005
On 11/6/05, Sam Stephenson <(E-Mail Removed)> wrote:
> | def -@
> | @swallow_stderr =3D true
> | value
> | end


Sorry, make that @silence_stderr.


 
Reply With Quote
 
 
 
 
Sean O'Halpin
Guest
Posts: n/a
 
      11-07-2005
On 11/6/05, Sam Stephenson <(E-Mail Removed)> wrote:
> The way I'm silencing stderr is a bit, um, agile. Can it be made to
> work in Ruby on Windows without loading an external library (since
> open3 doesn't work there)?


On Windows, you could use 2>nul: instead of 2> /dev/null or
win32-open3 (see http://raa.ruby-lang.org/project/win32-open3/)

Regards,

Sean


 
Reply With Quote
 
Sam Stephenson
Guest
Posts: n/a
 
      11-07-2005
On 11/6/05, Sean O'Halpin <(E-Mail Removed)> wrote:
> On 11/6/05, Sam Stephenson <(E-Mail Removed)> wrote:
> > The way I'm silencing stderr is a bit, um, agile. Can it be made to
> > work in Ruby on Windows without loading an external library (since
> > open3 doesn't work there)?

>
> On Windows, you could use 2>nul: instead of 2> /dev/null or
> win32-open3 (see http://raa.ruby-lang.org/project/win32-open3/)


I knew about win32-open3 but not about 2>:nul. Thanks for the tip Sean!

Sam


 
Reply With Quote
 
Sean O'Halpin
Guest
Posts: n/a
 
      11-07-2005
On 11/7/05, Sam Stephenson <(E-Mail Removed)> wrote:
> I knew about win32-open3 but not about 2>:nul. Thanks for the tip Sean!

Be careful where you put the colon! It's 2>nul: not 2>:nul. Win/DOS
has a few pseudo-devices that use the same basic syntax as drive
letters (A:, C such as NUL:, CON: and AUX:

Regards,
Sean


 
Reply With Quote
 
Mauricio Fernández
Guest
Posts: n/a
 
      11-07-2005
On Mon, Nov 07, 2005 at 08:33:35AM +0900, Sam Stephenson wrote:
> The way I'm silencing stderr is a bit, um, agile. Can it be made to
> work in Ruby on Windows without loading an external library (since
> open3 doesn't work there)?


batsman@tux-chan:/tmp$ cat test.rb
require 'rbconfig'
def nostderr
old = STDERR.dup
# unsure about the next line
file = (::Config::CONFIG["arch"] =~ /dos|win32|mingw/) ? "NUL" : "/dev/null"
STDERR.reopen(file)
STDERR.sync = true # you want this so `hello3` still outputs something below...
yield
ensure
STDERR.reopen(old)
end

`hello`
nostderr { `hello2`; $stderr.puts "foo" }
`hello3`
batsman@tux-chan:/tmp$ ruby test.rb
test.rb:2: command not found: hello
test.rb:2: command not found: hello3


--
Mauricio Fernandez


 
Reply With Quote
 
Sam Stephenson
Guest
Posts: n/a
 
      11-07-2005
On 11/6/05, Sean O'Halpin <(E-Mail Removed)> wrote:
> On 11/7/05, Sam Stephenson <(E-Mail Removed)> wrote:
> > I knew about win32-open3 but not about 2>:nul. Thanks for the tip Sean!

> Be careful where you put the colon! It's 2>nul: not 2>:nul. Win/DOS
> has a few pseudo-devices that use the same basic syntax as drive
> letters (A:, C such as NUL:, CON: and AUX:


My mistake. I'm full of typos tonight. Thanks again.

Sam


 
Reply With Quote
 
Sam Stephenson
Guest
Posts: n/a
 
      11-07-2005
On 11/6/05, Mauricio Fern=E1ndez <(E-Mail Removed)> wrote:
> batsman@tux-chan:/tmp$ cat test.rb
> require 'rbconfig'
> def nostderr
> old =3D STDERR.dup
> # unsure about the next line
> file =3D (::Config::CONFIG["arch"] =3D~ /dos|win32|mingw/) ? "NUL" : "/=

dev/null"
> STDERR.reopen(file)
> STDERR.sync =3D true # you want this so `hello3` still outputs somethi=

ng below...
> yield
> ensure
> STDERR.reopen(old)
> end
>
> `hello`
> nostderr { `hello2`; $stderr.puts "foo" }
> `hello3`
> batsman@tux-chan:/tmp$ ruby test.rb
> test.rb:2: command not found: hello
> test.rb:2: command not found: hello3


Interesting, I didn't know that reopening STDERR would affect
subshells. It's more code but I think I prefer this approach.

Sam


 
Reply With Quote
 
Florian Groß
Guest
Posts: n/a
 
      11-07-2005
Sam Stephenson wrote:

> I was reading about mentalguy's lazy.rb and thought it'd be fun to use
> lazy evaluation as a vehicle for adding new syntactic sugar to Ruby.
> Here's one such example, which lets you prefix backticks with a unary
> minus to silence stderr:
>
> | % irb -r lazy_backtick
> | irb(main):001:0> `hello`
> | /opt/local/lib/ruby/1.8/irb/workspace.rb:81: command not found: hello
> | => ""
> | irb(main):002:0> -`hello`
> | => ""


Nice hack, but here's a case that doesn't work and for that I don't have
a fix:

String.new(`echo foo`)

Which returns "" for me.

I guess you are better off not inheriting from String and letting the
String === test fail. Nowadays it's all about duck typing, anyway.



 
Reply With Quote
 
Caleb Clausen
Guest
Posts: n/a
 
      11-07-2005
On 11/6/05, Sam Stephenson <(E-Mail Removed)> wrote:
> (It would be nice to have a mixin alternative to BlankSlate.)


I hacked up a BlankSlate module for my own purposes. (This version doesn't
permenently remove any methods, just renames them to something.... unusual.=
)

Here it is:

module BlankSlate;
module ClassMethods
def restore(*names)
names.each{|name| alias_method name, "##{name}"}
end
def hide(*names)
names.each do|name|
undef_method name if instance_methods.include?(name.to_s)
end
end
end

def BlankSlate.included(othermod)
othermod.instance_eval {
instance_methods.each { |m|
alias_method "##{m}", m #archive m
undef_method m unless m =3D~ /^__/ || m=3D=3D'instance_eval'
}
extend BlankSlate::ClassMethods
}
end
end


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
unary minus strangeness sreservoir Perl Misc 7 03-31-2010 11:01 PM
What is happening with this Unary minus? Todd Burch Ruby 3 08-27-2007 09:22 PM
Overloading unary minus for use in function calls Matthew Cook C++ 6 12-20-2006 10:04 PM
Semantics of unary minus Marc C Programming 13 02-13-2006 04:52 PM
Unary minus applied to unsigned int Andrew Ward C++ 6 09-26-2003 03:19 PM



Advertisments