commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gnue/reports AUTHORS FAQ INSTALL samples/foobul...


From: Jason Cater
Subject: gnue/reports AUTHORS FAQ INSTALL samples/foobul...
Date: Tue, 09 Apr 2002 18:55:41 -0400

CVSROOT:        /cvsroot/gnue
Module name:    gnue
Changes by:     Jason Cater <address@hidden>    02/04/09 18:55:41

Modified files:
        reports        : AUTHORS FAQ INSTALL 
        reports/samples/foobulations: monthly.grd 
        reports/src    : GRDataMapper.py GRLayout.py GRParser.py 
                         GRRun.py 
Added files:
        reports/filters: README 

Log message:
        lots of work on summaries; misc cleanup

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/AUTHORS.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/FAQ.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/INSTALL.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/filters/README?rev=1.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/samples/foobulations/monthly.grd.diff?tr1=1.11&tr2=1.12&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/src/GRDataMapper.py.diff?tr1=1.11&tr2=1.12&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/src/GRLayout.py.diff?tr1=1.25&tr2=1.26&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/src/GRParser.py.diff?tr1=1.21&tr2=1.22&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue/reports/src/GRRun.py.diff?tr1=1.7&tr2=1.8&r1=text&r2=text

Patches:
Index: gnue/reports/AUTHORS
diff -c gnue/reports/AUTHORS:1.3 gnue/reports/AUTHORS:1.4
*** gnue/reports/AUTHORS:1.3    Sun Oct  7 02:28:34 2001
--- gnue/reports/AUTHORS        Tue Apr  9 18:55:41 2002
***************
*** 1,2 ****
--- 1,5 ----
  Jason Cater <address@hidden>:
    Initial coding
+ 
+ Derek Neighbors <address@hidden>: 
+   XSL transformation scripts
Index: gnue/reports/FAQ
diff -c gnue/reports/FAQ:1.1 gnue/reports/FAQ:1.2
*** gnue/reports/FAQ:1.1        Wed Apr 11 13:08:32 2001
--- gnue/reports/FAQ    Tue Apr  9 18:55:41 2002
***************
*** 0 ****
--- 1,9 ----
+ 
+ Q: Why do you use XSLT? Isn't it slow?
+ 
+ A: XSLT is a means to an end.  Currently, it provides the biggest bang 
+    for the buck.  Reports will have hooks so that "formatting engines" 
+    can be written that can output directly to the desired output.  
+    However, there are more pressing issues than such engines and XSLT
+    serves our needs well enough for the foreseeable future. 
+ 
Index: gnue/reports/INSTALL
diff -c gnue/reports/INSTALL:1.3 gnue/reports/INSTALL:1.4
*** gnue/reports/INSTALL:1.3    Sun Oct  7 02:28:34 2001
--- gnue/reports/INSTALL        Tue Apr  9 18:55:41 2002
***************
*** 25,36 ****
  The following minimum programs are required for running GNUe-Reports: 
  
   Python 2.0 or later          http://www.python.org/
!  PyXML                                http://pyxml.sourceforge.net/
!  GNUe-Common                  http://www.gnue.org/ 
  
! 
! To do any useful report conversions, you may need any of the following: 
!  * A TeX formatting engine (e.g., for Linux, TeTeX) 
!  * An XSLT processor (see Sablotron at ????) 
  
  
--- 25,33 ----
  The following minimum programs are required for running GNUe-Reports: 
  
   Python 2.0 or later          http://www.python.org/
!  GNUe-Common                  http://www.gnuenterprise.org/downloads/common
  
! To do any useful report conversions based on our samples, you will need:  
!  * An XSLT processor (currently we use Sablotron and PySablot)
  
  
Index: gnue/reports/samples/foobulations/monthly.grd
diff -c gnue/reports/samples/foobulations/monthly.grd:1.11 
gnue/reports/samples/foobulations/monthly.grd:1.12
*** gnue/reports/samples/foobulations/monthly.grd:1.11  Tue Apr  9 02:22:57 2002
--- gnue/reports/samples/foobulations/monthly.grd       Tue Apr  9 18:55:41 2002
***************
*** 28,34 ****
          </out:tablehead>
  
          <section source="dtsFoo" name="nameBreak">
