Anonymous methods, blocks etc. (Cont. 'default block params')

E

Eric Mahurin

--- Austin Ziegler said:
=20
Doubtful. I think to convince matz, real examples would need
to be
presented (as an RCR!) as to why this is necessary. IANM, but
IMO
theoretical need and wish ain't sufficient.

With 1.9 being able to specify local variables in the argument
list and if matz does something about closures holding all
variables in the scope, I doubt you'll find the "need". If
there are too many issues (i.e. compatibility problems) with
having closures not hold all variables in the scope, I think
having a non-closure block that didn't have that baggage
(excess memory usage) would be compelling. In the majority of
cases I use blocks, I don't need them to be closures.




=09
=09
__________________________________=20
Yahoo! Mail - PC Magazine Editors' Choice 2005=20
http://mail.yahoo.com
 
S

Sean O'Halpin

Doubtful. I think to convince matz, real examples would need to be
presented (as an RCR!) as to why this is necessary. IANM, but IMO
theoretical need and wish ain't sufficient.

-austin
Hi,

I ~was~ being ironic (hence the ;)
Doubtful. I think to convince matz, real examples would need to be
presented (as an RCR!) as to why this is necessary.

Good point. I don't think it would be hard to get examples.
IANM, but IMO
theoretical need and wish ain't sufficient.

This is no theoretical need - see the recent thread on Rails developer
mode reloading woes for a real world example of how badly managed
closures can cripple an application. Also, it would be interesting to
cook up an implementation to see if there is a performance gain (not
the primary motivation however). The problem would be in getting a
decent syntax!

I understand your point however - it's all too easy to just think up
something you think you might like to have without any real need.

Regards,

Sean
 
A

Austin Ziegler

Austin said:
Doubtful. I think to convince matz, real examples would need to be
presented (as an RCR!) as to why this is necessary. IANM, but IMO
theoretical need and wish ain't sufficient.
The easist is the old gotcha. Programmer has code (doesn't much matter
what it is)
[...]

And wants to resue the lambda so uses old fashion copy and paste:

class Y
def bar( n )
x =3D n * 3
l =3D lambda { |a| x =3D a**2; x + 1 }
return x + l[3]
end
end

Oopsy.

Dumb programmer. This part isn't nearly sufficient to justify a new
scope or kind of lambda (lambda without closure), IMO. If you want to
reuse a lambda that you're not passing around, make it a method.
For something a little more concrete:
[...]

Now try:

class X
def x;1;end
end
=3D> nil

Y =3D Class.new(X) do
X =3D Class.new do
def x;2;end
end
def x;3;end
end
(irb):5: warning: already initialized constant X
=3D> Y

X.new.x
=3D> 2
Y.new.x
=3D> 3
Y::X.new.x
(irb):12: warning: toplevel constant X referenced by Y::X
=3D> 2

This isn't a closure problem. This is a constant lookup problem, and
Matz has said that this should be fixed moving forward.

As I said, I'm very skeptical.

-austin
 
A

Austin Ziegler

With 1.9 being able to specify local variables in the argument list
and if matz does something about closures holding all variables in the
scope, I doubt you'll find the "need". If there are too many issues
(i.e. compatibility problems) with having closures not hold all
variables in the scope, I think having a non-closure block that didn't
have that baggage (excess memory usage) would be compelling. In the
majority of cases I use blocks, I don't need them to be closures.

