window.markdeepOptions={tocStyle:"medium"} Logging


  1.1  LogDebug
  1.2  Debug Logging
  1.3  Enabling Logs
  1.4  Ignored Op-Codes
  1.5  Module Logging
  1.6  More Modules
  1.7  Exec
  1.8  Interp logOpts

Javascript Shell Interpreter

Types Builtin Reference  Index  Fossil  Demos Log Test Debug Misc



The low level output commands are:

Command Description
puts Quotes arguments to stdout
printf Formatted output to stdout
log Like puts but including file/line info
console.puts Like puts but outputs to stderr
console.log Like log but outputs to stderr
assert When expression is false throw error (or output msg)

See System and console for details. All commands except printf automatically add a newline.


Quotes all arguments and outputs them to stdout.

puts("Batman begins"); var X = {a:1, b:"two"}; puts(X); puts(X.a, X.b);
Batman begins { a:1, b:"two" } 1 two


Processes arguments according to format and outputs to stdout.

printf("Batman begins: %d %S\n", X.a, X.b);

log(arg, ...)

Works like puts, but includes the current file, line and function.

log("Batman begins");
"Batman begins", file.jsi:12, func()

assert( expr:boolean|number|function, msg:string, options:object=void)

The assert command is used for constraint checking. When disabled (the default) none of it's arguments get evaluted.

When enabled and the expression evaluates to false, an error is thrown.

When expression is a function, its returned value is used instead.

"use assert"; var m = 1, n = -1; assert(m>0, "too small"); assert(n>=0 && n<100, "passed bad n", true);

In fact there are several wasy to make assert use puts rather than throwing errors:

jsish -T asserts
var m = 0; assert(++m<0, 'bad shit', {mode:'puts'}); puts(m); Interp.conf({assertMode:'puts'}); assert(++m<0, 'not bad'); assert(++m<0);
bad shit 1 not bad assert(++m<0)

It can also be made to output a message rather than throw an error.



The main logging and debugging commands in Jsi are of the form LogXXX.

There output in Jsi include the file and line number, which is useful for debugging applications:

var i = 0; while (i++ < 3) { LogInfo("test loop: %d", i); }
mytest.jsi:3, "INFO: test loop: 1", mytest.jsi:3, "INFO: test loop: 2", mytest.jsi:3, "INFO: test loop: 3",

One place this is useful is when running scripts from geany, as you can navigate through the messages just as you would compiler warnings.

The available Log commands are:

Command Notes
LogDebug Outputs only when logOpts.Debug is true
LogTrace Outputs only when logOpts.Trace is true
LogTest Outputs only when logOpts.Test is true


Debug Logging

The commands LogDebug, LogTrace, and LogTest are special in that unless enabled they produce no output (and in fact their op-codes are ignored).

We use enable LogDebug with “use Debug” as in this example:

"use strict,Debug,Test"; var i = 0; while (i++ < 2) { LogDebug("test loop:", i); LogTrace("test loop:", i); LogTest("test loop:", i); }
mydebug.jsi:4, "DEBUG: test loop: 1", mydebug.jsi:5, "TRACE: test loop: 1", mydebug.jsi:4, "DEBUG: test loop: 2", mydebug.jsi:5, "TRACE: test loop: 2",

In the discussion below, descriptions mentioning LogDebug apply equally to LogTrace, and LogTest.


Enabling Logs

As shown above, one way logging can be enable is by inserting a use directive.

Modules directly accept the -Debug option, etc. But there are several other ways from the command-line:

jsish -T Debug,Trace mydebug2.jsi JSI_INTERP_OPTS='{logOpts:{Debug:true,Trace:true}}' jsish mydebug2.jsi

A “use” directive will always override command-line options:

jsish -T Debug "use !Debug"; LogDebug("can't appear"); Interp.conf({logOpts:{Debug:true}}); LogDebug("can appear");

Ignored Op-Codes

It is important to understand that when disabled, assert and the LogDebug, LogTrace and LogTest functions and their arguments are essentially No-Ops:

