import EmitterSubscriberBase from "./emissary-helper" ; import * as V from "./const" ; import * as logger from "./logger" ; import * as ReVIEW from "review.js" ; import * as path from "path" ; import * as fs from "fs" ; import * as PrhValidator from "reviewjs-prh" ; class SingleFileAnalyzer extends ReVIEW . DefaultAnalyzer { inline_chap ( builder ) { this . inlineDecorationSyntax ( builder , "chap" ) ; } inline_title ( builder ) { this . inlineDecorationSyntax ( builder , "title" ) ; } inline_chapref ( builder ) { this . inlineDecorationSyntax ( builder , "chapref" ) ; } } class SingleFileHTMLBuilder extends ReVIEW . HtmlBuilder { inline_chap ( process , _node ) { process . out ( "第X章" ) ; return false ; } inline_title ( process , _node ) { process . out ( "章タイトル(仮)" ) ; return false ; } inline_chapref ( process , _node ) { process . out ( "第X章「章タイトル(仮)」" ) ; return false ; } } export default class ReVIEWRunner extends EmitterSubscriberBase { private watcher : ContentWatcher ; editor : AtomCore . IEditor ; lastAcceptableSyntaxes : ReVIEW . AcceptableSyntaxes ; lastSymbols : ReVIEW . Symbol [ ] ; lastReports : ReVIEW . ProcessReport [ ] ; lastBook : ReVIEW . Book ; constructor ( params ) { super ( ) ; this . editor = params . editor ; if ( this . editor ) { this . watcher = new EditorContentWatcher ( this , this . editor ) ; } else { throw new Error ( "editor is required" ) ; } } startWatching ( ) { logger . log ( ) ; this . watcher . startWatching ( ) ; } stopWatching ( ) { logger . log ( ) ; this . watcher . stopWatching ( ) ; } activate ( ) { logger . log ( ) ; this . watcher . activate ( ) ; } deactivate ( ) { logger . log ( ) ; this . watcher . deactivate ( ) ; } on ( eventNames , callback ) ; on ( eventNames , callback ) ; on ( eventNames , callback ) ; on ( eventNames , callback ) ; on ( eventNames , callback ) ; on ( eventNames , callback ) ; on ( eventNames , handler ) ; on ( _eventNames , _handler ) { throw new Error ( ) ; } doCompile ( ) { logger . log ( ) ; this . emit ( "start" ) ; let currentPath = this . watcher . getFilePath ( ) || "ch01.re" ; let basePath = path . isAbsolute ( currentPath ) ? path . dirname ( currentPath ) : undefined ; let filename = path . basename ( currentPath ) ; setTimeout ( ( ) => { let files = { } ; files [ filename ] = this . watcher . getContent ( ) ; let result = { } ; let validators = [ new ReVIEW . DefaultValidator ( ) , ] ; let dirName ; if ( this . editor ) { dirName = this . editor . getBuffer ( ) . file . getParent ( ) . getPath ( ) ; } let prhFilePath = path . join ( dirName , "prh.yml" ) ; if ( fs . existsSync ( prhFilePath ) ) { try { validators . push ( new PrhValidator . TextValidator ( prhFilePath ) ) ; } catch ( e ) { atom . notifications . addWarning ( "prh.ymlの定義に誤りがあります。\n" + e ) ; } } ReVIEW . start ( review => { review . initConfig ( { basePath : basePath , read : path => Promise . resolve ( files [ path ] ) , write : ( path , content ) => { result [ path ] = content ; return Promise . resolve < void > ( null ) ; } , listener : { onAcceptables : acceptableSyntaxes => { logger . log ( acceptableSyntaxes ) ; this . lastAcceptableSyntaxes = acceptableSyntaxes ; this . emit ( "syntax" , acceptableSyntaxes ) ; } , onSymbols : symbols => { logger . log ( symbols ) ; this . lastSymbols = symbols ; this . emit ( "symbol" , symbols ) ; } , onReports : reports => { logger . log ( reports ) ; this . lastReports = reports ; this . emit ( "report" , reports ) ; } , onCompileSuccess : book => { logger . log ( book ) ; this . lastBook = book ; this . emit ( "compile-success" , book ) ; } , onCompileFailed : book => { logger . log ( ) ; this . lastBook = null ; this . emit ( "compile-failed" , book ) ; } , } , analyzer : new SingleFileAnalyzer ( ) , validators : validators , builders : [ new SingleFileHTMLBuilder ( false ) ] , book : { contents : [ filename , ] , } , } ) ; } ) ; } ) ; } getContent ( ) { return this . watcher . getContent ( ) ; } getFilePath ( ) { return this . watcher . getFilePath ( ) ; } } ReVIEWRunner . emissarified ( ) ; interface ContentWatcher { startWatching ( ) : void ; stopWatching ( ) : void ; activate ( ) : void ; deactivate ( ) : void ; getContent ( ) : string ; getFilePath ( ) : string ; } class EditorContentWatcher extends EmitterSubscriberBase implements ContentWatcher { buffer : TextBuffer . ITextBuffer ; grammarChangeSubscription : AtomCore . IDisposable ; wasAlreadyActivated : boolean ; bufferSubscriptions : AtomCore . IDisposable [ ] = [ ] ; lastKeyHitTimeoutId : any ; static IN_EDIT_COMPILE_TIMEOUT : number = 3000 ; constructor ( public runner , public editor ) { super ( ) ; this . buffer = this . editor . getBuffer ( ) ; } startWatching ( ) { logger . log ( ) ; if ( this . grammarChangeSubscription ) { return ; } this . configureRunner ( ) ; this . grammarChangeSubscription = this . editor . onDidChangeGrammar ( ( ) => this . configureRunner ( ) ) ; } stopWatching ( ) { logger . log ( ) ; if ( ! this . grammarChangeSubscription ) { return ; } this . grammarChangeSubscription . dispose ( ) ; this . grammarChangeSubscription = null ; } configureRunner ( ) { let scopeName = this . editor . getGrammar ( ) . scopeName ; logger . log ( "configureRunner grammar " + scopeName ) ; if ( V . reviewScopeName === scopeName ) { this . activate ( ) ; } else { this . deactivate ( ) ; } } triggerCompile ( withDelay = false ) { if ( this . lastKeyHitTimeoutId ) { clearTimeout ( this . lastKeyHitTimeoutId ) ; } if ( withDelay ) { this . lastKeyHitTimeoutId = setTimeout ( ( ) => { this . lastKeyHitTimeoutId = null ; this . runner . doCompile ( ) ; } , EditorContentWatcher . IN_EDIT_COMPILE_TIMEOUT ) ; } else { this . lastKeyHitTimeoutId = null ; this . runner . doCompile ( ) ; } } activate ( ) { logger . log ( ) ; if ( ! this . wasAlreadyActivated ) { this . emit ( "activate" ) ; } this . wasAlreadyActivated = true ; this . runner . doCompile ( ) ; if ( this . bufferSubscriptions . length !== 0 ) { return ; } this . bufferSubscriptions . push ( this . buffer . onDidChange ( ( ) => this . triggerCompile ( true ) ) ) ; this . bufferSubscriptions . push ( this . buffer . onDidSave ( ( ) => this . triggerCompile ( ) ) ) ; this . bufferSubscriptions . push ( this . buffer . onDidReload ( ( ) => this . triggerCompile ( ) ) ) ; } deactivate ( ) { logger . log ( ) ; this . stopWatching ( ) ; this . bufferSubscriptions . forEach ( subscription => subscription . dispose ( ) ) ; this . bufferSubscriptions = [ ] ; this . runner . emit ( "deactivate" ) ; } getContent ( ) { return this . editor . buffer . getText ( ) ; } getFilePath ( ) { return this . buffer . getUri ( ) ; } }