As I said earlier, though, most of the blocks (I'd say 60%) that I use
are closures. Some of these are because I need a value to come out of
the block, but I still use them as closures.

-austin
 
A

Austin Ziegler

I ~was~ being ironic (hence the ;)

I know. I still think it was worth a response.
Good point. I don't think it would be hard to get examples.

Hmm. I think it will. But I encourage you and those interested in this
to write an RCR for it. Who knows? It might be accepted. It probably
won't be anything that affects me.
This is no theoretical need - see the recent thread on Rails developer
mode reloading woes for a real world example of how badly managed
closures can cripple an application. Also, it would be interesting to
cook up an implementation to see if there is a performance gain (not
the primary motivation however). The problem would be in getting a
decent syntax!

Hm. Is that necessarily a closure issue or an abuse of a particular
feature in search of something else? I'm not going to pretend that I
really understand the problem they were having, so ... it might be
something that can be solved in other ways in Ruby 1.9.
I understand your point however - it's all too easy to just think up
something you think you might like to have without any real need.

I'm glad you do.

-austin
 
T

Trans

Austin said:
Austin said:
But, I kind of still wish we had a syntax where the variables in a
block/lambda were local (non-closure) by default.
Maybe if we say it often enough? ;)
Doubtful. I think to convince matz, real examples would need to be
presented (as an RCR!) as to why this is necessary. IANM, but IMO
theoretical need and wish ain't sufficient.
The easist is the old gotcha. Programmer has code (doesn't much matter
what it is)
[...]

And wants to resue the lambda so uses old fashion copy and paste:

class Y
def bar( n )
x = n * 3
l = lambda { |a| x = a**2; x + 1 }
return x + l[3]
end
end

Oopsy.

Dumb programmer. This part isn't nearly sufficient to justify a new
scope or kind of lambda (lambda without closure), IMO. If you want to
reuse a lambda that you're not passing around, make it a method.

Dumb example. But I wasn't foging for "gold". Surely you can
extrapolate beyond this. Take a class context for instance, used to
define a few methods on a template. Class methods could interfere, etc.

[...]
This isn't a closure problem. This is a constant lookup problem, and
Matz has said that this should be fixed moving forward.

It has to do with closures in that the reference to constants is
relative to the given closure. So the current behavior is correct. A
non-closure block will allow the needed alternate behavior.

T.
 
A

Austin Ziegler

Austin said:
The easist is the old gotcha. Programmer has code (doesn't much
matter what it is) [...]
And wants to resue the lambda so uses old fashion copy and paste:

class Y
def bar( n )
x =3D n * 3
l =3D lambda { |a| x =3D a**2; x + 1 }
return x + l[3]
end
end

Oopsy.
Dumb programmer. This part isn't nearly sufficient to justify a new
scope or kind of lambda (lambda without closure), IMO. If you want to
reuse a lambda that you're not passing around, make it a method.
Dumb example. But I wasn't foging for "gold". Surely you can
extrapolate beyond this. Take a class context for instance, used to
define a few methods on a template. Class methods could interfere,
etc.

I'm not wanting to extrapolate. Consider me the conservative here,
Trans. Convince me that this is really useful and important.
[...]
This isn't a closure problem. This is a constant lookup problem, and
Matz has said that this should be fixed moving forward.
It has to do with closures in that the reference to constants is
relative to the given closure. So the current behavior is correct. A
non-closure block will allow the needed alternate behavior.

Not by my understanding. Constant lookup is handled separately from
closure rules, which mostly deals with local variables. That is to say
that:

class X; end
Y =3D Class.new(X) do
X =3D Class.new do
=09end
end

is and should be different than:

class X; end

x =3D X
p x # X

Y =3D Class.new(X) do
x =3D Class.new do
=09end
=09const_set("X", x)
end

p x # Y::X

Closure rules don't ahve anything to do with constant lookup, at least
at this point.

-austin
 
T

Trans

Austin said:
I'm not wanting to extrapolate. Consider me the conservative here,
Trans. Convince me that this is really useful and important.

It's all relative Austin. How *really useful and important* is
anything? Most things can be done in some other way. But this much is
certain, there are things you CAN'T do b/c of this --or at least not
wihtout jumping through some magical hoops like defining a method
grabing the UnboundMethod, converting to_proc and undefining the method
(which I have done). But as to the example I was trying to show here...
here's something a little bit more real-to-life, though still off the
top of my head.

dir = File.dirname(__FILE__)

m = module.new do

make_dir_method = lambda { |which, path|
class_eval {
define_method( "#{which}dir" ) { |name|
dir = File.dirname(path)
name = File.basename(path)
File.join(dir,which,name)
}
}
}

