On Sep 22, 3:47=A0pm, Robert Klemme <shortcut... / googlemail.com> wrote:
> On 22.09.2008 17:56, DMisener wrote:
>
>
>
> > On Sep 19, 6:57 am, Robert Dober <robert.do... / gmail.com> wrote:
> >> On Thu, Sep 18, 2008 at 10:07 PM, Robert Klemme> Oh, come on. =A0
> >> You can easily use that information to build what you want.
>
> > Actually inverting the logic isn't that easy (at least for me)
>
> >> Hmm maybe not Robert, my feeling is that they should not do what they
> >> are doing in the at_exit block.
>
> > I'm certainly not married to the the at_exit approach.
>
> >> OP can you give us the rationale behind this design. At first sight I
> >> believe you should do what you want in the main script. Look at Ara's =
ideas e.g.
>
> > Simple problem:
>
> > Create a tentative output working file. =A0If the program exits
> > "cleanly" then rename the work file
> > to its "final" name. =A0If not leave the work file for possible
> > examination.
>
> > Ideally this File.open_tentative_output_file would be plug
> > "compatible" with the simple File.open
> > (i.e. support modes and blocks).
>
> > Perhaps I'm trying to make life "too easy" for the application
> > programmer by eliminating the need for
> > an explicit File.close_all_pending_tentative_file routine.
>
> It rather seems that you're making *your* life too hard. :-)

Probably... :-)

>
> > =A0That is
> > really all that I am trying to achieve with the
> > at_exit{} code. =A0One less step to remember. =A0But perhaps the
> > implementation complexity isn't worth it.
>
> Why do you need at_exit for this - especially if you want to be
> compatible to File.open?
>
> def File.open_tentative_output_file(tmp, final, mode =3D "w", &b)
> =A0 =A0raise "Need a block" unless b
> =A0 =A0File.open(tmp, mode, &b)
> =A0 =A0File.rename tmp, final
> end

So the recommendation is that any "successful program completion"
cleanup be coerced into
the execute a block then cleanup construct cited above.

Enforcing the the block is required is the key. I was hoping to relax
that requirement but
you can't have everything.

That might do the trick...

BTW: here was my previous implementation... actually called OutputFile


# Setup ABORT detection preamble

$ABORTING=3Dtrue

def exit_program *args
    $ABORTING=3Dfalse
    __original_exit__(*args)
end


....


alias :exit :exit_program


class OutputFile
    def initialize filename,options=3D{},&block
        @filename,@options,@block=3Dfilename.dup,options.dup,block
        @mode=3Doptions[:mode] || 'w'
        unless append?
            # TODO: Nice if we could validate valid filename here
instead of at "open?" time
            # TODO: support :nosuperceed, :superceed
            File.send(@options[:backup] ? :backup : :delete,@filename)
if File.exists? @filename
            @work_filename=3DFilename.work filename
        end
        if block_given?
            yield self
            close
        else
            # TODO: Support suppression of autoclose on fatal_error
            at_exit{close unless $ABORTING}
        end
        @file
    end

    def puts *args
        open?
        @file.puts(*args)
    end

    def print *args
        open?
        @file.puts(*args)
    end

    def close
        if @file
            @file.close
            # TODO: what to do if rename fails for any reason
            File.rename @work_filename,@filename if @work_filename
        end
        @file=3Dnil
    end

    private

    def open? # Defer open until first require output request
        return if @file
        # TODO: support wait on busy
        @file=3DFile.open(@work_filename || @filename,@mode)
    end

    def append?
        /a/i.match(@mode)
    end
end

def OutputFile *args,&block
    OutputFile.new(*args,&block)
end