!            <section>
               <out:row>
                  <firstRow><out:col><field name="name" 
section="nameBreak"/></out:col></firstRow>
                  <notFirstRow><out:col/></notFirstRow>
--- 28,34 ----
          </out:tablehead>
  
          <section source="dtsFoo" name="nameBreak">
!            <section name="details">
               <out:row>
                  <firstRow><out:col><field name="name" 
section="nameBreak"/></out:col></firstRow>
                  <notFirstRow><out:col/></notFirstRow>
***************
*** 39,45 ****
            <out:row type="subtotal" level="2">  <!-- TODO: Replace w/summs 
once they work -->
              <out:col/>
              <out:col align="right">Total for <field name="name"/></out:col>
!             <out:col align="right">12<!--summ function="sum" 
section="nameBreak" field="foobs"/--></out:col>
            </out:row>
            <default>
              <out:row>
--- 39,45 ----
            <out:row type="subtotal" level="2">  <!-- TODO: Replace w/summs 
once they work -->
              <out:col/>
              <out:col align="right">Total for <field name="name"/></out:col>
!             <out:col align="right"><summ function="sum" section="details" 
field="foobs"/></out:col>
            </out:row>
            <default>
              <out:row>
***************
*** 52,58 ****
          <out:row type="subtotal" level="1">
            <out:col/>
            <out:col align="right">Grand Total</out:col>
!           <out:col align="right">36</out:col>
          </out:row>
  
  
--- 52,58 ----
          <out:row type="subtotal" level="1">
            <out:col/>
            <out:col align="right">Grand Total</out:col>
!           <out:col align="right"><summ function="sum" section="nameBreak" 
field="foobs"/></out:col>
          </out:row>
  
  
Index: gnue/reports/src/GRDataMapper.py
diff -c gnue/reports/src/GRDataMapper.py:1.11 
gnue/reports/src/GRDataMapper.py:1.12
*** gnue/reports/src/GRDataMapper.py:1.11       Mon Apr  8 12:03:20 2002
--- gnue/reports/src/GRDataMapper.py    Tue Apr  9 18:55:41 2002
***************
*** 1,19 ****
  #
  # This file is part of GNU Enterprise.
  #
! # GNU Enterprise is free software; you can redistribute it 
! # and/or modify it under the terms of the GNU General Public 
! # License as published by the Free Software Foundation; either 
  # version 2, or (at your option) any later version.
  #
! # GNU Enterprise is distributed in the hope that it will be 
! # useful, but WITHOUT ANY WARRANTY; without even the implied 
! # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  # PURPOSE. See the GNU General Public License for more details.
  #
! # You should have received a copy of the GNU General Public 
! # License along with program; see the file COPYING. If not, 
! # write to the Free Software Foundation, Inc., 59 Temple Place 
  # - Suite 330, Boston, MA 02111-1307, USA.
  #
  # Copyright 2000-2002 Free Software Foundation
--- 1,19 ----
  #
  # This file is part of GNU Enterprise.
  #
! # GNU Enterprise is free software; you can redistribute it
! # and/or modify it under the terms of the GNU General Public
! # License as published by the Free Software Foundation; either
  # version 2, or (at your option) any later version.
  #
! # GNU Enterprise is distributed in the hope that it will be
! # useful, but WITHOUT ANY WARRANTY; without even the implied
! # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  # PURPOSE. See the GNU General Public License for more details.
  #
! # You should have received a copy of the GNU General Public
! # License along with program; see the file COPYING. If not,
! # write to the Free Software Foundation, Inc., 59 Temple Place
  # - Suite 330, Boston, MA 02111-1307, USA.
  #
  # Copyright 2000-2002 Free Software Foundation
***************
*** 32,43 ****
--- 32,50 ----
  import GRExceptions
  from gnue.common import GDebug
  from gnue.common import GDataFormatter
+ import types, string
+ 
  
  #
  # Class used internally by GRDataMapper
  # Classes other than GRDataMapper should not
  # even care that this exists...
  #
+ # There is one instance of this for EACH GRSection
+ #
+ # TODO: should this functionality be moved to the
+ # TODO: GRSection class since there's a 1:1 relation?
+ #
  class GRDataMapperSection:
    def __init__(self, name, source, parent):
      self.parent = parent