make_dir_method('lib',dir)
make_dir_method('var',dir)
make_dir_method('bin',dir)

end

Not by my understanding. Constant lookup is handled separately from
closure rules, which mostly deals with local variables. That is to say
that:

class X; end
Y = Class.new(X) do
X = Class.new do
end
end

is and should be different than:

class X; end

x = X
p x # X

Y = Class.new(X) do
x = Class.new do
end
const_set("X", x)
end

p x # Y::X

Closure rules don't ahve anything to do with constant lookup, at least
at this point.
^^^^^^^^^^^^^

Doesn't it seem just a little odd that this causes an error?

class X
Y = 1
end

X.class_eval { Y }

I know, I know. It makes total sense with how Ruby works. Not so sure
how Ruby works makes total sense. Honestly, how can closure NOT be of
significant to constant lookup?

T.
 
A

Austin Ziegler

It's all relative Austin. How *really useful and important* is
anything?

Don't try that game with me, Trans. You can't play it that well. You're
wanting a new feature that I don't think makes any sense at all. Matz,
so far, has said things publicly that seem to indicate that he's
unconvinced of the need for this as well (or at least doesn't plan on
making it happen). What I'm really trying to get you to do is to write
an RCR stronger than that which you wrote for AOP for this. If you
convince Matz that we need this, then more power to you.

You don't have to convince me first, either. But so far, all I've heard
are what amount to "I don't get constant scoping" (and Matz has said
this is going to be fixed) and "cut and paste dumb programmer" issues.
If that's the best you can offer, I doubt you'll be able to convince
Matz of the need for it, either. We're getting a little more to the
heart of the possibilities now, I think.
Most things can be done in some other way. But this much is certain,
there are things you CAN'T do b/c of this -- or at least not wihtout
jumping through some magical hoops like defining a method grabing the
UnboundMethod, converting to_proc and undefining the method (which I
have done).

Why? What *need* do you have to grab an UnboundMethod, convert it to a
proc, and then undefine the method? In the three and a half years that
I've been working with Ruby, I haven't needed a UnboundMethod once, much
less needing to do what you've described here. And, I'd argue, if what
you're doing is bizarre/dangerous enough, then maybe you *need* to be
going through those hoops in order to make it so that such functionality
is unlikely to be abused.
But as to the example I was trying to show here... here's something a
little bit more real-to-life, though still off the top of my head.

dir =3D File.dirname(__FILE__)

m =3D Module.new do
make_dir_method =3D lambda { |which, path|
class_eval {
define_method( "#{which}dir" ) { |name|
dir =3D File.dirname(path)
name =3D File.basename(path)
File.join(dir,which,name)
}
}
}

make_dir_method.call('lib',dir)
make_dir_method.call('var',dir)
make_dir_method.call('bin',dir)
end

So ... you're trying to essentially do:

m =3D Module.new
class << m
def libdir(name)
dir =3D File.dirname(File.dirname(__FILE__))
name =3D File.basename(name)
File.join(dir, 'lib', name)
end
end

Yes, I know I did manually what you're trying to do automatically, but
I'm trying to understand here. I'm sure with a bit more thought, I could
come up with something cleaner to do this -- although I'm not really
understanding *why* you want to do this, in any case. FWIW, in 1.8.2 I
didn't get a compile error except from the fact that your code used the
1.9 deprecated () on lambdas.
^^^^^^^^^^^^^

Doesn't it seem just a little odd that this causes an error?

class X
Y =3D 1
end

X.class_eval { Y }

No. Because constants are defined separately from closures.
I know, I know. It makes total sense with how Ruby works. Not so sure
how Ruby works makes total sense. Honestly, how can closure NOT be of
significant to constant lookup?

Because, to be honest, I don't see any reason that they *should* be
significant to constant lookup. To me, there's other places where
constant lookup should be fixed -- but closures ain't one of them.

I've got a much bigger problem with:

class X
Y =3D 1
end

class X::Z
Y
end

vs.

class A
B =3D 1
class C
B
end
end

