mirror of
				https://github.com/flynx/Course-JavaScript.git
				synced 2025-10-30 03:20:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			270 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
| <html>
 | |
| <style>
 | |
| 
 | |
| #bootstrap {
 | |
| 	display: none;
 | |
| }
 | |
| #bootstrap[shown] {
 | |
| 	display: block;
 | |
| }
 | |
| 
 | |
| .command {
 | |
| 	padding-left: 5px;
 | |
| 	padding-right: 5px;
 | |
| }
 | |
| 
 | |
| .command:hover {
 | |
| 	background: #eee;
 | |
| 	cursor: hand;
 | |
| }
 | |
| 
 | |
| .command:empty:after {
 | |
| 	content: "input code here...";
 | |
| 	opacity: 0.5;
 | |
| }
 | |
| .command:focus:before {
 | |
| 	position: absolute;
 | |
| 	content: "ctrl+enter to run";
 | |
| 	opacity: 0.3;
 | |
| 	right: 15px;
 | |
| }
 | |
| .command:focus:after {
 | |
| 	opacity: 0.2;
 | |
| }
 | |
| .command:last-child {
 | |
| 	border: red 2px solid;
 | |
| 	border-radius: 5px;
 | |
| 	box-shadow: 2px 2px 5px 0px silver;
 | |
| }
 | |
| 
 | |
| .error {
 | |
| 	color: red;
 | |
| 	font-style: italic;
 | |
| }
 | |
| .output {
 | |
| 	font-weight: bold;
 | |
| }
 | |
| .error:before,
 | |
| .output:before {
 | |
| 	content: ">";
 | |
| 	color: red;
 | |
| 	font-weight: bold;
 | |
| 	margin: 5px;
 | |
| }
 | |
| .output:before {
 | |
| 	color: blue;
 | |
| }
 | |
| 
 | |
| #words {
 | |
| 	font-family: monospace;
 | |
| }
 | |
| 
 | |
| .word[word-type=constant] {
 | |
| 	font-weight: bold;
 | |
| 	color: red;
 | |
| }
 | |
| .word[word-type=builtin] {
 | |
| 	font-style: italic;
 | |
| 	color: blue;
 | |
| }
 | |
| 
 | |
| #stack {
 | |
| 	opacity: 0.8;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* syntax... */
 | |
| 
 | |
| pre .comment {
 | |
| 	font-style: italic;
 | |
| 	color: gray;
 | |
| }
 | |
| pre :not(.comment) {
 | |
| 	font-weight: bold;
 | |
| }
 | |
| pre :not(.comment) .string {
 | |
| 	font-style: italic;
 | |
| 	color: blue;
 | |
| }
 | |
| pre :not(.comment) .word {
 | |
| 	font-weight: bold;
 | |
| 	color: blue;
 | |
| }
 | |
| 
 | |
| </style>
 | |
| <script src="slang.js"></script>
 | |
| 
 | |
| <script>
 | |
| 
 | |
| function stringifySlangCode(code){
 | |
| 	if(code == null){
 | |
| 		return code
 | |
| 	}
 | |
| 	if(typeof(code) == typeof('str') && /\s/.test(code)){
 | |
| 		return '\''+code+'\''
 | |
| 	} else if(code && code.constructor.name == 'Array'){
 | |
| 		return '[ '+code.map(stringifySlangCode).join(' ')+' ]'
 | |
| 	}
 | |
| 	return code
 | |
| }
 | |
| 
 | |
| function runCommand(){
 | |
| 	var stack = document.getElementById('stack')
 | |
| 	var console = document.getElementById('console')
 | |
| 	var commands = document.getElementsByClassName('command')
 | |
| 	var command = commands[commands.length-1]
 | |
| 	command.removeAttribute('contenteditable')
 | |
| 
 | |
| 	command.addEventListener('click', function(e){
 | |
| 		var commands = document.getElementsByClassName('command')
 | |
| 		var c = commands[commands.length-1]
 | |
| 		c.innerText = command.innerText
 | |
| 		c.focus()
 | |
| 		window.scrollTo(0,document.body.scrollHeight)
 | |
| 	}, false)
 | |
| 	
 | |
| 	try{
 | |
| 		stack.innerText = 'stack: ' + stringifySlangCode(slang(command.innerText))
 | |
| 
 | |
| 	} catch(e) {
 | |
| 		stack.innerText = 'stack: ' + stringifySlangCode(CONTEXT.stack)
 | |
| 		var err = document.createElement('div')
 | |
| 		err.classList.add('error')
 | |
| 		if(e.message != null){
 | |
| 			err.innerText = e.message
 | |
| 		} else {
 | |
| 			err.innerText = e
 | |
| 		}
 | |
| 		console.appendChild(err)
 | |
| 	}
 | |
| 
 | |
| 	// create the next element...
 | |
| 	var next = document.createElement('div')
 | |
| 	next.classList.add('command')
 | |
| 	next.setAttribute('contenteditable', true)
 | |
| 	console.appendChild(next)
 | |
| 	next.focus()
 | |
| 
 | |
| 	window.scrollTo(0,document.body.scrollHeight)
 | |
| }
 | |