***************
*** 51,58 ****
--- 58,72 ----
      self.initial = 1    # Are we in an initial run in which we have no 
history?
      self.changed = 0    # Did this section change w/the last
      self.grouping = 0   # Is this a "grouping" section?
+     self._lastSection = None
      self.datasource = None
  
+     self._summMap = {'sum': self._summ_sum,
+                      'count': self._summ_count,
+                      'avg': self._summ_avg,
+                      'min': self._summ_min,
+                      'max': self._summ_max }
+ 
      if parent != None:
        parent.addChildSection(self)
  
***************
*** 82,92 ****
    #
    #  Add a summary
    #
!   def addSummary(self, name, function):
!     if not self.summaries.has_key(name):
!       self.summaries[name] = {function:0}
!     else:
!       self.summaries[name][function] = 0
  
    #
    #  Get a field's current value
--- 96,117 ----
    #
    #  Add a summary
    #
!   def addSummary(self, function, field):
!     try:
!       self.summaries[field][function] = None
!     except KeyError:
!       self.summaries[field] = {function:None}
! 
!     # If this function relies on other
!     # functions, add those as well (e.g.,
!     # average depends on sum and count)
!     try:
!       for func in _summMultiMapping[function]:
!         self.addSummary(self, func, field)
!     except KeyError:
!       pass
! 
! 
  
    #
    #  Get a field's current value
***************
*** 98,104 ****
    #  Get a summary's current value
    #
    def getSummary(self, name, function, format):
!     return self.summaries[name][function]
  
    #
    #  Add a section
--- 123,133 ----
    #  Get a summary's current value
    #
    def getSummary(self, name, function, format):
!     val = self.summaries[name][function]
!     if val is None:
!       return ""
!     else:
!       return "%s" % val
  
    #
    #  Add a section
***************
*** 113,122 ****
      self.initial = 1
      self.changed = 0
  
    #
    #  Save current values before new query occurs
    #
!   def _loadFields(self, recordset):
      self.changed = 0
      for field in self.fields.keys():
        val = recordset.getField(field)
--- 142,164 ----
      self.initial = 1
      self.changed = 0
  
+ 
+   #
+   #
+   #
+   def clearSummaries(self):
+     print "clearing summaries for %s" % self.name
+     print self.summaries
+     for field in self.summaries.keys():
+       for function in self.summaries[field].keys():
+         self.summaries[field][function] = None
+ 
+ 
    #
    #  Save current values before new query occurs
    #
!   def _loadFields(self, recordset, reset=0):
!     if reset: self.clearSummaries()
      self.changed = 0
      for field in self.fields.keys():
        val = recordset.getField(field)