...than I'll ever have with lambdas and blocks using the constants from
their current context.

-austin
 
E

Eric Mahurin

--- Trans said:
=20

important.
=20
It's all relative Austin. How *really useful and important*
is
anything? Most things can be done in some other way. But this
much is
certain, there are things you CAN'T do b/c of this --or at
least not
wihtout jumping through some magical hoops like defining a
method
grabing the UnboundMethod, converting to_proc and undefining
the method
(which I have done). But as to the example I was trying to
show here...
here's something a little bit more real-to-life, though still
off the
top of my head.
=20
dir =3D File.dirname(__FILE__)
=20
m =3D module.new do
=20
make_dir_method =3D lambda { |which, path|
class_eval {
define_method( "#{which}dir" ) { |name|
dir =3D File.dirname(path)
name =3D File.basename(path)
File.join(dir,which,name)
}
}
}
=20
make_dir_method('lib',dir)
make_dir_method('var',dir)
make_dir_method('bin',dir)
=20
end

Trans, I thought the discussion was the need for a non-closure
block/lambda. The above has very little to do with closure
blocks/lambdas vs. non-closure blocks/lambdas. All you're
asking for in the above is for a ()-like operator that
correlates to #call. I too would like that especially when the
lambda takes a block (only in v1.9). When it doesn't take a
block, you can easily get similar syntax by using the []
operator on a Proc:

make_dir_method['lib',dir]
make_dir_method['var',dir]
make_dir_method['bin',dir]

Another option is to simply allow the [] operator to take a
block.



__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
 
D

Dave Bettin

Does anybody have a .vimrc file geared specifically for Ruby development?

thanks,
Dave
 
T

Trans

Austin said:
Don't try that game with me, Trans. You can't play it that well. You're
wanting a new feature that I don't think makes any sense at all. Matz,
so far, has said things publicly that seem to indicate that he's
unconvinced of the need for this as well (or at least doesn't plan on
making it happen). What I'm really trying to get you to do is to write
an RCR stronger than that which you wrote for AOP for this. If you
convince Matz that we need this, then more power to you.

*Convince* Matz? Hah! Haven't you noticed he's a like rock? But thank
goodness, right? Maybe I can nudge him a bit...maybe an RCR in due
time, after I finish some other stuff.
You don't have to convince me first, either. But so far, all I've heard
are what amount to "I don't get constant scoping" (and Matz has said
this is going to be fixed) and "cut and paste dumb programmer" issues.
If that's the best you can offer, I doubt you'll be able to convince
Matz of the need for it, either. We're getting a little more to the
heart of the possibilities now, I think.

Sure. Usecases don't grow on trees. We're both working on assumptions
here: you that there are no worthy uses, me that there are. I've come
across a few spots where they could be useful (and I still think
constants aren't exactly foreign to the issue) but it's not like I've
been collecting them for this very day.

Nonetheless, I just happend upon one. Took me by surprise too, cause I
wasn't even thinking about it and couldn't understand the bug at
first... until I realized...

Simplifed for easy illistration:

module Kernel
def do_this_on( klass, &blk )
o = klass.new( self )
o.instance_eval( &blk )
end
end

x = "Hop"

class Pop
def initialize( o )
@o = o
end
def x ; "#{@o} on Pop" ; end
end

x.do_this_on Pop do
p x
end

Stupid example? Think about #with_namespace that everyone's chatting
about these days rather than #do_this_on and its not so stupid anymore.
Why? What *need* do you have to grab an UnboundMethod, convert it to a
proc, and then undefine the method? In the three and a half years that
I've been working with Ruby, I haven't needed a UnboundMethod once, much
less needing to do what you've described here. And, I'd argue, if what
you're doing is bizarre/dangerous enough, then maybe you *need* to be
going through those hoops in order to make it so that such functionality
is unlikely to be abused.

I do a lot of language abstraction stuff --meta programming. The
particular case was to create Module::class_inherit, an improvement
over using ClassMethods.

Speaking of the "game" you just lost a point for never using
UnboundMethod ;)

