Version 2 of Aifl: dynamically generated files

Updated 2009-04-23 11:51:55 by LV

I remember reading that somebody wished for this on the wiki the other day. I couldn't find where or who wished for it, but here it is.

Aifl (pronounced 'eiffel' - like the tower) is a very small package that redefines the open command. Whenever you try to open a file ending in '.aifl' (case insensitive), it will be executed as a script and have it's stdin and stdout hooked up to a channel, which is returned instead of a channel for reading (or writing to) the file. The 'aifl::nopen' command behaves exactly like the normal 'open' command, should you need it.

This could be used for many things - dynamically generated reports, for instance. Or perhaps running another file through gzip and returning the output, then writing the input. (For lack of a vfs::gzip) Or even pulling information off the Internet to generate files that can easily be read in programs not designed for such rigorous activity.

The downside to this is that such creativity only works in programs that use Aifl. Perhaps having a small script which generates the output of this.that.aifl and outputs it as this.that for other programs to read; but that strikes me as kludgy.

# aifl.tcl
# 
# Aifl - Automagically Interpreted File Layer (pronounced like 'eiffel')
# A small Tcl package which will let your program open .aifl files transparently.
# This is accomplished by redefining the 'open' command.

package provide aifl 0.1

# We have to make sure that Aifl is not loaded more than once.
if {![namespace exists aifl]} {
    namespace eval aifl {}

    proc aifl::open { filename {access r} {permissions 0666} } {
        if {[string match -nocase *.aifl $filename]} {
            return [aifl::nopen "|tclsh85 $filename" $access $permissions]
        } else {
            return [aifl::nopen $filename $access $permissions]
        }
    }

    rename open aifl::nopen 
    rename aifl::open open
}

Test files (feel free to add something more creative):

#!/usr/local/tclsh
if {[catch {package require aifl}]} {
    source aifl.tcl
}

# Opens the file as a script
set ch [open test.txt.aifl]
puts [read $ch]
close $ch

# Opens the file normally
set ch [aifl::nopen test.txt.aifl]
puts [read $ch]
close $ch

# test.txt.aifl
# 
# Some normal text:
puts "Hello World!
This text is generated by a script."

# Some dynamically-generated text:
puts "The random number of the day is [expr {rand()}]"
puts "The time of access is [clock format [clock seconds]]"