char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
1738b3c
main
1import { 2ArrayPrototypeUnshift , 3Error , 4ErrorCaptureStackTrace , 5ErrorGetStack , 6Map , 7MapPrototypeDelete , 8MapPrototypeGet , 9MapPrototypeHas , 10MapPrototypeSet , 11MathMin , 12NumberPrototypeToFixed , 13ObjectCreate , 14ObjectDefineProperty , 15ObjectGetOwnPropertyDescriptor , 16ObjectPrototype , 17ObjectSetPrototypeOf , 18StringPrototypeRepeat , 19StringPrototypeReplaceAll , 20SymbolToStringTag , 21TypeError , 22} from "ext:core/primordials" ; 23import { 24op_console_clear , 25op_console_colors , 26op_console_now , 27op_console_print , 28} from "ext:core/ops" ; 29import { onRuntimeStart } from "ext:core/bootstrap" ; 30import { inspect } from "./inspect.js" ; 31import { format , labelString } from "./format.js" ; 32import { table } from "./table.js" ; 33 34const counters = new Map < string , number >(); 35const timers = new Map < string , number >(); 36let groupDepth = 0 ; 37let stdoutColors :boolean | undefined , stderrColors :boolean | undefined ; 38onRuntimeStart (() => { 39stdoutColors = op_console_colors ( false ); 40stderrColors = op_console_colors ( true ); 41}); 42 43function ( stderr :boolean , text :unknown ) :void { 44const indent = StringPrototypeRepeat ( " " , MathMin ( groupDepth , 20 )); 45op_console_print ([ 46stderr , 47` ${ indent } ${ StringPrototypeReplaceAll ( text , "\n" , `\n ${ indent } ` )} \n` , 48]); 49} 50 51function logger ( stderr :boolean , args :unknown []) :void { 52if ( args . length ) { 53( stderr , format ( args , stderr ?stderrColors :stdoutColors )); 54} 55} 56 57function elapsed ( label :string ) :string | null { 58if ( ! MapPrototypeHas ( timers , label )) { 59( true , `Timer ' ${ label } ' does not exist` ); 60return null ; 61} 62const duration = op_console_now () - MapPrototypeGet ( timers , label ) ! ; 63return ` ${ label } : ${ NumberPrototypeToFixed ( duration , 3 )} ms` ; 64} 65 66const console = { 67log ( ...args :unknown []) { 68logger ( false , args ); 69}, 70debug ( ...args :unknown []) { 71logger ( false , args ); 72}, 73info ( ...args :unknown []) { 74logger ( false , args ); 75}, 76warn ( ...args :unknown []) { 77logger ( true , args ); 78}, 79error ( ...args :unknown []) { 80logger ( true , args ); 81}, 82assert ( condition :unknown = false , ...args :unknown []) { 83if ( condition ) return ; 84if ( typeof args [ 0 ] === "string" ) args [ 0 ] = `Assertion failed: ${ args [ 0 ]} ` ; 85else ArrayPrototypeUnshift ( args , "Assertion failed" ); 86logger ( true , args ); 87}, 88clear () { 89groupDepth = 0 ; 90op_console_clear (); 91}, 92count ( value :unknown = "default" ) { 93const label = labelString ( value ); 94const count = ( MapPrototypeGet ( counters , label ) || 0 ) + 1 ; 95MapPrototypeSet ( counters , label , count ); 96( false , ` ${ label } : ${ count } ` ); 97}, 98countReset ( value :unknown = "default" ) { 99const label = labelString ( value ); 100if ( MapPrototypeHas ( counters , label )) MapPrototypeSet ( counters , label , 0 ); 101else ( true , `Count for ' ${ label } ' does not exist` ); 102}, 103dir ( value :unknown = undefined , options :unknown = undefined ) { 104if ( 105options !== undefined && options !== null && 106typeof options !== "object" && typeof options !== "function" 107) { 108throw new TypeError ( "Console dir options must be an object" ); 109} 110const depth :unknown = options 111 ?ObjectGetOwnPropertyDescriptor ( options , "depth" )?. value 112 :undefined ; 113( false , inspect ( value , { depth, colors :stdoutColors })); 114}, 115dirxml ( ...args :unknown []) { 116logger ( false , args ); 117}, 118group ( ...args :unknown []) { 119( false , args . length ?format ( args , stdoutColors ) :"group" ); 120groupDepth ++ ; 121}, 122groupCollapsed ( ...args :unknown []) { 123( false , args . length ?format ( args , stdoutColors ) :"group" ); 124groupDepth ++ ; 125}, 126groupEnd () { 127if ( groupDepth ) groupDepth -- ; 128}, 129table ( data :unknown = undefined , columns :unknown = undefined ) { 130table ( data , columns , ); 131}, 132time ( value :unknown = "default" ) { 133const label = labelString ( value ); 134if ( MapPrototypeHas ( timers , label )) { 135( true , `Timer ' ${ label } ' already exists` ); 136} else MapPrototypeSet ( timers , label , op_console_now ()); 137}, 138timeLog ( label :unknown = "default" , ...args :unknown []) { 139const text = elapsed ( labelString ( label )); 140if ( text !== null ) { 141( 142false , 143args . length ?` ${ text } ${ format ( args , stdoutColors )} ` :text , 144); 145} 146}, 147timeEnd ( value :unknown = "default" ) { 148const label = labelString ( value ); 149const text = elapsed ( label ); 150if ( text !== null ) { 151MapPrototypeDelete ( timers , label ); 152( false , text ); 153} 154}, 155trace ( ...args :unknown []) { 156const error = new Error ( args . length ?format ( args ) :"" ); 157ObjectDefineProperty ( error , "name" , { value :"Trace" , configurable :true }); 158ErrorCaptureStackTrace ( error , traceMethod ); 159( true , ErrorGetStack ( error )); 160}, 161}; 162const traceMethod = console . trace ; 163ObjectSetPrototypeOf ( console , ObjectCreate ( ObjectPrototype )); 164ObjectDefineProperty ( console , SymbolToStringTag , { 165value :"console" , 166configurable :true , 167}); 168ObjectDefineProperty ( globalThis , "console" , { 169value :console , 170writable :true , 171configurable :true , 172});