Just kidding. I am suprised you've never used it though.
So ... you're trying to essentially do:

m = Module.new
class << m
def libdir(name)
dir = File.dirname(File.dirname(__FILE__))
name = File.basename(name)
File.join(dir, 'lib', name)
end
end

Yes, I know I did manually what you're trying to do automatically, but
I'm trying to understand here. I'm sure with a bit more thought, I could
come up with something cleaner to do this -- although I'm not really
understanding *why* you want to do this, in any case. FWIW, in 1.8.2 I
didn't get a compile error except from the fact that your code used the
1.9 deprecated () on lambdas.

The why of it is to ease the creation of some dynamic methods. It's not
a particular example, mind you, it's still just something I made up at
the spur of the moment to point out that under certain situations one
might get a "gotchya" because the lambda isn't isolated. Sure you could
get around this and make an actual def, but sometimes you don't really
need the procedure to hang around wasting memory, it's just a temp
thing, like a local var.
No. Because constants are defined separately from closures.


Because, to be honest, I don't see any reason that they *should* be
significant to constant lookup. To me, there's other places where
constant lookup should be fixed -- but closures ain't one of them.

I've got a much bigger problem with:

class X
Y = 1
end

class X::Z
Y
end

vs.

class A
B = 1
class C
B
end
end

..than I'll ever have with lambdas and blocks using the constants from
their current context.

Hey man, I'm with ya. I just think closure can't be exceptional to
this. Shouldn't constant lookup be relative to the closure? In fact, if
it were it might solve your bigger problem too.

T.
 
T

Trans

Eric said:
--- Trans said:
important.

It's all relative Austin. How *really useful and important*
is
anything? Most things can be done in some other way. But this
much is
certain, there are things you CAN'T do b/c of this --or at
least not
wihtout jumping through some magical hoops like defining a
method
grabing the UnboundMethod, converting to_proc and undefining
the method
(which I have done). But as to the example I was trying to
show here...
here's something a little bit more real-to-life, though still
off the
top of my head.

dir = File.dirname(__FILE__)

m = module.new do

make_dir_method = lambda { |which, path|
class_eval {
define_method( "#{which}dir" ) { |name|
dir = File.dirname(path)
name = File.basename(path)
File.join(dir,which,name)
}
}
}

make_dir_method('lib',dir)
make_dir_method('var',dir)
make_dir_method('bin',dir)

end

Trans, I thought the discussion was the need for a non-closure
block/lambda. The above has very little to do with closure
blocks/lambdas vs. non-closure blocks/lambdas. All you're
asking for in the above is for a ()-like operator that
correlates to #call. I too would like that especially when the
lambda takes a block (only in v1.9). When it doesn't take a
block, you can easily get similar syntax by using the []
operator on a Proc:

No no. That was actually just a mistype (well it works in an old 1.9
version, but) it's not the point at all.

Sorry,
T.
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Anonymous methods, blocks etc. (Cont. 'default block params')"

|*Convince* Matz? Hah! Haven't you noticed he's a like rock? But thank
|goodness, right? Maybe I can nudge him a bit...maybe an RCR in due
|time, after I finish some other stuff.

I know I am very conservative about language changes, and am aware of
that I refused many proposals from you. But still convincing me is
the only way to change Ruby, unless you fork off the new language,
like Sydney.

matz.
 
H

Hugh Sasse

Does anybody have a .vimrc file geared specifically for Ruby development?

I have
<quote>
set autoindent
set expandtab
set shiftwidth=2 " Mostly Ruby development -- std convention 2, not 4
set textwidth=68 " Do want this generally applied now...
"set ttyscroll=0
runtime ftplugin/man.vim " allows :Man to access manual on unix.
filetype plugin on "if you want the ftplugin to run
filetype indent on "if you want indenting support
syntax on
runtime plugin/matchit.vim
" redraw after pasting in non-paste mode. Doesn't seem to work in
"PuTTY???
"nmap <M-R> :exe ":undo|:set paste|:normal .:set nopaste"