***************
*** 127,135 ****
--- 169,195 ----
          self.changed = 1
          GDebug.printMesg(10, "Field %s changed after nextRecord 
(%s,%s,%s,%s)" % (field, self.initial, self.grouping, self.fields[field], val))
          self.fields[field] = val
+ 
+ ##      handler = self
+ ##      while handler:
+ ##        handler._handleSummary(field, val)
+ ##        handler = handler.parent
+ 
      GDebug.printMesg(10, "After _loadFields, changed=%s" % self.changed)
      self.initial = 0
  
+ 
+   #
+   # Initiate the calculation of summaries
+   #
+   def _handleSummary(self):
+     # Now, calc all summaries
+     for field in self.summaries.keys():
+ ##    if self.summaries.has_key(field):
+       for function in _summFunctions:
+         if self.summaries[field].has_key(function):
+           self._summMap[function](field, self.fields[field])
+ 
    #
    # Will the next recordset cause
    #
***************
*** 158,163 ****
--- 218,269 ----
      self.resultset = detailResultSet
  
  
+   ##
+   ##
+   ##
+ 
+   # Summary function: "count"
+   def _summ_count(self, field, value):
+     if value is not None:
+       try:
+         self.summaries[field]['count'] += 1
+       except TypeError:
+         self.summaries[field]['count'] = 1
+ 
+   # Summary function: "sum"
+   def _summ_sum(self, field, value):
+     if type(value) in _numericTypes:
+       try:
+         self.summaries[field]['sum'] += value
+       except TypeError:
+         self.summaries[field]['sum'] = value
+     else:
+       raise "Attempting to 'sum' a non-numeric field %s" % (field)
+ 
+   # Summary function: "average"
+   def _summ_avg(self, field, value):
+     if type(value) in _numericTypes:
+       self.summaries[field]['average'] = \
+           self.summaries[field]['sum'] / self.summaries[field]['count']
+     else:
+       raise "Attempting to 'average' a non-numeric field %s" % (field)
+ 
+   # Summary function: "min"
+   def _summ_min(self, field, value):
+     if value is not None:
+       existing = self.summaries[field]['min']
+       if existing is None or value < existing:
+         self.summaries[field]['min'] = value
+ 
+   # Summary function: "max"
+   def _summ_max(self, field, value):
+     if value is not None:
+       existing = self.summaries[field]['min']
+       if existing is None or value > existing:
+         self.summaries[field]['min'] = value
+ 
+ 
+ 
  ###########################################
  #
  #
***************
*** 209,216 ****
      self.sources.getDataSource(self.sectionMap[section].source) \
            .referenceField(field)
  
!   def addSummaryToSection(self, section, field, function):
!     pass  # This should probably be replaced with real code :)
  
  
    #
--- 315,326 ----
      self.sources.getDataSource(self.sectionMap[section].source) \
            .referenceField(field)
  
! 
!   def addSummaryToSection(self, function, section, field):
! 
!     self.sectionMap[section].addSummary(function, field)
!     self.sources.getDataSource(self.sectionMap[section].source) \
!           .referenceField(field)
  
  
    #
***************
*** 258,264 ****
      if not controlSection.__nextRecord:
        return (None, None)
      else:
!     
        recordset = controlSection.__nextRecord
        if controlSection.resultset.nextRecord():
          controlSection.__nextRecord = controlSection.resultset.current
--- 368,374 ----
      if not controlSection.__nextRecord:
        return (None, None)
      else:
! 
        recordset = controlSection.__nextRecord
        if controlSection.resultset.nextRecord():
          controlSection.__nextRecord = controlSection.resultset.current
***************
*** 282,289 ****
--- 392,421 ----
              s._precheckNextFields(controlSection.__nextRecord)):
            nextSection = s.name
  
+         if nextSection and nextSection != s._lastSection:
+           s._clearSummary()
+         s._handleSummary()
+ 
+       s._lastSection = firstSection
        return (firstSection, nextSection)
  
  
+ #
+ # Contains all valid "summary" functions
+ # and the order they need to be calculated
+ # (e.g., count and sum need to happen before
+ # average)
+ 
+ _summFunctions = ('count','sum','min','max','avg','_accum',)
  
+ #
+ # Contains all "summary" functions that
+ # depend on other record keeping. (e.g.,
+ # 'averages' need the total and the count
+ # tracked.
+ #
+ _summMultiMapping = { 'avg': ('sum','count'),
+                     }
  
+ # Python types that are numeric
+ _numericTypes = (types.FloatType, types.IntType, types.LongType)
Index: gnue/reports/src/GRLayout.py
diff -c gnue/reports/src/GRLayout.py:1.25 gnue/reports/src/GRLayout.py:1.26
*** gnue/reports/src/GRLayout.py:1.25   Tue Apr  9 01:00:35 2002
--- gnue/reports/src/GRLayout.py        Tue Apr  9 18:55:41 2002
***************
*** 115,121 ****
        elif isinstance(object, GRField):
          s = parentSection.getAncestorWithSource(object._source)
          if s == None:
!           raise SourceOutOfScope, \
                  'Field "%s" in section "%s" uses out-of-scope source "%s"' \
                       % (object.name, parentSection._name, object._source)
  
--- 115,121 ----
        elif isinstance(object, GRField):
          s = parentSection.getAncestorWithSource(object._source)
          if s == None:
!           raise GRExceptions.SourceOutOfScope, \
                  'Field "%s" in section "%s" uses out-of-scope source "%s"' \
                       % (object.name, parentSection._name, object._source)
  
***************
*** 132,138 ****
              curr = s._parent.findParentOfType('GRSection')
  
            if section == None:
