Methods

Class Index [+]

Quicksearch

TaskJuggler::TjpSyntaxRules

This module contains the rule definition for the TJP syntax. Every rule is put in a function who’s name must start with rule_. The functions are not necessary but make the file more readable and receptable to syntax folding.

Public Instance Methods

rule_absoluteTaskId() click to toggle source
    # File lib/taskjuggler/TjpSyntaxRules.rb, line 21
21:   def rule_absoluteTaskId
22:     pattern(%( !taskIdUnverifd ), lambda {
23:       id = (@taskprefix.empty? ? '' : @taskprefix + '.') + @val[0]
24:       if (task = @project.task(id)).nil?
25:         error('unknown_abs_task', "Unknown task #{id}", @sourceFileInfo[0])
26:       end
27:       task
28:     })
29:   end
rule_account() click to toggle source
    # File lib/taskjuggler/TjpSyntaxRules.rb, line 31
31:   def rule_account
32:     pattern(%( !accountHeader !accountBody ), lambda {
33:        @property = @property.parent
34:     })
35:     doc('account', Declares an account. Accounts can be used to calculate costs of tasks or thewhole project. Account declaration may be nested, but only leaf accounts maybe used to track turnover. When the cost of a task is split over multipleaccounts they all must have the same top-level group account. Top-levelaccounts can be used for profit/loss calculations. The sub-account structureof a top-level account should be organized accordingly.Accounts have a global name space. All IDs must be unique within the accounts of the project.
36:        )
37:     example('Account', '1')
38:   end
rule_accountAttributes() click to toggle source
    # File lib/taskjuggler/TjpSyntaxRules.rb, line 49
49:   def rule_accountAttributes
50:     repeatable
51:     optional
52:     pattern(%( !account))
53:     pattern(%( !accountScenarioAttributes ))
54:     pattern(%( !scenarioIdCol !accountScenarioAttributes ), lambda {
55:       @scenarioIdx = 0
56:     })
57:     # Other attributes will be added automatically.
58:   end
rule_accountBody() click to toggle source
    # File lib/taskjuggler/TjpSyntaxRules.rb, line 60
60:   def rule_accountBody
61:     optionsRule('accountAttributes')
62:   end
rule_accountHeader() click to toggle source
    # File lib/taskjuggler/TjpSyntaxRules.rb, line 64
64:   def rule_accountHeader
65:     pattern(%( _account !optionalID $STRING ), lambda {
66:       if @property.nil? && !@accountprefix.empty?
67:         @property = @project.accout(@accountprefix)
68:       end
69:       if @val[1] && @project.account(@val[1])
70:         error('account_exists', "Account #{@val[1]} has already been defined.",
71:               @sourceFileInfo[1], @property)
72:       end
73:       @property = Account.new(@project, @val[1], @val[2], @property)
74:       @property.sourceFileInfo = @sourceFileInfo[0]
75:       @property.inheritAttributes
76:       @scenarioIdx = 0
77:     })
78:     arg(2, 'name', 'A name or short description of the account')
79:   end
rule_accountId() click to toggle source
    # File lib/taskjuggler/TjpSyntaxRules.rb, line 81
81:   def rule_accountId
82:     pattern(%( $ID ), lambda {
83:       id = @val[0]
84:       id = @accountprefix + '.' + id unless @accountprefix.empty?
85:       # In case we have a nested supplement, we need to prepend the parent ID.
86:       id = @property.fullId + '.' + id if @property && @property.is_a?(Account)
87:       if (account = @project.account(id)).nil?
88:         error('unknown_account', "Unknown account #{id}", @sourceFileInfo[0])
89:       end
90:       account
91:     })
92:   end
rule_accountScenarioAttributes() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 94
 94:   def rule_accountScenarioAttributes
 95:     pattern(%( _credit !valDate $STRING !number ), lambda {
 96:       #@property['credit', @scenarioIdx] +=
 97:       #  AccountCredit.new(@val[1], @val[2], @val[3])
 98:     })
 99:     doc('credit', Book the specified amount to the account at the specified date.
100:        )
101:     example('Account', '1')
102:     arg(2, 'description', 'Short description of the transaction')
103:     arg(3, 'amount', 'Amount to be booked.')
104: 
105:     pattern(%( !flags ))
106:     doc('flags.account', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
107:        )
108: 
109:     # Other attributes will be added automatically.
110:   end
rule_alertLevel() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 117
117:   def rule_alertLevel
118:     pattern(%( $ID ), lambda {
119:       level = @project.alertLevelIndex(@val[0])
120:       unless level
121:         error('bad_alert', "Unknown alert level #{@val[1]}. Must be " +
122:               'green, yellow or red', @sourceFileInfo[0])
123:       end
124:       level
125:     })
126:     doc('alert level', Specify the alert level for this entry. Supported values are green, yellow andred. The default value is green. This attribute is inteded to be used forstatus reporting. When used for a journal entry that is associated with aproperty, the value can be reported in the alert column. When multiple entrieshave been specified for the property, the entry with the date closest to thereport end date will be used. Container properties will inherit the highestalert level of all its sub properties unless it has an own journal entry datedcloser to the report end than all of its sub properties.
127:        )
128:   end
rule_allocate() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 139
139:   def rule_allocate
140:     pattern(%( _allocate !allocations ), lambda {
141:       checkContainer('allocate')
142:       # Don't use << operator here so the 'provided' flag gets set properly.
143:       begin
144:         @property['allocate', @scenarioIdx] =
145:           @property['allocate', @scenarioIdx] + @val[1]
146:       rescue AttributeOverwrite
147:         # Adding multiple allocates for a task is a pretty common idiom.
148:       end
149:     })
150:     doc('allocate', Specify which resources should be allocated to the task. Theattributes provide numerous ways to control which resource is used and whenexactly it will be assigned to the task. Shifts and limits can be used torestrict the allocation to certain time intervals or to limit them to acertain maximum per time period. The purge statement can be used to removeinherited allocations or flags.
151:        )
152:     example('Allocate-1', '1')
153:   end
rule_allocation() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 162
162:   def rule_allocation
163:     pattern(%( !allocationHeader !allocationBody ), lambda {
164:       @val[0]
165:     })
166:   end
rule_allocationAttributes() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 168
168:   def rule_allocationAttributes
169:     optional
170:     repeatable
171: 
172:     pattern(%( _alternative !resourceId !moreAlternatives ), lambda {
173:       ([ @val[1] ] + (@val[2] ? @val[2] : [])).each do |candidate|
174:         @allocate.addCandidate(candidate)
175:       end
176:     })
177:     doc('alternative', Specify which resources should be allocated to the task. The optionalattributes provide numerous ways to control which resource is used and whenexactly it will be assigned to the task. Shifts and limits can be used torestrict the allocation to certain time intervals or to limit them to acertain maximum per time period.
178:        )
179:     example('Alternative', '1')
180: 
181:     pattern(%( !limits ), lambda {
182:       limits = @property['limits', @scenarioIdx] = @val[0]
183:       @allocate.candidates.each do |resource|
184:          limits.limits.each do |l|
185:            l.resource = resource if resource.leaf?
186:          end
187:       end
188:     })
189:     doc('limits.allocate', 'This keyword is deprecated. Don\t use it anymore!')
190: 
191:     pattern(%( _select !allocationSelectionMode ), lambda {
192:       @allocate.setSelectionMode(@val[1])
193:     })
194:     doc('select', The select functions controls which resource is picked from an allocation andit's alternatives. The selection is re-evaluated each time the resource usedin the previous time slot becomes unavailable.Even for non-persistent allocations a change in the resource selection onlyhappens if the resource used in the previous (or next for ASAP tasks) timeslot has become unavailable.
195:        )
196: 
197:     pattern(%( _persistent ), lambda {
198:       @allocate.persistent = true
199:     })
200:     doc('persistent', Specifies that once a resource is picked from the list of alternatives thisresource is used for the whole task. This is useful when several alternativeresources have been specified. Normally the selected resource can change aftereach break. A break is an interval of at least one timeslot where no resourceswere available.
201:        )
202: 
203:     pattern(%( _mandatory ), lambda {
204:       @allocate.mandatory = true
205:     })
206:     doc('mandatory', Makes a resource allocation mandatory. This means, that for each time slotonly then resources are allocated when all mandatory resources are available.So either all mandatory resources can be allocated for the time slot, or noresource will be allocated.
207:        )
208:     pattern(%( _shift !allocationShiftAssignment ))
209:     doc('shifts.allocate', Limits the allocations of resources during the specified interval to thespecified shift. Multiple shifts can be defined, but shift intervals may notoverlap. Allocation shifts are an additional restriction to the[[shifts.task|task shifts]] and [[shifts.resource|resource shifts]] or[[workinghours.resource|resource working hours]]. Allocations will only bemade for time slots that are specified as duty time in all relevant shifts.The restriction to the shift is only active during the specified timeinterval. Outside of this interval, no restrictions apply.
210:        )
211:   end
rule_allocationBody() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 247
247:   def rule_allocationBody
248:     optionsRule('allocationAttributes')
249:   end
rule_allocationHeader() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 251
251:   def rule_allocationHeader
252:     pattern(%( !resourceId ), lambda {
253:       @allocate = Allocation.new([ @val[0] ])
254:     })
255:   end
rule_allocationSelectionMode() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 261
261:   def rule_allocationSelectionMode
262:     singlePattern('_maxloaded')
263:     descr('Pick the available resource that has been used the most so far.')
264: 
265:     singlePattern('_minloaded')
266:     descr('Pick the available resource that has been used the least so far.')
267: 
268:     singlePattern('_minallocated')
269:     descr(Pick the resource that has the smallest allocation factor. Theallocation factor is calculated from the various allocations of the resourceacross the tasks. This is the default setting.)
270:          )
271: 
272:     singlePattern('_order')
273:     descr('Pick the first available resource from the list.')
274: 
275:     singlePattern('_random')
276:     descr('Pick a random resource from the list.')
277:   end
rule_allocationShiftAssignment() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 283
283:   def rule_allocationShiftAssignment
284:     pattern(%( !shiftId !intervalsOptional ), lambda {
285:       # Make sure we have a ShiftAssignment for the allocation.
286:       if @allocate.shifts.nil?
287:         @allocate.shifts = ShiftAssignments.new
288:         @allocate.shifts.project = @project
289:       end
290: 
291:       if @val[1].nil?
292:         intervals = [ Interval.new(@project['start'], @project['end']) ]
293:       else
294:         intervals = @val[1]
295:       end
296:       intervals.each do |interval|
297:         if !@allocate.shifts.
298:           addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx),
299:                                             interval))
300:           error('shift_assignment_overlap',
301:                 'Shifts may not overlap each other.', @sourceFileInfo[0])
302:         end
303:       end
304:     })
305:   end
rule_allocations() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 257
257:   def rule_allocations
258:     listRule('moreAllocations', '!allocation')
259:   end
rule_argument() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 307
307:   def rule_argument
308:     singlePattern('$ABSOLUTE_ID')
309:     singlePattern('!date')
310:     singlePattern('$ID')
311:     singlePattern('$INTEGER')
312:     singlePattern('$FLOAT')
313:   end
rule_argumentList() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 315
315:   def rule_argumentList
316:     optional
317:     pattern(%( _( !argumentListBody _) ), lambda {
318:       @val[1].nil? ? [] : @val[1]
319:     })
320:   end
rule_argumentListBody() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 322
322:   def rule_argumentListBody
323:     optional
324:     pattern(%( !argument !moreArguments ), lambda {
325:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
326:     })
327:   end
rule_author() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 329
329:   def rule_author
330:     pattern(%( _author !resourceId ), lambda {
331:       @journalEntry.author = @val[1]
332:     })
333:     doc('author', This attribute can be used to capture the authorship or source of theinformation.
334:        )
335:   end
rule_balance() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 340
340:   def rule_balance
341:     pattern(%( _balance !accountId !accountId ), lambda {
342:       if @val[1].parent
343:         error('cost_acct_no_top',
344:               "The cost account #{@val[1].fullId} is not a top-level account.",
345:               @sourceFileInfo[1])
346:       end
347:       if @val[2].parent
348:         error('rev_acct_no_top',
349:               "The revenue account #{@val[2].fullId} is not a top-level " +
350:               "account.", @sourceFileInfo[2])
351:       end
352:       if @val[1] == @val[2]
353:         error('cost_rev_same',
354:               'The cost and revenue accounts may not be the same.',
355:               @sourceFileInfo[1])
356:       end
357:       [ @val[1], @val[2] ]
358:     })
359:     doc('balance', During report generation, TaskJuggler can consider some accounts to be revenue accounts, while other can be considered cost accounts. By using the balance attribute, two top-level accounts can be designated for a profit-loss-analysis. This analysis includes all sub accounts of these two top-level accounts.
360:        )
361:     arg(1, 'cost account', The top-level account that is used for all cost related charges.
362:        )
363:     arg(2, 'revenue account', The top-level account that is used for all revenue related charges.
364:        )
365:   end
rule_bookingAttributes() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 373
373:   def rule_bookingAttributes
374:     optional
375:     repeatable
376: 
377:     pattern(%( _overtime $INTEGER ), lambda {
378:       if @val[1] < 0 || @val[1] > 2
379:         error('overtime_range',
380:               "Overtime value #{@val[1]} out of range (0 - 2).",
381:               @sourceFileInfo[1], @property)
382:       end
383:       @booking.overtime = @val[1]
384:     })
385:     doc('overtime.booking', This attribute enables bookings during off-hours and vacations. It implicitlysets the [[sloppy.booking|sloppy]] attribute accordingly.
386:        )
387:     arg(1, 'value', * '''0''': You can only book available working time. (Default)* '''1''': You can book off-hours as well.* '''2''': You can book working time, off-hours and vacation time.
388:        )
389: 
390:     pattern(%( _sloppy $INTEGER ), lambda {
391:       if @val[1] < 0 || @val[1] > 2
392:         error('sloppy_range',
393:               "Sloppyness value #{@val[1]} out of range (0 - 2).",
394:               @sourceFileInfo[1], @property)
395:       end
396:       @booking.sloppy = @val[1]
397:     })
398:     doc('sloppy.booking', Controls how strict TaskJuggler checks booking intervals for conflicts withworking periods and vacations. This attribute only affects the check forconflicts. No assignments will be made unless the [[overtime.booking|overtime]] attribute is set accordingly.
399:        )
400:     arg(1, 'sloppyness', * '''0''': Period may not contain any off-duty hours, vacation or other taskassignments. (default)* '''1''': Period may contain off-duty hours, but no vacation time or othertask assignments.* '''2''': Period may contain off-duty hours and vacation time, but no othertask assignments.
401:        )
402:   end
rule_bookingBody() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 427
427:   def rule_bookingBody
428:     optionsRule('bookingAttributes')
429:   end
rule_calendarDuration() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 431
431:   def rule_calendarDuration
432:     pattern(%( !number !durationUnit ), lambda {
433:       convFactors = [ 60.0, # minutes
434:                       60.0 * 60, # hours
435:                       60.0 * 60 * 24, # days
436:                       60.0 * 60 * 24 * 7, # weeks
437:                       60.0 * 60 * 24 * 30.4167, # months
438:                       60.0 * 60 * 24 * 365 # years
439:                      ]
440:       ((@val[0] * convFactors[@val[1]]) / @project['scheduleGranularity']).to_i
441:     })
442:     arg(0, 'value', 'A floating point or integer number')
443:   end
rule_chargeMode() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 484
484:   def rule_chargeMode
485:     singlePattern('_onstart')
486:     descr('Charge the amount on starting the task.')
487: 
488:     singlePattern('_onend')
489:     descr('Charge the amount on finishing the task.')
490: 
491:     singlePattern('_perhour')
492:     descr('Charge the amount for every hour the task lasts.')
493: 
494:     singlePattern('_perday')
495:     descr('Charge the amount for every day the task lasts.')
496: 
497:     singlePattern('_perweek')
498:     descr('Charge the amount for every week the task lasts.')
499:   end
rule_chargeSetItem() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 501
501:   def rule_chargeSetItem
502:     pattern(%( !accountId !optionalPercent ), lambda {
503:       [ @val[0], @val[1] ]
504:     })
505:     arg(0, 'account', 'The ID of a previously defined leaf account.')
506:     arg(1, 'share', 'A percentage between 0 and 100%')
507:   end
rule_chargeset() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 445
445:   def rule_chargeset
446:     pattern(%( _chargeset !chargeSetItem !moreChargeSetItems ), lambda {
447:       checkContainer('chargeset')
448:       items = [ @val[1] ]
449:       items += @val[2] if @val[2]
450:       chargeSet = ChargeSet.new
451:       begin
452:         items.each do |item|
453:           chargeSet.addAccount(item[0], item[1])
454:         end
455:         chargeSet.complete
456:       rescue TjException
457:         error('chargeset', $!.message, @sourceFileInfo[0], @property)
458:       end
459:       masterAccounts = []
460:       @property['chargeset', @scenarioIdx].each do |set|
461:         masterAccounts << set.master
462:       end
463:       if masterAccounts.include?(chargeSet.master)
464:         error('chargeset_master',
465:               "All charge sets for this task must have different top-level " +
466:               "accounts.", @sourceFileInfo[0], @property)
467:       end
468:       @property['chargeset', @scenarioIdx] =
469:         @property['chargeset', @scenarioIdx] + [ chargeSet ]
470:     })
471:     doc('chargeset', A chargeset defines how the turnover associated with the task will be chargedto one or more accounts. A task may have any number of charge sets, but eachchargeset must deal with a different top-level account. A charge set consistsof one or more accounts. Each account must be a leaf account. The account IDmay be followed by a percentage value that determines the share for thisaccount. The total percentage of all accounts must be exactly 100%. If someaccounts don't have a percentage specification, the remainder to 100% isdistributed evenly to them.
472:        )
473:   end
rule_chartScale() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 509
509:   def rule_chartScale
510:     singlePattern('_hour')
511:     descr('Set chart resolution to 1 hour.')
512: 
513:     singlePattern('_day')
514:     descr('Set chart resolution to 1 day.')
515: 
516:     singlePattern('_week')
517:     descr('Set chart resolution to 1 week.')
518: 
519:     singlePattern('_month')
520:     descr('Set chart resolution to 1 month.')
521: 
522:     singlePattern('_quarter')
523:     descr('Set chart resolution to 1 quarter.')
524: 
525:     singlePattern('_year')
526:     descr('Set chart resolution to 1 year.')
527:   end
rule_color() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 529
529:   def rule_color
530:     pattern(%( $STRING ), lambda {
531:       col = @val[0]
532:       unless /#[0-9A-Fa-f]{3}/ =~ col || /#[0-9A-Fa-f]{3}/ =~ col
533:         error('bad_color',
534:               "Color values must be specified as '#RGB' or '#RRGGBB' values",
535:               @sourceFileInfo[0])
536:       end
537:       col
538:     })
539:     arg(0, 'color', The RGB color values of the color. The following formats are supported: #RGBand #RRGGBB. Where R, G, B are hexadecimal values. See[http://en.wikipedia.org/wiki/Web_colors Wikipedia] for more details.
540:        )
541:   end
rule_columnBody() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 547
547:   def rule_columnBody
548:     optionsRule('columnOptions')
549:   end
rule_columnDef() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 551
551:   def rule_columnDef
552:     pattern(%( !columnId !columnBody ), lambda {
553:       @val[0]
554:     })
555:   end
rule_columnId() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 557
557:   def rule_columnId
558:     pattern(%( !reportableAttributes ), lambda {
559:       title = TableReport.defaultColumnTitle(@val[0]) ||
560:               @project.attributeName(@val[0])
561:       @column = TableColumnDefinition.new(@val[0], title)
562:     })
563:     doc('columnid', This is a comprehensive list of all pre-defined [[columns]]. In addition tothe listed IDs all user defined attributes can be used as column IDs.
564:        )
565:   end
rule_columnOptions() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 570
570:   def rule_columnOptions
571:     optional
572:     repeatable
573: 
574:     pattern(%( _celltext !logicalExpression $STRING ), lambda {
575:       @column.cellText.addPattern(
576:         CellSettingPattern.new(newRichText(@val[2], @sourceFileInfo[2]),
577:                                @val[1]))
578:     })
579:     doc('celltext.column', Specifies an alternative content that is used for the cells of the column.Usually such a text contains a query function. Otherwise all cells of thecolumn will have the same fixed value. The logical expression specifies forwhich cells the text should be used. If multiple celltext patterns areprovided for a column, the first matching one is taken for each cell.
580:         )
581:     arg(1, 'text',
582:         'Alterntive cell text specified as [[Rich_Text_Attributes|Rich Text]]')
583: 
584:     pattern(%( _cellcolor !logicalExpression !color ), lambda {
585:       @column.cellColor.addPattern(
586:         CellSettingPattern.new(@val[2], @val[1]))
587:     })
588:     doc('cellcolor.column', Specifies an alternative background color for the cells of this column. Thelogical expression specifies for which cells the color should be used. Ifmultiple cellcolor patterns are provided for a column, the firstmatching one is used for each cell.
589:        )
590: 
591:     pattern(%( _end !date ), lambda {
592:       @column.end = @val[1]
593:     })
594:     doc('end.column', Normally, columns with calculated values take the specified report period intoaccount when calculating their values. With this attribute, the user canspecify an end date for the period that should be used when calculating thevalues of this column. It does not have an impact on column with timeinvariant values.
595:        )
596: 
597:     pattern(%( _fontcolor !logicalExpression !color ), lambda {
598:       @column.fontColor.addPattern(
599:         CellSettingPattern.new(@val[2], @val[1]))
600:     })
601:     doc('fontcolor.column', Specifies an alternative font color for the cells of this column. Thelogical expression specifies for which cells the color should be used. Ifmultiple fontcolor patterns are provided for a column, the firstmatching one is used for each cell.
602:        )
603: 
604:     pattern(%( _halign !logicalExpression !hAlignment ), lambda {
605:       @column.hAlign.addPattern(
606:         CellSettingPattern.new(@val[2], @val[1]))
607:     })
608:     doc('halign.column', Specifies the horizontal alignment of the cell content. The logical expressionspecifies for which cells the alignment setting should be used. If multiplehalign patterns are provided for a column, the first matching one is used foreach cell.
609:        )
610: 
611:     pattern(%( _listitem $STRING ), lambda {
612:       @column.listItem = @val[1]
613:     })
614:     doc('listitem.column', Specifies a RichText pattern that is used to generate the text for the listitems. The pattern should contain at least one ''''<nowiki><</nowiki>-queryattribute='XXX'->'''' element that will be replaced with the value ofattribute XXX. For the replacement, the property of the query will be the listitem.
615:        )
616: 
617:     pattern(%( _listtype !listType ), lambda {
618:       @column.listType = @val[1]
619:     })
620:     also(%( listitem.column ))
621:     doc('listtype.column', Specifies what type of list should be used. This attribute only affectscolumns that contain a list of items.
622:        )
623: 
624:     pattern(%( _period !interval ), lambda {
625:       @column.start = @val[1].start
626:       @column.end = @val[1].end
627:     })
628:     doc('period.column', This property is a shortcut for setting the [[start.column|start]] and[[end.column|end]] property at the same time.
629:        )
630: 
631:     pattern(%( _scale !chartScale ), lambda {
632:       @column.scale = @val[1]
633:     })
634:     doc('scale.column', Specifies the scale that should be used for a chart column. This value is ignored for all other columns.
635:        )
636: 
637:     pattern(%( _start !date ), lambda {
638:       @column.start = @val[1]
639:     })
640:     doc('start.column', Normally, columns with calculated values take the specified report period intoaccount when calculating their values. With this attribute, the user canspecify a start date for the period that should be used when calculating thevalues of this column. It does not have an impact on column with timeinvariant values.
641:        )
642: 
643:     pattern(%( _title $STRING ), lambda {
644:       @column.title = @val[1]
645:     })
646:     doc('title.column', Specifies an alternative title for a report column.
647:        )
648:     arg(1, 'text', 'The new column title.')
649: 
650:     pattern(%( _tooltip !logicalExpression $STRING ), lambda {
651:       @column.tooltip.addPattern(
652:         CellSettingPattern.new(newRichText(@val[2], @sourceFileInfo[2]),
653:                                @val[1]))
654:     })
655:     doc('tooltip.column', Specifies an alternative content for the tooltip. This will replace theoriginal content of the tooltip that would be available for columns with textthat does not fit the column with.  The logical expression specifies for whichcells the text should be used. If multiple tooltip patterns are provided for acolumn, the first matching one is taken for each cell.
656:        )
657:     arg(2, 'text', The content of the tooltip. The text is interpreted as [[Rich_Text_Attributes|Rich Text]].
658:        )
659: 
660:     pattern(%( _width !number ), lambda {
661:       @column.width = @val[1]
662:     })
663:     doc('width.column', Specifies the width of the column in screen pixels. If the content of thecolumn does not fit into this width, it will be cut off. In some cases ascrollbar is added or a tooltip window with the complete content is shown whenthe mouse is moved over the column. The latter is only supported ininteractive output formats.
664:        )
665:   end
rule_currencyFormat() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 731
731:   def rule_currencyFormat
732:     pattern(%( _currencyformat $STRING $STRING $STRING $STRING $INTEGER ),
733:         lambda {
734:       RealFormat.new(@val.slice(1, 5))
735:     })
736:     doc('currencyformat',
737:         'These values specify the default format used for all currency ' +
738:         'values.')
739:     example('Currencyformat')
740:     arg(1, 'negativeprefix', 'Prefix for negative numbers')
741:     arg(2, 'negativesuffix', 'Suffix for negative numbers')
742:     arg(3, 'thousandsep', 'Separator used for every 3rd digit')
743:     arg(4, 'fractionsep', 'Separator used to separate the fraction digits')
744:     arg(5, 'fractiondigits', 'Number of fraction digits to show')
745:   end
rule_date() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 747
747:   def rule_date
748:     pattern(%( !dateCalcedOrNot ), lambda {
749:       resolution = @project.nil? ? Project.maxScheduleGranularity :
750:                                    @project['scheduleGranularity']
751:       if @val[0] % resolution != 0
752:         error('misaligned_date',
753:               "The date must be aligned to the timing resolution (" +
754:               "#{resolution / 60} min) of the project.",
755:               @sourceFileInfo[0])
756:       end
757:       @val[0]
758:     })
759:     doc('date', A DATE is an ISO-compliant date in the format''''<nowiki>YYYY-MM-DD[-hh:mm[:ss]][-TIMEZONE]</nowiki>''''. Hour, minutes,seconds, and the ''''TIMEZONE'''' are optional. If not specified, the valuesare set to 0.  ''''TIMEZONE'''' must be an offset to GMT or UTC, specified as''''+HHMM'''' or ''''-HHMM''''. Dates must always be aligned with the[[timingresolution]].TaskJuggler also supports simple date calculations. You can add or substract agiven interval from a fixed date. %{2009-11-01 + 8m}This will result in an actual date of around 2009-07-01. Keep in mind that due to the varying lengths of months TaskJuggler cannot add exactly 8 calendar months. The date calculation functionality makes most sense when used with macros. %{${now} - 2w}This is result in a date 2 weeks earlier than the current (or specified) date.See [[duration]] for a complete list of supported time intervals. Don't forgetto put at least one space character after the date to prevent TaskJuggler frominterpreting the interval as an hour.
760:        )
761:   end
rule_dateCalcedOrNot() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 784
784:   def rule_dateCalcedOrNot
785:     singlePattern('$DATE')
786:     pattern(%( _% _{ $DATE !plusOrMinus !intervalDuration _} ), lambda {
787:       @val[2] + ((@val[3] == '+' ? 1 : 1) * @val[4])
788:     })
789:   end
rule_declareFlagList() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 791
791:   def rule_declareFlagList
792:     listRule('moreDeclareFlagList', '$ID')
793:   end
rule_details() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 795
795:   def rule_details
796:     pattern(%( _details $STRING ), lambda {
797:       return if @val[1].empty?
798: 
799:       rtTokenSetMore =
800:         [ :LINEBREAK, :SPACE, :WORD, :BOLD, :ITALIC, :CODE, :BOLDITALIC,
801:           :PRE, :HREF, :HREFEND, :REF, :REFEND, :HLINE, :TITLE2, :TITLE3,
802:           :TITLE4, :TITLE2END, :TITLE3END, :TITLE4END,
803:           :BULLET1, :BULLET2, :BULLET3, :BULLET4, :NUMBER1, :NUMBER2, :NUMBER3,
804:           :NUMBER4 ]
805:       if @val[1] == "Some more details\n"
806:         error('ts_default_details',
807:               "'Some more details' is not a valid value",
808:               @sourceFileInfo[1])
809:       end
810:       @journalEntry.details = newRichText(@val[1], @sourceFileInfo[1],
811:                                           rtTokenSetMore)
812:     })
813:     doc('details', This is a continuation of the [[summary]] of the journal or status entry. Itcan be several paragraphs long.
814:        )
815:     arg(1, 'text', The text will be interpreted as [[Rich_Text_Attributes|Rich Text]]. Only asubset of the markup is supported for this attribute. You can use wordformatting, paragraphs, hyperlinks, lists, section and subsectionheaders.
816:        )
817:   end
rule_durationUnit() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 827
827:   def rule_durationUnit
828:     pattern(%( _min ), lambda { 0 })
829:     descr('minutes')
830: 
831:     pattern(%( _h ), lambda { 1 })
832:     descr('hours')
833: 
834:     pattern(%( _d ), lambda { 2 })
835:     descr('days')
836: 
837:     pattern(%( _w ), lambda { 3 })
838:     descr('weeks')
839: 
840:     pattern(%( _m ), lambda { 4 })
841:     descr('months')
842: 
843:     pattern(%( _y ), lambda { 5 })
844:     descr('years')
845:   end
rule_durationUnitOrPercent() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 847
847:   def rule_durationUnitOrPercent
848:     pattern(%( _% ), lambda { 1 })
849:     descr('percentage of reported period')
850: 
851:     pattern(%( _min ), lambda { 0 })
852:     descr('minutes')
853: 
854:     pattern(%( _h ), lambda { 1 })
855:     descr('hours')
856: 
857:     pattern(%( _d ), lambda { 2 })
858:     descr('days')
859:   end
rule_export() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 861
861:   def rule_export
862:     pattern(%( !exportHeader !exportBody ), lambda {
863:       @property = nil
864:     })
865:     doc('export', The export report looks like a regular TaskJuggler file with the providedinput data complemented by the results of the scheduling process. The contentof the report can be controlled with the [[definitions]] attribute. In casethe file contains the project header, a ''''.tjp'''' extension is added to thefile name. Otherwise, a ''''.tji'''' extension is used.The [[resourceattributes]] and [[taskattributes]] attributes provide even morecontrol over the content of the file.The export report can be used to share certain tasks or milestones with otherprojects or to save past resource allocations as immutable part for futurescheduling runs. When an export report is included the project IDs of theincluded tasks must be declared first with the project id property.
866:        )
867:     example('Export')
868:   end
rule_exportAttributes() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 907
907:   def rule_exportAttributes
908:     optional
909:     repeatable
910: 
911:     pattern(%( _definitions !exportDefinitions ), lambda {
912:       @property.set('definitions', @val[1])
913:     })
914:     doc('definitions', This attributes controls what definitions will be contained in the report. Ifthe list includes ''project'', the generated file will have a ''''.tjp''''extension. Otherwise it will have a ''''.tji'''' extension.By default, the report contains everything and the generated files has a ''''.tjp'''' extension.
915:        )
916:     allOrNothingListRule('exportDefinitions',
917:                          { 'flags' => 'Include flag definitions',
918:                            'project' => 'Include project header',
919:                            'projecids' => 'Include project IDs',
920:                            'tasks' => 'Include task definitions',
921:                            'resources' => 'Include resource definitions' })
922:     pattern(%( !hideresource ))
923:     pattern(%( !hidetask ))
924:     pattern(%( !reportEnd ))
925:     pattern(%( !reportPeriod ))
926:     pattern(%( !reportStart ))
927: 
928:     pattern(%( _resourceattributes !exportableResourceAttributes ), lambda {
929:       @property.set('resourceAttributes', @val[1])
930:     })
931:     doc('resourceattributes', Define a list of resource attributes that should be included in the report.
932:        )
933:     allOrNothingListRule('exportableResourceAttributes',
934:                          { 'vacation' => 'Include vacations',
935:                            'workinghours' => 'Include working hours' })
936: 
937:     pattern(%( !rollupresource ))
938:     pattern(%( !rolluptask ))
939: 
940:     pattern(%( _scenarios !scenarioIdList ), lambda {
941:       # Don't include disabled scenarios in the report
942:       @val[1].delete_if { |sc| !@project.scenario(sc).get('active') }
943:       @property.set('scenarios', @val[1])
944:     })
945:     doc('scenarios.export', List of scenarios that should be included in the report. By default, allscenarios will be included. This attribute can be used to limit the includedscenarios to a defined list.
946:        )
947: 
948:     pattern(%( _taskattributes !exportableTaskAttributes ), lambda {
949:       @property.set('taskAttributes', @val[1])
950:     })
951:     doc('taskattributes', Define a list of task attributes that should be included in the report.
952:        )
953:     allOrNothingListRule('exportableTaskAttributes',
954:                          { 'booking' => 'Include bookings',
955:                            'complete' => 'Include completion values',
956:                            'depends' => 'Include dependencies',
957:                            'flags' => 'Include flags',
958:                            'maxend' => 'Include maximum end dates',
959:                            'maxstart' => 'Include maximum start dates',
960:                            'minend' =>  'Include minimum end dates',
961:                            'minstart' => 'Include minimum start dates',
962:                            'note' => 'Include notes',
963:                            'priority' => 'Include priorities',
964:                            'responsible' => 'Include responsible resource' })
965: 
966:     pattern(%( _timezone !validTimeZone ), lambda {
967:       @property.set('timezone', @val[1])
968:     })
969:     doc('timezone.export',
970:         "Set the time zone to be used for all dates in the report.")
971:   end
rule_exportBody() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 987
987:   def rule_exportBody
988:     optionsRule('exportAttributes')
989:   end
rule_exportHeader() click to toggle source
     # File lib/taskjuggler/TjpSyntaxRules.rb, line 884