"Give a status line always
set ls=2
</quote>

What did you want to achieve?
 
T

Trans

Yukihiro said:
Hi,

In message "Re: Anonymous methods, blocks etc. (Cont. 'default block params')"

|*Convince* Matz? Hah! Haven't you noticed he's a like rock? But thank
|goodness, right? Maybe I can nudge him a bit...maybe an RCR in due
|time, after I finish some other stuff.

I know I am very conservative about language changes, and am aware of
that I refused many proposals from you. But still convincing me is
the only way to change Ruby, unless you fork off the new language,
like Sydney.

I mean it: Thank Goodness!

I think we all know in our hearts, your being conservative is really a
blessing. That gives us the liberty to have wild and crazy ideas to
share with you. I don't mind most of my proposals are refused. I have
made quite a few, some I know full well won't be accepted, but only
wanted to get some idea on your (and others) thoughts so I can improve
my own.

With all due respect, thank you.

T.
 
E

Eric Mahurin

--- Trans said:
=20
Eric said:
--- Trans said:
Austin Ziegler wrote:

I'm not wanting to extrapolate. Consider me the
conservative here,
Trans. Convince me that this is really useful and
important.

It's all relative Austin. How *really useful and important*
is
anything? Most things can be done in some other way. But this
much is
certain, there are things you CAN'T do b/c of this --or at
least not
wihtout jumping through some magical hoops like defining a
method
grabing the UnboundMethod, converting to_proc and undefining
the method
(which I have done). But as to the example I was trying to
show here...
here's something a little bit more real-to-life, though still
off the
top of my head.

dir =3D File.dirname(__FILE__)

m =3D module.new do

make_dir_method =3D lambda { |which, path|
class_eval {
define_method( "#{which}dir" ) { |name|
dir =3D File.dirname(path)
name =3D File.basename(path)
File.join(dir,which,name)
}
}
}

make_dir_method('lib',dir)
make_dir_method('var',dir)
make_dir_method('bin',dir)

end

Trans, I thought the discussion was the need for a non-closure
block/lambda. The above has very little to do with closure
blocks/lambdas vs. non-closure blocks/lambdas. All you're
asking for in the above is for a ()-like operator that
correlates to #call. I too would like that especially when the
lambda takes a block (only in v1.9). When it doesn't take a
block, you can easily get similar syntax by using the []
operator on a Proc:
=20
No no. That was actually just a mistype (well it works in an
old 1.9
version, but) it's not the point at all.

Then what was your point of the above code? All 3 of the
blocks above need to be closures. The inner block references
dir which is defined in the outer-most scope. I thought you
were trying to convince the need of a non-closure.



__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
 
M

Mauricio Fernández

Does anybody have a .vimrc file geared specifically for Ruby development?

Here's something I wrote to switch block delimiters (do/end <=3D> {})
It creates a :B command that will turn

foo{|x| f(x); g; bar(x)}

into

foo do |x|
f(x)
g
bar(x)
end

and contrariwise.

You can also turn do/end into {} by selecting the block in visual mode and =
using the=20
<Leader>B (in my case ,B) mapping.