!             raise SourceOutOfScope, \
                  'Field "%s" in section "%s" uses out-of-scope section "%s"' \
                       % (object.name, parentSection._name, object.section)
  
--- 132,138 ----
              curr = s._parent.findParentOfType('GRSection')
  
            if section == None:
!             raise GRExceptions.SourceOutOfScope, \
                  'Field "%s" in section "%s" uses out-of-scope section "%s"' \
                       % (object.name, parentSection._name, object.section)
  
***************
*** 145,172 ****
          self._mapper.addFieldToSection(object._section, object.name)
  
        elif isinstance(object, GRSumm):
-         sec = string.lower(object.section)
          if object.section == None:
!           s = 
object._parent.findObjectOfType('GRSection').getAncestorWithSource(object._source)
!           if s == None:
!             raise SourceOutOfScope, \
!               'Summary "%s" in section "%s" uses out-of-scope source "%s"' \
!                    % (object.name, object._parent.name, object._source)
          else:
!           s = self._mapper.sectionMap[sec]._object.\
!                  getAncestorWithSource(object._source)
!           if s == None:
!             raise SourceOutOfScope, \
!               'Summary "%s" in section "%s" uses out-of-scope source "%s"' \
!                    % (object.name, object._parent.name, object._source)
  
          object._section = s._name
!         object._mymapper = self._mapper.sectionMap[object._section]
  
          GDebug.printMesg(6,'Mapping summary %s [%s] to section %s' \
!                    % (object.name, object.function, object._section))
!         self._mapper.addSummaryToSection(object._section, object.name, \
!                  object.function)
  
  
    #
--- 145,167 ----
          self._mapper.addFieldToSection(object._section, object.name)
  
        elif isinstance(object, GRSumm):
          if object.section == None:
!           s = object._parent.findObjectOfType('GRSection')
          else:
!           sec = string.lower(object.section)
!           s = self._mapper.sectionMap[sec]._object
!         if s == None:
!           raise GRExceptions.SourceOutOfScope, \
!             'Summary "%s" in section "%s" uses out-of-scope source "%s"' \
!                  % (object._field, object._parent.name, object._source)
  
          object._section = s._name
!         object._mymapper = self._mapper.sectionMap[s._name]
  
          GDebug.printMesg(6,'Mapping summary %s [%s] to section %s' \
!                    % (object._field, object.function, object._section))
!         self._mapper.addSummaryToSection(object.function,
!                                  object._section, object._field)
  
  
    #
***************
*** 237,246 ****
--- 232,249 ----
          if child._type == "_content_":
            dest.write(child.getContent())
          else:
+           # Handle GRSections specially as
+           # they require extra logic
            if isinstance(child, GRSection):
+ 
+             # If this is the top-most section for a datasource,
+             # it needs to be called with processAsController.
              if child._mymapper.toplevel:
                GDebug.printMesg(10, "Calling new controlling section")
+ 
                child.processAsController(dest, mapper)
+ 
+             # ..otherwise call the GRSection's process method.
              else:
                nextSection = child.process(dest, mapper,
                   isfirst=1,
***************
*** 250,255 ****
--- 253,259 ----
                   nextSection=nextSection)
  
            else:
+             # Handle the layout element.
              nextSection = child.process(dest, mapper, first, islast,
                                          firstSection, nextSection)
  
***************
*** 316,327 ****
        self.process(dest, mapper, 1, 1, None, None)
  
      else:
-       if mapper.getFirstRecord(self._source):
-         # This is a data-bound section and there
-         # was data returned, so process section
  
!         firstSection, nextSection = self.getGotos(mapper,1)
  
          self.process(dest, mapper, 1, nextSection == None, self, nextSection)
  
        else:
--- 320,331 ----
        self.process(dest, mapper, 1, 1, None, None)
  
      else:
  
!       firstSection, nextSection = self.getGotos(mapper, 1)
  
+       if firstSection:
+         # This is a data-bound section and there
+         # was data returned, so process section
          self.process(dest, mapper, 1, nextSection == None, self, nextSection)
  
        else:
***************
*** 337,346 ****
    #
    # Used internally to determine next section to move
    #
!   def getGotos(self, mapper, first=0):
      # Determine the next section to process our data.
      # (i.e., handle section grouping)
