'use strict' ; import * as vscode from 'vscode' ; let highlightDecoration ; let currentDecoration ; let omitLanguages ; var TAB_SIZE = 4 ; var lineTable = new Map ( ) ; export function activate ( context ) { console . log ( 'Congratulations, your extension "indented-block-highlighting" is now active! (var ts)' ) ; let config = vscode . workspace . getConfiguration ( "blockhighlight" ) ; omitLanguages = config . get ( "omit" , [ "plaintext" ] ) ; let blockHighlighter = new BlockHL ; let blockHighlighterController = new BHLController ( blockHighlighter ) ; blockHighlighter . updateLine ( ) ; context . subscriptions . push ( blockHighlighter ) ; context . subscriptions . push ( blockHighlighterController ) ; } export function deactivate ( ) { } class BlockHL { public updateLine ( ) { var start = new Date ( ) . getTime ( ) ; let editor = vscode . window . activeTextEditor ; if ( ! editor ) { return ; } if ( omitLanguages . indexOf ( editor . document . languageId ) > - 1 ) { return ; } if ( editor . selection . isSingleLine ) { let topLine = this . findTop ( editor ) ; let botLine = this . findBot ( editor , topLine ) ; let HLRange ; if ( editor . document . languageId === 'python' ) { botLine = this . pruneTrailingWhitespace ( editor , botLine ) ; } if ( this . getIndentLevel ( editor , editor . document . lineAt ( editor . selection . active ) ) === 0 && ! editor . document . lineAt ( editor . selection . active ) . isEmptyOrWhitespace ) { this . unhighlightAll ( editor ) ; } else { HLRange = new vscode . Range ( topLine . lineNumber + 1 , 0 , botLine . lineNumber - 1 , Number . MAX_VALUE ) ; this . highlightRange ( editor , HLRange ) ; } } else { this . unhighlightAll ( editor ) ; } var end = new Date ( ) . getTime ( ) ; console . log ( "Update Time: " . concat ( String ( end - start ) ) ) ; console . log ( "Selected Line Level: " + this . getIndentLevel ( editor , editor . document . lineAt ( editor . selection . active ) ) ) ; } findTop ( editor ) { let line = editor . document . lineAt ( editor . selection . active ) ; while ( line . isEmptyOrWhitespace && line . lineNumber > 0 ) { line = editor . document . lineAt ( line . lineNumber - 1 ) ; } if ( line . lineNumber < editor . document . lineCount - 1 && ! line . isEmptyOrWhitespace ) { let nextLine = editor . document . lineAt ( line . lineNumber + 1 ) ; while ( nextLine . isEmptyOrWhitespace && nextLine . lineNumber < editor . document . lineCount - 1 ) { nextLine = editor . document . lineAt ( nextLine . lineNumber + 1 ) ; } } let indentLevel = NaN ; while ( line . lineNumber > 0 ) { if ( ! line . isEmptyOrWhitespace ) { let nextLevel = this . getIndentLevel ( editor , line ) ; if ( Number . isNaN ( indentLevel ) ) { indentLevel = nextLevel ; } if ( nextLevel === 0 ) { return line ; } if ( nextLevel < indentLevel ) { return line ; } } line = editor . document . lineAt ( line . lineNumber - 1 ) ; } return line ; } findBot ( editor , topLine ) { let line = editor . document . lineAt ( topLine . lineNumber + 1 ) ; let baseLevel = this . getIndentLevel ( editor , editor . document . lineAt ( editor . selection . active ) ) ; while ( line . lineNumber < editor . document . lineCount - 1 ) { if ( ! line . isEmptyOrWhitespace ) { let nextLevel = this . getIndentLevel ( editor , line ) ; if ( nextLevel < baseLevel || nextLevel === 0 ) { return line ; } } line = editor . document . lineAt ( line . lineNumber + 1 ) ; } console . log ( "EOF Reached" ) ; return line ; } param line returns getIndentLevel ( editor , line ) { let indentLevel = line . firstNonWhitespaceCharacterIndex ; let lineText = line . text ; for ( var i = 0 ; i < indentLevel ; i ++ ) { if ( lineText . charAt ( i ) === '\t' ) { indentLevel += ( TAB_SIZE - 1 ) ; } } lineTable . set ( line , indentLevel ) ; return indentLevel ; } freeCurrentLine ( ) { let editor = vscode . window . activeTextEditor ; if ( ! editor ) { return ; } lineTable . delete ( editor . document . lineAt ( editor . selection . active ) ) ; } pruneTrailingWhitespace ( editor , bot ) { if ( editor . document . lineCount < 2 ) { return bot ; } let newBot = editor . document . lineAt ( bot . lineNumber - 1 ) ; while ( newBot . isEmptyOrWhitespace ) { newBot = editor . document . lineAt ( newBot . lineNumber - 1 ) ; } newBot = editor . document . lineAt ( newBot . lineNumber + 1 ) ; return newBot ; } setCurrentDocumentTabSize ( ) { let editor = vscode . window . activeTextEditor ; if ( ! editor ) { return ; } let tabs ; tabs = editor . options . tabSize as number ; TAB_SIZE = tabs ; console . log ( "Tab size of current document: " + TAB_SIZE ) ; } changeActive ( ) { console . log ( "Active Window Changed" ) ; this . setCurrentDocumentTabSize ( ) ; } highlightRange ( editor , range ) { if ( highlightDecoration ) { highlightDecoration . dispose ( ) ; } if ( currentDecoration ) { currentDecoration . dispose ( ) ; } let config = vscode . workspace . getConfiguration ( "blockhighlight" ) ; let wholeLine = config . get ( "isWholeLine" , true ) ; let accentCurrent = config . get ( "accentCurrentLine" , true ) ; let rgbaArray = config . get ( "background" , [ "200" , "100" , "255" , ".05" ] ) ; let rgbaStr = "rgba(" . concat ( rgbaArray [ 0 ] ) . concat ( ", " ) . concat ( rgbaArray [ 1 ] ) . concat ( ", " ) . concat ( rgbaArray [ 2 ] ) . concat ( ", " ) . concat ( rgbaArray [ 3 ] ) . concat ( ")" ) ; highlightDecoration = vscode . window . createTextEditorDecorationType ( < vscode . DecorationRenderOptions > { backgroundColor : rgbaStr , isWholeLine : wholeLine } ) ; currentDecoration = vscode . window . createTextEditorDecorationType ( < vscode . DecorationRenderOptions > { backgroundColor : rgbaStr , isWholeLine : wholeLine } ) ; editor . setDecorations ( highlightDecoration , [ range ] ) ; if ( accentCurrent ) { editor . setDecorations ( currentDecoration , [ editor . selection ] ) ; } } unhighlightAll ( editor ) { if ( highlightDecoration ) { highlightDecoration . dispose ( ) ; } if ( currentDecoration ) { currentDecoration . dispose ( ) ; } } dispose ( ) { } } class BHLController { private _blockHL : BlockHL ; private _disposable : vscode . Disposable ; public constructor ( blockHL ) { this . _blockHL = blockHL ; let subscriptions = [ ] ; vscode . window . onDidChangeActiveTextEditor ( this . _onChangeActive , this , subscriptions ) ; vscode . window . onDidChangeTextEditorSelection ( this . _onLineChange , this , subscriptions ) ; vscode . window . onDidChangeTextEditorOptions ( this . _onChangeOptions , this , subscriptions ) ; vscode . workspace . onDidChangeTextDocument ( this . _onChangeText , this , subscriptions ) ; this . _disposable = vscode . Disposable . from ( ... subscriptions ) ; } dispose ( ) { this . _disposable . dispose ( ) ; } private _onChangeOptions ( ) { this . _blockHL . setCurrentDocumentTabSize ( ) ; } private _onChangeText ( ) { this . _blockHL . freeCurrentLine ( ) ; } private _onChangeActive ( ) { this . _blockHL . changeActive ( ) ; } private _onLineChange ( ) { this . _blockHL . updateLine ( ) ; } }