'use strict' ; import { TextDocument , TextLine , Position , CompletionItem , Range } from 'vscode' ; export class TodoDocument { public static SYMBOL_PROJECT = ":" ; public static SYMBOL_NEW_TASK = "☐" ; public static SYMBOL_DONE_TASK = "✔" ; public static SYMBOL_CANCEL_TASK = "✘" ; public static SYMBOL_TAG = "@" ; public static TAG_CRITICAL = "critical" ; public static TAG_HIGH = "high" ; public static TAG_LOW = "low" ; public static TAG_TODAY = "today" ; public static ACTION_DONE = "done" ; public static ACTION_CANCELLED = "cancelled" ; constructor ( private _textDocument ) { } public getProject ( pos ) { let line = this . _textDocument . lineAt ( pos . line ) ; let projectText = line . text . trim ( ) ; if ( projectText . endsWith ( TodoDocument . SYMBOL_PROJECT ) ) { return new Project ( line ) ; } return null ; } public getTasks ( ) { let result = [ ] ; var text = this . _textDocument . getText ( ) ; var regEx = /^\s*[☐|✘|✔]/gm ; var match ; while ( match = regEx . exec ( text ) ) { let line = this . _textDocument . lineAt ( this . _textDocument . positionAt ( match . index + 1 ) . line ) ; result . push ( new Task ( line ) ) ; } return result ; } public getTask ( pos ) { if ( ! this . isTask ( pos ) ) { return null ; } let line = this . _textDocument . lineAt ( pos . line ) ; return new Task ( line ) ; } public isTask ( pos ) { let task = this . _textDocument . lineAt ( pos . line ) . text . trim ( ) ; return task . startsWith ( TodoDocument . SYMBOL_NEW_TASK ) || task . startsWith ( TodoDocument . SYMBOL_CANCEL_TASK ) || task . startsWith ( TodoDocument . SYMBOL_DONE_TASK ) ; } public static toTag ( tagName ) { return TodoDocument . SYMBOL_TAG + tagName ; } } export class Task { private taskText : string ; constructor ( public taskLine ) { this . taskText = taskLine . text . trim ( ) ; } public getDescription ( ) { if ( this . isDone ( ) ) { let index = this . taskText . indexOf ( TodoDocument . toTag ( TodoDocument . ACTION_DONE ) ) ; return index !== - 1 ? this . taskText . substring ( TodoDocument . SYMBOL_DONE_TASK . length , index ) . trim ( ) : this . taskText . substring ( TodoDocument . SYMBOL_DONE_TASK . length ) . trim ( ) ; } if ( this . isCancelled ( ) ) { var index = this . taskText . indexOf ( TodoDocument . toTag ( TodoDocument . ACTION_CANCELLED ) ) ; return index !== - 1 ? this . taskText . substring ( TodoDocument . SYMBOL_CANCEL_TASK . length , index ) . trim ( ) : this . taskText . substring ( TodoDocument . SYMBOL_CANCEL_TASK . length ) . trim ( ) ; } return this . taskText . substring ( TodoDocument . SYMBOL_NEW_TASK . length ) . trim ( ) ; } public isEmpty ( ) { return ! this . getDescription ( ) . trim ( ) ; } public isDone ( ) { return this . taskText . indexOf ( TodoDocument . SYMBOL_DONE_TASK ) !== - 1 ; } public isCancelled ( ) { return this . taskText . indexOf ( TodoDocument . SYMBOL_CANCEL_TASK ) !== - 1 ; } public hasTag ( tag ) { return this . taskText . toLocaleLowerCase ( ) . indexOf ( TodoDocument . toTag ( tag ) . toLocaleLowerCase ( ) ) !== - 1 ; } public getTagRanges ( tag ) { var result = [ ] ; var regEx = /@[^@\s]+/g ; var match ; while ( match = regEx . exec ( this . taskText ) ) { if ( TodoDocument . toTag ( tag ) . toLocaleLowerCase ( ) === match [ 0 ] . toLocaleLowerCase ( ) ) { let start = this . taskLine . range . start ; let lineText = this . taskLine . text ; let startPosition = new Position ( start . line , this . taskLine . firstNonWhitespaceCharacterIndex + match . index ) ; let endPosition = new Position ( start . line , this . taskLine . firstNonWhitespaceCharacterIndex + match . index + match [ 0 ] . length ) ; result . push ( new Range ( startPosition , endPosition ) ) ; } } return result ; } public getTags ( ) { var result = [ ] ; var regEx = /@[^@\s]+/g ; var match ; while ( match = regEx . exec ( this . taskText ) ) { if ( TodoDocument . toTag ( TodoDocument . ACTION_CANCELLED ) !== match [ 0 ] && TodoDocument . toTag ( TodoDocument . ACTION_DONE ) !== match [ 0 ] ) { result . push ( match [ 0 ] ) ; } } return result ; } public getTagsRanges ( ) { var result = [ ] ; var regEx = /@[^@\s]+/g ; var match ; while ( match = regEx . exec ( this . taskText ) ) { if ( TodoDocument . toTag ( TodoDocument . ACTION_CANCELLED ) !== match [ 0 ] && TodoDocument . toTag ( TodoDocument . ACTION_DONE ) !== match [ 0 ] ) { let start = this . taskLine . range . start ; let lineText = this . taskLine . text ; let startPosition = new Position ( start . line , this . taskLine . firstNonWhitespaceCharacterIndex + match . index ) ; let endPosition = new Position ( start . line , this . taskLine . firstNonWhitespaceCharacterIndex + match . index + match [ 0 ] . length ) ; result . push ( new Range ( startPosition , endPosition ) ) ; } } return result ; } } export class Project { constructor ( public line ) { } }