var i = 0, cnt = 0; while (i++ < 3) { LogDebug("test loop:", i, ":", cnt++); } printf("cnt=%d\n", cnt);

Which can be confusing when cnt is 0 here:

jsish myincr.jsi

but cnt is 3 here:

jsish -T Debug myincr.jsi
myincr.jsi:3, "DEBUG: test loop: 1 : 0", myincr.jsi:3, "DEBUG: test loop: 2 : 1", myincr.jsi:3, "DEBUG: test loop: 3 : 2", cnt=3

The explanation is that when disabled, argument op-codes are simply being ignored.

While potentially confusing it means that these commands exact no runtime penalty until enabled, and so can be scattered liberally throughout code.


Module Logging

In a larger application it may be undesirable to turn on global logging. Which is where module-local logging comes in.

Here is a minimal module (mycall):

function mycall(args:array=void, conf:object=void) { var options = {}; var self = { cnt:0 }; parseOpts(self,options,conf); LogDebug("MYLOC 1:", args.join(',')); LogTrace("MYLOC 2:", args.join(',')); } LogDebug("MYGLOB 1"); LogTrace("MYGLOB 2"); provide(); if (isMain()) runModule(mycall);

which we run with local logging:

jsish mycall.jsi -Debug true A B C
mycall.jsi:6, "DEBUG: test 1: A,B,C", mycall() jsish -T Debug mycall.jsi -Trace true A B C mycall.jsi:10, "DEBUG: MYGLOB 1" mycall.jsi:6, "DEBUG: MYLOC 1: A,B,C", mycall() mycall.jsi:7, "TRACE: MYLOC 2: A,B,C", mycall()

This demonstrates that logging can be local, global or a mixture of both.

The parseOpts implicitly accepts the boolean options Debug, Trace, Test.


More Modules

Here is a more complete module mytest1 using parseOpts and logging:

#!/usr/bin/env jsish "use strict"; function mytest1(args:array, conf:object=void):object { var options = { // Here is my test. label :'' // Some other argument }; var self = { count: 0 }; parseOpts(self, options, conf); for (var msg of args) { self.count++; LogDebug("testing:", msg); } puts("Done"); return self; } provide('mytest1'); LogDebug("Loading test1"); if (isMain()) runModule(mytest1);

This allows us to turn on module-local debugging from the command line:

jsish mytest1.jsi a b c


jsish mytest1.jsi -Debug true a b c
mytest1.jsi:17, "DEBUG: testing: a", mytest1() mytest1.jsi:17, "DEBUG: testing: b", mytest1() mytest1.jsi:17, "DEBUG: testing: c", mytest1() Done


jsish mytest1.jsi -h
/home/user/mytest1.jsi:121: error: ... OPTIONS FOR 'mytest1.jsi' // Here is my test. -label "" // Some other argument. -Test false // Testing output. -Trace false // Tracing output. ERROR


By making your script executable, you can run it directly from Geany with F9.

Then you can employ jsish as an replacement for /usr/bin/env, with support for arguments:

#!/usr/local/bin/jsish -T Debug %s -Trace true myinput1.txt puts(console.args.join(' '));

See Shell


Interp logOpts

The interp option logOpts is used to control when the above commands are to output the current file, line and function.

It can also arrange for all such messages to be directed to a log file.

If you are debugging a program and need to find where a puts is coming from, try adding to the top


The same can be done from the command-line eg:

JSI_INTERP_OPTS='{tracePuts:true}'   jsish tests/assert.js
"caught error" --> assert.js:16 "K" --> assert.js:24 "caught error2" --> assert.js:28 "this assert failed" --> assert.js:31 "assert also failed" --> assert.js:34 "done" --> assert.js:36

The Jsi_LogFile() command can be used to send logging to a file.

var startOfMarkDeep=true; window.alreadyProcessedMarkdeep||('visible'); document.title=location.pathname.match(/\/([\w]+)1;

formatted by Markdeep 1.03