!     if first:
        goto, gotoNext = mapper.getFirstRecord(self._source)
      else:
        goto, gotoNext = mapper.getNextRecord(self._source)
--- 341,350 ----
    #
    # Used internally to determine next section to move
    #
!   def getGotos(self, mapper, init=0):
      # Determine the next section to process our data.
      # (i.e., handle section grouping)
!     if init:
        goto, gotoNext = mapper.getFirstRecord(self._source)
      else:
        goto, gotoNext = mapper.getNextRecord(self._source)
***************
*** 440,450 ****
        self._section = string.lower(self.section)
      else:
        self._section = None
      return GRLayoutElement._buildObject(self)
  
    def process(self, dest, mapper, isfirst, islast, firstSection, nextSection):
      structuralComment(dest,"<!--[summ:%s]-->" % self.name)
!     dest.write (self._mymapper.getSummary(self.name, self.function, 
self.format))
      structuralComment(dest,"<!--[/summ:%s]-->" % self.name)
      return nextSection
  
--- 444,456 ----
        self._section = string.lower(self.section)
      else:
        self._section = None
+ 
+     self._field = string.lower(self.field)
      return GRLayoutElement._buildObject(self)
  
    def process(self, dest, mapper, isfirst, islast, firstSection, nextSection):
      structuralComment(dest,"<!--[summ:%s]-->" % self.name)
!     dest.write (self._mymapper.getSummary(self._field, self.function, 
self.format))
      structuralComment(dest,"<!--[/summ:%s]-->" % self.name)
      return nextSection
  
Index: gnue/reports/src/GRParser.py
diff -c gnue/reports/src/GRParser.py:1.21 gnue/reports/src/GRParser.py:1.22
*** gnue/reports/src/GRParser.py:1.21   Tue Apr  9 01:00:35 2002
--- gnue/reports/src/GRParser.py        Tue Apr  9 18:55:41 2002
***************
*** 22,28 ****
  # GRParser.py
  #
  # DESCRIPTION:
! # Class that contains a sax based xml processor for GNUe Reports
  #
  # NOTES:
  #
--- 22,28 ----
  # GRParser.py
  #
  # DESCRIPTION:
! # Class that contains a SAX-based xml processor for GNUe Reports
  #
  # NOTES:
  #
Index: gnue/reports/src/GRRun.py
diff -c gnue/reports/src/GRRun.py:1.7 gnue/reports/src/GRRun.py:1.8
*** gnue/reports/src/GRRun.py:1.7       Sat Apr  6 20:20:36 2002
--- gnue/reports/src/GRRun.py   Tue Apr  9 18:55:41 2002
***************
*** 63,73 ****
            'and fax. Note that printer, email, and fax are sent via the '
            'server\'s machine, not the client\'s machine.  To '
            '\nNOTE: Only file, printer, and email are currently implemented!' 
],
!       [ 'destination', 'p', 'destination', 1, '-', 'dest',
            'Where should the report be output to?  The value of this '
            'depends on the destination type (e.g., if sending to printer, '
!           'then -p specifies the printer name; if sending via email, then '
!           '-p specifies the email address.) If <dest> is "-", then output is '
            'sent to stdout -- NOTE: when sending to stdout, also use the -q '
            '[--quiet] option or you may get junk in your output stream. '
            'NOTE: Currently the default value is "-" -- this may change once 
GNUe '
--- 63,73 ----
            'and fax. Note that printer, email, and fax are sent via the '
            'server\'s machine, not the client\'s machine.  To '
            '\nNOTE: Only file, printer, and email are currently implemented!' 
],
!       [ 'destination', 'd', 'destination', 1, '-', 'dest',
            'Where should the report be output to?  The value of this '
            'depends on the destination type (e.g., if sending to printer, '
!           'then -d specifies the printer name; if sending via email, then '
!           '-d specifies the email address.) If <dest> is "-", then output is '
            'sent to stdout -- NOTE: when sending to stdout, also use the -q '
            '[--quiet] option or you may get junk in your output stream. '
            'NOTE: Currently the default value is "-" -- this may change once 
GNUe '



reply via email to

[Prev in Thread] Current Thread [Next in Thread]