diff --git a/js/com/nav.js b/js/com/nav.js new file mode 100644 index 0000000..a5041ce --- /dev/null +++ b/js/com/nav.js @@ -0,0 +1,265 @@ +/** + ** ================================== + ** OOOO OOOO OOOO O O OOOO + ** O O O O O O O O O + ** O O O O O O O O O + ** OOOO OOOO OOOO O OOO OOOO + ** O O O O O O O O O + ** O O O O O O O O O + ** OOOO OOOO OOOO OOOO O O OOOO + ** ================================== + ** BSSLAB, Dr. Stefan Bosse http://www.bsslab.de + ** + ** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED + ** BY THE AUTHOR. + ** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED, + ** MODIFIED, OR OTHERWISE USED IN A CONTEXT + ** OUTSIDE OF THE SOFTWARE SYSTEM. + ** + ** $AUTHORS: Stefan Bosse + ** $INITIAL: (C) 2006-2016 BSSLAB + ** $CREATED: by sbosse on 12/11/15 + ** $REVESIO: 1.1.7 + ** + ** $INFO: + ** + ** AST: Tree-based Navigator + ** + ** $ENDOFINFO + */ +"use strict"; +var Io = Require('com/io'); +var Comp = Require('com/compat'); +var Hashtbl = Comp.hashtbl; +var Array = Comp.array; +var Hashtbl = Comp.hashtbl; +var String = Comp.string; +var Perv = Comp.pervasives; +var Obj = Comp.obj; +var Rnd = Comp.random; +var Filename = Comp.filename; +var Err = Require('com/err'); +var Printf = Comp.printf; +var blessed = Require('term/blessed'); + + +/** A JS Tree-Object Navigator + * + * options:{title:string,info:string,showfun:boolean} + */ + +var navigator = function (data,options) { + var self=this; + this.log=''; + var mem; + this.options=options||{}; + if (this.options.showfun==undefined) this.options.showfun=true; + this.info = function (element) { + if (Obj.isObject(element)) return '{..}'; + else if(Obj.isArray(element)) return '[..]'; + else if (element != undefined) { + var name=element.toString(); + var funpat = /function [0-9A-Z_$]*\(/i; + var isfun=Obj.isFunction(element)||funpat.test(name); + if (isfun) { + return String.sub(name,0,name.indexOf('{')); + } else return element + } else return 'undefined'; + }; + this.maketree = function (element) { + var content,children; + children={}; + if (Obj.isObject(element) || Obj.isArray(element)) { + for (var p in element) { + children[p]={}; + } + content={ + children : children, + data : element + } + } else if (element != undefined) { + var name=element.toString(); + var funpat = /function [0-9A-Z_$]*\(/i; + var isfun=Obj.isFunction(element)||funpat.test(name); + if (isfun) { + element=String.sub(name,0,name.indexOf('{')); + } + if (!isfun || (isfun && self.options.showfun)) { + children[element]={}; + content={children : children}; + } + } else { + children[element]={}; + content={children : children}; + } + return content; + }; + this.screen = blessed.screen({ + smartCSR: false, + terminal: 'xterm-color' + }); + + this.screen.title = this.options.title||'my window title'; + this.screen.cursor.color='red'; + this.tree = blessed.tree({ + top: 3, + left: 'left', + width: '100%', + height: this.screen.height>20?'75%':'60%', + label: this.options.info||'AST', + focus:true, + border: { + type: 'line' + }, + style: { + border: { + fg: 'black' + }, + hover: { + border: { + fg: 'red' + } + }, + focus : { + border: { + fg: 'red' + } + } + } + }); + this.tree.focus(); + // Create sub-trees + this.tree.on('preselect',function(node){ + var content,children; + if (node.name != '/' && !node.extended) { + // Io.out(node.extended); + var data = node.data; + if (data != none && (Obj.isObject(data) || Obj.isArray(data))) { + node.children = {}; + if (Obj.isArray(data) && Array.empty(data) && Hashtbl.empty(data)) { + node.children={'[]' : {}}; + } else for (var p in data) { + var element = data[p]; + content=self.maketree(element); + if (content) node.children[p]=content; + } + } + } + }); + // Update preview + this.tree.on('selected',function(node){ + mem=Io.mem(); + self.stats.setValue('Data: '+Perv.int_of_float(mem.data/1024)+' MB'+ + ' Heap: '+Perv.int_of_float(mem.heap/1024)+ ' MB'); + self.preview.setValue(node.name); + if (node.data) { + for (var p in node.data) { + self.preview.setValue(p+':'+self.info(node.data[p])); + break; + } + } else if (node.children) self.preview.setValue(node.name+':'+Obj.head(node.children)); + self.screen.render(); + }); + this.tree.DATA = { + name:'/', + extended:true, + children: {} + }; + this.lastobj = data; + for (var p in data) { + var element=data[p]; + var content=this.maketree(element); + if (content) this.tree.DATA.children[p]=content; + } + + this.screen.append(this.tree); + this.screen.key(['escape', 'q', 'C-c'], function(ch, key) { + return process.exit(0); + }); + + this.tree.setData(this.tree.DATA); + + + this.preview = blessed.textbox({ + top: this.screen.height>20?'90%':'80%', + left: 'left', + width: '100%', + height: 3, + label: 'Preview', + focus:false, + border: { + type: 'line' + }, + style: { + fg:'blue' + } + }); + this.screen.append(this.preview); + this.preview.setValue(''); + + this.stats = blessed.textbox({ + top: 0, + left: this.screen.width-40, + width: 40, + height: 3, + label: 'Statistics', + focus:false, + border: { + type: 'line' + }, + style: { + fg:'blue' + } + }); + this.screen.append(this.stats); + mem=Io.mem(); + this.stats.setValue('Data: '+Perv.int_of_float(mem.data/1024)+' MB'+ + ' Heap: '+Perv.int_of_float(mem.heap/1024)+ ' MB'); + + this.but1 = blessed.button({ + width: 8, + top: 0, + height: 3, + align: 'center', + content: 'QUIT', + mouse:true, + focus:true, + border: { + type: 'line' + }, + style: { + fg: 'white', + bg: 'blue', + bold:true, + border: { + fg: 'black' + }, + hover: { + border: { + fg: 'red' + } + }, + focus : { + border: { + fg: 'red' + } + } + } + }); + this.but1.on('press', function(data) { + return process.exit(0); + }); + this.screen.append(this.but1); + this.screen.render(); + +} + +var Navigator = function(data,options){ + var obj = new navigator(data,options); + // Object.preventExtensions(obj); + return obj; +}; + +module.exports = { + Navigator:Navigator +}