884:   def rule_exportHeader
885:     pattern(%( _export !optionalID $STRING ), lambda {
886:       report = newReport(@val[1], @val[2], :export, sourceFileInfo)
887: 
888:       # By default, we export all scenarios.
889:       scenarios = Array.new(@project.scenarios.items) { |i| i }
890:       scenarios.delete_if { |sc| !@project.scenario(sc).get('active') }
891:       report.set('scenarios', scenarios)
892:       # Show all tasks, sorted by seqno-up.
893:       report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
894:       report.set('sortTasks', [ [ 'seqno', true, 1 ] ])
895:       # Show all resources, sorted by seqno-up.
896:       report.set('hideResource',
897:                   LogicalExpression.new(LogicalOperation.new(0)))
898:       report.set('sortResources', [ [ 'seqno', true, 1 ] ])
899:     })
900:     arg(1, 'file name', The name of the report file to generate. It must end with a .tjp or .tjiextension, or use . to use the standard output channel.
901:        )
902:   end
rule_extendAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 991
 991:   def rule_extendAttributes
 992:     optional
 993:     repeatable
 994: 
 995:     pattern(%( _date !extendId  $STRING !extendOptionsBody ), lambda {
 996:       # Extend the propertySet definition and parser rules
 997:       if extendPropertySetDefinition(DateAttribute, nil)
 998:         @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
 999:           [ '_' + @val[1], '!date' ], lambda {
1000:             @property[@val[0], @scenarioIdx] = @val[1]
1001:           }))
1002:       else
1003:         @ruleToExtend.addPattern(TextParser::Pattern.new(
1004:           [ '_' + @val[1], '!date' ], lambda {
1005:             @property.set(@val[0], @val[1])
1006:           }))
1007:       end
1008:     })
1009:     doc('date.extend', Extend the property with a new attribute of type date.
1010:        )
1011:     arg(2, 'name', 'The name of the new attribute. It is used as header ' +
1012:                    'in report columns and the like.')
1013: 
1014:     pattern(%( _reference !extendId $STRING !extendOptionsBody ), lambda {
1015:       # Extend the propertySet definition and parser rules
1016:       if extendPropertySetDefinition(ReferenceAttribute, nil)
1017:         @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
1018:           [ '_' + @val[1], '$STRING', '!referenceBody' ], lambda {
1019:             @property[@val[0], @scenarioIdx] = [ @val[1], @val[2] ]
1020:           }))
1021:       else
1022:         @ruleToExtend.addPattern(TextParser::Pattern.new(
1023:           [ '_' + @val[1], '$STRING', '!referenceBody' ], lambda {
1024:             @property.set(@val[0], [ @val[1], @val[2] ])
1025:           }))
1026:       end
1027:     })
1028:     doc('reference.extend', Extend the property with a new attribute of type reference. A reference is aURL and an optional text that will be shown instead of the URL if needed.
1029:        )
1030:     arg(2, 'name', 'The name of the new attribute. It is used as header ' +
1031:                    'in report columns and the like.')
1032: 
1033:     pattern(%( _richtext !extendId $STRING !extendOptionsBody ), lambda {
1034:       # Extend the propertySet definition and parser rules
1035:       if extendPropertySetDefinition(RichTextAttribute, nil)
1036:         @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
1037:           [ '_' + @val[1], '$STRING' ], lambda {
1038:             @property[@val[0], @scenarioIdx] =
1039:               newRichText(@val[1], @sourceFileInfo[1])
1040:           }))
1041:       else
1042:         @ruleToExtend.addPattern(TextParser::Pattern.new(
1043:           [ '_' + @val[1], '$STRING' ], lambda {
1044:             @property.set(@val[0], newRichText(@val[1], @sourceFileInfo[1]))
1045:           }))
1046:       end
1047:     })
1048:     doc('richtext.extend', Extend the property with a new attribute of type [[Rich_Text_Attributes|RichText]].
1049:        )
1050:     arg(2, 'name', 'The name of the new attribute. It is used as header ' +
1051:                    'in report columns and the like.')
1052: 
1053:     pattern(%( _text !extendId $STRING !extendOptionsBody ), lambda {
1054:       # Extend the propertySet definition and parser rules
1055:       if extendPropertySetDefinition(StringAttribute, nil)
1056:         @ruleToExtendWithScenario.addPattern(TextParser::Pattern.new(
1057:           [ '_' + @val[1], '$STRING' ], lambda {
1058:             @property[@val[0], @scenarioIdx] = @val[1]
1059:           }))
1060:       else
1061:         @ruleToExtend.addPattern(TextParser::Pattern.new(
1062:           [ '_' + @val[1], '$STRING' ], lambda {
1063:             @property.set(@val[0], @val[1])
1064:           }))
1065:       end
1066:     })
1067:     doc('text.extend', Extend the property with a new attribute of type text. A text is a charactersequence enclosed in single or double quotes.
1068:        )
1069:     arg(2, 'name', 'The name of the new attribute. It is used as header ' +
1070:                    'in report columns and the like.')
1071: 
1072:   end
rule_extendBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1085
1085:   def rule_extendBody
1086:     optionsRule('extendAttributes')
1087:   end
rule_extendId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1089
1089:   def rule_extendId
1090:     pattern(%( $ID ), lambda {
1091:       unless (AA..ZZ) === @val[0][0]
1092:         error('extend_id_cap',
1093:               "User defined attributes IDs must start with a capital letter",
1094:               @sourceFileInfo[0])
1095:       end
1096:       @val[0]
1097:     })
1098:     arg(0, 'id', 'The ID of the new attribute. It can be used like the ' +
1099:                  'built-in IDs.')
1100:   end
rule_extendOptions() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1102
1102:   def rule_extendOptions
1103:     optional
1104:     repeatable
1105: 
1106:     singlePattern('_inherit')
1107:     doc('inherit.extend', If the this attribute is used, the property extension will be inherited bychild properties from their parent property.
1108:        )
1109: 
1110:     singlePattern('_scenariospecific')
1111:     doc('scenariospecific.extend', If this attribute is used, the property extension is scenario specific. Adifferent value can be set for each scenario.
1112:        )
1113:   end
rule_extendOptionsBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1121
1121:   def rule_extendOptionsBody
1122:     optionsRule('extendOptions')
1123:   end
rule_extendProperty() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1125
1125:   def rule_extendProperty
1126:     pattern(%( !extendPropertyId ), lambda {
1127:       case @val[0]
1128:       when 'task'
1129:         @ruleToExtend = @rules[:taskAttributes]
1130:         @ruleToExtendWithScenario = @rules[:taskScenarioAttributes]
1131:         @propertySet = @project.tasks
1132:       when 'resource'
1133:         @ruleToExtend = @rules[:resourceAttributes]
1134:         @ruleToExtendWithScenario = @rules[:resourceScenarioAttributes]
1135:         @propertySet = @project.resources
1136:       end
1137:     })
1138:   end
rule_extendPropertyId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1140
1140:   def rule_extendPropertyId
1141:     singlePattern('_task')
1142:     singlePattern('_resource')
1143:   end
rule_fail() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1145
1145:   def rule_fail
1146:     pattern(%( _fail !logicalExpression ), lambda {
1147:       begin
1148:         @property.set('fail', @property.get('fail') + [ @val[1] ])
1149:       rescue AttributeOverwrite
1150:       end
1151:     })
1152:     doc('fail', The fail attribute adds a logical expression to the property. The conditiondescribed by the logical expression is checked after the scheduling and anerror is raised if the condition evaluates to true. This attribute isprimarily intended for testing purposes.
1153:        )
1154:   end
rule_flag() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1161
1161:   def rule_flag
1162:     pattern(%( $ID ), lambda {
1163:       unless @project['flags'].include?(@val[0])
1164:         error('undecl_flag', "Undeclared flag '#{@val[0]}'",
1165:               @sourceFileInfo[0])
1166:       end
1167:       @val[0]
1168:     })
1169:   end
rule_flagList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1279
1279:   def rule_flagList
1280:     listRule('moreFlagList', '!flag')
1281:   end
rule_flagLogicalExpression() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1171
1171:   def rule_flagLogicalExpression
1172:     pattern(%( !flagOperation ), lambda {
1173:       LogicalExpression.new(@val[0], sourceFileInfo)
1174:     })
1175:     doc('logicalflagexpression', A logical flag expression is a combination of operands and mathematicaloperations.  The final result of a logical expression is always true or false.Logical expressions are used the reduce the properties in a report to acertain subset or to select alternatives for the cell content of a table. Whenused with attributes like [[hidejournalentry]] the logical expressionevaluates to true for a certain property, this property is hidden or rolled-upin the report.Operands must be previously declared flags or another logical expression.When you combine logical operations to a more complex expression, theoperators are evaluated from left to right. '''a | b & c''' is identical to'''(a | b) & c'''. It's highly recommended that you always use brackets tocontrol the evaluation sequence. Currently, TaskJuggler does not support theconcept of operator precedence or right-left associativity. This may change inthe future.
1176:        )
1177:     also(%( functions ))
1178:   end
rule_flagOperand() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1196
1196:   def rule_flagOperand
1197:     pattern(%( _( !flagOperation _) ), lambda {
1198:       @val[1]
1199:     })
1200:     pattern(%( _~ !flagOperand ), lambda {
1201:       operation = LogicalOperation.new(@val[1])
1202:       operation.operator = '~'
1203:       operation
1204:     })
1205: 
1206:     pattern(%( $ID ), lambda {
1207:       unless @project['flags'].include?(@val[0])
1208:         error('operand_unkn_flag', "Undeclared flag '#{@val[0]}'",
1209:               @sourceFileInfo[0])
1210:       end
1211:       LogicalFlag.new(@val[0])
1212:     })
1213:   end
rule_flagOperation() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1215
1215:   def rule_flagOperation
1216:     pattern(%( !flagOperand !flagOperationChain ), lambda {
1217:       operation = LogicalOperation.new(@val[0])
1218:       if @val[1]
1219:         # Further operators/operands create an operation tree.
1220:         @val[1].each do |ops|
1221:           operation = LogicalOperation.new(operation)
1222:           operation.operator = ops[0]
1223:           operation.operand2 = ops[1]
1224:         end
1225:       end
1226:       operation
1227:     })
1228:     arg(0, 'operand', An operand is a declared flag. An operand can be a negated operand byprefixing a ~ charater or it can be another logical expression enclosed inbraces.
1229:         )
1230:   end
rule_flagOperationChain() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1236
1236:   def rule_flagOperationChain
1237:     optional
1238:     repeatable
1239:     pattern(%( !flagOperatorAndOperand), lambda {
1240:       @val[0]
1241:     })
1242:   end
rule_flagOperator() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1256
1256:   def rule_flagOperator
1257:     singlePattern('_|')
1258:     descr('The \or\ operator')
1259: 
1260:     singlePattern('_&')
1261:     descr('The \and\ operator')
1262:   end
rule_flagOperatorAndOperand() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1244
1244:   def rule_flagOperatorAndOperand
1245:     pattern(%( !flagOperator !flagOperand), lambda{
1246:       [ @val[0], @val[1] ]
1247:     })
1248:     arg(1, 'operand', An operand is a declared flag. An operand can be a negated operand byprefixing a ~ charater or it can be another logical expression enclosed inbraces.
1249:         )
1250:   end
rule_flags() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1265
1265:   def rule_flags
1266:     pattern(%( _flags !flagList ), lambda {
1267:       @val[1].each do |flag|
1268:         next if @property['flags', @scenarioIdx].include?(flag)
1269: 
1270:         # We allow multiple instances of flag definitions.
1271:         begin
1272:           @property['flags', @scenarioIdx] << flag
1273:         rescue AttributeOverwrite
1274:         end
1275:       end
1276:     })
1277:   end
rule_formats() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1283
1283:   def rule_formats
1284:     pattern(%( _formats !outputFormats ), lambda {
1285:       @property.set('formats', @val[1])
1286:     })
1287:     doc('formats', This attribute defines for which output formats the report should begenerated. By default, this list is empty. Unless a formats attribute wasadded to a report definition, no output will be generated for this report.As reports are composable, a report may include other report definitions. Aformat definition is only needed for the outermost report that includes theothers.
1288:        )
1289:   end
rule_functionPatterns() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1344
1344:   def rule_functionPatterns
1345:     # This rule is not used by the parser. It's only for the documentation.
1346:     pattern(%( _hasalert _( $INTEGER _, !date _) ))
1347:     doc('hasalert', Will evaluate to true if the current property has a current alert message within the report time frame and with at least the provided alert level.
1348:        )
1349:     arg(2, 'Level', 'The minimum required alert level to be considered.')
1350: 
1351:     pattern(%( _isactive _( $ID _) ))
1352:     doc('isactive', Will evaluate to true for tasks and resources if they have bookings inthe scenario during the report time frame.
1353:        )
1354:     arg(2, 'ID', 'A scenario ID')
1355: 
1356:     pattern(%( _ischildof _( $ID _) ))
1357:     doc('ischildof', Will evaluate to true for tasks and resources if current property is a childof the provided parent property.
1358:        )
1359:     arg(2, 'ID', 'The ID of the parent')
1360: 
1361:     pattern(%( _isdependencyof _( $ID _, $ID _, $INTEGER _) ))
1362:     doc('isdependencyof', Will evaluate to true for tasks that depend on the specified task inthe specified scenario and are no more than distance tasks away. Ifdistance is 0, all dependencies are considered independent of theirdistance.
1363:        )
1364:     arg(2, 'Task ID', 'The ID of a defined task')
1365:     arg(4, 'Scenario ID', 'A scenario ID')
1366:     arg(6, 'Distance', 'The maximum task distance to be considered')
1367: 
1368:     pattern(%( _isdutyof _( $ID _, $ID _) ))
1369:     doc('isdutyof', Will evaluate to true for tasks that have the specified resourceassigned to it in the specified scenario.
1370:        )
1371:     arg(2, 'Resource ID', 'The ID of a defined resource')
1372:     arg(4, 'Scenario ID', 'A scenario ID')
1373: 
1374:     pattern(%( _isfeatureof _( $ID _, $ID _) ))
1375:     doc('isfeatureof', If the provided task or any of its sub-tasks depend on this task or any of itssub-tasks, we call this task a feature of the provided task.
1376:        )
1377:     arg(2, 'Task ID', 'The ID of a defined task')
1378:     arg(4, 'Scenario ID', 'A scenario ID')
1379: 
1380:     pattern(['_isleaf', '_(', '_)' ])
1381:     doc('isleaf', 'The result is true if the property is not a container.')
1382: 
1383:     pattern(%( _ismilestone _( $ID _) ))
1384:     doc('ismilestone', The result is true if the property is a milestone in the provided scenario.
1385:        )
1386:     arg(2, 'Scenario ID', 'A scenario ID')
1387: 
1388:     pattern(%( _isongoing _( $ID _) ))
1389:     doc('isongoing', Will evaluate to true for tasks that overlap with the report period in givenscenario.
1390:        )
1391:     arg(2, 'ID', 'A scenario ID')
1392: 
1393:     pattern(['_isresource', '_(', '_)' ])
1394:     doc('isresource', 'The result is true if the property is a resource.')
1395: 
1396:     pattern(['_istask', '_(', '_)' ])
1397:     doc('istask', 'The result is true if the property is a task.')
1398: 
1399:     pattern(%( _treelevel _( _) ))
1400:     doc('treelevel', Returns the nesting level of a property in the property tree.Top level properties have a level of 1, their children 2 and so on.
1401:        )
1402:   end
rule_functions() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1299
1299:   def rule_functions
1300:     # This rule is not used by the parser. It's only for the documentation.
1301:     pattern(%( !functionsBody ))
1302:     doc('functions', The following functions are supported in logical expressions. These functionsare evaluated in logical conditions such as hidetask or rollupresource. Forthe evaluation, implicit and explicit parameters are used.All functions may operate on the current property and the scope property. Thescope property is the enclosing property in reports with nested properties.Imagine e. g a task report with nested resources. When the function is calledfor a task line, the task is the property and we don't have a scope property.When the function is called for a resource line, the resource is the propertyand the enclosing task is the scope property.These number of arguments that are passed in brackets to the function dependson the specific function. See the reference for details on each function.All functions can be suffixed with an underscore character. In that case, thefunction is operating on the scope property as if it were the property. Theoriginal property is ignored in that case. In our task report example fromabove, calling a function with an appended dash would mean that a taskline would be evaluated for the enclosing resource.In the example below you can see how this can be used. To generate a taskreport that lists all assigned leaf resources for leaf task lines only we usethe expression hideresource ~(isleaf() & isleaf_())The tilde in front of the bracketed expression means not that expression. Inother words: show resources that are leaf resources and show them for leaftasks only. The regular form isleaf() (without the appended underscore)operates on the resource. The isleaf_() variant operates on theenclosing task.
1303:        )
1304:     example('LogicalFunction', '1')
1305:   end
rule_functionsBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1339
1339:   def rule_functionsBody
1340:     # This rule is not used by the parser. It's only for the documentation.
1341:     optionsRule('functionPatterns')
1342:   end
rule_hAlignment() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1431
1431:   def rule_hAlignment
1432:     pattern(%( _center ), lambda {
1433:       :center
1434:     })
1435:     doc('halign.center', 'Center the cell content')
1436: 
1437:     pattern(%( _left ), lambda {
1438:       :left
1439:     })
1440:     doc('halign.left', 'Left align the cell content')
1441: 
1442:     pattern(%( _right ), lambda {
1443:       :right
1444:     })
1445:     doc('halign.right', 'Right align the cell content')
1446:   end
rule_headline() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1448
1448:   def rule_headline
1449:     pattern(%( _headline $STRING ), lambda {
1450:       @property.set('headline', newRichText(@val[1], @sourceFileInfo[1]))
1451:     })
1452:     doc('headline', Specifies the headline for a report.
1453:        )
1454:     arg(1, 'text', The text used for the headline. It is interpreted as[[Rich_Text_Attributes|Rich Text]].
1455:        )
1456:   end
rule_hidejournalentry() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1463
1463:   def rule_hidejournalentry
1464:     pattern(%( _hidejournalentry !flagLogicalExpression ), lambda {
1465:       @property.set('hideJournalEntry', @val[1])
1466:     })
1467:     doc('hidejournalentry', Do not include journal entries that match the specified logical expression.
1468:        )
1469:   end
rule_hideresource() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1473
1473:   def rule_hideresource
1474:     pattern(%( _hideresource !logicalExpression ), lambda {
1475:       @property.set('hideResource', @val[1])
1476:     })
1477:     doc('hideresource', Do not include resources that match the specified logical expression. If thereport is sorted in ''''tree'''' mode (default) then enclosing resources arelisted even if the expression matches the resource.
1478:        )
1479:     also(%( sortresources ))
1480:   end
rule_hidetask() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1486
1486:   def rule_hidetask
1487:     pattern(%( _hidetask !logicalExpression ), lambda {
1488:       @property.set('hideTask', @val[1])
1489:     })
1490:     doc('hidetask', Do not include tasks that match the specified logical expression. If thereport is sorted in ''''tree'''' mode (default) then enclosing tasks arelisted even if the expression matches the task.
1491:        )
1492:     also(%( sorttasks ))
1493:   end
rule_idOrAbsoluteId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1499
1499:   def rule_idOrAbsoluteId
1500:     singlePattern('$ID')
1501:     singlePattern('$ABSOLUTE_ID')
1502:   end
rule_includeAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1504
1504:   def rule_includeAttributes
1505:     optionsRule('includeAttributesBody')
1506:   end
rule_includeAttributesBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1508
1508:   def rule_includeAttributesBody
1509:     optional
1510:     repeatable
1511: 
1512:     pattern(%( _accountprefix !accountId ), lambda {
1513:       @accountprefix = @val[1].fullId
1514:     })
1515:     doc('accountprefix', This attribute can be used to insert the accounts of the included file assub-account of the account specified by ID. The parent account must already bedefined.
1516:     )
1517:     arg(1, 'account ID', 'The absolute ID of an already defined account')
1518: 
1519:     pattern(%( _reportprefix !reportId ), lambda {
1520:       @reportprefix = @val[1].fullId
1521:     })
1522:     doc('reportprefix', This attribute can be used to insert the reports of the included file assub-report of the report specified by ID. The parent report must alreadybe defined.
1523:     )
1524:     arg(1, 'report ID', 'The absolute ID of an already defined report.')
1525: 
1526:     pattern(%( _resourceprefix !resourceId ), lambda {
1527:       @resourceprefix = @val[1].fullId
1528:     })
1529:     doc('resourceprefix', This attribute can be used to insert the resources of the included file assub-resource of the resource specified by ID. The parent resource must alreadybe defined.
1530:     )
1531:     arg(1, 'resource ID', 'The ID of an already defined resource')
1532: 
1533:     pattern(%( _taskprefix !taskId ), lambda {
1534:       @taskprefix = @val[1].fullId
1535:     })
1536:     doc('taskprefix', This attribute can be used to insert the tasks of the included file assub-task of the task specified by ID. The parent task must already be defined.
1537:     )
1538:     arg(1, 'task ID', 'The absolute ID of an already defined task.')
1539:   end
rule_includeFile() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1556
1556:   def rule_includeFile
1557:     pattern(%( !includeFileName ), lambda {
1558:       unless @project
1559:         error('include_before_project',
1560:               "You must declare the project header before you include other " +
1561:               "files.")
1562:       end
1563:       @project.inputFiles << @scanner.include(@val[0], @sourceFileInfo[0]) do
1564:         popFileStack
1565:       end
1566:     })
1567:   end
rule_includeFileName() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1569
1569:   def rule_includeFileName
1570:     pattern(%( $STRING ), lambda {
1571:       unless @val[0][4, 4] == '.tji'
1572:         error('bad_include_suffix', "Included files must have a '.tji'" +
1573:                                     "extension: '#{@val[0]}'",
1574:               @sourceFileInfo[0])
1575:       end
1576:       pushFileStack
1577:       @val[0]
1578:     })
1579:     arg(0, 'filename', Name of the file to include. This must have a ''''.tji'''' extension. The namemay have an absolute or relative path. You need to use ''''/'''' characters toseparate directories.
1580:        )
1581:   end
rule_includeProperties() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1587
1587:   def rule_includeProperties
1588:     pattern(%( !includeFileName !includeAttributes ), lambda {
1589:       @project.inputFiles << @scanner.include(@val[0], @sourceFileInfo[0]) do
1590:         popFileStack
1591:       end
1592:     })
1593:   end
rule_interval() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1627
1627:   def rule_interval
1628:     pattern(%( !date !intervalEnd ), lambda {
1629:       mode = @val[1][0]
1630:       endSpec = @val[1][1]
1631:       if mode == 0
1632:         unless @val[0] < endSpec
1633:           error('start_before_end', "The end date (#{endSpec}) must be after " +
1634:                 "the start date (#{@val[0]}).", @sourceFileInfo[0])
1635:         end
1636:         Interval.new(@val[0], endSpec)
1637:       else
1638:         Interval.new(@val[0], @val[0] + endSpec)
1639:       end
1640:     })
1641:     doc('interval2', There are two ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form specifies the start date and an interval duration. Theduration must be prefixed by a plus character.
1642:        )
1643:   end
rule_intervalDuration() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1654
1654:   def rule_intervalDuration
1655:     pattern(%( !number !durationUnit ), lambda {
1656:       convFactors = [ 60, # minutes
1657:                       60 * 60, # hours
1658:                       60 * 60 * 24, # days
1659:                       60 * 60 * 24 * 7, # weeks
1660:                       60 * 60 * 24 * 30.4167, # months
1661:                       60 * 60 * 24 * 365 # years
1662:                      ]
1663:       if @val[0] == 0.0
1664:         error('zero_duration', "The interval duration may not be 0.",
1665:               @sourceFileInfo[1])
1666:       end
1667:       duration = @val[0] * convFactors[@val[1]]
1668:       resolution = @project.nil? ? 60 * 60 : @project['scheduleGranularity']
1669:       # Make sure the interval aligns with the timing resolution.
1670:       (duration / resolution).to_i * resolution
1671:     })
1672:     arg(0, 'duration', 'The duration of the interval. May not be 0.')
1673:   end
rule_intervalEnd() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1675
1675:   def rule_intervalEnd
1676:     pattern([ '_-', '!date' ], lambda {
1677:       [ 0, @val[1] ]
1678:     })
1679: 
1680:     pattern(%( _+ !intervalDuration ), lambda {
1681:       [ 1, @val[1] ]
1682:     })
1683:   end
rule_intervalOptionalEnd() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1685
1685:   def rule_intervalOptionalEnd
1686:     optional
1687:     pattern([ '_-', '!date' ], lambda {
1688:       [ 0, @val[1] ]
1689:     })
1690: 
1691:     pattern(%( _+ !intervalDuration ), lambda {
1692:       [ 1, @val[1] ]
1693:     })
1694:   end
rule_intervalOrDate() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1595
1595:   def rule_intervalOrDate
1596:     pattern(%( !date !intervalOptionalEnd ), lambda {
1597:       if @val[1]
1598:         mode = @val[1][0]
1599:         endSpec = @val[1][1]
1600:         if mode == 0
1601:           unless @val[0] < endSpec
1602:             error('start_before_end', "The end date (#{endSpec}) must be " +
1603:                   "after the start date (#{@val[0]}).", @sourceFileInfo[0])
1604:           end
1605:           Interval.new(@val[0], endSpec)
1606:         else
1607:           Interval.new(@val[0], @val[0] + endSpec)
1608:         end
1609:       else
1610:         Interval.new(@val[0], @val[0].sameTimeNextDay)
1611:       end
1612:     })
1613:     doc('interval3', There are three ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form, the end date is omitted. A 24 hour interval is assumed.The third form specifies the start date and an interval duration. The duration must be prefixed by a plus character.
1614:        )
1615:   end
rule_intervals() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1696
1696:   def rule_intervals
1697:     listRule('moreIntervals', '!intervalOrDate')
1698:   end
rule_intervalsOptional() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1700
1700:   def rule_intervalsOptional
1701:     optional
1702:     singlePattern('!intervals')
1703:   end
rule_journalEntry() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1705
1705:   def rule_journalEntry
1706:     pattern(%( !journalEntryHeader !journalEntryBody ), lambda {
1707:       @val[0]
1708:     })
1709:     doc('journalentry', This attribute adds an entry to the journal of the project. A journal can beused to record events, decisions or news that happened at a particular momentduring the project. Depending on the context, a journal entry may or may notbe associated with a specific property or author.A journal entry can consists of up to three parts. The headline is mandatoryand should be only 5 to 10 words long. The introduction is optional and shouldbe only one or two sentences long. All other details should be put into thethird part.Depending on the context, journal entries are listed with headlines only, asheadlines plus introduction or in full.
1710:        )
1711:   end
rule_journalEntryAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1726
1726:   def rule_journalEntryAttributes
1727:     optional
1728:     repeatable
1729: 
1730:     pattern(%( _alert $ID ), lambda {
1731:       level = @project.alertLevelIndex(@val[1])
1732:       unless level
1733:         error('bad_alert', "Unknown alert level #{@val[1]}. Must be " +
1734:               'green, yellow or red', @sourceFileInfo[0])
1735:       end
1736:       @journalEntry.alertLevel = level
1737:     })
1738:     doc('alert', Specify the alert level for this entry. Supported values are green, yellow andred. The default value is green. This attribute is inteded to be used forstatus reporting. When used for a journal entry that is associated with aproperty, the value can be reported in the alert column. When multiple entrieshave been specified for the property, the entry with the date closest to thereport end date will be used. Container properties will inherit the highestalert level of all its sub properties unless it has an own journal entry datedcloser to the report end than all of its sub properties.
1739:        )
1740: 
1741:     pattern(%( !author ))
1742: 
1743:     pattern(%( _flags !flagList ), lambda {
1744:       @val[1].each do |flag|
1745:         next if @journalEntry.flags.include?(flag)
1746: 
1747:         @journalEntry.flags << flag
1748:       end
1749:     })
1750:     doc('flags.journalentry', Journal entries can have flags attached to them. These can be used toinclude only entries in a report that have a certain flag.
1751:        )
1752: 
1753:     pattern(%( !summary ))
1754: 
1755:     pattern(%( !details ))
1756:   end
rule_journalEntryBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1770
1770:   def rule_journalEntryBody
1771:     optionsRule('journalEntryAttributes')
1772:   end
rule_journalEntryHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1774
1774:   def rule_journalEntryHeader
1775:     pattern(%( _journalentry !valDate $STRING ), lambda {
1776:       @journalEntry = JournalEntry.new(@project['journal'], @val[1], @val[2],
1777:                                        @property, @sourceFileInfo[0])
1778:     })
1779:     arg(2, 'headline', The headline of the journal entry. It will be interpreted as[[Rich_Text_Attributes|Rich Text]].
1780:        )
1781:   end
rule_leafResourceId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1785
1785:   def rule_leafResourceId
1786:     pattern(%( !resourceId ), lambda {
1787:       resource = @val[0]
1788:       unless resource.leaf?
1789:         error('leaf_resource_id_expected',
1790:               "#{resource.id} is not a leaf resource.", @sourceFileInfo[0])
1791:       end
1792:       resource
1793:     })
1794:     arg(0, 'resource', 'The ID of a leaf resource')
1795:   end
rule_limitAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1797
1797:   def rule_limitAttributes
1798:     optionsRule('limitAttributesBody')
1799:   end
rule_limitAttributesBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1801
1801:   def rule_limitAttributesBody
1802:     optional
1803:     repeatable
1804: 
1805:     pattern(%( _end !valDate ), lambda {
1806:       @limitInterval.end = @val[1]
1807:     })
1808:     doc('end.limit', The end date of the limit interval. It must be within the project time frame.
1809:     )
1810: 
1811:     pattern(%( _period !valInterval ), lambda {
1812:       @limitInterval = @val[1]
1813:     })
1814:     doc('period.limit', This property is a shortcut for setting the start and end dates of the limitinterval. Both dates must be within the project time frame.
1815:        )
1816: 
1817:     pattern(%( _resources !resourceLeafList ), lambda {
1818:       @limitResources = @val[1]
1819:     })
1820:     doc('resources.limit', When [[limits]] are used in a [[task]] context, the limits can be restrictedto a list of resources that are allocated to the task. In that case eachlisted resource will not be allocated more than the specified upper limit.Lower limits have no impact on the scheduler but do generate a warning whennot met.  All specified resources must be leaf resources.
1821:        )
1822:     example('Limits-1', '5')
1823: 
1824:     pattern(%( _start !valDate ), lambda {
1825:       @limitInterval.start = @val[1]
1826:     })
1827:     doc('start.limit', The start date of the limit interval. It must be within the project time frame.
1828:     )
1829:   end
rule_limitValue() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1844
1844:   def rule_limitValue
1845:     pattern([ '!workingDuration' ], lambda {
1846:       @limitInterval = Interval.new(@project['start'], @project['end'])
1847:       @limitResources = []
1848:       @val[0]
1849:     })
1850:   end
rule_limits() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1852
1852:   def rule_limits
1853:     pattern(%( !limitsHeader !limitsBody ), lambda {
1854:       @val[0]
1855:     })
1856:   end
rule_limitsAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1858
1858:   def rule_limitsAttributes
1859:     optional
1860:     repeatable
1861: 
1862:     pattern(%( _dailymax !limitValue !limitAttributes), lambda {
1863:       setLimit(@val[0], @val[1], @limitInterval)
1864:     })
1865:     doc('dailymax', Set a maximum limit for each calendar day.
1866:        )
1867:     example('Limits-1', '1')
1868: 
1869:     pattern(%( _dailymin !limitValue !limitAttributes), lambda {
1870:       setLimit(@val[0], @val[1], @limitInterval)
1871:     })
1872:     doc('dailymin', Minimum required effort for any calendar day. This value cannot be guaranteed bythe scheduler. It is only checked after the schedule is complete. In case theminium required amount has not been reached, a warning will be generated.
1873:        )
1874:     example('Limits-1', '4')
1875: 
1876:     pattern(%( _maximum !limitValue !limitAttributes), lambda {
1877:       setLimit(@val[0], @val[1], @limitInterval)
1878:     })
1879:     doc('maximum', Set a maximum limit for the specified period. You must ensure that the overalleffort can be achieved!
1880:        )
1881: 
1882:     pattern(%( _minimum !limitValue !limitAttributes), lambda {
1883:       setLimit(@val[0], @val[1], @limitInterval)
1884:     })
1885:     doc('minimum', Set a minim limit for each calendar month. This will only result in a warningif not met.
1886:        )
1887: 
1888:     pattern(%( _monthlymax !limitValue !limitAttributes), lambda {
1889:       setLimit(@val[0], @val[1], @limitInterval)
1890:     })
1891:     doc('monthlymax', Set a maximum limit for each calendar month.
1892:        )
1893: 
1894:     pattern(%( _monthlymin !limitValue !limitAttributes), lambda {
1895:       setLimit(@val[0], @val[1], @limitInterval)
1896:     })
1897:     doc('monthlymin', Minimum required effort for any calendar month. This value cannot beguaranteed by the scheduler. It is only checked after the schedule iscomplete. In case the minium required amount has not been reached, a warningwill be generated.
1898:        )
1899: 
1900:     pattern(%( _weeklymax !limitValue !limitAttributes), lambda {
1901:       setLimit(@val[0], @val[1], @limitInterval)
1902:     })
1903:     doc('weeklymax', Set a maximum limit for each calendar week.
1904:        )
1905: 
1906:     pattern(%( _weeklymin !limitValue !limitAttributes), lambda {
1907:       setLimit(@val[0], @val[1], @limitInterval)
1908:     })
1909:     doc('weeklymin', Minimum required effort for any calendar week. This value cannot be guaranteed bythe scheduler. It is only checked after the schedule is complete. In case theminium required amount has not been reached, a warning will be generated.
1910:        )
1911:   end
rule_limitsBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1938
1938:   def rule_limitsBody
1939:     optionsRule('limitsAttributes')
1940:   end
rule_limitsHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1942
1942:   def rule_limitsHeader
1943:     pattern(%( _limits ), lambda {
1944:       @limits = Limits.new
1945:       @limits.setProject(@project)
1946:       @limits
1947:     })
1948:   end
rule_listOfDays() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1950
1950:   def rule_listOfDays
1951:     pattern(%( !weekDayInterval !moreListOfDays), lambda {
1952:       weekDays = Array.new(7, false)
1953:       ([ @val[0] ] + (@val[1] ? @val[1] : [])).each do |dayList|
1954:         7.times { |i| weekDays[i] = true if dayList[i] }
1955:       end
1956:       weekDays
1957:     })
1958:   end
rule_listOfTimes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1960
1960:   def rule_listOfTimes
1961:     pattern(%( _off ), lambda {
1962:       [ ]
1963:     })
1964:     pattern(%( !timeInterval !moreTimeIntervals ), lambda {
1965:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
1966:     })
1967:   end
rule_listType() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1969
1969:   def rule_listType
1970:     pattern([ '_bullets' ], lambda { :bullets })
1971:     descr('List items as bullet list')
1972: 
1973:     pattern([ '_comma' ], lambda { :comma })
1974:     descr('List items as comma separated list')
1975: 
1976:     pattern([ '_numbered' ], lambda { :numbered })
1977:     descr('List items as numbered list')
1978:   end
rule_loadunit() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 1980
1980:   def rule_loadunit
1981:     pattern([ '_days' ], lambda { :days })
1982:     descr('Display all load and duration values as days.')
1983: 
1984:     pattern([ '_hours' ], lambda { :hours })
1985:     descr('Display all load and duration values as hours.')
1986: 
1987:     pattern([ '_longauto'] , lambda { :longauto })
1988:     descr(Automatically select the unit that produces the shortest and most readablevalue. The unit name will not be abbreviated.
1989:          )
1990: 
1991:     pattern([ '_minutes' ], lambda { :minutes })
1992:     descr('Display all load and duration values as minutes.')
1993: 
1994:     pattern([ '_months' ], lambda { :months })
1995:     descr('Display all load and duration values as monts.')
1996: 
1997:     pattern([ '_shortauto' ], lambda { :shortauto })
1998:     descr(Automatically select the unit that produces the shortest and most readablevalue. The unit name will be abbreviated.
1999:          )
2000: 
2001:     pattern([ '_weeks' ], lambda { :weeks })
2002:     descr('Display all load and duration values as weeks.')
2003: 
2004:     pattern([ '_years' ], lambda { :years })
2005:     descr('Display all load and duration values as years.')
2006:   end
rule_logicalExpression() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2014
2014:   def rule_logicalExpression
2015:     pattern(%( !operation ), lambda {
2016:       LogicalExpression.new(@val[0], sourceFileInfo)
2017:     })
2018:     doc('logicalexpression', A logical expression is a combination of operands and mathematical operations.The final result of a logical expression is always true or false. Logicalexpressions are used the reduce the properties in a report to a certain subsetor to select alternatives for the cell content of a table. When used withattributes like [[hidetask]] or [[hideresource]] the logical expressionevaluates to true for a certain property, this property is hidden or rolled-upin the report.Operands can be previously declared flags, built-in [[functions]], propertyattributes (specified as scenario.attribute) or another logical expression.When you combine logical operations to a more complex expression, theoperators are evaluated from left to right. '''a | b & c''' is identical to'''(a | b) & c'''. It's highly recommended that you always use brackets tocontrol the evaluation sequence. Currently, TaskJuggler does not support theconcept of operator precedence or right-left associativity. This may change inthe future.An operand can also be just a number. 0 evaluates to false, all other numbersto true.
2019:        )
2020:     also(%( functions ))
2021:   end
rule_macro() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2043
2043:   def rule_macro
2044:     pattern(%( _macro $ID $MACRO ), lambda {
2045:       if @scanner.macroDefined?(@val[1])
2046:         warning('marco_redefinition', "Redefining macro #{@val[1]}")
2047:       end
2048:       @scanner.addMacro(TextParser::Macro.new(@val[1], @val[2],
2049:                                               @sourceFileInfo[0]))
2050:     })
2051:     doc('macro', Defines a text fragment that can later be inserted by using the specified ID.To insert the text fragment anywhere in the text you need to write ${ID}.Thebody is not optional. It must be enclosed in square brackets. Macros can bedeclared like this: macro FOO [ This text ]If later ''''${FOO}'''' is found in the project file, it is expanded to''''This text''''.Macros may have arguments. Arguments are accessed with special macros withnumbers as names.  The number specifies the index of the argument. macro FOO [ This ${1} text ]will expand to ''''This stupid text'''' if called as ''''${FOO "stupid"}''''.Macros may call other macros. All macro arguments must be enclosed by doublequotes. In case the argument contains a double quote, it must be escaped by aslash (''''/'''').User defined macro IDs must have at least one uppercase letter as alllowercase letter IDs are reserved for built-in macros.To terminate the macro definition, the ''''<nowiki>]</nowiki>'''' must be thelast character in the line. If there are any other characters trailing it(even spaces or comments) the ''''<nowiki>]</nowiki>'''' will not beconsidered the end of the macro definition.In macro calls the macro names can be prefixed by a question mark. In thiscase the macro will expand to nothing if the macro is not defined. Otherwisethe undefined macro would be flagged with an error message.The macro call ${?foo}will expand to nothing if foo is undefined.
2052:        )
2053:     example('Macro-1')
2054:   end
rule_moreAlternatives() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2100
2100:   def rule_moreAlternatives
2101:     commaListRule('!resourceId')
2102:   end
rule_moreArguments() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2104
2104:   def rule_moreArguments
2105:     commaListRule('!argument')
2106:   end
rule_moreBangs() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2094
2094:   def rule_moreBangs
2095:     optional
2096:     repeatable
2097:     singlePattern('_!')
2098:   end
rule_moreChargeSetItems() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2108
2108:   def rule_moreChargeSetItems
2109:     commaListRule('!chargeSetItem')
2110:   end
rule_moreColumnDef() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2112
2112:   def rule_moreColumnDef
2113:     commaListRule('!columnDef')
2114:   end
rule_moreDepTasks() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2116
2116:   def rule_moreDepTasks
2117:     commaListRule('!taskDep')
2118:   end
rule_moreLeafResources() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2120
2120:   def rule_moreLeafResources
2121:     commaListRule('!resourceLeafList')
2122:   end
rule_moreListOfDays() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2124
2124:   def rule_moreListOfDays
2125:     commaListRule('!weekDayInterval')
2126:   end
rule_moreOutputFormats() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2128
2128:   def rule_moreOutputFormats
2129:     commaListRule('!outputFormat')
2130:   end
rule_morePredTasks() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2136
2136:   def rule_morePredTasks
2137:     commaListRule('!taskPred')
2138:   end
rule_moreProjectIDs() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2132
2132:   def rule_moreProjectIDs
2133:     commaListRule('$ID')
2134:   end
rule_moreSortCriteria() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2140
2140:   def rule_moreSortCriteria
2141:     commaListRule('!sortNonTree')
2142:   end
rule_moreTimeIntervals() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2144
2144:   def rule_moreTimeIntervals
2145:     commaListRule('!timeInterval')
2146:   end
rule_navigator() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2148
2148:   def rule_navigator
2149:     pattern(%( !navigatorHeader !navigatorBody ), lambda {
2150:       @project['navigators'][@navigator.id] = @navigator
2151:     })
2152:     doc('navigator', Defines a navigator object with the specified ID. This object can be used inreports to include a navigation bar with references to other reports.
2153:           )
2154:   end
rule_navigatorAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2159
2159:   def rule_navigatorAttributes
2160:     optional
2161:     repeatable
2162:     pattern(%( _hidereport !logicalExpression ), lambda {
2163:       @navigator.hideReport = @val[1]
2164:     })
2165:     doc('hidereport', This attribute can be used to exclude the reports that match the specifiedexpression from the navigation bar.
2166:           )
2167:   end
rule_navigatorBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2172
2172:   def rule_navigatorBody
2173:     optional
2174:     pattern(%( _{ !navigatorAttributes _} ))
2175:   end
rule_navigatorHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2177
2177:   def rule_navigatorHeader
2178:     pattern(%( _navigator $ID ), lambda {
2179:       if @project['navigators'][@val[1]]
2180:         error('navigator_exists',
2181:               "The navigator #{@val[1]} has already been defined.",
2182:               @sourceFileInfo[0])
2183:       end
2184:       @navigator = Navigator.new(@val[1], @project)
2185:     })
2186:   end
rule_nikuReport() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2236
2236:   def rule_nikuReport
2237:     pattern(%( !nikuReportHeader !nikuReportBody ), lambda {
2238:       @property = nil
2239:     })
2240:     doc('nikureport', This report generates an XML file to be imported into the enterprise resourcemanagement software Clarity(R) from Computer Associates(R). The files containsallocation curves for the specified resources. All tasks with identical userdefined attributes ''''ClarityPID'''' and ''''ClarityPNAME'''' are bundledinto a Clarity project. The resulting XML file can be imported into Claritywith the xog-in tool.
2241:        )
2242:     example('Niku')
2243:   end
rule_nikuReportAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2188
2188:   def rule_nikuReportAttributes
2189:     optional
2190:     repeatable
2191: 
2192:     pattern(%( !formats ))
2193:     pattern(%( !headline ))
2194:     pattern(%( !hideresource ))
2195:     pattern(%( !hidetask ))
2196: 
2197:     pattern(%( !numberFormat ), lambda {
2198:       @property.set('numberFormat', @val[0])
2199:     })
2200: 
2201:     pattern(%( !reportEnd ))
2202:     pattern(%( !reportPeriod ))
2203:     pattern(%( !reportStart ))
2204:     pattern(%( !reportTitle ))
2205: 
2206:     pattern(%( _timeoff $STRING $STRING ), lambda {
2207:       @property.set('timeOffId', @val[1])
2208:       @property.set('timeOffName', @val[2])
2209:     })
2210:     doc('timeoff.nikureport', Set the Clarity project ID and name that the vacation time will be reported to.
2211:        )
2212:     arg(1, 'ID', 'The Clarity project ID')
2213:     arg(2, 'Name', 'The Clarity project name')
2214:   end
rule_nikuReportBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2218
2218:   def rule_nikuReportBody
2219:     pattern(%( _{ !nikuReportAttributes _} ), lambda {
2220: 
2221:     })
2222:   end
rule_nikuReportHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2224
2224:   def rule_nikuReportHeader
2225:     pattern(%( _nikureport !optionalID $STRING ), lambda {
2226:       newReport(@val[1], @val[2], :niku, sourceFileInfo)
2227:       @property.set('numberFormat', RealFormat.new(['-', '', '', '.', 2]))
2228:     })
2229:     arg(1, 'file name', The name of the time sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel.
2230:        )
2231:   end
rule_nodeId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2252
2252:   def rule_nodeId
2253:     pattern(%( !idOrAbsoluteId !subNodeId ), lambda {
2254:       case @property.typeSpec
2255:       when :taskreport
2256:         if (p1 = @project.task(@val[0])).nil?
2257:           error('unknown_main_node',
2258:                 "Unknown task ID #{@val[0]}", @sourceFileInfo[0])
2259:         end
2260:         if @val[1]
2261:           if (p2 = @project.resource(@val[1])).nil?
2262:             error('unknown_sub_node',
2263:                   "Unknown resource ID #{@val[0]}", @sourceFileInfo[0])
2264:           end
2265:           return [ p2, p1 ]
2266:         end
2267:         return [ p1, nil ]
2268:       when :resourcereport
2269:         if (p1 = @project.task(@val[0])).nil?
2270:           error('unknown_main_node',
2271:                 "Unknown task ID #{@val[0]}", @sourceFileInfo[0])
2272:         end
2273:         if @val[1]
2274:           if (p2 = @project.resource(@val[1])).nil?
2275:             error('unknown_sub_node',
2276:                   "Unknown resource ID #{@val[0]}", @sourceFileInfo[0])
2277:           end
2278:           return [ p2, p1 ]
2279:         end
2280:         return [ p1, nil ]
2281:       end
2282: 
2283:       raise "Node list is not supported for this report type: " +
2284:             "#{@property.typeSpec}"
2285:     })
2286:   end
rule_nodeIdList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2288
2288:   def rule_nodeIdList
2289:     listRule('moreNodeIdList', '!nodeId')
2290:     pattern([ '_-' ], lambda {
2291:       []
2292:     })
2293:   end
rule_number() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2295
2295:   def rule_number
2296:     singlePattern('$INTEGER')
2297:     singlePattern('$FLOAT')
2298:   end
rule_numberFormat() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2300
2300:   def rule_numberFormat
2301:     pattern(%( _numberformat $STRING $STRING $STRING $STRING $INTEGER ),
2302:         lambda {
2303:       RealFormat.new(@val.slice(1, 5))
2304:     })
2305:     doc('numberformat',
2306:         'These values specify the default format used for all numerical ' +
2307:         'real values.')
2308:     arg(1, 'negativeprefix', 'Prefix for negative numbers')
2309:     arg(2, 'negativesuffix', 'Suffix for negative numbers')
2310:     arg(3, 'thousandsep', 'Separator used for every 3rd digit')
2311:     arg(4, 'fractionsep', 'Separator used to separate the fraction digits')
2312:     arg(5, 'fractiondigits', 'Number of fraction digits to show')
2313:   end
rule_operand() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2315
2315:   def rule_operand
2316:     pattern(%( _( !operation _) ), lambda {
2317:       @val[1]
2318:     })
2319:     pattern(%( _~ !operand ), lambda {
2320:       operation = LogicalOperation.new(@val[1])
2321:       operation.operator = '~'
2322:       operation
2323:     })
2324: 
2325:     pattern(%( $ABSOLUTE_ID ), lambda {
2326:       if @val[0].count('.') > 1
2327:         error('operand_attribute',
2328:               'Attributes must be specified as <scenarioID>.<attribute>',
2329:               @sourceFileInfo[0])
2330:       end
2331:       scenario, attribute = @val[0].split('.')
2332:       if (scenarioIdx = @project.scenarioIdx(scenario)).nil?
2333:         error('operand_unkn_scen', "Unknown scenario ID #{scenario}",
2334:               @sourceFileInfo[0])
2335:       end
2336:       LogicalAttribute.new(attribute, @project.scenario(scenarioIdx))
2337:     })
2338:     pattern(%( !date ), lambda {
2339:       LogicalOperation.new(@val[0])
2340:     })
2341:     pattern(%( $ID !argumentList ), lambda {
2342:       if @val[1].nil?
2343:         unless @project['flags'].include?(@val[0])
2344:           error('operand_unkn_flag', "Undeclared flag '#{@val[0]}'",
2345:                 @sourceFileInfo[0])
2346:         end
2347:         LogicalFlag.new(@val[0])
2348:       else
2349:         func = LogicalFunction.new(@val[0])
2350:         res = func.setArgumentsAndCheck(@val[1])
2351:         unless res.nil?
2352:           error(*res)
2353:         end
2354:         func
2355:       end
2356:     })
2357:     pattern(%( $INTEGER ), lambda {
2358:       LogicalOperation.new(@val[0])
2359:     })
2360:     pattern(%( $FLOAT ), lambda {
2361:       LogicalOperation.new(@val[0])
2362:     })
2363:     pattern(%( $STRING ), lambda {
2364:       LogicalOperation.new(@val[0])
2365:     })
2366:   end
rule_operation() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2368
2368:   def rule_operation
2369:     pattern(%( !operand !operationChain ), lambda {
2370:       operation = LogicalOperation.new(@val[0])
2371:       if @val[1]
2372:         # Further operators/operands create an operation tree.
2373:         @val[1].each do |ops|
2374:           operation = LogicalOperation.new(operation)
2375:           operation.operator = ops[0]
2376:           operation.operand2 = ops[1]
2377:         end
2378:       end
2379:       operation
2380:     })
2381:     arg(0, 'operand', An operand can consist of a date, a text string, a [[functions|function]], aproperty attribute or a numerical value. It can also be the name of a declaredflag. Use the ''''scenario_id.attribute'''' notation to use an attribute of thecurrently evaluated property. The scenario ID always has to be specified, alsofor non-scenario specific attributes. This is necessary to distinguish themfrom flags.An operand can be a negated operand by prefixing a ~ charater or it can beanother logical expression enclosed in braces.
2382:         )
2383:   end
rule_operationChain() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2395
2395:   def rule_operationChain
2396:     optional
2397:     repeatable
2398:     pattern(%( !operatorAndOperand), lambda {
2399:       @val[0]
2400:     })
2401:   end
rule_operator() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2413
2413:   def rule_operator
2414:     singlePattern('_|')
2415:     descr('The \or\ operator')
2416: 
2417:     singlePattern('_&')
2418:     descr('The \and\ operator')
2419: 
2420:     singlePattern('_>')
2421:     descr('The \greater than\ operator')
2422: 
2423:     singlePattern('_<')
2424:     descr('The \smaller than\ operator')
2425: 
2426:     singlePattern('_=')
2427:     descr('The \equal\ operator')
2428: 
2429:     singlePattern('_>=')
2430:     descr('The \greater-or-equal\ operator')
2431: 
2432:     singlePattern('_<=')
2433:     descr('The \smaller-or-equal\ operator')
2434: 
2435:     singlePattern('_!=')
2436:     descr('The \not-equal\ operator')
2437:   end
rule_operatorAndOperand() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2403
2403:   def rule_operatorAndOperand
2404:     pattern(%( !operator !operand), lambda{
2405:       [ @val[0], @val[1] ]
2406:     })
2407:     arg(1, 'operand', An operand can consist of a date, a text string or a numerical value. It can also be the name of a declared flag. Finally, an operand can be a negated operand by prefixing a ~ charater or it can be another operation enclosed in braces.
2408:         )
2409:   end
rule_optionalID() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2439
2439:   def rule_optionalID
2440:     optional
2441:     pattern(%( $ID ), lambda {
2442:       @val[0]
2443:     })
2444:     arg(0, 'id', An optional ID. If you ever want to reference this property, you must specifyyour own unique ID. If no ID is specified one will be automatically generated.These IDs may become visible in reports, but may change at any time. You maynever rely on automatically generated IDs.
2445:        )
2446:   end
rule_optionalPercent() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2453
2453:   def rule_optionalPercent
2454:     optional
2455:     pattern(%( !number _% ), lambda {
2456:       @val[0] / 100.0
2457:     })
2458:   end
rule_optionalVersion() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2460
2460:   def rule_optionalVersion
2461:     optional
2462:     pattern(%( $STRING ), lambda {
2463:       @val[0]
2464:     })
2465:     arg(0, 'version', An optional version ID. This can be something simple as "4.2" or an ID tag ofa revision control system. If not specified, it defaults to "1.0".
2466:        )
2467:   end
rule_outputFormat() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2472
2472:   def rule_outputFormat
2473:     pattern(%( _csv ), lambda {
2474:       :csv
2475:     })
2476:     descr(The report lists the resources and their respective values ascolon-separated-value (CSV) format. Due to the very simple nature of the CSVformat, only a small subset of features will be supported for CSV output.Including tasks or listing multiple scenarios will result in very difficult toread reports.
2477:          )
2478: 
2479:     pattern(%( _html ), lambda {
2480:       :html
2481:     })
2482:     descr('Generate a web page (HTML file)')
2483: 
2484:     pattern(%( _niku ), lambda {
2485:       :niku
2486:     })
2487:     descr('Generate a XOG XML file to be used with Clarity.')
2488:   end
rule_outputFormats() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2496
2496:   def rule_outputFormats
2497:     pattern(%( !outputFormat !moreOutputFormats ), lambda {
2498:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
2499:     })
2500:   end
rule_plusOrMinus() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2502
2502:   def rule_plusOrMinus
2503:     singlePattern('_+')
2504:     singlePattern('_-')
2505:   end
rule_project() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2507
2507:   def rule_project
2508:     pattern(%( !projectProlog !projectDeclaration !properties . ), lambda {
2509:       @val[1]
2510:     })
2511:   end
rule_projectBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2513
2513:   def rule_projectBody
2514:     optionsRule('projectBodyAttributes')
2515:   end
rule_projectBodyAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2517
2517:   def rule_projectBodyAttributes
2518:     repeatable
2519:     optional
2520: 
2521:     pattern(%( !currencyFormat ), lambda {
2522:       @project['currencyFormat'] = @val[0]
2523:     })
2524: 
2525:     pattern(%( _currency $STRING ), lambda {
2526:       @project['currency'] = @val[1]
2527:     })
2528:     doc('currency', 'The default currency unit.')
2529:     example('Account')
2530:     arg(1, 'symbol', 'Currency symbol')
2531: 
2532:     pattern(%( _dailyworkinghours !number ), lambda {
2533:       @project['dailyworkinghours'] = @val[1]
2534:     })
2535:     doc('dailyworkinghours', Set the average number of working hours per day. This is used asthe base to convert working hours into working days. This affectsfor example the length task attribute. The default value is 8 hoursand should work for most Western countries. The value you specify should matchthe settings you specified as your default [[workinghours.project|workinghours]].
2536:        )
2537:     example('Project')
2538:     arg(1, 'hours', 'Average number of working hours per working day')
2539: 
2540:     pattern(%( _extend !extendProperty !extendBody ), lambda {
2541:       updateParserTables
2542:     })
2543:     doc('extend', Often it is desirable to collect more information in the project file than isnecessary for task scheduling and resource allocation. To add such informationto tasks, resources or accounts the user can extend these properties withuser-defined attributes. The new attributes can be of various types such astext, date or reference to capture various types of data. Optionally the usercan specify if the attribute value should be inherited from the enclosingproperty.
2544:        )
2545:     example('CustomAttributes')
2546: 
2547:     pattern(%( !projectBodyInclude ))
2548: 
2549:     pattern(%( !journalEntry ))
2550: 
2551:     pattern(%( _now !date ), lambda {
2552:       @project['now'] = @val[1]
2553:       @scanner.addMacro(TextParser::Macro.new('now', @val[1].to_s,
2554:                                               @sourceFileInfo[0]))
2555:       @scanner.addMacro(TextParser::Macro.new(
2556:         'today', @val[1].to_s(@project['timeFormat']), @sourceFileInfo[0]))
2557:     })
2558:     doc('now', Specify the date that TaskJuggler uses for calculation as currentdate. If no value is specified, the current value of the systemclock is used.
2559:        )
2560:     arg(1, 'date', 'Alternative date to be used as current date for all ' +
2561:         'computations')
2562: 
2563:     pattern(%( !numberFormat ), lambda {
2564:       @project['numberFormat'] = @val[0]
2565:     })
2566: 
2567:     pattern(%( !scenario ))
2568:     pattern(%( _shorttimeformat $STRING ), lambda {
2569:       @project['shortTimeFormat'] = @val[1]
2570:     })
2571:     doc('shorttimeformat',
2572:         'Specifies time format for time short specifications. This is normal' +
2573:         'just the hour and minutes.')
2574:     arg(1, 'format', 'strftime like format string')
2575: 
2576:     pattern(%( !timeformat ), lambda {
2577:       @project['timeFormat'] = @val[0]
2578:     })
2579: 
2580:     pattern(%( !timezone ), lambda {
2581:       @val[0]
2582:     })
2583: 
2584:     pattern(%( _timingresolution $INTEGER _min ), lambda {
2585:       goodValues = [ 5, 10, 15, 20, 30, 60 ]
2586:       unless goodValues.include?(@val[1])
2587:         error('bad_timing_res',
2588:               "Timing resolution must be one of #{goodValues.join(', ')} min.",
2589:               @sourceFileInfo[1])
2590:       end
2591:       if @val[1] > (Project.maxScheduleGranularity / 60)
2592:         error('too_large_timing_res',
2593:               'The maximum allowed timing resolution for the timezone is ' +
2594:               "#{Project.maxScheduleGranularity / 60} minutes.",
2595:               @sourceFileInfo[1])
2596:       end
2597:       @project['scheduleGranularity'] = @val[1] * 60
2598:     })
2599:     doc('timingresolution', Sets the minimum timing resolution. The smaller the value, the longer thescheduling process lasts and the more memory the application needs. Thedefault and maximum value is 1 hour. The smallest value is 5 min.This value is a pretty fundamental setting of TaskJuggler. It has a severeimpact on memory usage and scheduling performance. You should set this valueto the minimum required resolution. Make sure that all values that you specifyare aligned with the resolution.Changing the timing resolution will reset the [[workinghours.project|workinghours]] to the default times. It's recommended that this is the very firstoption in the project header section.Do not use this option after you've set the time zone!
2600:         )
2601: 
2602:     pattern(%( _trackingscenario !scenarioId ), lambda {
2603:       @project['trackingScenarioIdx'] = @val[1]
2604:       # The tracking scenario and all child scenarios will always be scheduled
2605:       # in projection mode.
2606:       @project.scenario(@val[1]).all.each do |scenario|
2607:         scenario.set('projection', true)
2608:       end
2609:     })
2610:     doc('trackingscenario', Specifies which scenario is used to capture what actually has happened withthe project. All sub-scenarios of this scenario inherit the bookings of thetracking scenario and may not have any bookings of their own. The trackingscenario must also be specified to use time and status sheet reports.The tracking scenario and all scenarios derived from it will be scheduled inprojection mode. This means that the scheduler will only add bookings afterthe current date or the date specified by [[now]]. It is assumed that allallocations prior to this date have been provided as [[booking.task|task bookings]] or [[booking.resource|resource bookings]].
2611:        )
2612:     example('TimeSheet1', '2')
2613: 
2614:     pattern(%( _weekstartsmonday ), lambda {
2615:       @project['weekStartsMonday'] = true
2616:     })
2617:     doc('weekstartsmonday',
2618:         'Specify that you want to base all week calculation on weeks ' +
2619:         'starting on Monday. This is common in many European countries.')
2620: 
2621:     pattern(%( _weekstartssunday ), lambda {
2622:       @project['weekStartsMonday'] = false
2623:     })
2624:     doc('weekstartssunday',
2625:         'Specify that you want to base all week calculation on weeks ' +
2626:         'starting on Sunday. This is common in the United States of America.')
2627: 
2628:     pattern(%( !workinghoursProject ))
2629:     pattern(%( _yearlyworkingdays !number ), lambda {
2630:       @project['yearlyworkingdays'] = @val[1]
2631:     })
2632:     doc('yearlyworkingdays', Specifies the number of average working days per year. This should correlateto the specified workinghours and vacation. It affects the conversion ofworking hours, working days, working weeks, working months and working yearsinto each other.When public holidays and vacations are disregarded, this value should be equalto the number of working days per week times 52.1428 (the average number ofweeks per year). E. g. for a culture with 5 working days it is 260.714 (thedefault), for 6 working days it is 312.8568 and for 7 working days it is365.
2633:        )
2634:     arg(1, 'days', 'Number of average working days for a year')
2635:   end
rule_projectBodyInclude() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2786
2786:   def rule_projectBodyInclude
2787:     pattern(%( _include !includeFile !projectBodyAttributes . ))
2788:     lastSyntaxToken(1)
2789:     doc('include.project', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in.The included files may only contain content that may be present in a projectheader section.If the include statement is the last statement in the file it must have the option block. The option block can be empty, but the curly braces must be present.
2790:        )
2791:   end
rule_projectDeclaration() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2692
2692:   def rule_projectDeclaration
2693:     pattern(%( !projectHeader !projectBody ), lambda {
2694:       # If the user has specified a tracking scenario, we mark all children of
2695:       # that scenario to disallow own bookings. These scenarios will inherit
2696:       # their bookings from the tracking scenario.
2697:       if (idx = @project['trackingScenarioIdx'])
2698:         @project.scenario(idx).allLeaves(true).each do |scenario|
2699:           scenario.set('ownbookings', false)
2700:         end
2701:       end
2702:       @val[0]
2703:     })
2704:     doc('project', The project property is mandatory and should be the first propertyin a project file. It is used to capture basic attributes such asthe project id, name and the expected time frame.Be aware that the dates for the project period default to UTC times. See [[interval2]] for details.
2705:        )
2706:   end
rule_projectHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2714
2714:   def rule_projectHeader
2715:     pattern(%( _project !optionalID $STRING !optionalVersion !interval ), lambda {
2716:       @project = Project.new(@val[1], @val[2], @val[3], @messageHandler)
2717:       @project['start'] = @val[4].start
2718:       @project['end'] = @val[4].end
2719:       @projectId = @val[1]
2720:       setGlobalMacros
2721:       @property = nil
2722:       @reportCounter = 0
2723:       @project
2724:     })
2725:     arg(2, 'name', 'The name of the project')
2726:   end
rule_projectIDs() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2728
2728:   def rule_projectIDs
2729:     pattern(%( $ID !moreProjectIDs ), lambda {
2730:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
2731:     })
2732:   end
rule_projectProlog() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2763
2763:   def rule_projectProlog
2764:     optional
2765:     repeatable
2766:     pattern(%( !prologInclude ))
2767:     pattern(%( !macro ))
2768:   end
rule_projectProperties() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2770
2770:   def rule_projectProperties
2771:     # This rule is not defining actual syntax. It's only used for the
2772:     # documentation.
2773:     pattern(%( !projectPropertiesBody ))
2774:     doc('properties', The project properties. Every project must consists of at least one task. The other properties are optional. To save the scheduled data at least one output generating property should be used.
2775:        )
2776:   end
rule_projectPropertiesBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2780
2780:   def rule_projectPropertiesBody
2781:     # This rule is not defining actual syntax. It's only used for the
2782:     # documentation.
2783:     optionsRule('properties')
2784:   end
rule_projection() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2734
2734:   def rule_projection
2735:     optionsRule('projectionAttributes')
2736:   end
rule_projectionAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2738
2738:   def rule_projectionAttributes
2739:     optional
2740:     repeatable
2741:     pattern(%( _sloppy ), lambda {
2742:       warning('projection_sloppy',
2743:               'The sloppy projection mode has been deprecated. The ' +
2744:               'functionality is no longer supported.')
2745:     })
2746:     doc('sloppy.projection', The sloppy projection mode has been deprecated. Please use[[trackingscenario]] feature instead.
2747:        )
2748: 
2749:     pattern(%( _strict ), lambda {
2750:       warning('projection_strict',
2751:               'The strict mode is now always used.')
2752:     })
2753:     doc('strict.projection', The strict projection mode has been deprecated. Please use[[trackingscenario]] feature instead.
2754:        )
2755:   end
rule_prologInclude() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2804
2804:   def rule_prologInclude
2805:     pattern(%( _include !includeFile !projectProlog . ))
2806:     lastSyntaxToken(1)
2807:     doc('include.macro', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in.The included file may only contain macro definitions.
2808:        )
2809:   end
rule_properties() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2819
2819:   def rule_properties
2820:     pattern(%( !propertiesBody ))
2821:   end
rule_propertiesBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2823
2823:   def rule_propertiesBody
2824:     repeatable
2825:     optional
2826: 
2827:     pattern(%( !account ))
2828: 
2829:     pattern(%( _copyright $STRING ), lambda {
2830:       @project['copyright'] = @val[1]
2831:     })
2832:     doc('copyright', Set a copyright notice for the project file and its content. This copyright notice will be added to all reports that can support it.
2833:        )
2834:     example('Caption', '2')
2835: 
2836:     pattern(%( !balance ), lambda {
2837:       @project['costAccount'] = @val[0][0]
2838:       @project['revenueAccount'] = @val[0][1]
2839:     })
2840: 
2841:     pattern(%( !export ))
2842: 
2843:     pattern(%( _flags !declareFlagList ), lambda {
2844:       unless @project['flags'].include?(@val[1])
2845:         @project['flags'] += @val[1]
2846:       end
2847:     })
2848:     doc('flags', Declare one or more flag for later use. Flags can be used to mark tasks, resources or other properties to filter them in reports.
2849:        )
2850: 
2851:     pattern(%( !propertiesInclude ))
2852: 
2853:     pattern(%( !limits ), lambda {
2854:       @project['limits'] = @val[0]
2855:     })
2856:     doc('limits', Set per-interval allocation limits for the following resource definitions.The limits can be overwritten in each resource definition and the globallimits can be changed later.
2857:        )
2858: 
2859:     pattern(%( !macro ))
2860: 
2861:     pattern(%( !nikuReport ))
2862: 
2863:     pattern(%( !navigator ))
2864: 
2865:     pattern(%( _projectid $ID ), lambda {
2866:       @project['projectids'] << @val[1]
2867:       @project['projectids'].uniq!
2868:       @project['projectid'] = @projectId = @val[1]
2869:     })
2870:     doc('projectid', This declares a new project id and activates it. All subsequenttask definitions will inherit this ID. The tasks of a project can havedifferent IDs.  This is particularly helpful if the project is merged fromseveral sub projects that each have their own ID.
2871:        )
2872: 
2873:     pattern(%( _projectids !projectIDs ), lambda {
2874:       @project['projectids'] += @val[1]
2875:       @project['projectids'].uniq!
2876:     })
2877:     doc('projectids', Declares a list of project IDs. When an include file that was generated from another project brings different project IDs, these need to be declared first.
2878:         )
2879: 
2880:     pattern(%( _rate !number ), lambda {
2881:       @project['rate'] = @val[1].to_f
2882:     })
2883:     doc('rate', Set the default rate for all subsequently defined resources. The rate describes the daily cost of a resource.
2884:         )
2885: 
2886:     pattern(%( !report ))
2887:     pattern(%( !resource ))
2888:     pattern(%( !shift ))
2889:     pattern(%( !statusSheet ))
2890:     pattern(%( !statusSheetReport ))
2891: 
2892:     pattern(%( _supplement !supplement ))
2893:     doc('supplement', The supplement keyword provides a mechanism to add more attributes to alreadydefined accounts, tasks or resources. The additional attributes must obey thesame rules as in regular task or resource definitions and must be enclosed bycurly braces.This construct is primarily meant for situations where the information about atask or resource is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool.
2894:        )
2895:     example('Supplement')
2896: 
2897:     pattern(%( !task ))
2898:     pattern(%( !timeSheet ))
2899:     pattern(%( !timeSheetReport ))
2900:     pattern(%( _vacation !vacationName !intervals ), lambda {
2901:       begin
2902:         @project['vacations'] = @project['vacations'] + @val[2]
2903:       rescue AttributeOverwrite
2904:       end
2905:     })
2906:     doc('vacation', Specify a global vacation period for all subsequently defined resources. Avacation can also be used to block out the time before a resource joined orafter it left. For employees changing their work schedule from full-time topart-time, or vice versa, please refer to the 'Shift' property.
2907:        )
2908:     arg(1, 'name', 'Name or purpose of the vacation')
2909:   end
rule_propertiesFile() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2942
2942:   def rule_propertiesFile
2943:     pattern(%( !propertiesBody . ))
2944:   end
rule_propertiesInclude() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2946
2946:   def rule_propertiesInclude
2947:     pattern(%( _include !includeProperties !properties . ), lambda {
2948:     })
2949:     doc('include.properties', Includes the specified file name as if its contents would be writteninstead of the include property. The only exception is the includestatement itself. When the included files contains other includestatements or report definitions, the filenames are relative to filewhere they are defined in. include commands can be used in the projectheader, at global scope or between property declarations of tasks,resources, and accounts.For technical reasons you have to supply the optional pair of curlybrackets if the include is followed immediately by a macro call thatis defined within the included file.
2950:        )
2951:   end
rule_purge() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2965
2965:   def rule_purge
2966:     pattern(%( _purge $ID ), lambda {
2967:       if (attributeDefinition = @property.attributeDefinition(@val[1])).nil?
2968:         error('purge_unknown_id',
2969:               "#{@val[1]} is not a known attribute for this property",
2970:               @sourceFileInfo[1])
2971:       end
2972:       if attributeDefinition.scenarioSpecific
2973:         attr = @property[@val[1], 0]
2974:       else
2975:         attr = @property.get(@val[1])
2976:       end
2977:       unless attr.is_a?(Array)
2978:         error('purge_no_list',
2979:               "#{@val[1]} is not a list attribute. Only those can be purged.",
2980:               @sourceFileInfo[1])
2981:       end
2982:       @property.getAttribute(@val[1], @scenarioIdx).reset
2983:     })
2984:     doc('purge', List attributes, like regular attributes, can inherit their values from theenclosing property. By defining more values for such a list attribute, the newvalues will be appended to the existing ones. The purge statement clears sucha list atribute. A subsequent definition for the attribute within the propertywill then add their values to an empty list.
2985:        )
2986:     arg(1, 'attribute', 'Any name of a list attribute')
2987:   end
rule_referenceAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 2995
2995:   def rule_referenceAttributes
2996:     optional
2997:     repeatable
2998:     pattern(%( _label $STRING ), lambda {
2999:       @val[1]
3000:     })
3001:   end
rule_referenceBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3003
3003:   def rule_referenceBody
3004:     optionsRule('referenceAttributes')
3005:   end
rule_relativeId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3007
3007:   def rule_relativeId
3008:     pattern(%( _! !moreBangs !idOrAbsoluteId ), lambda {
3009:       str = '!'
3010:       if @val[1]
3011:         @val[1].each { |bang| str += bang }
3012:       end
3013:       str += @val[2]
3014:       str
3015:     })
3016:   end
rule_report() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3018
3018:   def rule_report
3019:     pattern(%( !reportHeader !reportBody ), lambda {
3020:       @property = @property.parent
3021:     })
3022:     doc('report', Reports are used to store and vizualize the results of a scheduled project.The content, the output format and the appearance of a report can be adjustedwith report attributes. Reports can be nested to create structured documenttrees. As with other properties, the resource attributes can be inherited fromthe enclosing report or the project.By default, report definitions do not generate any files. With more complexprojects, most report definitions will be used to describe elements ofcomposed reports. If you want to generate a file from this report, you mustspecify the list of [[formats]] that you want to generate. The report namewill then be used as a base name to create the file. The suffix will beappended based on the generated format.Reports have a local name space. All IDs must be unique within the reportsthat belong to the same enclosing report. To reference a report for inclusioninto another report, you need to specify the full report ID. This is composedof the report ID, prefixed by a dot-separated list of all parent report IDs.
3023:        )
3024:     also(%( resourcereport taskreport textreport ))
3025:   end
rule_reportAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3374
3374:   def rule_reportAttributes
3375:     optional
3376:     repeatable
3377: 
3378:     pattern(%( !balance ), lambda {
3379:       @property.set('costAccount', @val[0][0])
3380:       @property.set('revenueAccount', @val[0][1])
3381:     })
3382: 
3383:     pattern(%( _caption $STRING ), lambda {
3384:       @property.set('caption', newRichText(@val[1], @sourceFileInfo[1]))
3385:     })
3386:     doc('caption', The caption will be embedded in the footer of the table or data segment. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
3387:        )
3388:     arg(1, 'text', 'The caption text.')
3389:     example('Caption', '1')
3390: 
3391:     pattern(%( _center $STRING ), lambda {
3392:       @property.set('center', newRichText(@val[1], @sourceFileInfo[1]))
3393:     })
3394:     doc('center', This attribute defines the center section of the [[textreport]]. The text willbe interpreted as [[Rich_Text_Attributes|Rich Text]].
3395:        )
3396:     arg(1, 'text', 'The text')
3397: 
3398:     pattern(%( _columns !columnDef !moreColumnDef ), lambda {
3399:       columns = [ @val[1] ]
3400:       columns += @val[2] if @val[2]
3401:       @property.set('columns', columns)
3402:     })
3403:     doc('columns', Specifies which columns shall be included in a report. Some columns showvalues that are constant over the course of the project. Other columns showcalculated values that depend on the time period that was chosen for thereport.
3404:        )
3405: 
3406:     pattern(%( !currencyFormat ), lambda {
3407:       @property.set('currencyFormat', @val[0])
3408:     })
3409: 
3410:     pattern(%( !reportEnd ))
3411: 
3412:     pattern(%( _epilog $STRING ), lambda {
3413:       @property.set('epilog', newRichText(@val[1], @sourceFileInfo[1]))
3414:     })
3415:     doc('epilog', Define a text section that is printed right after the actual report data. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
3416:        )
3417:     also(%( footer header prolog ))
3418: 
3419:     pattern(%( !flags ))
3420:     doc('flags.report', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
3421:        )
3422: 
3423:     pattern(%( _footer $STRING ), lambda {
3424:       @property.set('footer', newRichText(@val[1], @sourceFileInfo[1]))
3425:     })
3426:     doc('footer', Define a text section that is put at the bottom of the report. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
3427:        )
3428:     also(%( epilog header prolog ))
3429: 
3430:     pattern(%( !formats ))
3431: 
3432:     pattern(%( _header $STRING ), lambda {
3433:       @property.set('header', newRichText(@val[1], @sourceFileInfo[1]))
3434:     })
3435:     doc('header', Define a text section that is put at the top of the report. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
3436:        )
3437:     also(%( epilog footer prolog ))
3438: 
3439:     pattern(%( !headline ))
3440:     pattern(%( !hidejournalentry ))
3441:     pattern(%( !hideresource ))
3442: 
3443:     pattern(%( !hidetask ))
3444: 
3445:     pattern(%( _left $STRING ), lambda {
3446:       @property.set('left', newRichText(@val[1], @sourceFileInfo[1]))
3447:     })
3448:     doc('left', This attribute defines the left margin section of the [[textreport]]. The textwill be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will notspan the [[header]] or [[footer]] sections.
3449:        )
3450: 
3451:     pattern(%( _loadunit !loadunit ), lambda {
3452:       @property.set('loadUnit', @val[1])
3453:     })
3454:     doc('loadunit', Determines what unit should be used to display all load values in this report.
3455:        )
3456: 
3457:     pattern(%( !numberFormat ), lambda {
3458:       @property.set('numberFormat', @val[0])
3459:     })
3460: 
3461:     pattern(%( !reportPeriod ))
3462: 
3463:     pattern(%( _prolog $STRING ), lambda {
3464:       @property.set('prolog', newRichText(@val[1], @sourceFileInfo[1]))
3465:     })
3466:     doc('prolog', Define a text section that is printed right before the actual report data. Thetext will be interpreted as [[Rich_Text_Attributes|Rich Text]].
3467:        )
3468:     also(%( epilog footer header ))
3469: 
3470:     pattern(%( _opennodes !nodeIdList ), lambda {
3471:       @property.set('openNodes', @val[1])
3472:     })
3473:     doc('opennodes', 'For internal use only!')
3474: 
3475:     pattern(%( !report ))
3476: 
3477:     pattern(%( _right $STRING ), lambda {
3478:       @property.set('right', newRichText(@val[1], @sourceFileInfo[1]))
3479:     })
3480:     doc('right', This attribute defines the right margin section of the [[textreport]]. The textwill be interpreted as [[Rich_Text_Attributes|Rich Text]]. The margin will notspan the [[header]] or [[footer]] sections.
3481:        )
3482: 
3483:     pattern(%( !rollupresource ))
3484:     pattern(%( !rolluptask ))
3485: 
3486:     pattern(%( _scenarios !scenarioIdList ), lambda {
3487:       # Don't include disabled scenarios in the report
3488:       @val[1].delete_if { |sc| !@project.scenario(sc).get('active') }
3489:       @property.set('scenarios', @val[1])
3490:     })
3491:     doc('scenarios', List of scenarios that should be included in the report. By default, only thetop-level scenario will be included. You can use this attribute to includedata from the defined set of scenarios. Not all reports support reporting datafrom multiple scenarios. They will only include data from the first one in thelist.
3492:        )
3493: 
3494:     pattern(%( _selfcontained !yesNo ), lambda {
3495:       @property.set('selfcontained', @val[1])
3496:     })
3497:     doc('selfcontained', Try to generate selfcontained output files when the format supports this. E.g. for HTML reports, the style sheet will be included and no icons will beused.
3498:        )
3499: 
3500:     pattern(%( !sortResources ))
3501:     pattern(%( !sortTasks ))
3502: 
3503:     pattern(%( !reportStart ))
3504: 
3505:     pattern(%( _resourceroot !resourceId), lambda {
3506:       if @val[1].leaf?
3507:         error('resourceroot_leaf',
3508:               "#{@val[1].fullId} is not a group resource",
3509:               @sourceFileInfo[1])
3510:       end
3511:       @property.set('resourceRoot', @val[1])
3512:     })
3513:     doc('resourceroot', Only resources below the specified root-level resources are exported. Theexported resources will have the ID of the root-level resource stripped fromtheir ID, so that the sub-resourcess of the root-level resource becometop-level resources in the report file.
3514:        )
3515:     example('ResourceRoot')
3516: 
3517:     pattern(%( _taskroot !taskId), lambda {
3518:       if @val[1].leaf?
3519:         error('taskroot_leaf',
3520:               "#{@val[1].fullId} is not a container task",
3521:               @sourceFileInfo[1])
3522:       end
3523:       @property.set('taskRoot', @val[1])
3524:     })
3525:     doc('taskroot', Only tasks below the specified root-level tasks are exported. The exportedtasks will have the ID of the root-level task stripped from their ID, so thatthe sub-tasks of the root-level task become top-level tasks in the reportfile.
3526:        )
3527:     example('TaskRoot')
3528: 
3529:     pattern(%( !timeformat ), lambda {
3530:       @property.set('timeFormat', @val[0])
3531:     })
3532: 
3533:     pattern(%( _timezone !validTimeZone ), lambda {
3534:       @property.set('timezone', @val[1])
3535:     })
3536:     doc('timezone.report', Sets the time zone used for all dates in the report. This setting is ignoredif the report is embedded into another report. Embedded in this context meansthe report is part of another generated report. It does not mean that thereport definition is a sub report of another report definition.
3537:        )
3538: 
3539:     pattern(%( !reportTitle ))
3540:   end
rule_reportBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3670
3670:   def rule_reportBody
3671:     optionsRule('reportAttributes')
3672:   end
rule_reportEnd() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3603
3603:   def rule_reportEnd
3604:     pattern(%( _end !date ), lambda {
3605:       if @val[1] < @property.get('start')
3606:         error('report_end',
3607:               "End date must be before start date #{@property.get('start')}",
3608:               @sourceFileInfo[1])
3609:       end
3610:       @property.set('end', @val[1])
3611:     })
3612:     doc('end.report', Specifies the end date of the report. In task reports only tasks that startbefore this end date are listed.
3613:        )
3614:     example('Export', '2')
3615:   end
rule_reportHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3674
3674:   def rule_reportHeader
3675:     pattern(%( !reportType !optionalID $STRING ), lambda {
3676:       if @property.nil? && !@reportprefix.empty?
3677:         @property = @project.report(@reportprefix)
3678:       end
3679:       if @val[1]
3680:         id = (@property ? @property.fullId + '.' : '') + @val[1]
3681:         if @project.report(id)
3682:           error('report_exists', "report #{id} has already been defined.",
3683:                 @sourceFileInfo[1], @property)
3684:         end
3685:       end
3686:       @property = Report.new(@project, @val[1], @val[2], @property)
3687:       @property.sourceFileInfo = @sourceFileInfo[0]
3688:       @property.inheritAttributes
3689:       case @val[0]
3690:       when 'taskreport'
3691:         @property.typeSpec = :taskreport
3692:         unless @property.modified?('columns')
3693:           # Set the default columns for this report.
3694:           %( bsi name start end effort chart ).each do |col|
3695:             @property.get('columns') <<
3696:             TableColumnDefinition.new(col, columnTitle(col))
3697:           end
3698:         end
3699:         # Show all tasks, sorted by tree, start-up, seqno-up.
3700:         unless @property.modified?('hideTask')
3701:           @property.set('hideTask',
3702:                         LogicalExpression.new(LogicalOperation.new(0)))
3703:         end
3704:         unless @property.modified?('softTask')
3705:           @property.set('sortTasks',
3706:                         [ [ 'tree', true, 1 ],
3707:                           [ 'start', true, 0 ],
3708:                           [ 'seqno', true, 1 ] ])
3709:         end
3710:         # Show no resources, but set sorting to id-up.
3711:         unless @property.modified?('hideResource')
3712:           @property.set('hideResource',
3713:                         LogicalExpression.new(LogicalOperation.new(1)))
3714:         end
3715:         unless @property.modified?('sortResources')
3716:           @property.set('sortResources', [ [ 'id', true, 1 ] ])
3717:         end
3718:       when 'resourcereport'
3719:         @property.typeSpec = :resourcereport
3720:         if @property.modified?('columns')
3721:           # Set the default columns for this report.
3722:           %( no name ).each do |col|
3723:             @property.get('columns') <<
3724:             TableColumnDefinition.new(col, columnTitle(col))
3725:           end
3726:         end
3727:         # Show all resources, sorted by tree and id-up.
3728:         unless @property.modified?('hideResource')
3729:           @property.set('hideResource',
3730:                         LogicalExpression.new(LogicalOperation.new(0)))
3731:         end
3732:         unless @property.modified?('sortResources')
3733:           @property.set('sortResources', [ [ 'tree', true, 1 ],
3734:                         [ 'id', true, 1 ] ])
3735:         end
3736:         # Hide all resources, but set sorting to tree, start-up, seqno-up.
3737:         unless @property.modified?('hideTask')
3738:           @property.set('hideTask',
3739:                         LogicalExpression.new(LogicalOperation.new(1)))
3740:         end
3741:         unless @property.modified?('sortTasks')
3742:           @property.set('sortTasks',
3743:                         [ [ 'tree', true, 1 ],
3744:                           [ 'start', true, 0 ],
3745:                           [ 'seqno', true, 1 ] ])
3746:         end
3747:       when 'textreport'
3748:         @property.typeSpec = :textreport
3749:       else
3750:         raise "Unsupported report type #{@val[0]}"
3751:       end
3752:     })
3753:     arg(2, 'name', The name of the report. This will be the base name for generated output files.The suffix will depend on the specified [[formats]].It will also be used innavigation bars.
3754:        )
3755:   end
rule_reportId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3619
3619:   def rule_reportId
3620:     pattern(%( !reportIdUnverifd ), lambda {
3621:       id = @val[0]
3622:       if @property && @property.is_a?(Report)
3623:         id = @property.fullId + '.' + id
3624:       else
3625:         id = @reportprefix + '.' + id unless @reportprefix.empty?
3626:       end
3627:       # In case we have a nested supplement, we need to prepend the parent ID.
3628:       if (report = @project.report(id)).nil?
3629:         error('report_id_expected', "#{id} is not a defined report.",
3630:               @sourceFileInfo[0])
3631:       end
3632:       report
3633:     })
3634:     arg(0, 'report', 'The ID of a defined report')
3635:   end
rule_reportIdUnverifd() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3637
3637:   def rule_reportIdUnverifd
3638:     singlePattern('$ABSOLUTE_ID')
3639:     singlePattern('$ID')
3640:   end
rule_reportPeriod() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3642
3642:   def rule_reportPeriod
3643:     pattern(%( _period !interval ), lambda {
3644:       @property.set('start', @val[1].start)
3645:       @property.set('end', @val[1].end)
3646:     })
3647:     doc('period.report', This property is a shortcut for setting the start and end property at thesame time.
3648:        )
3649:   end
rule_reportStart() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3654
3654:   def rule_reportStart
3655:     pattern(%( _start !date ), lambda {
3656:       if @val[1] > @property.get('end')
3657:         error('report_start',
3658:               "Start date must be before end date #{@property.get('end')}",
3659:               @sourceFileInfo[1])
3660:       end
3661:       @property.set('start', @val[1])
3662:     })
3663:     doc('start.report', Specifies the start date of the report. In task reports only tasks that endafter this end date are listed.
3664:        )
3665:   end
rule_reportTitle() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3761
3761:   def rule_reportTitle
3762:     pattern(%( _title $STRING ), lambda {
3763:       @property.set('title', @val[1])
3764:     })
3765:     doc('title', The title of the report will be used in external references to the report. Itwill not show up in the reports directly. It's used e. g. by [[navigator]].
3766:        )
3767:   end
rule_reportType() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3772
3772:   def rule_reportType
3773:     singlePattern('_resourcereport')
3774:     doc('resourcereport', The report lists resources and their respective values in a table. The taskthat are the resources are allocated to can be listed as well. To reduce thelist of included resources, you can use the [[hideresource]],[[rollupresource]] or [[resourceroot]] attributes. The order of the task canbe controlled with [[sortresources]]. If the first sorting criteria is treesorting, the parent resources will always be included to form the tree.Tree sorting is the default. You need to change it if you do not want certainparent resources to be included in the report.The tasks that the resources are allocated to can be included as well. Use the[[hidetask]] attribute for this. See [[report]] for a complete list ofattributes and the full syntax for this keyword.
3775:        )
3776:     singlePattern('_taskreport')
3777:     doc('taskreport', The report lists tasks and their respective values in a table. To reduce thelist of included tasks, you can use the [[hidetask]], [[rolluptask]] or[[taskroot]] attributes. The order of the task can be controlled with[[sorttasks]]. If the first sorting criteria is tree sorting, the parent taskswill always be included to form the tree. Tree sorting is the default. Youneed to change it if you do not want certain parent tasks to be included inthe report.The resources that are allocated to each task can be listed as well. Use the[[hideresource]] attribute for this. See [[report]] for a complete list ofattributes and the full syntax for this keyword.
3778:        )
3779:     singlePattern('_textreport')
3780:     doc('textreport', This report consists of 5 RichText sections, a header, a center section with aleft and right margin and a footer. The sections may contain the output ofother defined reports. See [[report]] for further details.
3781:        )
3782:   end
rule_reportableAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3046
3046:   def rule_reportableAttributes
3047:     singlePattern('_alert')
3048:     descr(The alert level of the property that was reported with the date closest to theend date of the report. Container properties that don't have their own alertlevel reported with a date equal or newer than the alert levels of all theirsub properties will get the highest alert level of their direct subproperties.
3049:          )
3050: 
3051:     singlePattern('_alertmessages')
3052:     descr(The headlines, the summary and the details of the message from the journalentries that caused the current alert level to be larger than the defaul levelfor this task or any of its sub tasks.
3053:          )
3054: 
3055:     singlePattern('_alertsummaries')
3056:     descr(The headlines and the summary message from the journal entries that caused thecurrent alert level to be larger than the default for this task or any of itssub tasks.
3057:          )
3058: 
3059:     singlePattern('_alerttrend')
3060:     descr(Shows how the alert level at the end of the report period compares to thealert level at the begining of the report period. Possible values are up, downor flat.
3061:          )
3062: 
3063:     singlePattern('_chart')
3064:     descr(A Gantt chart. This column type requires all lines to have the same fixedheight. This does not work well with rich text columns in some browsers. Someshow a scrollbar for the compressed table cells, others don't. It isrecommended, that you don't use rich text columns in conjuction with the chartcolumn.
3065:          )
3066: 
3067:     singlePattern('_complete')
3068:     descr('The completion degree of a task')
3069: 
3070:     pattern([ '_completed' ], lambda {
3071:       'complete'
3072:     })
3073:     descr('Deprecated alias for complete')
3074: 
3075:     singlePattern('_criticalness')
3076:     descr('A measure for how much effort the resource is allocated for, or' +
3077:           'how strained the allocated resources of a task are')
3078: 
3079:     singlePattern('_cost')
3080:     descr(The cost of the task or resource. The use of this column requires that a costaccount has been set for the report using the [[balance]] attribute.
3081:          )
3082: 
3083:     singlePattern('_daily')
3084:     descr('A group of columns with one column for each day')
3085: 
3086:     singlePattern('_directreports')
3087:     descr(The resources that have this resource assigned as manager.The list can be customized by the [listitem.column listitem] attribute.
3088:          )
3089: 
3090:     singlePattern('_duration')
3091:     descr('The duration of a task')
3092: 
3093:     singlePattern('_duties')
3094:     descr('List of tasks that the resource is allocated to')
3095: 
3096:     singlePattern('_efficiency')
3097:     descr('Measure for how efficient a resource can perform tasks')
3098: 
3099:     singlePattern('_effort')
3100:     descr('The allocated effort during the reporting period')
3101: 
3102:     singlePattern('_effortdone')
3103:     descr('The already completed effort as of now')
3104: 
3105:     singlePattern('_effortleft')
3106:     descr('The remaining allocated effort as of now')
3107: 
3108:     singlePattern('_email')
3109:     descr('The email address of a resource')
3110: 
3111:     singlePattern('_end')
3112:     descr('The end date of a task')
3113: 
3114:     singlePattern('_flags')
3115:     descr('List of attached flags')
3116: 
3117:     singlePattern('_followers')
3118:     descr(A list of tasks that depend on the current task. The list contains the names,the IDs, the date and the type of dependency. For the type the followingsymbols are used for <nowiki><dep></nowiki>.* '''<nowiki>]->[</nowiki>''': End-to-Start dependency* '''<nowiki>[->[</nowiki>''': Start-to-Start dependency* '''<nowiki>]->]</nowiki>''': End-to-End dependency* '''<nowiki>[->]</nowiki>''': Start-to-End dependencyThe list can be customized by the [listitem.column listitem] attribute.The dependency symbol can be generated via the ''''dependency'''' attributeinthe query, the target date via the ''''date'''' attribute.
3119:          )
3120: 
3121:     singlePattern('_freetime')
3122:     descr(The amount of unallocated work time of a resource during the reporting period.
3123:          )
3124: 
3125:     singlePattern('_freework')
3126:     descr(The amount of unallocated work capacity of a resource during the reportingperiod. This is the product of unallocated work time times the efficiency ofthe resource.
3127:          )
3128: 
3129:     singlePattern('_fte')
3130:     descr('The Full-Time-Equivalent of a resource or group')
3131: 
3132:     singlePattern('_headcount')
3133:     descr('The headcount number of the resource or group')
3134: 
3135:     pattern([ '_hierarchindex' ], lambda {
3136:       'bsi'
3137:     })
3138:     descr('Deprecated alias for bsi')
3139: 
3140:     singlePattern('_hourly')
3141:     descr('A group of columns with one column for each hour')
3142: 
3143:     singlePattern('_id')
3144:     descr('The id of the item')
3145: 
3146:     singlePattern('_index')
3147:     descr('The index of the item based on the nesting hierachy')
3148: 
3149:     singlePattern('_inputs')
3150:     descr(A list of milestones that are a prerequiste for the current task. Forcontainer tasks it will also include the inputs of the child tasks. Inputs maynot have any predecessors.The list can be customized by the [listitem.column listitem] attribute.
3151:          )
3152: 
3153:     singlePattern('_journal')
3154:     descr(The journal entries for the task or resource for the reported interval.
3155:          )
3156: 
3157:     singlePattern('_journal_sub')
3158:     descr(The journal entries for the task or resource and all its subtasks or resourcesfor the reported interval.
3159:          )
3160: 
3161:     singlePattern('_journalmessages')
3162:     descr(The headlines, the summary and the details of the message from the journalentries that caused the current alert level for this task.
3163:          )
3164: 
3165:     singlePattern('_journalsummaries')
3166:     descr(The headlines and the summary message from the journal entries that caused thecurrent alert level for this task.
3167:          )
3168: 
3169:     singlePattern('_line')
3170:     descr('The line number in the report')
3171: 
3172:     singlePattern('_managers')
3173:     descr(A list of managers that the resource reports to.The list can be customized by the [listitem.column listitem] attribute.
3174:         )
3175: 
3176:     singlePattern('_maxend')
3177:     descr('The latest allowed end of a task')
3178: 
3179:     singlePattern('_maxstart')
3180:     descr('The lastest allowed start of a task')
3181: 
3182:     singlePattern('_minend')
3183:     descr('The earliest allowed end of a task')
3184: 
3185:     singlePattern('_minstart')
3186:     descr('The earliest allowed start of a task')
3187: 
3188:     singlePattern('_monthly')
3189:     descr('A group of columns with one column for each month')
3190: 
3191:     singlePattern('_no')
3192:     descr('The object line number in the report (Cannot be used for sorting!)')
3193: 
3194:     singlePattern('_name')
3195:     descr('The name or description of the item')
3196: 
3197:     singlePattern('_note')
3198:     descr('The note attached to a task')
3199: 
3200:     singlePattern('_pathcriticalness')
3201:     descr('The criticalness of the task with respect to all the paths that ' +
3202:           'it is a part of.')
3203: 
3204:     singlePattern('_precursors')
3205:     descr(A list of tasks the current task depends on. The list contains the names, theIDs, the date and the type of dependency. For the type the following symbolsare used* '''<nowiki>]->[</nowiki>''': End-to-Start dependency* '''<nowiki>[->[</nowiki>''': Start-to-Start dependency* '''<nowiki>]->]</nowiki>''': End-to-End dependency* '''<nowiki>[->]</nowiki>''': Start-to-End dependencyThe list can be customized by the [listitem.column listitem] attribute.The dependency symbol can be generated via the ''''dependency'''' attributeinthe query, the target date via the ''''date'''' attribute.
3206:          )
3207: 
3208:     singlePattern('_priority')
3209:     descr('The priority of a task')
3210: 
3211:     singlePattern('_quarterly')
3212:     descr('A group of columns with one column for each quarter')
3213: 
3214:     singlePattern('_rate')
3215:     descr('The daily cost of a resource.')
3216: 
3217:     singlePattern('_reports')
3218:     descr(All resources that have this resource assigned as a direct or indirect manager.The list can be customized by the [listitem.column listitem] attribute.
3219:          )
3220: 
3221:     singlePattern('_resources')
3222:     descr(A list of resources that are assigned to the task in the report time frame.The list can be customized by the [listitem.column listitem] attribute.
3223:          )
3224: 
3225:     singlePattern('_responsible')
3226:     descr(The responsible people for this task.The list can be customized by the [listitem.column listitem] attribute.
3227:          )
3228: 
3229:     singlePattern('_revenue')
3230:     descr(The revenue of the task or resource. The use of this column requires that arevenue account has been set for the report using the [[balance]] attribute.
3231:          )
3232: 
3233:     singlePattern('_scenario')
3234:     descr('The name of the scenario')
3235: 
3236:     singlePattern('_seqno')
3237:     descr('The index of the item based on the declaration order')
3238: 
3239:     singlePattern('_start')
3240:     descr('The start date of the task')
3241: 
3242:     singlePattern('_status')
3243:     descr(The status of a task. It is determined based on the current date or the datespecified by [[now]].
3244:          )
3245: 
3246:     singlePattern('_targets')
3247:     descr(A list of milestones that depend on the current task. For container tasks itwill also include the targets of the child tasks. Targets may not have anyfollower tasks.The list can be customized by the [listitem.column listitem] attribute.
3248:          )
3249: 
3250:     pattern([ '_wbs' ], lambda {
3251:       'bsi'
3252:     })
3253:     descr('Deprecated alias for bsi.')
3254: 
3255:     singlePattern('_bsi')
3256:     descr('The hierarchical or work breakdown structure index')
3257: 
3258:     singlePattern('_weekly')
3259:     descr('A group of columns with one column for each week')
3260: 
3261:     singlePattern('_yearly')
3262:     descr('A group of columns with one column for each year')
3263: 
3264:   end
rule_resource() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3813
3813:   def rule_resource
3814:     pattern(%( !resourceHeader !resourceBody ), lambda {
3815:        @property = @property.parent
3816:     })
3817:     doc('resource', Tasks that have an effort specification need to have at least one resourceassigned to do the work. Use this property to define resources or groups ofresources.Resources have a global name space. All IDs must be unique within the resourcesof the project.
3818:        )
3819:   end
rule_resourceAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3828
3828:   def rule_resourceAttributes
3829:     repeatable
3830:     optional
3831:     pattern(%( _email $STRING ), lambda {
3832:       @property.set('email', @val[1])
3833:     })
3834:     doc('email',
3835:         'The email address of the resource.')
3836: 
3837:     pattern(%( !journalEntry ))
3838:     pattern(%( !purge ))
3839:     pattern(%( !resource ))
3840:     pattern(%( !resourceScenarioAttributes ))
3841:     pattern(%( !scenarioIdCol !resourceScenarioAttributes ), lambda {
3842:       @scenarioIdx = 0
3843:     })
3844: 
3845:     pattern(%( _supplement !resourceId !resourceBody ), lambda {
3846:       @property = @property.parent
3847:     })
3848:     doc('supplement.resource', The supplement keyword provides a mechanism to add more attributes to alreadydefined resources. The additional attributes must obey the same rules as inregular resource definitions and must be enclosed by curly braces.This construct is primarily meant for situations where the information about aresource is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool.
3849:        )
3850:     example('Supplement', 'resource')
3851: 
3852:     # Other attributes will be added automatically.
3853:   end
rule_resourceBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3863
3863:   def rule_resourceBody
3864:     optionsRule('resourceAttributes')
3865:   end
rule_resourceBooking() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3867
3867:   def rule_resourceBooking
3868:     pattern(%( !resourceBookingHeader !bookingBody ), lambda {
3869:       unless @project.scenario(@scenarioIdx).get('ownbookings')
3870:         error('no_own_resource_booking',
3871:               "The scenario #{@project.scenario(@scenarioIdx).fullId} " +
3872:               'inherits its bookings from the tracking ' +
3873:               'scenario. You cannot specificy additional bookings for it.')
3874:       end
3875:       @val[0].task.addBooking(@scenarioIdx, @val[0])
3876:     })
3877:   end
rule_resourceBookingHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3879
3879:   def rule_resourceBookingHeader
3880:     pattern(%( !taskId !valIntervals ), lambda {
3881:       checkBooking(@val[0], @property)
3882:       @booking = Booking.new(@property, @val[0], @val[1])
3883:       @booking.sourceFileInfo = @sourceFileInfo[0]
3884:       @booking
3885:     })
3886:     arg(0, 'id', 'Absolute ID of a defined task')
3887:   end
rule_resourceHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3901
3901:   def rule_resourceHeader
3902:     pattern(%( _resource !optionalID $STRING ), lambda {
3903:       if @property.nil? && !@resourceprefix.empty?
3904:         @property = @project.resource(@resourceprefix)
3905:       end
3906:       if @val[1] && @project.resource(@val[1])
3907:         error('resource_exists',
3908:               "Resource #{@val[1]} has already been defined.",
3909:               @sourceFileInfo[1], @property)
3910:       end
3911:       @property = Resource.new(@project, @val[1], @val[2], @property)
3912:       @property.sourceFileInfo = @sourceFileInfo[0]
3913:       @property.inheritAttributes
3914:       @scenarioIdx = 0
3915:     })
3916: #    arg(1, 'id', <<'EOT'
3917: #The ID of the resource. Resources have a global name space. The ID must be
3918: #unique within the whole project.
3919: #EOT
3920: #       )
3921:     arg(2, 'name', 'The name of the resource')
3922:   end
rule_resourceId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3889
3889:   def rule_resourceId
3890:     pattern(%( $ID ), lambda {
3891:       id = (@resourceprefix.empty? ? '' : @resourceprefix + '.') + @val[0]
3892:       if (resource = @project.resource(id)).nil?
3893:         error('resource_id_expected', "#{id} is not a defined resource.",
3894:               @sourceFileInfo[0])
3895:       end
3896:       resource
3897:     })
3898:     arg(0, 'resource', 'The ID of a defined resource')
3899:   end
rule_resourceLeafList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3924
3924:   def rule_resourceLeafList
3925:     pattern(%( !leafResourceId !moreLeafResources ), lambda {
3926:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
3927:     })
3928:   end
rule_resourceList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3930
3930:   def rule_resourceList
3931:     listRule('moreResources', '!resourceId')
3932:   end
rule_resourceScenarioAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 3934
3934:   def rule_resourceScenarioAttributes
3935:     pattern(%( _efficiency !number ), lambda {
3936:       @property['efficiency', @scenarioIdx] = @val[1]
3937:     })
3938:     doc('efficiency', The efficiency of a resource can be used for two purposes. First you can useit as a crude way to model a team. A team of 5 people should have anefficiency of 5.0. Keep in mind that you cannot track the members of the teamindividually if you use this feature. They always act as a group.The other use is to model performance variations between your resources. Again, this is a fairly crude mechanism and should be used with care. A resource that isn't every good at some task might be pretty good at another. This can't be taken into account as the resource efficiency can only set globally for all tasks.All resources that do not contribute effort to the task, should have anefficiency of 0.0. A typical example would be a conference room. It's necessary for a meeting, but it does not contribute any work.
3939:        )
3940:     example('Efficiency')
3941:     pattern(%( !flags ))
3942:     doc('flags.resource', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
3943:        )
3944: 
3945:     pattern(%( _booking !resourceBooking ))
3946:     doc('booking.resource', The booking attribute can be used to report actually completed work.  A taskwith bookings must be [[scheduling|scheduled]] in ''''asap'''' mode.  If thescenario is not the [[trackingscenario|tracking scenario]] or derived from it,the scheduler will not allocate resources prior to the current date or thedate specified with [[now]] when a task has at least one booking.Bookings are only valid in the scenario they have been defined in. They willin general not be passed to any other scenario. If you have defined a[[trackingscenario|tracking scenario]], the bookings of this scenario will bepassed to all the derived scenarios of the tracking scenario.The sloppy attribute can be used when you want to skip non-working time orother allocations automatically. If it's not given, all bookings must onlycover working time for the resource.The booking attributes is designed to capture the exact amount of completedwork. This attribute is not really intended to specify completed effort byhand. Usually, booking statements are generated by [[export]] reports. The[[sloppy.booking|sloppy]] and [[overtime.booking|overtime]] attributes areonly kludge for users who want to write them manually.Bookings can be used to report already completed work by specifying the exacttime intervals a certain resource has worked on this task.Bookings can be defined in the task or resource context. If you move tasksaround very often, put your bookings in the task context.
3947:        )
3948:     also(%( scheduling booking.task ))
3949:     example('Booking')
3950: 
3951:     pattern(%( !fail ))
3952: 
3953:     pattern(%( !limits ), lambda {
3954:       @property['limits', @scenarioIdx] = @val[0]
3955:     })
3956:     doc('limits.resource', Set per-interval usage limits for the resource.
3957:        )
3958:     example('Limits-1', '6')
3959: 
3960:     pattern(%( _managers !resourceList ), lambda {
3961:       @property['managers', @scenarioIdx] =
3962:         @property['managers', @scenarioIdx] + @val[1]
3963:     })
3964:     doc('managers', Defines one or more resources to be the manager who is responsible for thisresource. Managers must be leaf resources. This attribute does not impact thescheduling. It can only be used for documentation purposes.You must only specify direct managers here. Do not list higher level managershere. If necessary, use the [[purge]] attribute to clearinherited managers. For most use cases, there should be only one manager. ButTaskJuggler is not limited to just one manager. Dotted reporting lines can becaptured as well as long as the managers are not reporting to each other.
3965:        )
3966:     also(%( statussheet ))
3967:     example('Manager')
3968: 
3969: 
3970:     pattern(%( _rate !number ), lambda {
3971:       @property['rate', @scenarioIdx] = @val[1]
3972:     })
3973:     doc('rate.resource', The rate specifies the daily cost of the resource.
3974:        )
3975: 
3976:     pattern(%( _shift !shiftAssignments ))
3977:     doc('shift.resource', This keyword has been deprecated. Please use [[shifts.resource|shifts(resource)]] instead.
3978:        )
3979: 
3980:     pattern(%( _shifts !shiftAssignments ))
3981:     doc('shifts.resource', Limits the working time of a resource to a defined shift during the specifiedinterval. Multiple shifts can be defined, but shift intervals may not overlap.In case a shift is defined for a certain interval, the shift working hoursreplace the standard resource working hours for this interval.
3982:         )
3983: 
3984:     pattern(%( _vacation !vacationName !intervals ), lambda {
3985:       begin
3986:         @property['vacations', @scenarioIdx] =
3987:           @property['vacations', @scenarioIdx ] + @val[2]
3988:       rescue AttributeOverwrite
3989:       end
3990:     })
3991:     doc('vacation.resource', Specify a vacation period for the resource. It can also be used to block outthe time before a resource joined or after it left. For employees changingtheir work schedule from full-time to part-time, or vice versa, please referto the 'Shift' property.
3992:        )
3993: 
3994:     pattern(%( !warn ))
3995: 
3996:     pattern(%( !workinghoursResource ))
3997:     # Other attributes will be added automatically.
3998:   end
rule_rollupresource() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4066
4066:   def rule_rollupresource
4067:     pattern(%( _rollupresource !logicalExpression ), lambda {
4068:       @property.set('rollupResource', @val[1])
4069:     })
4070:     doc('rollupresource', Do not show sub-resources of resources that match the specified logicalexpression.
4071:        )
4072:     example('RollupResource')
4073:   end
rule_rolluptask() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4078
4078:   def rule_rolluptask
4079:     pattern(%( _rolluptask !logicalExpression ), lambda {
4080:       @property.set('rollupTask', @val[1])
4081:     })
4082:     doc('rolluptask', Do not show sub-tasks of tasks that match the specified logical expression.
4083:        )
4084:   end
rule_scenario() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4089
4089:   def rule_scenario
4090:     pattern(%( !scenarioHeader !scenarioBody ), lambda {
4091:       @property = @property.parent
4092:     })
4093:     doc('scenario', Defines a new project scenario. By default, the project has only one scenariocalled ''''plan''''. To do plan vs. actual comparisons or to do awhat-if-analysis, you can define a set of scenarios. There can only be onetop-level scenario. Additional scenarios are either derived from thistop-level scenario or other scenarios.Each nested scenario is a variation of the enclosing scenario. All scenariosshare the same set of properties (task, resources, etc.) but the attributesthat are listed as scenario specific may differ between the variousscenarios. A nested scenario uses all attributes from the enclosing scenariounless the user has specified a different value for this attribute.By default, the scheduler assigns resources to task beginning with the projectstart date. If the scenario is switched to projection mode, no assignmentswill be made prior to the current date or the date specified by [[now]]. Inthis case, TaskJuggler assumes, that all assignements prior to thecurrent date have been provided by [[booking.task]] statements.
4094:        )
4095:   end
rule_scenarioAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4115
4115:   def rule_scenarioAttributes
4116:     optional
4117:     repeatable
4118: 
4119:     pattern(%( _active !yesNo), lambda {
4120:       @property.set('active', @val[1])
4121:     })
4122:     doc('active', Enable the scenario to be scheduled or not. By default, all scenarios will bescheduled. If a scenario is marked as inactive, it not be scheduled and willbe ignored in the reports.
4123:        )
4124:     pattern(%( _disabled ), lambda {
4125:       @property.set('active', false)
4126:     })
4127:     doc('disabled', This attribute is deprecated. Please use [active] instead.Disable the scenario for scheduling. The default for the top-levelscenario is to be enabled.
4128:        )
4129:     example('Scenario')
4130:     pattern(%( _enabled ), lambda {
4131:       @property.set('active', true)
4132:     })
4133:     doc('enabled', This attribute is deprecated. Please use [active] instead.Enable the scenario for scheduling. This is the default for the top-levelscenario.
4134:        )
4135: 
4136:     pattern(%( _projection !projection ), lambda {
4137:       warning('projection',
4138:               'The \projection\ keyword has been deprecated. Please use ' +
4139:               '[[trackingscenario]] feature instead.')
4140:     })
4141:     doc('projection', This keyword has been deprecated! Don't use it anymore!Projection mode is now automatically enabled as soon as a scenario hasbookings.
4142:        )
4143: 
4144:     pattern(%( !scenario ))
4145:   end
rule_scenarioBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4166
4166:   def rule_scenarioBody
4167:     optionsRule('scenarioAttributes')
4168:   end
rule_scenarioHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4170
4170:   def rule_scenarioHeader
4171: 
4172:     pattern(%( _scenario $ID $STRING ), lambda {
4173:       # If this is the top-level scenario, we must delete the default scenario
4174:       # first.
4175:       @project.scenarios.clearProperties if @property.nil?
4176:       if @project.scenario(@val[1])
4177:         error('scenario_exists',
4178:               "Scenario #{@val[1]} has already been defined.",
4179:               @sourceFileInfo[1])
4180:       end
4181:       @property = Scenario.new(@project, @val[1], @val[2], @property)
4182:       @property.inheritAttributes
4183:     })
4184:     arg(1, 'id', 'The ID of the scenario')
4185:     arg(2, 'name', 'The name of the scenario')
4186:   end
rule_scenarioId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4188
4188:   def rule_scenarioId
4189:     pattern(%( $ID ), lambda {
4190:       if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
4191:         error('unknown_scenario_id', "Unknown scenario: #{@val[0]}",
4192:               @sourceFileInfo[0])
4193:       end
4194:       @scenarioIdx
4195:     })
4196:     arg(0, 'scenario', 'ID of a defined scenario')
4197:   end
rule_scenarioIdCol() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4199
4199:   def rule_scenarioIdCol
4200:     pattern(%( $ID_WITH_COLON ), lambda {
4201:       if (@scenarioIdx = @project.scenarioIdx(@val[0])).nil?
4202:         error('unknown_scenario_id', "Unknown scenario: @val[0]",
4203:               @sourceFileInfo[0])
4204:       end
4205:     })
4206:   end
rule_scenarioIdList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4208
4208:   def rule_scenarioIdList
4209:     listRule('moreScnarioIdList', '!scenarioIdx')
4210:   end
rule_scenarioIdx() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4212
4212:   def rule_scenarioIdx
4213:     pattern(%( $ID ), lambda {
4214:       if (scenarioIdx = @project.scenarioIdx(@val[0])).nil?
4215:         error('unknown_scenario_idx', "Unknown scenario #{@val[0]}",
4216:               @sourceFileInfo[0])
4217:       end
4218:       scenarioIdx
4219:     })
4220:   end
rule_schedulingDirection() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4222
4222:   def rule_schedulingDirection
4223:     singlePattern('_alap')
4224:     singlePattern('_asap')
4225:   end
rule_shift() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4227
4227:   def rule_shift
4228:     pattern(%( !shiftHeader !shiftBody ), lambda {
4229:       @property = @property.parent
4230:     })
4231:     doc('shift', A shift combines several workhours related settings in a reusable entity.Besides the weekly working hours it can also hold information such asvacations and a time zone.Shifts have a global name space. All IDs must be unique within the shifts ofthe project.
4232:        )
4233:     also(%( shifts.task shifts.resource ))
4234:   end
rule_shiftAssignment() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4243
4243:   def rule_shiftAssignment
4244:     pattern(%( !shiftId !intervalsOptional ), lambda {
4245:       # Make sure we have a ShiftAssignment for the property.
4246:       sa = @property['shifts', @scenarioIdx] || ShiftAssignments.new
4247:       sa.project = @project
4248: 
4249:       if @val[1].nil?
4250:         intervals = [ Interval.new(@project['start'], @project['end']) ]
4251:       else
4252:         intervals = @val[1]
4253:       end
4254:       intervals.each do |interval|
4255:         if !sa.addAssignment(ShiftAssignment.new(@val[0].scenario(@scenarioIdx),
4256:                                                  interval))
4257:           error('shift_assignment_overlap',
4258:                 'Shifts may not overlap each other.',
4259:                 @sourceFileInfo[0], @property)
4260:         end
4261:       end
4262:       # Set same value again to set the 'provided' state for the attribute.
4263:       begin
4264:         @property['shifts', @scenarioIdx] = sa
4265:       rescue AttributeOverwrite
4266:         # Multiple shift assignments are a common idiom, so don't warn about
4267:         # them.
4268:       end
4269:     })
4270:   end
rule_shiftAssignments() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4272
4272:   def rule_shiftAssignments
4273:     listRule('moreShiftAssignments', '!shiftAssignment')
4274:   end
rule_shiftAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4276
4276:   def rule_shiftAttributes
4277:     optional
4278:     repeatable
4279: 
4280:     pattern(%( !shift ))
4281:     pattern(%( !shiftScenarioAttributes ))
4282:     pattern(%( !scenarioIdCol !shiftScenarioAttributes ), lambda {
4283:       @scenarioIdx = 0
4284:     })
4285:   end
rule_shiftBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4287
4287:   def rule_shiftBody
4288:     optionsRule('shiftAttributes')
4289:   end
rule_shiftHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4291
4291:   def rule_shiftHeader
4292:     pattern(%( _shift !optionalID $STRING ), lambda {
4293:       if @val[1] && @project.shift(@val[1])
4294:         error('shift_exists', "Shift #{@val[1]} has already been defined.",
4295:               @sourceFileInfo[1])
4296:       end
4297:       @property = Shift.new(@project, @val[1], @val[2], @property)
4298:       @property.sourceFileInfo = @sourceFileInfo[0]
4299:       @property.inheritAttributes
4300:       @scenarioIdx = 0
4301:     })
4302:     arg(2, 'name', 'The name of the shift')
4303:   end
rule_shiftId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4305
4305:   def rule_shiftId
4306:     pattern(%( $ID ), lambda {
4307:       if (shift = @project.shift(@val[0])).nil?
4308:         error('shift_id_expected', "#{@val[0]} is not a defined shift.",
4309:               @sourceFileInfo[0])
4310:       end
4311:       shift
4312:     })
4313:     arg(0, 'shift', 'The ID of a defined shift')
4314:   end
rule_shiftScenarioAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4316
4316:   def rule_shiftScenarioAttributes
4317:     pattern(%( _replace ), lambda {
4318:       @property['replace', @scenarioIdx] = true
4319:     })
4320:     doc('replace', Use this attribute if the vacation definition for the shift should replace the vacation settings of a resource. This is only effective for shifts that are assigned to resources directly. It is not effective for shifts that are assigned to tasks or allocations.
4321:        )
4322: 
4323:     pattern(%( _timezone !validTimeZone ), lambda {
4324:       @property['timezone', @scenarioIdx] = @val[1]
4325:     })
4326:     doc('timezone.shift', Sets the time zone of the shift. The working hours of the shift are assumed tobe within the specified time zone. The time zone does not effect the vactioninterval. The latter is assumed to be within the project time zone.TaskJuggler stores all dates internally as UTC. Since all events must alignwith the [[timingresolution|timing resolution]] for time zones you may have tochange the timing resolution appropriately. The time zone difference comparedto UTC must be a multiple of the used timing resolution.
4327:         )
4328:     arg(1, 'zone', Time zone to use. E. g. 'Europe/Berlin' or 'America/Denver'. Don't use the 3letter acronyms. See[http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones Wikipedia] forpossible values.
4329:        )
4330: 
4331:     pattern(%( _vacation !vacationName !intervalsOptional ), lambda {
4332:       @property['vacations', @scenarioIdx] =
4333:         @property['vacations', @scenarioIdx ] + @val[2]
4334:     })
4335:     doc('vacation.shift', Specify a vacation period associated with this shift.
4336:        )
4337: 
4338:     pattern(%( !workinghoursShift ))
4339:   end
rule_sortCriteria() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4359
4359:   def rule_sortCriteria
4360:     pattern([ "!sortCriterium", "!moreSortCriteria" ], lambda {
4361:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
4362:     })
4363:   end
rule_sortCriterium() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4365
4365:   def rule_sortCriterium
4366:     pattern(%( !sortTree ), lambda {
4367:       @val[0]
4368:     })
4369:     pattern(%( !sortNonTree ), lambda {
4370:       @val[0]
4371:     })
4372:   end
rule_sortNonTree() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4374
4374:   def rule_sortNonTree
4375:     pattern(%( $ABSOLUTE_ID ), lambda {
4376:       args = @val[0].split('.')
4377:       case args.length
4378:       when 2
4379:         # <attribute>.<up|down>
4380:         scenario = 1
4381:         direction = args[1] == 'up'
4382:         attribute = args[0]
4383:       when 3
4384:         # <scenario>.<attribute>.<up|down>
4385:         if (scenario = @project.scenarioIdx(args[0])).nil?
4386:           error('sort_unknown_scen',
4387:                 "Unknown scenario #{args[0]} in sorting criterium",
4388:                 @sourceFileInfo[0])
4389:         end
4390:         attribute = args[1]
4391:         if args[2] != 'up' && args[2] != 'down'
4392:           error('sort_direction', "Sorting direction must be 'up' or 'down'",
4393:                 @sourceFileInfo[0])
4394:         end
4395:         direction = args[2] == 'up'
4396:       else
4397:         error('sorting_crit_exptd1',
4398:               "Sorting criterium expected (e.g. tree, start.up or " +
4399:               "plan.end.down).", @sourceFileInfo[0])
4400:       end
4401:       if attribute == 'bsi'
4402:         error('sorting_bsi',
4403:               "Sorting by bsi is not supported. Please use 'tree' " +
4404:               '(without appended .up or .down) instead.',
4405:               @sourceFileInfo[0])
4406:       end
4407:       [ attribute, direction, scenario ]
4408:     })
4409:     arg(0, 'criteria', The sorting criteria must consist of a property attribute ID. See [[columnid]]for a complete list of available attributes. The ID must be suffixed by '.up'or '.down' to determine the sorting direction. Optionally the ID may beprefixed with a scenario ID and a dot to determine the scenario that should beused for sorting. So, possible values are 'plan.start.up' or 'priority.down'.
4410:          )
4411:   end
rule_sortResources() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4419
4419:   def rule_sortResources
4420:     pattern(%( _sortresources !sortCriteria ), lambda {
4421:       @property.set('sortResources', @val[1])
4422:     })
4423:     doc('sortresources', Determines how the resources are sorted in the report. Multiple criteria can bespecified as a comma separated list. If one criteria is not sufficient to sorta group of resources, the next criteria will be used to sort the resources inthis group.
4424:        )
4425:   end
rule_sortTasks() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4432
4432:   def rule_sortTasks
4433:     pattern(%( _sorttasks !sortCriteria ), lambda {
4434:       @property.set('sortTasks', @val[1])
4435:     })
4436:     doc('sorttasks', Determines how the tasks are sorted in the report. Multiple criteria can bespecified as comma separated list. If one criteria is not sufficient to sort agroup of tasks, the next criteria will be used to sort the tasks withinthis group.
4437:        )
4438:   end
rule_sortTree() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4445
4445:   def rule_sortTree
4446:     pattern(%( $ID ), lambda {
4447:       if @val[0] != 'tree'
4448:         error('sorting_crit_exptd2',
4449:               "Sorting criterium expected (e.g. tree, start.up or " +
4450:               "plan.end.down).", @sourceFileInfo[0])
4451:       end
4452:       [ 'tree', true, 1 ]
4453:     })
4454:     arg(0, 'tree',
4455:         'Use \tree\ as first criteria to keep the breakdown structure.')
4456:   end
rule_ssReportAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4486
4486:   def rule_ssReportAttributes
4487:     optional
4488:     repeatable
4489: 
4490:     pattern(%( !hideresource ))
4491:     pattern(%( !hidetask ))
4492:     pattern(%( !reportEnd ))
4493:     pattern(%( !reportPeriod ))
4494:     pattern(%( !reportStart ))
4495:     pattern(%( !sortResources ))
4496:     pattern(%( !sortTasks ))
4497:   end
rule_ssReportBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4499
4499:   def rule_ssReportBody
4500:     optionsRule('ssReportAttributes')
4501:   end
rule_ssReportHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4457
4457:   def rule_ssReportHeader
4458:     pattern(%( _statussheetreport !optionalID $STRING ), lambda {
4459:       if (fileName = @val[2]) != '.'
4460:         if @project.reports[fileName]
4461:           error('report_redefinition',
4462:                 "A report with the name '#{fileName}' has already been " +
4463:                 "defined.", @sourceFileInfo[2])
4464:         end
4465:       else
4466:         fileName = "statusSheet#{@project.reports.length + 1}"
4467:       end
4468:       report = newReport(@val[1], fileName, :statusSheet, sourceFileInfo)
4469:       report.set('scenarios', [ 0 ])
4470:       # Show all tasks, sorted by id-up.
4471:       report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
4472:       report.set('sortTasks', [ [ 'id', true, 1 ] ])
4473:       # Show all resources, sorted by seqno-up.
4474:       report.set('hideResource', LogicalExpression.new(LogicalOperation.new(0)))
4475:       report.set('sortResources', [ [ 'seqno', true, 1 ] ])
4476:       report.set('loadUnit', :hours)
4477:       report.set('definitions', [])
4478:     })
4479:     arg(1, 'file name', The name of the status sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel.
4480:        )
4481:   end
rule_ssStatus() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4542
4542:   def rule_ssStatus
4543:     pattern(%( !ssStatusHeader !ssStatusBody ))
4544:     doc('status.statussheet', The status attribute can be used to describe the current status of the task orresource. The content of the status messages is added to the project journal.
4545:        )
4546:   end
rule_ssStatusAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4503
4503:   def rule_ssStatusAttributes
4504:     optional
4505:     repeatable
4506: 
4507:     pattern(%( !author ))
4508:     pattern(%( !details ))
4509: 
4510:     pattern(%( _flags !flagList ), lambda {
4511:       @val[1].each do |flag|
4512:         next if @journalEntry.flags.include?(flag)
4513: 
4514:         @journalEntry.flags << flag
4515:       end
4516:     })
4517:     doc('flags.statussheet', Status sheet entries can have flags attached to them. These can be used toinclude only entries in a report that have a certain flag.
4518:        )
4519: 
4520:     pattern(%( !summary ))
4521:   end
rule_ssStatusBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4526
4526:   def rule_ssStatusBody
4527:     optional
4528:     pattern(%( _{ !ssStatusAttributes _} ))
4529:   end
rule_ssStatusHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4531
4531:   def rule_ssStatusHeader
4532:     pattern(%( _status !alertLevel $STRING ), lambda {
4533:       @journalEntry = JournalEntry.new(@project['journal'], @sheetEnd,
4534:                                        @val[2], @property,
4535:                                        @sourceFileInfo[0])
4536:       @journalEntry.alertLevel = @val[1]
4537:       @journalEntry.author = @sheetAuthor
4538: 
4539:     })
4540:   end
rule_statusSheet() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4551
4551:   def rule_statusSheet
4552:     pattern(%( !statusSheetHeader !statusSheetBody ), lambda {
4553:       [ @sheetAuthor, @sheetStart, @sheetEnd ]
4554:     })
4555:     doc('statussheet', A status sheet can be used to capture the status of various tasks outside ofthe regular task tree definition. It is intended for use by managers thatdon't directly work with the full project plan, but need to report the currentstatus of each task or task-tree that they are responsible for.
4556:        )
4557:     example('StatusSheet')
4558:   end
rule_statusSheetAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4565
4565:   def rule_statusSheetAttributes
4566:     optional
4567:     repeatable
4568: 
4569:     pattern(%( !statusSheetTask ))
4570:   end
rule_statusSheetBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4572
4572:   def rule_statusSheetBody
4573:     optionsRule('statusSheetAttributes')
4574:   end
rule_statusSheetFile() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4576
4576:   def rule_statusSheetFile
4577:     pattern(%( !statusSheet . ), lambda {
4578:       @val[0]
4579:     })
4580:     lastSyntaxToken(1)
4581:   end
rule_statusSheetHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4584
4584:   def rule_statusSheetHeader
4585:     pattern(%( _statussheet !resourceId !valIntervalOrDate ), lambda {
4586:       unless (scenarioIdx = @project['trackingScenarioIdx'])
4587:         error('ss_no_tracking_scenario',
4588:               'No trackingscenario defined.')
4589:       end
4590:       @sheetAuthor = @val[1]
4591:       @sheetStart = @val[2].start
4592:       @sheetEnd = @val[2].end
4593:     })
4594:     arg(1, 'reporter', The ID of a defined resource. This identifies the status reporter. Unless thestatus entries provide a different author, the sheet author will be used asstatus entry author.
4595:        )
4596:   end
rule_statusSheetReport() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4602
4602:   def rule_statusSheetReport
4603:     pattern(%( !ssReportHeader !ssReportBody ), lambda {
4604:       @property = nil
4605:     })
4606:     doc('statussheetreport', A status sheet report is a template for a status sheet. It collects all thestatus information of the top-level task that a resource is responsible for.This report is typically used by managers or team leads to review the timesheet status information and destill it down to a summary that can beforwarded to the next person in the reporting chain. The report will be forthe specified [trackingscenario].
4607:        )
4608:   end
rule_statusSheetTask() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4617
4617:   def rule_statusSheetTask
4618:     pattern(%( !statusSheetTaskHeader !statusSheetTaskBody), lambda {
4619:       @property = @propertyStack.pop
4620:     })
4621:     doc('task.statussheet', Opens the task with the specified ID to add a status report. Child task can beopened inside this context by specifying their relative ID to this parent.
4622:        )
4623:   end
rule_statusSheetTaskAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4628
4628:   def rule_statusSheetTaskAttributes
4629:     optional
4630:     repeatable
4631:     pattern(%( !ssStatus ))
4632:     pattern(%( !statusSheetTask ), lambda {
4633:     })
4634:   end
rule_statusSheetTaskBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4636
4636:   def rule_statusSheetTaskBody
4637:     optionsRule('statusSheetTaskAttributes')
4638:   end
rule_statusSheetTaskHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4640
4640:   def rule_statusSheetTaskHeader
4641:     pattern(%( _task !taskId ), lambda {
4642:       if @property
4643:         @propertyStack.push(@property)
4644:       else
4645:         @propertyStack = []
4646:       end
4647:       @property = @val[1]
4648:     })
4649:   end
rule_subNodeId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4651
4651:   def rule_subNodeId
4652:     optional
4653:     pattern(%( _: !idOrAbsoluteId ), lambda {
4654:       @val[1]
4655:     })
4656:   end
rule_summary() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4658
4658:   def rule_summary
4659:     pattern(%( _summary $STRING ), lambda {
4660:       return if @val[1].empty?
4661: 
4662:       if @val[1].length > 480
4663:         error('ts_summary_too_long',
4664:               "The summary text must be 480 characters long or shorter. " +
4665:               "This text has #{@val[1].length} characters.",
4666:               @sourceFileInfo[1])
4667:       end
4668:       if @val[1] == "A summary text\n"
4669:           error('ts_default_summary',
4670:                 "'A summary text' is not a valid summary",
4671:                 @sourceFileInfo[1])
4672:       end
4673:       rtTokenSetIntro =
4674:         [ :LINEBREAK, :SPACE, :WORD, :BOLD, :ITALIC, :CODE, :BOLDITALIC,
4675:           :HREF, :HREFEND ]
4676:       @journalEntry.summary = newRichText(@val[1], @sourceFileInfo[1],
4677:                                           rtTokenSetIntro)
4678:     })
4679:     doc('summary', This is the introductory part of the journal or status entry. It shouldonly summarize the full entry but should contain more details than theheadline. The text including formatting characters must be 240 characters longor less.
4680:        )
4681:     arg(1, 'text', The text will be interpreted as [[Rich_Text_Attributes|Rich Text]]. Only asmall subset of the markup is supported for this attribute. You can use wordformatting, hyperlinks and paragraphs.
4682:        )
4683:   end
rule_supplement() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4694
4694:   def rule_supplement
4695:     pattern(%( !supplementAccount !accountBody ), lambda {
4696:       @property = nil
4697:     })
4698:     pattern(%( !supplementReport !reportBody ), lambda {
4699:       @property = nil
4700:     })
4701:     pattern(%( !supplementResource !resourceBody ), lambda {
4702:       @property = nil
4703:     })
4704:     pattern(%( !supplementTask !taskBody ), lambda {
4705:       @property = nil
4706:     })
4707:   end
rule_supplementAccount() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4709
4709:   def rule_supplementAccount
4710:     pattern(%( _account !accountId ), lambda {
4711:       @property = @val[1]
4712:     })
4713:     arg(1, 'account ID', 'The ID of an already defined account.')
4714:   end
rule_supplementReport() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4716
4716:   def rule_supplementReport
4717:     pattern(%( _report !reportId ), lambda {
4718:       @property = @val[1]
4719:     })
4720:     arg(1, 'report ID', 'The ID of an already defined report.')
4721:   end
rule_supplementResource() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4723
4723:   def rule_supplementResource
4724:     pattern(%( _resource !resourceId ), lambda {
4725:       @property = @val[1]
4726:     })
4727:     arg(1, 'resource ID', 'The ID of an already defined resource.')
4728:   end
rule_supplementTask() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4730
4730:   def rule_supplementTask
4731:     pattern(%( _task !taskId ), lambda {
4732:       @property = @val[1]
4733:     })
4734:     arg(1, 'task ID', 'The ID of an already defined task.')
4735:   end
rule_task() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4737
4737:   def rule_task
4738:     pattern(%( !taskHeader !taskBody ), lambda {
4739:       @property = @property.parent
4740:     })
4741:     doc('task', Tasks are the central elements of a project plan. Use a task to specify thevarious steps and phases of the project. Depending on the attributes of thattask, a task can be a container task, a milestone or a regular leaf task. Thelatter may have resources assigned. By specifying dependencies the user canforce a certain sequence of tasks.Tasks have a local name space. All IDs must be unique within the tasksthat belong to the same enclosing task.
4742:        )
4743:   end
rule_taskAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4754
4754:   def rule_taskAttributes
4755:     repeatable
4756:     optional
4757: 
4758:     pattern(%( _adopt !taskList ), lambda {
4759:       @val[1].each do |task|
4760:         @property.adopt(task)
4761:       end
4762:     })
4763:     doc('adopt.task', Add a previously defined task to the sub-tasks of this task. This can be usedto create virtual sub projects that contain of task trees that were defined assub tasks of other tasks. Adopted tasks don't inherit anything from their stepparents. However, the adopting task is scheduled to fit all adopted childs aswell.The adopting task and the adopted task must not share a common top-level task.Adopted tasks may not have overlaping sub trees.'''This feature is experimental right now. Don't use it!'''.
4764:        )
4765: 
4766:     pattern(%( !journalEntry ))
4767: 
4768:     pattern(%( _note $STRING ), lambda {
4769:       @property.set('note', newRichText(@val[1], @sourceFileInfo[1]))
4770:     })
4771:     doc('note.task', Attach a note to the task. This is usually a more detailed specification ofwhat the task is about.
4772:        )
4773: 
4774:     pattern(%( !purge ))
4775: 
4776:     pattern(%( _supplement !supplementTask !taskBody ), lambda {
4777:       @property = @property.parent
4778:     })
4779:     doc('supplement.task', The supplement keyword provides a mechanism to add more attributes to alreadydefined tasks. The additional attributes must obey the same rules as inregular task definitions and must be enclosed by curly braces.This construct is primarily meant for situations where the information about atask is split over several files. E. g. the vacation dates for theresources may be in a separate file that was generated by some other tool.
4780:        )
4781:     example('Supplement', 'task')
4782: 
4783:     pattern(%( !task ))
4784:     pattern(%( !taskScenarioAttributes ))
4785:     pattern(%( !scenarioIdCol !taskScenarioAttributes ), lambda {
4786:       @scenarioIdx = 0
4787:     })
4788:     # Other attributes will be added automatically.
4789:   end
rule_taskBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4813
4813:   def rule_taskBody
4814:     optionsRule('taskAttributes')
4815:   end
rule_taskBooking() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4817
4817:   def rule_taskBooking
4818:     pattern(%( !taskBookingHeader !bookingBody ), lambda {
4819:       unless @project.scenario(@scenarioIdx).get('ownbookings')
4820:         error('no_own_task_booking',
4821:               "The scenario #{@project.scenario(@scenarioIdx).fullId} " +
4822:               'inherits its bookings from the tracking ' +
4823:               'scenario. You cannot specificy additional bookings for it.')
4824:       end
4825:       @val[0].task.addBooking(@scenarioIdx, @val[0])
4826:     })
4827:   end
rule_taskBookingHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4829
4829:   def rule_taskBookingHeader
4830:     pattern(%( !resourceId !valIntervals ), lambda {
4831:       checkBooking(@property, @val[0])
4832:       @booking = Booking.new(@val[0], @property, @val[1])
4833:       @booking.sourceFileInfo = @sourceFileInfo[0]
4834:       @booking
4835:     })
4836:   end
rule_taskDep() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4838
4838:   def rule_taskDep
4839:     pattern(%( !taskDepHeader !taskDepBody ), lambda {
4840:       @val[0]
4841:     })
4842:   end
rule_taskDepAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4844
4844:   def rule_taskDepAttributes
4845:     optional
4846:     repeatable
4847: 
4848:     pattern(%( _gapduration !intervalDuration ), lambda {
4849:       @taskDependency.gapDuration = @val[1]
4850:     })
4851:     doc('gapduration', Specifies the minimum required gap between the end of a preceding task and thestart of this task, or the start of a following task and the end of this task.This is calendar time, not working time. 7d means one week.
4852:        )
4853: 
4854:     pattern(%( _gaplength !workingDuration ), lambda {
4855:       @taskDependency.gapLength = @val[1]
4856:     })
4857:     doc('gaplength', Specifies the minimum required gap between the end of a preceding task and thestart of this task, or the start of a following task and the end of this task.This is working time, not calendar time. 7d means 7 working days, not oneweek. Whether a day is considered a working day or not depends on the definedworking hours and global vacations.
4858:        )
4859: 
4860:     pattern(%( _onend ), lambda {
4861:       @taskDependency.onEnd = true
4862:     })
4863:     doc('onend', The target of the dependency is the end of the task.
4864:        )
4865: 
4866:     pattern(%( _onstart ), lambda {
4867:       @taskDependency.onEnd = false
4868:     })
4869:     doc('onstart', The target of the dependency is the start of the task.
4870:        )
4871:   end
rule_taskDepBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4887
4887:   def rule_taskDepBody
4888:     optionsRule('taskDepAttributes')
4889:   end
rule_taskDepHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4891
4891:   def rule_taskDepHeader
4892:     pattern(%( !taskDepId ), lambda {
4893:       @taskDependency = TaskDependency.new(@val[0], true)
4894:     })
4895:   end
rule_taskDepId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4897
4897:   def rule_taskDepId
4898:     singlePattern('$ABSOLUTE_ID')
4899:     arg(0, 'ABSOLUTE ID', A reference using the full qualified ID of a task. The IDs of all enclosingparent tasks must be prepended to the task ID and separated with a dot, e.g.''''proj.plan.doc''''.
4900:          )
4901: 
4902:     singlePattern('$ID')
4903:     arg(0, 'ID', 'Just the ID of the task without and parent IDs.')
4904: 
4905:     pattern(%( !relativeId ), lambda {
4906:       task = @property
4907:       id = @val[0]
4908:       while task && id[0] == !!
4909:         id = id.slice(1, id.length)
4910:         task = task.parent
4911:       end
4912:       error('too_many_bangs',
4913:             "Too many '!' for relative task in this context.",
4914:             @sourceFileInfo[0], @property) if id[0] == !!
4915:       if task
4916:         task.fullId + '.' + id
4917:       else
4918:         id
4919:       end
4920:     })
4921:     arg(0, 'RELATIVE ID', A relative task ID always starts with one or more exclamation marks and isfollowed by a task ID. Each exclamation mark lifts the scope where the ID islooked for to the enclosing task. The ID may contain some of the parent IDsseparated by dots, e. g. ''''!!plan.doc''''.
4922:          )
4923:   end
rule_taskDepList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4934
4934:   def rule_taskDepList
4935:     pattern(%( !taskDep !moreDepTasks ), lambda {
4936:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
4937:     })
4938:   end
rule_taskHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4940
4940:   def rule_taskHeader
4941:     pattern(%( _task !optionalID $STRING ), lambda {
4942:       if @property.nil? && !@taskprefix.empty?
4943:         @property = @project.task(@taskprefix)
4944:       end
4945:       if @val[1]
4946:         id = (@property ? @property.fullId + '.' : '') + @val[1]
4947:         if @project.task(id)
4948:           error('task_exists', "Task #{id} has already been defined.",
4949:                 @sourceFileInfo[0])
4950:         end
4951:       end
4952:       @property = Task.new(@project, @val[1], @val[2], @property)
4953:       @property['projectid', 0] = @projectId
4954:       @property.sourceFileInfo = @sourceFileInfo[0]
4955:       @property.inheritAttributes
4956:       @scenarioIdx = 0
4957:     })
4958:     arg(2, 'name', 'The name of the task')
4959:   end
rule_taskId() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4961
4961:   def rule_taskId
4962:     pattern(%( !taskIdUnverifd ), lambda {
4963:       id = @val[0]
4964:       if @property && @property.is_a?(Task)
4965:         # In case we have a nested supplement, we need to prepend the parent ID.
4966:         id = @property.fullId + '.' + id
4967:       else
4968:         id = @taskprefix + '.' + id unless @taskprefix.empty?
4969:       end
4970:       if (task = @project.task(id)).nil?
4971:         error('unknown_task', "Unknown task #{id}", @sourceFileInfo[0])
4972:       end
4973:       task
4974:     })
4975:   end
rule_taskIdUnverifd() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4977
4977:   def rule_taskIdUnverifd
4978:     singlePattern('$ABSOLUTE_ID')
4979:     singlePattern('$ID')
4980:   end
rule_taskList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4982
4982:   def rule_taskList
4983:     listRule('moreTasks', '!absoluteTaskId')
4984:   end
rule_taskPeriod() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4986
4986:   def rule_taskPeriod
4987:     pattern(%( _period !valInterval), lambda {
4988:       @property['start', @scenarioIdx] = @val[1].start
4989:       @property['end', @scenarioIdx] = @val[1].end
4990:     })
4991:     doc('period.task', This property is a shortcut for setting the start and end property at the sametime. In contrast to using these, it does not change the scheduling direction.
4992:        )
4993:   end
rule_taskPred() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 4998
4998:   def rule_taskPred
4999:     pattern(%( !taskPredHeader !taskDepBody ), lambda {
5000:       @val[0]
5001:     })
5002:   end
rule_taskPredHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5004
5004:   def rule_taskPredHeader
5005:     pattern(%( !taskDepId ), lambda {
5006:       @taskDependency = TaskDependency.new(@val[0], false)
5007:     })
5008:   end
rule_taskPredList() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5010
5010:   def rule_taskPredList
5011:     pattern(%( !taskPred !morePredTasks ), lambda {
5012:       [ @val[0] ] + (@val[1].nil? ? [] : @val[1])
5013:     })
5014:   end
rule_taskScenarioAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5016
5016:   def rule_taskScenarioAttributes
5017: 
5018:     pattern(%( _account $ID ), lambda {
5019:       # TODO
5020:     })
5021:     doc('account.task', This property has been deprecated. Use [[charge]] instead.
5022:         )
5023: 
5024:     pattern(%( !allocate ))
5025: 
5026:     pattern(%( _booking !taskBooking ))
5027:     doc('booking.task', The booking attribute can be used to report actually completed work.  A taskwith bookings must be [[scheduling|scheduled]] in ''''asap'''' mode.  If thescenario is not the [[trackingscenario|tracking scenario]] or derived from it,the scheduler will not allocate resources prior to the current date or thedate specified with [[now]] when a task has at least one booking.Bookings are only valid in the scenario they have been defined in. They willin general not be passed to any other scenario. If you have defined a[[trackingscenario|tracking scenario]], the bookings of this scenario will bepassed to all the derived scenarios of the tracking scenario.The sloppy attribute can be used when you want to skip non-working time orother allocations automatically. If it's not given, all bookings must onlycover working time for the resource.The booking attributes is designed to capture the exact amount of completedwork. This attribute is not really intended to specify completed effort byhand. Usually, booking statements are generated by [[export]] reports. The[[sloppy.booking|sloppy]] and [[overtime.booking|overtime]] attributes areonly kludge for users who want to write them manually.Bookings can be used to report already completed work by specifying the exacttime intervals a certain resource has worked on this task.Bookings can be defined in the task or resource context. If you move tasksaround very often, put your bookings in the task context.
5028:        )
5029:     also(%( booking.resource ))
5030:     example('Booking')
5031: 
5032:     pattern(%( _charge !number !chargeMode ), lambda {
5033:       checkContainer('charge')
5034: 
5035:       if @property['chargeset', @scenarioIdx].empty?
5036:         error('task_without_chargeset',
5037:               'The task does not have a chargeset defined.',
5038:               @sourceFileInfo[0], @property)
5039:       end
5040:       case @val[2]
5041:       when 'onstart'
5042:         mode = :onStart
5043:         amount = @val[1]
5044:       when 'onend'
5045:         mode = :onEnd
5046:         amount = @val[1]
5047:       when 'perhour'
5048:         mode = :perDiem
5049:         amount = @val[1] * 24
5050:       when 'perday'
5051:         mode = :perDiem
5052:         amount = @val[1]
5053:       when 'perweek'
5054:         mode = :perDiem
5055:         amount = @val[1] / 7.0
5056:       end
5057:       # Multiple 'charge' attributes are allowed.
5058:       begin
5059:         @property['charge', @scenarioIdx] +=
5060:           [ Charge.new(amount, mode, @property, @scenarioIdx) ]
5061:       rescue AttributeOverwrite
5062:       end
5063:     })
5064:     doc('charge', Specify a one-time or per-period charge to a certain account. The charge canoccur at the start of the task, at the end of it, or continuously over theduration of the task. The accounts to be charged are determined by the[[chargeset]] setting of the task.
5065:        )
5066:     arg(1, 'amount', 'The amount to charge')
5067: 
5068:     pattern(%( !chargeset ))
5069: 
5070:     pattern(%( _complete !number), lambda {
5071:       if @val[1] < 0.0 || @val[1] > 100.0
5072:         error('task_complete', "Complete value must be between 0 and 100",
5073:               @sourceFileInfo[1], @property)
5074:       end
5075:       @property['complete', @scenarioIdx] = @val[1]
5076:     })
5077:     doc('complete', Specifies what percentage of the task is already completed. This can be usefulfor project tracking. Reports with calendar elements may show the completedpart of the task in a different color. The completion percentage has no impacton the scheduler. It's meant for documentation purposes only.Tasks may not have subtasks if this attribute is used.
5078:         )
5079:     example('Complete', '1')
5080: 
5081:     arg(1, 'percent', 'The percent value. It must be between 0 and 100.')
5082: 
5083:     pattern(%( _depends !taskDepList ), lambda {
5084:       checkContainer('depends')
5085:       begin
5086:         @property['depends', @scenarioIdx] =
5087:           @property['depends', @scenarioIdx] + @val[1]
5088:         @property['forward', @scenarioIdx] = true
5089:       rescue AttributeOverwrite
5090:       end
5091:     })
5092:     doc('depends', Specifies that the task cannot start before the specified tasks have beenfinished.By using the 'depends' attribute, the scheduling policy is automatically setto asap. If both depends and precedes are used, the last policy counts.
5093:         )
5094:     example('Depends1')
5095:     pattern(%( _duration !calendarDuration ), lambda {
5096:       setDurationAttribute('duration', @val[1])
5097:     })
5098:     doc('duration', Specifies the time the task should last. This is calendar time, not workingtime. 7d means one week. If resources are specified they are allocated whenavailable. Availability of resources has no impact on the duration of thetask. It will always be the specified duration.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[effort]] and [[length]] attributes.
5099:        )
5100:     example('Durations')
5101:     also(%( effort length ))
5102: 
5103:     pattern(%( _effort !workingDuration ), lambda {
5104:       if @val[1] <= 0.0
5105:         error('effort_zero', "Effort value must be larger than 0",
5106:               @sourceFileInfo[1], @property)
5107:       end
5108:       setDurationAttribute('effort', @val[1])
5109:     })
5110:     doc('effort', Specifies the effort needed to complete the task. An effort of 4d can be donewith 2 full-time resources in 2 days. The task will not finish before theresources have contributed the specified effort. So the duration of the taskwill depend on the availability of the resources.WARNING: In almost all real world projects effort is not the product of timeand resources. This is only true if the task can be partitioned without addingany overhead. For more information about this read ''The Mythical Man-Month'' byFrederick P. Brooks, Jr.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[duration]] and [[length]] attributes.
5111:        )
5112:     example('Durations')
5113:     also(%( duration length ))
5114: 
5115:     pattern(%( _end !valDate ), lambda {
5116:       @property['end', @scenarioIdx] = @val[1]
5117:       begin
5118:         @property['forward', @scenarioIdx] = false
5119:       rescue AttributeOverwrite
5120:       end
5121:     })
5122:     doc('end', The end attribute provides a guideline to the scheduler when the task shouldend. It will never end later, but it may end earlier when allocatedresources are not available that long. When an end date is provided for acontainer task, it will be passed down to ALAP task that don't have a welldefined end criteria.Setting an end date will implicitely set the scheduling policy for this taskto ALAP.
5123:        )
5124:     example('Export', '1')
5125:     pattern(%( _endcredit !number ), lambda {
5126:       @property['charge', @scenarioIdx] =
5127:         @property['charge', @scenarioIdx] +
5128:         [ Charge.new(@val[1], :onEnd, @property, @scenarioIdx) ]
5129:     })
5130:     doc('endcredit', Specifies an amount that is credited to the accounts specified by the[[chargeset]] attributes at the moment the tasks ends. This attribute has beendeprecated and should no longer be used. Use [[charge]] instead.
5131:        )
5132:     example('Account', '1')
5133:     pattern(%( !flags ))
5134:     doc('flags.task', Attach a set of flags. The flags can be used in logical expressions to filterproperties from the reports.
5135:        )
5136: 
5137:     pattern(%( !fail ))
5138: 
5139:     pattern(%( _length !workingDuration ), lambda {
5140:       setDurationAttribute('length', @val[1])
5141:     })
5142:     doc('length', Specifies the global working time to be used for this task. The value isspecified in working time, not calendar time. 7d means 7 working days, or 7times 8 hours (assuming default settings), not one week.A task with a length specification may have resource allocations. Resourcesare allocated when they are available.  There is no guarantee that the taskwill get any resources allocated.  The availability of resources has no impacton the duration of the task. A time slot where none of the specified resourcesis available is still considered working time, if there is no global vacationand global working hours are defined accordingly.For the length calculation, only the global working hours and the globalvacations matter. If a resource has additinal working hours defined, it'squite possible that a task with a length of 5d will have an allocated effortlarger than 40 hours. Resource working hours only have an impact on whether anallocation is made or not for a particular time slot. They don't effect theresulting duration of the task.Tasks may not have subtasks if this attribute is used. Setting this attributewill reset the [[duration]], [[effort]] and [[milestone]] attributes.
5143:        )
5144:     also(%( duration effort ))
5145: 
5146:     pattern(%( !limits ), lambda {
5147:       checkContainer('limits')
5148:       @property['limits', @scenarioIdx] = @val[0]
5149:     })
5150:     doc('limits.task', Set per-interval allocation limits for the task. This setting affects all allocations for this task.
5151:        )
5152:     example('Limits-1', '2')
5153: 
5154:     pattern(%( _maxend !valDate ), lambda {
5155:       @property['maxend', @scenarioIdx] = @val[1]
5156:     })
5157:     doc('maxend', Specifies the maximum wanted end time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If theend of the task is later than the specified value, then an error is reported.
5158:        )
5159: 
5160:     pattern(%( _maxstart !valDate ), lambda {
5161:       @property['maxstart', @scenarioIdx] = @val[1]
5162:     })
5163:     doc('maxstart', Specifies the maximum wanted start time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If thestart of the task is later than the specified value, then an error isreported.
5164:        )
5165: 
5166:     pattern(%( _milestone ), lambda {
5167:       setDurationAttribute('milestone')
5168:     })
5169:     doc('milestone', Turns the task into a special task that has no duration. You may not specify aduration, length, effort or subtasks for a milestone task.A task that only has a start or an end specification and no durationspecification, inherited start or end dates, no dependencies or sub tasks,will be recognized as milestone automatically.
5170:        )
5171: 
5172:     pattern(%( _minend !valDate ), lambda {
5173:       @property['minend', @scenarioIdx] = @val[1]
5174:     })
5175:     doc('minend', Specifies the minimum wanted end time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If theend of the task is earlier than the specified value, then an error isreported.
5176:        )
5177: 
5178:     pattern(%( _minstart !valDate ), lambda {
5179:       @property['minstart', @scenarioIdx] = @val[1]
5180:     })
5181:     doc('minstart', Specifies the minimum wanted start time of the task. The value is not usedduring scheduling, but is checked after all tasks have been scheduled. If thestart of the task is earlier than the specified value, then an error isreported.
5182:        )
5183: 
5184:     pattern(%( _startcredit !number ), lambda {
5185:       @property['charge', @scenarioIdx] +=
5186:         [ Charge.new(@val[1], :onStart, @property, @scenarioIdx) ]
5187:     })
5188:     doc('startcredit', Specifies an amount that is credited to the account specified by the[[chargeset]] attributes at the moment the tasks starts. This attribute hasbeen deprecated and should no longer be used. Use [[charge]] instead.
5189:        )
5190:     pattern(%( !taskPeriod ))
5191: 
5192:     pattern(%( _precedes !taskPredList ), lambda {
5193:       checkContainer('precedes')
5194:       begin
5195:         @property['precedes', @scenarioIdx] += @val[1]
5196:         @property['forward', @scenarioIdx] = false
5197:       rescue AttributeOverwrite
5198:       end
5199:     })
5200:     doc('precedes', Specifies that the tasks with the specified IDs cannot start before the taskhas been finished. If multiple IDs are specified, they must be separated bycommas. IDs must be either global or relative. A relative ID starts with anumber of '!'. Each '!' moves the scope to the parent task. Global IDs do notcontain '!', but have IDs separated by dots.By using the 'precedes' attribute, the scheduling policy is automatically setto alap. If both depends and precedes are used within a task, the last policycounts.
5201:        )
5202: 
5203:     pattern(%( _priority $INTEGER ), lambda {
5204:       if @val[1] < 0 || @val[1] > 1000
5205:         error('task_priority', "Priority must have a value between 0 and 1000",
5206:               @sourceFileInfo[1], @property)
5207:       end
5208:       @property['priority', @scenarioIdx] = @val[1]
5209:     })
5210:     doc('priority', Specifies the priority of the task. A task with higher priority is morelikely to get the requested resources. The default priority value of all tasksis 500. Don't confuse the priority of a tasks with the importance or urgencyof a task. It only increases the chances that the tasks gets the requestedresources. It does not mean that the task happens earlier, though that isusually the effect you will see. It also does not have any effect on tasksthat don't have any resources assigned (e.g. milestones).For milestones it will raise or lower the chances that task leading up themilestone will get their resources over task with equal priority that competefor the same resources.This attribute is inherited by subtasks if specified prior to the definitionof the subtask.
5211:        )
5212:     arg(1, 'value', 'Priority value (1 - 1000)')
5213:     example('Priority')
5214: 
5215:     pattern(%( _projectid $ID ), lambda {
5216:       unless @project['projectids'].include?(@val[1])
5217:         error('unknown_projectid', "Unknown project ID #{@val[1]}",
5218:               @sourceFileInfo[1])
5219:       end
5220:       begin
5221:         @property['projectid', @scenarioIdx] = @val[1]
5222:       rescue AttributeOverwrite
5223:         # This attribute always overwrites the implicitely provided ID.
5224:       end
5225:     })
5226:     doc('projectid.task', In larger projects it may be desireable to work with different project IDs forparts of the project. This attribute assignes a new project ID to this task anall subsequently defined sub tasks. The project ID needs to be declared first using [[projectid]] or [[projectids]].
5227:        )
5228: 
5229:     pattern(%( _responsible !resourceList ), lambda {
5230:       @property['responsible', @scenarioIdx] += @val[1]
5231:       @property['responsible', @scenarioIdx].uniq!
5232:     })
5233:     doc('responsible', The ID of the resource that is responsible for this task. This value is fordocumentation purposes only. It's not used by the scheduler.
5234:        )
5235: 
5236:     pattern(%( _scheduled ), lambda {
5237:       if (@property['milestone', @scenarioIdx] &&
5238:           @property['start', @scenarioIdx].nil? &&
5239:           @property['end', @scenarioIdx].nil?) ||
5240:          (!@property['milestone', @scenarioIdx] &&
5241:           (@property['start', @scenarioIdx].nil? ||
5242:            @property['end', @scenarioIdx].nil?))
5243:         error('not_scheduled',
5244:               "Task #{@property.fullId} is marked as scheduled but does not " +
5245:               'have a fixed start and end date.',
5246:               @sourceFileInfo[0], @property)
5247:       end
5248:       @property['scheduled', @scenarioIdx] = true
5249:     })
5250:     doc('scheduled', This is mostly for internal use. It specifies that the task can be ignored forscheduling in the scenario.
5251:        )
5252: 
5253:     pattern(%( _scheduling !schedulingDirection ), lambda {
5254:       if @val[1] == 'alap'
5255:         begin
5256:           @property['forward', @scenarioIdx] = false
5257:         rescue AttributeOverwrite
5258:         end
5259:       elsif @val[1] == 'asap'
5260:         begin
5261:           @property['forward', @scenarioIdx] = true
5262:         rescue AttributeOverwrite
5263:         end
5264:       end
5265:     })
5266:     doc('scheduling', Specifies the scheduling policy for the task. A task can be scheduled fromstart to end (As Soon As Possible, asap) or from end to start (As Late AsPossible, alap).A task can be scheduled from start to end (ASAP mode) when it has a hard(start) or soft (depends) criteria for the start time. A task can be scheduledfrom end to start (ALAP mode) when it has a hard (end) or soft (precedes)criteria for the end time.Some task attributes set the scheduling policy implicitly. This attribute canbe used to explicitly set the scheduling policy of the task to a certaindirection. To avoid it being overwritten again by an implicit attribute thisattribute should always be the last attribute of the task.A random mixture of ASAP and ALAP tasks can have unexpected side effects onthe scheduling of the project. It increases significantly the schedulingcomplexity and results in much longer scheduling times. Especially in projectswith many hundreds of tasks the scheduling time of a project with a mixture ofASAP and ALAP times can be 2 to 10 times longer. When the projects containschains of ALAP and ASAP tasks the tasks further down the dependency chain willbe served much later than other non-chained task even when they have a muchhigher priority. This can result in situations where high priority tasks donot get their resources even though the parallel competing tasks have a muchlower priority.As a general rule, try to avoid ALAP tasks whenever possible. Have a closeeye on tasks that have been switched implicitly to ALAP mode because theend attribute comes after the start attribute.
5267:        )
5268: 
5269:     pattern(%( _shift !shiftAssignments ), lambda {
5270:       checkContainer('shift')
5271:     })
5272:     doc('shift.task', This keyword has been deprecated. Please use [[shifts.task|shifts(task)]] instead.
5273:        )
5274: 
5275:     pattern(%( _shifts !shiftAssignments ), lambda {
5276:       checkContainer('shifts')
5277:     })
5278:     doc('shifts.task', Limits the working time for this task during the during the specified intervalto the working hours of the given shift. Multiple shifts can be defined, butshift intervals may not overlap. This is an additional working timerestriction ontop of the working hours of the allocated resources. It does notreplace the resource working hour restrictions. For a resource to be assignedto a time slot, both the respective task shift as well as the resource workinghours must declare the time slot as duty slot.
5279:         )
5280: 
5281:     pattern(%( _start !valDate), lambda {
5282:       @property['start', @scenarioIdx] = @val[1]
5283:       begin
5284:         @property['forward', @scenarioIdx] = true
5285:       rescue AttributeOverwrite
5286:       end
5287:     })
5288:     doc('start', The start attribute provides a guideline to the scheduler when the task shouldstart. It will never start earlier, but it may start later when allocatedresources are not available immediately. When a start date is provided for acontainer task, it will be passed down to ASAP task that don't have a welldefined start criteria.Setting a start date will implicitely set the scheduling policy for this taskto ASAP.
5289:        )
5290:     also(%( end period.task maxstart minstart scheduling ))
5291: 
5292:     pattern(%( !warn ))
5293: 
5294:     # Other attributes will be added automatically.
5295:   end
rule_timeInterval() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5658
5658:   def rule_timeInterval
5659:     pattern([ '$TIME', '_-', '$TIME' ], lambda {
5660:       if @val[0] >= @val[2]
5661:         error('time_interval',
5662:               "End time of interval must be larger than start time",
5663:               @sourceFileInfo[0])
5664:       end
5665:       [ @val[0], @val[2] ]
5666:     })
5667:   end
rule_timeSheet() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5669
5669:   def rule_timeSheet
5670:     pattern(%( !timeSheetHeader !timeSheetBody ), lambda {
5671:       @timeSheet
5672:     })
5673:     doc('timesheet', A time sheet record can be used to capture the current status of the tasksassigned to a specific resource and the achieved progress for a given periodof time. The status is assumed to be for the end of this time period. Theremust be a separate time sheet record for each resource per period. Differentresources can use different reporting periods and reports for the sameresource may have different reporting periods as long as they don't overlap.For the time after the last time sheet, TaskJuggler will project the resultbased on the plan data. For periods without a time sheet record prior to thelast record for this resource, TaskJuggler assumes that no work has been done.The work is booked for the scenario specified by [[trackingscenario]].The intended use for time sheets is to have all resources report a time sheetevery day, week or month. All time sheets can be added to the project plan.The status information is always used to determin the current status of theproject. The [[work]], [[remaining]] and [[end.timesheet|end]] attributes areignored if there are also [[booking.task|bookings]] for the resource in thetime sheet period. The non-ignored attributes of the time sheets will beconverted into [[booking.task|booking]] statements internally. These bookingscan then be [[export|exported]] into a file which can then be added to theproject again. This way, you can use time sheets to incrementally recordprogress of your project. There is a possibility that time sheets conflictwith other data in the plan. In case TaskJuggler cannot automatically resolvethem, these conflicts have to be manually resolved by either changing the planor the time sheet.The status messages are interpreted as [[journalentry|journal entries]]. Thealert level will be evaluated and the current state of the project can be putinto a dashboard using the ''''alert'''' and ''''alertmessage'''' [[columnid|columns]].Currently, the provided effort values and dates are not yet used toautomatically update the plan data. This feature will be added in futureversions.
5674:        )
5675:     example('TimeSheet1', '1')
5676:   end
rule_timeSheetAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5712
5712:   def rule_timeSheetAttributes
5713:     optional
5714:     repeatable
5715: 
5716:     pattern(%( !tsNewTaskHeader !tsTaskBody ), lambda {
5717:       @property = nil
5718:       @timeSheetRecord = nil
5719:     })
5720:     doc('newtask', The keyword can be used add a new task to the project. If the task ID requiresfurther parent task that don't exist yet, these tasks will be created as well.If the task exists already, an error is generated. The new task can be usedimmediately to report progress and status against it.
5721:        )
5722:     example('TimeSheet1', '3')
5723: 
5724:     pattern(%( _shift !shiftId ), lambda {
5725:       #TODO
5726:     })
5727:     doc('shift.timesheet', Specifies an alternative [[shift]] for the time sheet period. This shift willoverride any existing working hour definitions for the resource. It will notoverride already declared [[vacation|vacations]] though.The primary use of this feature is to let the resources report different totalwork time for the report period.
5728:        )
5729: 
5730:     pattern(%( !tsStatus ))
5731: 
5732:     pattern(%( !tsTaskHeader !tsTaskBody ), lambda {
5733:       @property = nil
5734:       @timeSheetRecord = nil
5735:     })
5736:     doc('task.timesheet', Specifies an existing task that progress and status should be reportedagainst.
5737:        )
5738:     example('TimeSheet1', '4')
5739:   end
rule_timeSheetBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5763
5763:   def rule_timeSheetBody
5764:     pattern(%( _{ !timeSheetAttributes _} ), lambda {
5765: 
5766:     })
5767:   end
rule_timeSheetFile() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5756
5756:   def rule_timeSheetFile
5757:     pattern(%( !timeSheet . ), lambda {
5758:       @val[0]
5759:     })
5760:     lastSyntaxToken(1)
5761:   end
rule_timeSheetHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5769
5769:   def rule_timeSheetHeader
5770:     pattern(%( _timesheet !resourceId !valIntervalOrDate ), lambda {
5771:       @sheetAuthor = @val[1]
5772:       @property = nil
5773:       unless @sheetAuthor.leaf?
5774:         error('ts_group_author',
5775:               'A resource group cannot file a time sheet',
5776:               @sourceFileInfo[1])
5777:       end
5778:       unless (scenarioIdx = @project['trackingScenarioIdx'])
5779:         error('ts_no_tracking_scenario',
5780:               'No trackingscenario defined.')
5781:       end
5782:       # Currently time sheets are hardcoded for scenario 0.
5783:       @timeSheet = TimeSheet.new(@sheetAuthor, @val[2], scenarioIdx)
5784:       @timeSheet.sourceFileInfo = @sourceFileInfo[0]
5785:       @project.timeSheets << @timeSheet
5786:     })
5787:   end
rule_timeSheetReport() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5789
5789:   def rule_timeSheetReport
5790:     pattern(%( !tsReportHeader !tsReportBody ), lambda {
5791:       @property = nil
5792:     })
5793:     doc('timesheetreport', For projects that flow mostly according to plan, TaskJuggler already knowsmuch of the information that should be contained in the time sheets. With thisproperty, you can generate a report that contains drafts of the time sheetsfor one or more resources. The time sheet drafts will be for thespecified report period and the specified [trackingscenario].
5794:        )
5795:   end
rule_timeformat() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5516
5516:   def rule_timeformat
5517:     pattern(%( _timeformat $STRING ), lambda {
5518:       @val[1]
5519:     })
5520:     doc('timeformat', Determines how time specifications in reports look like.
5521:        )
5522:     arg(1, 'format', Ordinary characters placed in the format string are copied withoutconversion. Conversion specifiers are introduced by a `%' character, and arereplaced in s as follows:* ''''%a''''  The abbreviated weekday name according to the current locale.* ''''%A''''  The full weekday name according to the current locale.* ''''%b''''  The abbreviated month name according to the current locale.* ''''%B''''  The full month name according to the current locale.* ''''%c''''  The preferred date and time representation for the current locale.* ''''%C''''  The century number (year/100) as a 2-digit integer. (SU)* ''''%d''''  The day of the month as a decimal number (range 01 to 31).* ''''%e''''  Like ''''%d'''', the day of the month as a decimal number, but aleading zero is replaced by a space. (SU)* ''''%E''''  Modifier: use alternative format, see below. (SU)* ''''%F''''  Equivalent to ''''%Y-%m-%d'''' (the ISO 8601 date format). (C99)* ''''%G''''  The ISO 8601 year with century as a decimal number. The 4-digityear corresponding to the ISO week number (see %V). This has the same formatand value as ''''%y'''', except that if the ISO week number belongs to theprevious or next year, that year is used instead. (TZ)* ''''%g''''  Like %G, but without century, i.e., with a 2-digit year (00-99).(TZ)* ''''%h''''  Equivalent to ''''%b''''. (SU)* ''''%H''''  The hour as a decimal number using a 24-hour clock (range 00 to23).* ''''%I''''  The hour as a decimal number using a 12-hour clock (range 01 to12).* ''''%j''''  The day of the year as a decimal number (range 001 to 366).* ''''%k''''  The hour (24-hour clock) as a decimal number (range 0 to 23);single digits are preceded by a blank. (See also ''''%H''''.) (TZ)* ''''%l''''  The hour (12-hour clock) as a decimal number (range 1 to 12);single digits are preceded by a blank. (See also ''''%I''''.) (TZ)* ''''%m''''  The month as a decimal number (range 01 to 12).* ''''%M''''  The minute as a decimal number (range 00 to 59).* ''''%n''''  A newline character. (SU)* ''''%O''''  Modifier: use alternative format, see below. (SU)* ''''%p''''  Either 'AM' or 'PM' according to the given time value, or thecorresponding strings for the current locale. Noon is treated as `pm' andmidnight as 'am'.* ''''%P''''  Like %p but in lowercase: 'am' or 'pm' or ''''%a''''corresponding string for the current locale. (GNU)* ''''%r''''  The time in a.m. or p.m. notation. In the POSIX locale this isequivalent to ''''%I:%M:%S %p''''. (SU)* ''''%R''''  The time in 24-hour notation (%H:%M). (SU) For a versionincluding the seconds, see ''''%T'''' below.* ''''%s''''  The number of seconds since the Epoch, i.e., since 1970-01-0100:00:00 UTC.  (TZ)* ''''%S''''  The second as a decimal number (range 00 to 61).* ''''%t''''  A tab character. (SU)* ''''%T''''  The time in 24-hour notation (%H:%M:%S). (SU)* ''''%u''''  The day of the week as a decimal, range 1 to 7, Monday being 1.See also ''''%w''''. (SU)* ''''%U''''  The week number of the current year as a decimal number, range00 to 53, starting with the first Sunday as the first day of week 01. See also''''%V'''' and ''''%W''''.* ''''%V''''  The ISO 8601:1988 week number of the current year as a decimalnumber, range 01 to 53, where week 1 is the first week that has at least 4days in the current year, and with Monday as the first day of the week. Seealso ''''%U'''' and ''''%W''''. %(SU)* ''''%w''''  The day of the week as a decimal, range 0 to 6, Sunday being 0. See also ''''%u''''.* ''''%W''''  The week number of the current %year as a decimal number, range00 to 53, starting with the first Monday as the first day of week 01.* ''''%x''''  The preferred date representation for the current locale withoutthe time.* ''''%X''''  The preferred time representation for the current locale withoutthe date.* ''''%y''''  The year as a decimal number without a century (range 00 to 99).* ''''%Y''''   The year as a decimal number including the century.* ''''%z''''   The time zone as hour offset from GMT. Required to emitRFC822-conformant dates (using ''''%a, %d %%b %Y %H:%M:%S %%z''''). (GNU)* ''''%Z''''  The time zone or name or abbreviation.* ''''%+''''  The date and time in date(1) format. (TZ)* ''''%%''''  A literal ''''%'''' character.Some conversion specifiers can be modified by preceding them by the E or Omodifier to indicate that an alternative format should be used. If thealternative format or specification does not exist for the current locale, thebehavior will be as if the unmodified conversion specification were used.(SU) The Single Unix Specification mentions %Ec, %EC, %Ex, %%EX, %Ry, %EY,%Od, %Oe, %OH, %OI, %Om, %OM, %OS, %Ou, %OU, %OV, %Ow, %OW, %Oy, where theeffect of the O modifier is to use alternative numeric symbols (say, Romannumerals), and that of the E modifier is to use a locale-dependent alternativerepresentation.This documentation of the timeformat attribute has been taken from the man pageof the GNU strftime function.
5523:        )
5524: 
5525:   end
rule_timezone() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5803
5803:   def rule_timezone
5804:     pattern(%( _timezone !validTimeZone ), lambda{
5805:       TjTime.setTimeZone(@val[1])
5806:       @project['timezone'] = @val[1]
5807:     })
5808:     doc('timezone', Sets the default time zone of the project. All dates and times that have notime zones specified will be assumed to be in this time zone. If no time zoneis specified for the project, UTC is assumed.The project start and end time are not affected by this setting. They arealways considered to be UTC unless specified differently.In case the specified time zone is not hour-aligned with UTC, the[[timingresolution]] will automatically be decreased accordingly. Do notchange the timingresolution after you've set the time zone!Changing the time zone will reset the [[workinghours.project|working hours]]to the default times. It's recommended that you declare your working hoursafter the time zone.
5809:         )
5810:     arg(1, 'zone', Time zone to use. E. g. 'Europe/Berlin' or 'America/Denver'. Don't use the 3letter acronyms. See[http://en.wikipedia.org/wiki/List_of_zoneinfo_time_zones Wikipedia] forpossible values.
5811:        )
5812:   end
rule_tsNewTaskHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5834
5834:   def rule_tsNewTaskHeader
5835:     pattern(%( _newtask !taskIdUnverifd $STRING ), lambda {
5836:       @timeSheetRecord = TimeSheetRecord.new(@timeSheet, @val[1])
5837:       @timeSheetRecord.name = @val[2]
5838:       @timeSheetRecord.sourceFileInfo = @sourceFileInfo[0]
5839:     })
5840:     arg(1, 'task', 'ID of the new task')
5841:   end
rule_tsReportAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5862
5862:   def rule_tsReportAttributes
5863:     optional
5864:     repeatable
5865: 
5866:     pattern(%( !hideresource ))
5867:     pattern(%( !reportEnd ))
5868:     pattern(%( !reportPeriod ))
5869:     pattern(%( !reportStart ))
5870:   end
rule_tsReportBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5872
5872:   def rule_tsReportBody
5873:     optionsRule('tsReportAttributes')
5874:   end
rule_tsReportHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5842
5842:   def rule_tsReportHeader
5843:     pattern(%( _timesheetreport !optionalID $STRING ), lambda {
5844:       report = newReport(@val[1], @val[2], :timeSheet, sourceFileInfo)
5845:       report.set('scenarios', [ 0 ])
5846:       # Show all tasks, sorted by seqno-up.
5847:       report.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
5848:       report.set('sortTasks', [ [ 'seqno', true, 1 ] ])
5849:       # Show all resources, sorted by seqno-up.
5850:       report.set('hideResource', LogicalExpression.new(LogicalOperation.new(0)))
5851:       report.set('sortResources', [ [ 'seqno', true, 1 ] ])
5852:       report.set('loadUnit', :hours)
5853:       report.set('definitions', [])
5854:     })
5855:     arg(1, 'file name', The name of the time sheet report file to generate. It must end with a .tjiextension, or use . to use the standard output channel.
5856:        )
5857:   end
rule_tsStatus() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5927
5927:   def rule_tsStatus
5928:     pattern(%( !tsStatusHeader !tsStatusBody ))
5929:     doc('status.timesheet', The status attribute can be used to describe the current status of the task orresource. The content of the status messages is added to the project journal.
5930:        )
5931:     arg(2, 'headline', A short headline for the status. Must be 60 characters or shorter.
5932:        )
5933:     example('TimeSheet1', '4')
5934:   end
rule_tsStatusAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5876
5876:   def rule_tsStatusAttributes
5877:     optional
5878:     repeatable
5879: 
5880:     pattern(%( !details ))
5881: 
5882:     pattern(%( _flags !flagList ), lambda {
5883:       @val[1].each do |flag|
5884:         next if @journalEntry.flags.include?(flag)
5885: 
5886:         @journalEntry.flags << flag
5887:       end
5888:     })
5889:     doc('flags.timesheet', Time sheet entries can have flags attached to them. These can be used toinclude only entries in a report that have a certain flag.
5890:        )
5891: 
5892:     pattern(%( !summary ))
5893:   end
rule_tsStatusBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5898
5898:   def rule_tsStatusBody
5899:     optional
5900:     pattern(%( _{ !tsStatusAttributes _} ))
5901:   end
rule_tsStatusHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5903
5903:   def rule_tsStatusHeader
5904:     pattern(%( _status !alertLevel $STRING ), lambda {
5905:       if @val[2].length > 120
5906:         error('ts_headline_too_long',
5907:               "The headline must be 120 or less characters long. This one " +
5908:               "has #{@val[2].length} characters.", @sourceFileInfo[2])
5909:       end
5910:       if @val[2] == 'Your headline here!'
5911:         error('ts_no_headline',
5912:               "'Your headline here!' is not a valid headline",
5913:               @sourceFileInfo[2])
5914:       end
5915:       @journalEntry = JournalEntry.new(@project['journal'],
5916:                                        @timeSheet.interval.end,
5917:                                        @val[2],
5918:                                        @property || @timeSheet.resource,
5919:                                        @sourceFileInfo[0])
5920:       @journalEntry.alertLevel = @val[1]
5921:       @journalEntry.timeSheetRecord = @timeSheetRecord
5922:       @journalEntry.author = @sheetAuthor
5923:       @timeSheetRecord.status = @journalEntry if @timeSheetRecord
5924:     })
5925:   end
rule_tsTaskAttributes() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 5941
5941:   def rule_tsTaskAttributes
5942:     optional
5943:     repeatable
5944: 
5945:     pattern(%( _end !valDate ), lambda {
5946:       if @val[1] < @timeSheet.interval.start
5947:         error('ts_end_too_early',
5948:               "The expected task end date must be after the start date of " +
5949:               "this time sheet report.", @sourceFileInfo[1])
5950:       end
5951:       @timeSheetRecord.expectedEnd = @val[1]
5952:     })
5953:     doc('end.timesheet', The expected end date for the task. This can only be used for duration basedtask. For effort based task [[remaining]] has to be used.
5954:        )
5955:     example('TimeSheet1', '5')
5956: 
5957:     pattern(%( _priority $INTEGER ), lambda {
5958:       priority = @val[1]
5959:       if priority < 1 || priority > 1000
5960:         error('ts_bad_priority',
5961:               "Priority value #{priority} must be between 1 and 1000.",
5962:               @sourceFileInfo[1])
5963:       end
5964:       @timeSheetRecord.priority = priority
5965:     })
5966:     doc('priority.timesheet', The priority is a value between 1 and 1000. It is used to determine thesequence of task when converting [[work]] to [[booking.task|bookings]]. Tasksthat need to finish earlier in the period should have a high priority, tasksthat end later in the period should have a low priority. For tasks that don'tget finished in the reported period the priority should be set to 1.
5967:        )
5968: 
5969:     pattern(%( _remaining !workingDuration ), lambda {
5970:       @timeSheetRecord.remaining = @val[1]
5971:     })
5972:     doc('remaining', The remaining effort for the task. This value is ignored if there are[[booking.task|bookings]] for the resource that overlap with the time sheetperiod.  If there are no bookings, the value is compared with the [[effort]]specification of the task. If there a mismatch between the accumulated effortspecified with bookings, [[work]] and [[remaining]] on one side and thespecified [[effort]] on the other, a warning is generated.This attribute can only be used with tasks that are effort based. Durationbased tasks need to have an [[end.timesheet|end]] attribute.
5973:        )
5974:     example('TimeSheet1', '6')
5975: 
5976:     pattern(%( !tsStatus ))
5977: 
5978:     pattern(%( _work !workingDurationPercent ), lambda {
5979:       @timeSheetRecord.work = @val[1]
5980:     })
5981:     doc('work', The amount of time that the resource has spend with the task during thereported period. This value is ignored when there are[[booking.task|bookings]] for the resource overlapping with the time sheetperiod. If there are no bookings, TaskJuggler will try to convert the workspecification into bookings internally before the actual scheduling isstarted.Every task listed in the time sheet needs to have a work attribute. The totalaccumulated work time that is reported must match exactly the total workinghours for the resource for that period.If a resource has no vacation during the week that is reported and it has aregular 40 hour work week, exactly 40 hours total or 5 working days have to bereported.
5982:        )
5983:     example('TimeSheet1', '4')
5984:   end
rule_tsTaskBody() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6020
6020:   def rule_tsTaskBody
6021:     pattern(%( _{ !tsTaskAttributes _} ))
6022:   end
rule_tsTaskHeader() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6024
6024:   def rule_tsTaskHeader
6025:     pattern(%( _task !taskId ), lambda {
6026:       @property = @val[1]
6027:       unless @property.leaf?
6028:         error('ts_task_not_leaf',
6029:               'You cannot specify a task that has sub tasks here.',
6030:               @sourceFileInfo[1], @property)
6031:       end
6032: 
6033:       @timeSheetRecord = TimeSheetRecord.new(@timeSheet, @property)
6034:       @timeSheetRecord.sourceFileInfo = @sourceFileInfo[0]
6035:     })
6036:     arg(1, 'task', 'ID of an already existing task')
6037:   end
rule_vacationName() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6039
6039:   def rule_vacationName
6040:     optional
6041:     pattern(%( $STRING )) # We just throw the name away
6042:     arg(0, 'name', 'An optional name for the vacation')
6043:   end
rule_valDate() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6045
6045:   def rule_valDate
6046:     pattern(%( !date ), lambda {
6047:       if @val[0] < @project['start'] || @val[0] > @project['end']
6048:         error('date_in_range',
6049:               "Date #{@val[0]} must be within the project time frame " +
6050:               "#{@project['start']}  - #{@project['end']}",
6051:               @sourceFileInfo[0])
6052:       end
6053:       @val[0]
6054:     })
6055:   end
rule_valInterval() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6105
6105:   def rule_valInterval
6106:     pattern(%( !date !intervalEnd ), lambda {
6107:       mode = @val[1][0]
6108:       endSpec = @val[1][1]
6109:       if mode == 0
6110:         unless @val[0] < endSpec
6111:           error('start_before_end', "The end date (#{endSpec}) must be after " +
6112:                 "the start date (#{@val[0]}).", @sourceFileInfo[1])
6113:         end
6114:         iv = Interval.new(@val[0], endSpec)
6115:       else
6116:         iv = Interval.new(@val[0], @val[0] + endSpec)
6117:       end
6118:       checkInterval(iv)
6119:       iv
6120:     })
6121:     doc('interval1', There are two ways to specify a date interval. The start and end date must lie within the specified project period.The first is the most obvious. A date interval consists of a start and endDATE. Watch out for end dates without a time specification! Datespecifications are 0 extended. An end date without a time is expanded tomidnight that day. So the day of the end date is not included in the interval!The start and end dates must be separated by a hyphen character.In the second form specifies the start date and an interval duration. Theduration must be prefixed by a plus character.
6122:        )
6123:   end
rule_valIntervalOrDate() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6067
6067:   def rule_valIntervalOrDate
6068:     pattern(%( !date !intervalOptionalEnd ), lambda {
6069:       if @val[1]
6070:         mode = @val[1][0]
6071:         endSpec = @val[1][1]
6072:         if mode == 0
6073:           unless @val[0] < endSpec
6074:             error('start_before_end', "The end date (#{endSpec}) must be " +
6075:                   "after the start date (#{@val[0]}).",
6076:                   @sourceFileInfo[1])
6077:           end
6078:           iv = Interval.new(@val[0], endSpec)
6079:         else
6080:           iv = Interval.new(@val[0], @val[0] + endSpec)
6081:         end
6082:       else
6083:         iv = Interval.new(@val[0], @val[0].sameTimeNextDay)
6084:       end
6085:       checkInterval(iv)
6086:       iv
6087:     })
6088:     doc('interval4', There are three ways to specify a date interval. The first is the mostobvious. A date interval consists of a start and end DATE. Watch out for enddates without a time specification! Date specifications are 0 extended. Anend date without a time is expanded to midnight that day. So the day of theend date is not included in the interval! The start and end dates must be separated by a hyphen character.In the second form, the end date is omitted. A 24 hour interval is assumed.The third form specifies the start date and an interval duration. The duration must be prefixed by a plus character.The start and end date of the interval must be within the specified projecttime frame.
6089:        )
6090:   end
rule_valIntervals() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6136
6136:   def rule_valIntervals
6137:     listRule('moreValIntervals', '!valIntervalOrDate')
6138:   end
rule_validTimeZone() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6057
6057:   def rule_validTimeZone
6058:     pattern(%( $STRING ), lambda {
6059:       unless TjTime.checkTimeZone(@val[0])
6060:         error('bad_time_zone', "#{@val[0]} is not a known time zone",
6061:               @sourceFileInfo[0])
6062:       end
6063:       @val[0]
6064:     })
6065:   end
rule_warn() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6140
6140:   def rule_warn
6141:     pattern(%( _warn !logicalExpression ), lambda {
6142:       begin
6143:         @property.set('warn', @property.get('warn') + [ @val[1] ])
6144:       rescue AttributeOverwrite
6145:       end
6146:     })
6147:     doc('warn', The warn attribute adds a logical expression to the property. The conditiondescribed by the logical expression is checked after the scheduling and anwarning is generated if the condition evaluates to true. This attribute isprimarily intended for testing purposes.
6148:        )
6149:   end
rule_weekDayInterval() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6167
6167:   def rule_weekDayInterval
6168:     pattern(%( !weekday !weekDayIntervalEnd ), lambda {
6169:       weekdays = Array.new(7, false)
6170:       if @val[1].nil?
6171:         weekdays[@val[0]] = true
6172:       else
6173:         d = @val[0]
6174:         loop do
6175:           weekdays[d] = true
6176:           break if d == @val[1]
6177:           d = (d + 1) % 7
6178:         end
6179:       end
6180: 
6181:       weekdays
6182:     })
6183:     arg(0, 'weekday', 'Weekday (sun - sat)')
6184:   end
rule_weekDayIntervalEnd() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6186
6186:   def rule_weekDayIntervalEnd
6187:     optional
6188:     pattern([ '_-', '!weekday' ], lambda {
6189:       @val[1]
6190:     })
6191:     arg(1, 'end weekday',
6192:         'Weekday (sun - sat). It is included in the interval.')
6193:   end
rule_weekday() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6157
6157:   def rule_weekday
6158:     pattern(%( _sun ), lambda { 0 })
6159:     pattern(%( _mon ), lambda { 1 })
6160:     pattern(%( _tue ), lambda { 2 })
6161:     pattern(%( _wed ), lambda { 3 })
6162:     pattern(%( _thu ), lambda { 4 })
6163:     pattern(%( _fri ), lambda { 5 })
6164:     pattern(%( _sat ), lambda { 6 })
6165:   end
rule_workingDuration() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6195
6195:   def rule_workingDuration
6196:     pattern(%( !number !durationUnit ), lambda {
6197:       convFactors = [ 60, # minutes
6198:                       60 * 60, # hours
6199:                       60 * 60 * @project['dailyworkinghours'], # days
6200:                       60 * 60 * @project['dailyworkinghours'] *
6201:                       (@project['yearlyworkingdays'] / 52.1429), # weeks
6202:                       60 * 60 * @project['dailyworkinghours'] *
6203:                       (@project['yearlyworkingdays'] / 12), # months
6204:                       60 * 60 * @project['dailyworkinghours'] *
6205:                       @project['yearlyworkingdays'] # years
6206:                     ]
6207:       # The result will always be in number of time slots.
6208:       (@val[0] * convFactors[@val[1]] /
6209:        @project['scheduleGranularity']).round.to_i
6210:     })
6211:     arg(0, 'value', 'A floating point or integer number')
6212:   end
rule_workingDurationPercent() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6214
6214:   def rule_workingDurationPercent
6215:     pattern(%( !number !durationUnitOrPercent ), lambda {
6216:       if @val[1] >= 0
6217:         # Absolute value in minutes, hours or days.
6218:         convFactors = [ 60, # minutes
6219:           60 * 60, # hours
6220:           60 * 60 * @project['dailyworkinghours'] # days
6221:         ]
6222:         # The result will always be in number of time slots.
6223:         (@val[0] * convFactors[@val[1]] /
6224:          @project['scheduleGranularity']).round.to_i
6225:       else
6226:         # Percentage values are always returned as Float in the rage of 0.0 to
6227:         # 1.0.
6228:         if @val[0] < 0.0 || @val[0] > 100.0
6229:           error('illegal_percentage',
6230:                 "Percentage values must be between 0 and 100%.",
6231:                 @sourceFileInfo[1])
6232:         end
6233:         @val[0] / 100.0
6234:       end
6235:     })
6236:     arg(0, 'value', 'A floating point or integer number')
6237:   end
rule_workinghours() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6239
6239:   def rule_workinghours
6240:     pattern(%( _workinghours !listOfDays !listOfTimes), lambda {
6241:       if @property.nil?
6242:         # We are changing global working hours.
6243:         wh = @project['workinghours']
6244:       else
6245:         unless (wh = @property['workinghours', @scenarioIdx])
6246:           # The property does not have it's own WorkingHours yet.
6247:           wh = WorkingHours.new(@project['workinghours'])
6248:           @property['workinghours', @scenarioIdx] = wh
6249:         end
6250:       end
6251:       wh.timezone = @project['timezone']
6252:       7.times { |i| wh.setWorkingHours(i, @val[2]) if @val[1][i] }
6253:     })
6254:   end
rule_workinghoursProject() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6256
6256:   def rule_workinghoursProject
6257:     pattern(%( !workinghours ))
6258:     doc('workinghours.project', Set the default working hours for all subsequent resource definitions. Thestandard working hours are 9:00am - 12:00am, 1:00pm - 18:00pm, Monday toFriday. The working hours specification limits the availability of resourcesto certain time slots of week days.These default working hours can be replaced with other working hours forindividual resources.
6259:        )
6260:     also(%( dailyworkinghours workinghours.resource workinghours.shift ))
6261:     example('Project')
6262:   end
rule_workinghoursResource() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6272
6272:   def rule_workinghoursResource
6273:     pattern(%( !workinghours ))
6274:     doc('workinghours.resource', Set the working hours for a specific resource. The working hours specificationlimits the availability of resources to certain time slots of week days.
6275:        )
6276:     also(%( workinghours.project workinghours.shift ))
6277:   end
rule_workinghoursShift() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6282
6282:   def rule_workinghoursShift
6283:     pattern(%( !workinghours ))
6284:     doc('workinghours.shift', Set the working hours for the shift. The working hours specification limitsthe availability of resources or the activity on a task to certain timeslots of week days.The shift working hours will replace the default or resource working hours forthe specified time frame when assigning the shift to a resource.In case the shift is used for a task, resources are only assigned during theworking hours of this shift and during the working hours of the allocatedresource. Allocations only happen when both the task shift and the resourcework hours allow work to happen.
6285:        )
6286:     also(%( workinghours.project workinghours.resource ))
6287:   end
rule_yesNo() click to toggle source
      # File lib/taskjuggler/TjpSyntaxRules.rb, line 6301
6301:   def rule_yesNo
6302:     pattern(%( _yes ), lambda {
6303:       true
6304:     })
6305:     pattern(%( _no ), lambda {
6306:       false
6307:     })
6308:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.