| 
 | |
| NAMESPACE.print = function(context){
 | |
| 	var c = document.getElementById('console')
 | |
| 	var o = context.stack[context.stack.length-1]
 | |
| 	console.log('>>>', o)
 | |
| 
 | |
| 	var data = document.createElement('div')
 | |
| 	data.classList.add('output')
 | |
| 	data.innerHTML = stringifySlangCode(o)
 | |
| 	c.appendChild(data)
 | |
| }
 | |
| 
 | |
| // XXX should this break exec?
 | |
| NAMESPACE.err = function(context){
 | |
| 	var c = document.getElementById('console')
 | |
| 	var e = context.stack[context.stack.length-1]
 | |
| 	console.error('>>>', e)
 | |
| 
 | |
| 	var err = document.createElement('div')
 | |
| 	err.classList.add('error')
 | |
| 	if(e.message != null){
 | |
| 		err.innerText = e.message
 | |
| 	} else {
 | |
| 		err.innerText = e
 | |
| 	}
 | |
| 	c.appendChild(err)
 | |
| }
 | |
| 
 | |
| 
 | |
| function toggleBootstrapCode(){
 | |
| 	var bootstrap = document.getElementById('bootstrap')
 | |
| 	if(bootstrap.hasAttribute('shown')){
 | |
| 		bootstrap.removeAttribute('shown')
 | |
| 	} else {
 | |
| 		bootstrap.setAttribute('shown', true)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| function showAvailableWords(){
 | |
| 	document.getElementById('words').innerHTML = Object.keys(NAMESPACE)
 | |
| 		.sort()
 | |
| 		.filter(function(e){
 | |
| 			// skip words starting with '_'...
 | |
| 			if(e[0] == '_'){
 | |
| 				return false
 | |
| 			}
 | |
| 			return true
 | |
| 		})
 | |
| 		.map(function(e){
 | |
| 			var code = NAMESPACE[e]
 | |
| 			var type
 | |
| 			if(code && code.constructor.name == 'Array'){
 | |
| 				type = 'word'
 | |
| 				code = stringifySlangCode(code)
 | |
| 			} else if(typeof(code) == typeof(function(){})){
 | |
| 				type = 'builtin'
 | |
| 			} else {
 | |
| 				type = 'constant'
 | |
| 			}
 | |
| 			return '<span class="word" word-type="'+type+'" title="'+code+'">'+e+'</span>'
 | |
| 		})
 | |
| 		.join(' ')
 | |
| }
 | |
| 
 | |
| 
 | |
| </script>
 | |
| 
 | |
| <body>
 | |
| 	<h1>Slang</h1>
 | |
| 	<a href="#" onclick="toggleBootstrapCode()">Toggle bootstrap code view...</a>
 | |
| 	<div id="bootstrap"></div>
 | |
| 	<h2>Available words</h2>
 | |
| 	<p>
 | |
| 		This section includes constants (red) ond constant-like
 | |
| 		words (words that allways yield the same value), 
 | |
| 		built-in words (blue), and 2'nd gen words (black):
 | |
| 	</p>
 | |
| 	<p id="words"></p>
 | |
| 	<h2>Slang Console</h2>
 | |
| 	<div id="console">
 | |
| 		<div class="command" contenteditable="true"></div>
 | |
| 	</div>
 | |
| 	<div id="stack"></div>
 | |
| </body>
 | |
| <script>
 | |
| var bootstrap = BOOTSTRAP
 | |
| 	// basic HTML compatibility stuff...
 | |
| 	.replace(/&/g, '&')
 | |
| 	.replace(/>/g, '>')
 | |
| 	.replace(/</g, '<')
 | |
| 	// very basic syntax highlighting...
 | |
| 	// comments...
 | |
| 	.replace(/(\(.*)-(.*\))/g, '<span class="comment">$1−$2</span>')
 | |
| 	.replace(/(\([^\)]*\))/g, '<span class="comment">$1</span>')
 | |
| 	.replace(/(\s*--.*\n)/g, '<span class="comment">$1</span>')
 | |
| /*
 | |
| Object.keys(NAMESPACE).forEach(function(k){
 | |
| 	bootstrap = bootstrap.replace(
 | |
| 		RegExp('('+k
 | |
| 			.replace('&', '&')
 | |
| 			.replace('<', '<')
 | |
| 			.replace('>', '>')
 | |
| 			.replace(/([\|\[\]\.\*\/\\\?\+\-])/g, '\\$1')+')', 'g'), 
 | |
| 		'<span class="word">$1</span>')
 | |
| })
 | |
| */
 | |
| document.getElementById('bootstrap').innerHTML='<pre>'+bootstrap+'</pre>'
 | |
| 
 | |
| document.getElementById('console')
 | |
| 	.addEventListener("keyup", function(e) {
 | |
| 		if(e.keyCode == 13 && e.ctrlKey){
 | |
| 			runCommand()
 | |
| 			showAvailableWords()
 | |
| 		}
 | |
| 	}, false);
 | |
| 
 | |
| showAvailableWords()
 | |
| 
 | |
| </script>
 | |
| </html>
 |