mirror of
				https://github.com/flynx/Course-JavaScript.git
				synced 2025-11-04 05:50:08 +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>
 |