NS-DOS

From Hobby'dev
Jump to: navigation, search

Overview[edit | edit source]

That's a Nodejs command line repl that smells like MS-DOS.

Every "folder" is a global namespace where you can store variables and functions. Subfolders appears as objects. The whole thing is persistent.

Type ".help" for help.

For example:

db> test = { one: "ok", two: "fine" }
{ one: 'ok', two: 'fine' }

db> .cv test

db/test> one
'ok'


Source[edit | edit source]

  1 const repl = require('repl');
  2 const fs = require('fs');
  3 const serialize = require('serialize-javascript');
  4 const vm = require('vm');
  5 const util = require('util');
  6 const fmt = require('fmt');
  7 const prettyjson = require('prettyjson');
  8 const asTable = require('as-table');
  9 
 10 eval("db="+fs.readFileSync('./db.js','utf8'));
 11 
 12 var today = new Date();
 13 var now = today.toLocaleTimeString().replace(/:/g,'-');
 14 today = today.toLocaleDateString();
 15 fs.writeFileSync('./past/db-'+today+'-'+now+'.js',serialize(db));
 16 
 17 
 18 eval('db.today='+serialize(db.planner[today]));
 19 
 20 
 21 global.isArray = function(a) {
 22     return (!!a) && (a.constructor === Array);
 23 };
 24 
 25 /*
 26 global.isObject = function(a) {
 27     return (!!a) && (a.constructor === Object);
 28 };
 29 */
 30 
 31 function isObject(obj) {
 32   return obj === Object(obj);
 33 }
 34 
 35 pretty = function(x,opt) { if (x !== undefined) console.log(prettyjson.render(x,opt)); }
 36 
 37 
 38 db.zero.fmt = fmt;
 39 db.zero.strfy = function(x) { console.log(serialize(x,2)); };
 40 db.zero.pretty = pretty
 41 db.zero.asTable = function(x,conf) { console.log(asTable.configure(conf)(x)); };
 42 db.zero.isArray = isArray;
 43 db.zero.isObject = isObject;
 44 
 45 
 46 global.folderStack = ['db'];
 47 global.folder = global;
 48 
 49 global.evalTimeout = 1000;
 50 
 51 jsonColor = { noColor:true };
 52 
 53 inspectOptions = {
 54 	depth: null,
 55 	colors: true
 56 };
 57 
 58 function setFolder() {
 59 	
 60 	folder = global;
 61 	for (var f=0; f<folderStack.length; f++) folder=folder[folderStack[f]];
 62 }
 63 
 64 function setPrompt() {
 65 
 66 	replServer._initialPrompt = '\n'+folderStack.join('/')+'> ';
 67 	replServer.displayPrompt();
 68 }
 69 
 70 function showPage() {
 71 	
 72 	if (db.auto[folderStack[folderStack.length-1]]) {
 73 		
 74 		Object.defineProperty(folder,'z',{value:db.zero,enumerable:false,configurable:true});
 75 		
 76 		var replContext = vm.createContext(folder);
 77 		var cmd = '('+serialize(db.auto[folderStack[folderStack.length-1]])+')()';
 78 
 79 		try {
 80 			
 81 			result = vm.runInContext(cmd,replContext,{timeout: evalTimeout});
 82 			
 83 		} catch(e) { console.log(util.inspect(e,inspectOptions)); }
 84 	}
 85 }
 86 
 87 function myEval(cmd, context, filename, callback) {
 88 
 89 	setFolder();
 90 	
 91 	var replContext = vm.createContext(folder);
 92 	
 93 	var result;
 94 
 95 	try {
 96 		
 97 		result = vm.runInContext(cmd,replContext,{timeout: evalTimeout});
 98 		
 99 	} catch(e) { console.log(util.inspect(e,inspectOptions)); }
100 	
101 	if (result !== undefined) console.log(util.inspect(result,inspectOptions));
102 	
103 	var sdb = serialize(db);
104 	
105 	fs.writeFileSync('./db.js',sdb);
106 
107 	setFolder();
108 	setPrompt();
109 }
110 
111 
112 function completer(line) {
113 	const completions = '.help .error .exit .quit .q'.split(' ');
114 	const hits = completions.filter((c) => c.startsWith(line));
115 
116 	// show all completions if none found
117 	return [hits.length ? hits : completions, line];
118 }
119 
120 
121 
122 
123 var replServer = repl.start({ prompt: '', eval: myEval, context: db, completer: completer });
124 
125 setFolder();
126 showPage();
127 setPrompt();
128 
129 
130 function changeView(name) {
131 		
132 	setFolder();
133 	delete folder.z;
134 	
135 	if (name==='..') {
136 		
137 		if (folderStack.length>1) folderStack.pop();
138 		
139 	} else if (isObject(folder[name]) && !isArray(folder[name])) {
140 		
141 		folderStack.push(name);
142 		
143 	}
144 
145 	setFolder();
146 	Object.defineProperty(folder,'z',{value:db.zero,enumerable:false,configurable:true});
147 }
148 
149 
150 replServer.defineCommand('cv', {
151 	help: 'Change view',
152 	action(name) {
153 		
154 		name.split('/').map(changeView);
155 		showPage();
156 		setPrompt();
157 	}
158 });
159 
160 
161 replServer.defineCommand('keys', {
162 	help: 'Show keys of current view',
163 	action(name) {
164 		
165 		setFolder();
166 		console.log(pretty(Object.keys(folder)));
167 		setPrompt();
168 	}
169 });
170 
171 
172 replServer.defineCommand('show', {
173 	help: 'Show serialized object',
174 	action(name) {
175 		
176 		setFolder();
177 		
178 		if (typeof folder[name]==='function')
179 			console.log(serialize(folder[name],2));
180 		else
181 			console.log(pretty(folder[name]));
182 		
183 		setPrompt();
184 	}
185 });
186 
187 
188 replServer.defineCommand('del', {
189 	help: 'Delete an object',
190 	action(name) {
191 		
192 		setFolder();
193 		delete folder[name];
194 		setPrompt();
195 	}
196 });
197 
198 
199 replServer.defineCommand('look', {
200 	help: 'Pretty print current view',
201 	action(name) {
202 		
203 		setFolder();
204 		delete folder.z;
205 		pretty(folder);
206 		Object.defineProperty(folder,'z',{value:db.zero,enumerable:false,configurable:true});
207 		setPrompt();
208 	}
209 });