On Mon, 06 Dec 1999 18:36:44 +1100, the world broke into rejoicing as
Robert Graham Merkel <[EMAIL PROTECTED]> said:
>
> > I think this is very much the right idea; there is no doubt but that
> > there will be value to having a variety of output forms.
> >
> > Creating what amounts to a "financial reporting language" that can
> > be used to push data at multiple output forms would be a *big* win.
> >
>
> I think we're all in agreement on this.
>
> However, from reading your sample language, I'm not clear whether my
> understanding of how such a language would work matches yours.
>
> My conception was that there would be NO output-format specific
> information in the reporting language. Therefore, we shouldn't
> be specifying font names, page length, and the like in the reporting
> language.
Ah. I think you're thinking that (report-open) is part of the reporting
language. It's not. it's the interface between the reporting language
and:
a) The users, specifying what they want rendered, and
b) The rendering systems.
> The output filters would obtain this information from
> elsewhere (from the user or hardcoded into them). That way,
> report generators could be written to output to this reporting
> language without worrying about how the output filter would
> deal with them.
>
> My comments below should primarily interpreted in this context.
>
> > The basic operators would include things like the following, which
> > I've added to report.scm as comments at this point...
> >
> > ;;; Suggested set of functions to manage report data in a
> > ;;; device-independent manner.
> >
> > ;;; report-string, report-total, report-value are used to output
> > ;;; values. "string" should be obvious; "value" will be a currency
> > ;;; amount, and probably should be currency-aware. "total" allows
> > ;;; a bunch of "values" to be collected into a single total "cell."
> > ;;; The point to totals being distinct from values is that this allows
> > ;;; the total to remain a dynamic calculation if, for instance, output
> > ;;; is going into a spreadsheet.
> > ;;;
> > ;;; (define (report-string string indentation style))
>
> How do we place a string in a specific column?
My bad.
Should be:
(define (report-string report-port string column indentation style))
that allows you to specify which column to put it in.
Note that this isn't indicating a physical column, but rather a logical
column.
- In text form, column 1 might be physical columns 1-55, column 2 physical
columns 56-67, and column 3 columns 68-79.
- In a spreadsheet, you'd just plain have 3 columns.
- In HTML, there would be a table with 3 columns.
> > ;;; (define (report-value value collector-thunk column
> > ;;; linkname style))
> > ;;; (define (report-total input-collector-thunk
> > ;;; output-collector-thunk column
> > ;;; linkname style))
>
> What's the "linkname" parameter?
That allows you to indicate that the value has some symbolic name
that could be referred to. Meaningful for spreadsheets and for HTML
(and by the same token other SGML-based forms):
--> Spreadsheets can have named cells/regions
--> SGML offers the ability to add an ID to things
--> In HTML, this would be implemented by the code:
(display (string-append "<A NAME=" linkname "> ") physical-port)
> > ;;; You pass a list of the thunks established above into (report-line)
> > ;;; which combines them into a single line.
> > ;;; (define (report-line report-port . list-of-thunks))
In trying to draft up a sample implementation, it makes *no* sense
for these to be thunks; the three functions need to get passed the
'report-port' and then infer what action to take based on that.
> > ;;; (define (define-report-total-collector))
> > ;;; define-report-total-collector returns a thunk used by report-value
> > ;;; and report-total to collect together values to establish a "total"
> > ;;; In the case of HTML/Text output forms, this can just grab the
> > ;;; values. In the case of a spreadsheet output form, this would
> > ;;; collect up the cell IDs so that (report-total) would generate a
> > ;;; formula like "=D2+D3+D4+D5+...+D15"
>
> Makes good sense.
>
> > ;;; (define (report-start-section report-port linkname))
> > ;;; (define (report-end-section report-port))
> > ;;; These functions are necessary for the HTML output form to generate
> > ;;; the table start/end info. It would not be a bad move to change
> > ;;; this to:
> > ;;; (define (report-start-section report-port linkname . list-of-thunks))
> > ;;; that works like (report-line), so that the first line in the table
> > ;;; can contain header data.
>
> Yep.
>
> > ;;; style:
> > (define style-structure
> > (make-record-type
> > "style"
> > '(alignment fontinfo color)))
> >
> Hmmmm. I'm not so sure about this, as this encodes output-format
> specific information into the intermediate language, doesn't it?
> Wouldn't it make more sense to define a limited set of styles, such as
> Heading, subheading, body text, emphasis (roughly analagous to
> \emph{} in LaTeX), etc, and let the final renderer interpret these?
The problem is that you can't get away from having something like this.
Supposing we're using HTML as the output form, then even if we're using
CSS, and can keep the style declarations completely independent of the
HTML file, we still need to attach at least the style *identifier* to
the HTML that gets generated. Thus, we need to have some sort of list
of styles and their names, at least.
Unfortunately, if we are using a CSS-less HTML browser, we need to have
a way of embedding the style info in with the HTML.
All that should get passed around in the intermediate language is the
*name* of the style; the physical renditions may, depending on their
natures, need to make use of that information.
> > ;;; (define (report-newpage) report-port)
> > ;;; Jump to a new page... More-or-less a no-op with HTML, but could
> > ;;; do a switch to a new sheet with Gnumeric...
>
> Fine.
>
> > ;;; (define (report-open physical-port title medium
> > ;;; page-dimensions collist))
> > ;;; This "opens" the report, associating it with a "physical" port,
> > ;;; indicating a title, medium (e.g. - 'html 'text 'gnumeric
> > ;;; 'postscript ...),
> > ;;; page dimensions such as:
> > ;;; (80 'cols 66 'rows) - Common text formats
> > ;;; (132 'cols 66 'rows)
> > ;;; (8.5 'in 11 'in) - Likely useful for Postscript
> > ;;; (8.5 'in 14 'in)
> > ;;; (0 'generic 0 'generic) - For formats with no fixed limits
> > ;;; like HTML/Spreadsheet
>
> Are the medium and page dimensions something we want to code into our
> reporting language?
It's not part of the reporting language; it is part of the declaration
of the deployment of the report.
At some point, the report has to be made "physical," and rendered
in HTML/Text/XML/...; this is what makes it happen.
I could (and would) argue that this isn't part of the reporting language,
but rather part of the instantiation of an actual report instance.
In order to make an actual report, you need to specify an output form,
and (report-open physical-port title 'html requested-dimensions collist)
does that. The underlying operators, (report-value), (report-string),
(report-total) are the "language," and are generic across output forms.
> > ;;; collist is a list of columns:
> > ;;; ('text (1 55) (57 10) (69 10)) -- For use with text
> > ;;; - This describes 3 cols, one 55 chars wide, and 2 of width 10.
> > ;;; Good for a report that is to have 2 numeric columns
> > ;;; ('html (8 'in) ((5 'in) (1.5 'in) (1.5 'in)))
> > ;;; - Hopefully obvious?
> > ;;; ('html (8 'in) (('rest) (1.5 'in) (15 'percent)))
> > ;;; (15 'percent) is equivalent to 15% of 8 'in, e.g. (1.2 'in)
> > ;;; ('rest) takes up the "rest" of the width, in this case, (5.3 in)
> > ;;; ('columns 3)
> > ;;; Good for a spreadsheet; indicates that there are three columns.
> > ;;; It might be nice for this to add further options to configure
> > ;;; the widths of these columns...
>
> Yes, we want to specify how many columns there are, and some measure
> of how wide they have to be, but, again, this is output-form specific.
The point here is that there are various functions that need to be
"generic," able to be applied to whatever device may be used for output.
(report-value), (report-string), (report-total), (report-need),
(report-page-header), (report-page-footer) all need forcibly to be
generic.
But (report-open) is the function that crosses the "great divide;" it
is the point at which you specify the physical rendition information.
At some point, the physical parameters do have to be specified, and it
seems to me that this is the right point at which to do this.
The alternative is to create a language that is "completely platonic"
in being totally unaware at all times what the output form will be.
That would mean we have to then create a separate translator, and
effectively add a further sorta-language to the mix. I think it rather
preferable to keep it pretty simple, having the operators inside be
device-independent.
> > ;;; (define (report-close report-port))
> > ;;; This cleans up the data structures so that they may be
> > ;;; garbage-collected.
> > ;;;
> > ;;; (define (report-page-header report-port thunk))
> > ;;; (define (report-page-footer report-port length thunk))
> > ;;;
> > ;;; These two functions attach thunks that do stuff at the top and
> > ;;; bottom of each page. The footer needs to know how its length so
> > ;;; that (report-need) can be aware of this in determining how close
> > ;;; to the bottom of the page it can safely get...
> > ;;;
> > ;;; (define (report-need report-port need-amount))
> > ;;; This function indicates that if there aren't "need-amount" lines
> > ;;; left on the present page, the system should display the footer and
> > ;;; jump on to the next page... Note that in the "body," this will
> > ;;; add in the number of lines that the footer produces...
> > ;;; (define (report-newpage) report-port)
>
> This make sense.
--
"No, I'm not interested in developing a powerful brain. All I'm after
is just a mediocre brain, something like the president of American
Telephone and Telegraph Company." -- Alan Turing on the possibilities
of a thinking machine, 1943.
[EMAIL PROTECTED] - <http://www.ntlug.org/~cbbrowne/lsf.html>
--
Gnucash Developer's List
To unsubscribe send empty email to: [EMAIL PROTECTED]