(cut/paste carefully since it contains ESC and other 'raw' chars.
=0C
"{{{ Ruby block delimiter conversion: do end <=3D> { }
"Copyright =A9 2005 Mauricio Fernandez
"Subject to the Ruby license.
" requires matchit and friends=20
" since it uses the % and =3D bindings
function! s:String_Strip(str)
let s =3D substitute(a:str, '\v^\s*', '', '')
return substitute(s, '\v\s*$', '', '')
endfunction

function! s:RubyBlockBraceToDoEnd(lineno)
" { } =3D> do end
let oldz =3D getreg("z")
call setreg("z", "")
execute 'normal ^f{%l"zd$'
let suffix =3D s:String_Strip(getreg("z"))
call setreg("z", oldz)
let orig =3D getline(".")
let repl =3D substitute(orig, '\v\s*\{\s*(\|[^|]*\|)?.*', ' do \1', '')
call setline(".", repl)
let nextline =3D substitute(orig, '\v[^{]*\v\s*\{\s*(\|[^|]*\|)?', '', =
'')
let nextline =3D substitute(nextline, '\}[^}]*$', '', '')
let numlines =3D 0
=20

" uncomment one of the following:
=20
" (1) just insert the body without splitting the lines on ;
"call append(a:lineno, nextline)
"call append(a:lineno+1, 'end' . suffix)
"
=20
" (2) try to split on ; ...
call append(a:lineno, 'end' . suffix)
" this is what we would want to do:=20
"let nextline =3D substitute(nextline, ';', "\n", 'g')
=20
while stridx(nextline, ";") !=3D -1
let eom =3D stridx(nextline, ";")
let line =3D s:String_Strip(strpart(nextline, 0, eom))
call append(a:lineno + numlines, line)=20
let numlines =3D numlines + 1
let nextline =3D strpart(nextline, eom+1, strlen(nextline) - eom - 1)
endwhile
let nextline =3D s:String_Strip(nextline)
if strlen(nextline) > 0
call append(a:lineno + numlines, nextline)
let numlines =3D numlines + 1
endif

" this is what it all began with...
"execute 'normal :s/\v\s*\{\s*(\|.*\|)?/ do \1\r/=0D'
"execute 'normal g_cw=0Dend=1B'
execute 'normal V' . (1 + numlines) . 'j=3D'
"echo "{ } =3D> do end"
endfunction

function! s:RubyBlockDoEndToBrace(_firstline, _lastline)
" do end =3D> { }
let linenum =3D a:_firstline + 1
let orig =3D getline(".")
while linenum < a:_lastline - 1
let addline =3D getline(linenum)
if '\v^\s*$' !~ addline
let addline =3D substitute(addline, '\v^\s*', '', '')
let addline =3D substitute(addline, '\s*$', '; ', '')
let orig =3D orig . addline
endif
let linenum =3D linenum + 1
endwhile
let l =3D substitute(getline(a:_lastline-1), '\v^\s*', '', '')
let l =3D substitute(l, '\s*$', '', '')
let orig =3D orig . l
let l =3D substitute(getline(a:_lastline), '\v^\s*end(\.|\s|$)@=3D', ' =
}', '')
let l =3D substitute(l, '\s*$', '', '')
let orig =3D orig . l
=20
"echo orig
"input(orig)
let repl =3D substitute(orig, '\v\s*do\s*(\|[^|]*\|)?', '{\1 ', '')
"execute 'normal d' . (a:_lastline - a:_firstline) . 'j'
execute ':' . a:_firstline . ',' . a:_lastline . 'd'
call append(a:_firstline - 1, repl)
execute ':' . a:_firstline
"echo "do end =3D> { }"
endfunction

map <SID>xx <SID>xx
let s:sid =3D maparg("<SID>xx")
unmap <SID>xx
let s:sid =3D substitute(s:sid, 'xx', '', '')

function! <SID>RubyBlockSwitchDelimiters() range
set nofoldenable
if a:firstline =3D=3D a:lastline
let braceidx =3D match(getline("."), '{')
let doidx =3D match(getline("."), '\<do\>')
if braceidx !=3D -1 && (doidx =3D=3D -1 || braceidx < doidx)
call s:RubyBlockBraceToDoEnd(a:firstline)
elseif doidx !=3D -1
execute 'normal /\<do\>' . "\n" . 'V%:call ' .=20
\ s:sid . 'RubyBlockSwitchDelimiters()' . "\n"
else
echo "No block found"
end
else
call s:RubyBlockDoEndToBrace(a:firstline, a:lastline)
endif
"execute 'normal V2k=3D'
"execute 'normal v5j'
endfunction

command! -range B <line1>,<line2>call <SID>RubyBlockSwitchDelimiters()
vmap <Leader>B :call <SID>RubyBlockSwitchDelimiters()<cr>
"vmap <Leader>B :B<cr>
=0C

--=20
Mauricio Fernandez
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top