1111{% include common.html %}
1212
1313< style >
14- .playground-wrap {
14+ .playground-outer {
1515 display : flex;
1616 gap : 0 ;
1717 min-height : 500px ;
18+ }
19+ .examples-sidebar {
20+ width : 220px ;
21+ min-width : 220px ;
22+ border : 1px solid # ddd ;
23+ border-radius : 4px 0 0 4px ;
24+ background : # f9f9f9 ;
25+ overflow-y : auto;
26+ }
27+ .examples-sidebar-header {
28+ background : # f5f5f5 ;
29+ padding : 6px 12px ;
30+ font-size : 0.8rem ;
31+ text-transform : uppercase;
32+ letter-spacing : 0.1em ;
33+ color : # 888 ;
34+ border-bottom : 1px solid # ddd ;
35+ }
36+ .example-item {
37+ display : block;
38+ width : 100% ;
39+ text-align : left;
40+ padding : 8px 12px ;
41+ border : none;
42+ border-bottom : 1px solid # eee ;
43+ background : transparent;
44+ cursor : pointer;
45+ font-size : 0.85rem ;
46+ color : # 555 ;
47+ transition : background 0.15s ;
48+ }
49+ .example-item : hover {
50+ background : # eef ;
51+ }
52+ .example-item .active {
53+ background : # d9534f ;
54+ color : # fff ;
55+ }
56+ .playground-main {
57+ flex : 1 ;
58+ display : flex;
59+ flex-direction : column;
60+ min-width : 0 ;
61+ }
62+ .playground-wrap {
63+ display : flex;
64+ gap : 0 ;
65+ flex : 1 ;
1866 border : 1px solid # ddd ;
19- border-radius : 4px ;
67+ border-left : none;
68+ border-radius : 0 4px 4px 0 ;
2069 overflow : hidden;
2170 }
2271 .playground-panel {
79128 font-size : 0.75rem ;
80129 color : # 999 ;
81130 }
131+ .playground-controls label {
132+ font-size : 0.8rem ;
133+ color : # 666 ;
134+ margin-bottom : 0 ;
135+ cursor : pointer;
136+ }
82137</ style >
83138
84139</ head >
@@ -93,40 +148,30 @@ <h3>Interactive Playground <span id="chai-status" class="loading">Loading&hellip
93148</ div >
94149
95150< div class ="body-with-margin ">
96- < div class ="playground-wrap ">
97- < div class ="playground-panel ">
98- < div class ="playground-panel-header "> Input</ div >
99- < textarea id ="chai-input " spellcheck ="false "> // Welcome to ChaiScript!
100- // Write your code here and click Run (or press Ctrl+Enter).
101-
102- def greet(name) {
103- return "Hello, " + name + "!"
104- }
105-
106- print(greet("World"))
107- print(greet("ChaiScript"))
108-
109- // Math example
110- def factorial(n) {
111- if (n <= 1) { return 1 }
112- return n * factorial(n - 1)
113- }
114-
115- print("5! = " + to_string(factorial(5)))
116- print("10! = " + to_string(factorial(10)))
117- </ textarea >
118- </ div >
119- < div class ="playground-divider "> </ div >
120- < div class ="playground-panel ">
121- < div class ="playground-panel-header "> Output</ div >
122- < div id ="chai-output "> </ div >
151+ < div class ="playground-outer ">
152+ < div class ="examples-sidebar ">
153+ < div class ="examples-sidebar-header "> Examples</ div >
123154 </ div >
124- </ div >
155+ < div class ="playground-main ">
156+ < div class ="playground-wrap ">
157+ < div class ="playground-panel ">
158+ < div class ="playground-panel-header "> Input</ div >
159+ < textarea id ="chai-input " spellcheck ="false "> </ textarea >
160+ </ div >
161+ < div class ="playground-divider "> </ div >
162+ < div class ="playground-panel ">
163+ < div class ="playground-panel-header "> Output</ div >
164+ < div id ="chai-output "> </ div >
165+ </ div >
166+ </ div >
125167
126- < div class ="playground-controls ">
127- < button id ="btn-run " class ="btn btn-danger " disabled > Run</ button >
128- < button id ="btn-clear " class ="btn btn-default "> Clear</ button >
129- < span class ="hint "> Ctrl+Enter to run</ span >
168+ < div class ="playground-controls ">
169+ < button id ="btn-run " class ="btn btn-danger " disabled > Run</ button >
170+ < button id ="btn-clear " class ="btn btn-default "> Clear</ button >
171+ < label > < input type ="checkbox " id ="chk-live " checked > Live execution</ label >
172+ < span class ="hint "> Ctrl+Enter to run</ span >
173+ </ div >
174+ </ div >
130175 </ div >
131176</ div >
132177
@@ -136,6 +181,86 @@ <h3>Interactive Playground <span id="chai-status" class="loading">Loading&hellip
136181 var btnRun = document . getElementById ( 'btn-run' ) ;
137182 var btnClear = document . getElementById ( 'btn-clear' ) ;
138183 var statusEl = document . getElementById ( 'chai-status' ) ;
184+ var chkLive = document . getElementById ( 'chk-live' ) ;
185+ var sidebar = document . querySelector ( '.examples-sidebar' ) ;
186+ var debounceTimer = null ;
187+ var runtimeReady = false ;
188+
189+ var examples = [
190+ {
191+ name : "Hello World" ,
192+ code : '// Hello World\nprint("Hello, ChaiScript!")\n'
193+ } ,
194+ {
195+ name : "Variables & Types" ,
196+ code : '// Variables & Types\nvar x = 42\nvar pi = 3.14159\nvar name = "ChaiScript"\nvar flag = true\n\nprint("x = " + to_string(x))\nprint("pi = " + to_string(pi))\nprint("name = " + name)\nprint("flag = " + to_string(flag))\n\n// Type inspection\nprint("type of x: " + type_name(x))\nprint("type of pi: " + type_name(pi))\nprint("type of name: " + type_name(name))\n'
197+ } ,
198+ {
199+ name : "Functions" ,
200+ code : '// Functions\ndef greet(name) {\n return "Hello, " + name + "!"\n}\n\ndef factorial(n) {\n if (n <= 1) { return 1 }\n return n * factorial(n - 1)\n}\n\ndef fibonacci(n) {\n if (n <= 1) { return n }\n return fibonacci(n - 1) + fibonacci(n - 2)\n}\n\nprint(greet("World"))\nprint("5! = " + to_string(factorial(5)))\nprint("fib(10) = " + to_string(fibonacci(10)))\n'
201+ } ,
202+ {
203+ name : "Conditionals" ,
204+ code : '// Conditionals\ndef classify(n) {\n if (n > 0) {\n return "positive"\n } else if (n < 0) {\n return "negative"\n } else {\n return "zero"\n }\n}\n\nprint(classify(5))\nprint(classify(-3))\nprint(classify(0))\n\n// Ternary-style with inline if\nvar x = 10\nvar label = if (x > 5) { "big" } else { "small" }\nprint(to_string(x) + " is " + label)\n'
205+ } ,
206+ {
207+ name : "Loops" ,
208+ code : '// For loop\nfor (var i = 0; i < 5; ++i) {\n print("i = " + to_string(i))\n}\n\n// While loop\nvar n = 1\nwhile (n <= 32) {\n print("2^" + to_string(n) + " region")\n n = n * 2\n}\n\n// Range-based for\nvar items = [10, 20, 30, 40, 50]\nfor (item : items) {\n print("item: " + to_string(item))\n}\n'
209+ } ,
210+ {
211+ name : "Strings" ,
212+ code : '// String operations\nvar s = "Hello, ChaiScript!"\nprint("Original: " + s)\nprint("Size: " + to_string(s.size()))\nprint("Find \'Chai\': " + to_string(s.find("Chai")))\n\n// String concatenation\nvar first = "Chai"\nvar second = "Script"\nprint(first + second)\n\n// Converting to string\nprint("The answer is " + to_string(42))\nprint("Pi is about " + to_string(3.14))\n'
213+ } ,
214+ {
215+ name : "Vectors & Maps" ,
216+ code : '// Vectors\nvar v = [1, 2, 3, 4, 5]\nprint("Vector: " + to_string(v))\nprint("Size: " + to_string(v.size()))\nprint("First: " + to_string(v[0]))\n\nv.push_back(6)\nprint("After push_back: " + to_string(v))\n\n// Maps\nvar m = ["name": "ChaiScript", "version": "7"]\nprint("Name: " + m["name"])\nprint("Version: " + m["version"])\n\nm["author"] = "Jason Turner"\nprint("Author: " + m["author"])\n'
217+ } ,
218+ {
219+ name : "Lambdas" ,
220+ code : '// Lambda functions\nvar square = fun(x) { return x * x }\nvar add = fun(a, b) { return a + b }\n\nprint("square(5) = " + to_string(square(5)))\nprint("add(3, 4) = " + to_string(add(3, 4)))\n\n// Higher-order functions\ndef apply(f, x) {\n return f(x)\n}\n\nprint("apply(square, 7) = " + to_string(apply(square, 7)))\n\n// Lambda with capture\nvar offset = 10\nvar add_offset = fun(x) { return x + offset }\nprint("add_offset(5) = " + to_string(add_offset(5)))\n'
221+ } ,
222+ {
223+ name : "Classes" ,
224+ code : '// Classes and objects\nclass Point {\n var x\n var y\n def Point(x, y) {\n this.x = x\n this.y = y\n }\n def to_string() {\n return "(" + to_string(this.x) + ", " + to_string(this.y) + ")"\n }\n}\n\nvar p1 = Point(3, 4)\nvar p2 = Point(1, 2)\nprint("p1 = " + p1.to_string())\nprint("p2 = " + p2.to_string())\nprint("p1.x = " + to_string(p1.x))\n'
225+ } ,
226+ {
227+ name : "Guards" ,
228+ code : '// Method guards\ndef describe(x) : x > 0 {\n print(to_string(x) + " is positive")\n}\n\ndef describe(x) : x < 0 {\n print(to_string(x) + " is negative")\n}\n\ndef describe(x) : x == 0 {\n print(to_string(x) + " is zero")\n}\n\ndescribe(5)\ndescribe(-3)\ndescribe(0)\n'
229+ } ,
230+ {
231+ name : "Error Handling" ,
232+ code : '// Error handling with try/catch\ntry {\n var x = 10 / 0\n print("This may or may not print")\n} catch (e) {\n print("Caught: " + to_string(e))\n}\n\n// Throwing exceptions\ndef safe_sqrt(x) {\n if (x < 0) {\n throw("Cannot take sqrt of negative number")\n }\n // Simple Newton\'s method approximation\n var guess = x / 2.0\n for (var i = 0; i < 20; ++i) {\n guess = (guess + x / guess) / 2.0\n }\n return guess\n}\n\nprint("sqrt(25) = " + to_string(safe_sqrt(25.0)))\n\ntry {\n safe_sqrt(-1.0)\n} catch (e) {\n print("Caught: " + to_string(e))\n}\n'
233+ } ,
234+ {
235+ name : "Scope & Variables" ,
236+ code : '// Variable scoping\nvar x = "global"\n\ndef show_scope() {\n var x = "local"\n print("Inside function: " + x)\n}\n\nshow_scope()\nprint("Outside function: " + x)\n\n// Global assignment\ndef modify_global() {\n // Use := for global reassignment\n x = "modified"\n}\n\nmodify_global()\nprint("After modify: " + x)\n'
237+ }
238+ ] ;
239+
240+ function buildSidebar ( ) {
241+ for ( var i = 0 ; i < examples . length ; ++ i ) {
242+ var btn = document . createElement ( 'button' ) ;
243+ btn . className = 'example-item' ;
244+ btn . innerHTML = examples [ i ] . name ;
245+ btn . setAttribute ( 'data-index' , i ) ;
246+ btn . addEventListener ( 'click' , function ( ) {
247+ selectExample ( parseInt ( this . getAttribute ( 'data-index' ) , 10 ) ) ;
248+ } ) ;
249+ sidebar . appendChild ( btn ) ;
250+ }
251+ }
252+
253+ function selectExample ( index ) {
254+ var items = sidebar . querySelectorAll ( '.example-item' ) ;
255+ for ( var i = 0 ; i < items . length ; ++ i ) {
256+ items [ i ] . className = 'example-item' + ( i === index ? ' active' : '' ) ;
257+ }
258+ inputEl . value = examples [ index ] . code ;
259+ outputEl . innerHTML = '' ;
260+ if ( runtimeReady ) {
261+ runCode ( ) ;
262+ }
263+ }
139264
140265 function appendOutput ( text , className ) {
141266 var line = document . createElement ( 'div' ) ;
@@ -156,27 +281,41 @@ <h3>Interactive Playground <span id="chai-status" class="loading">Loading&hellip
156281 statusEl . textContent = 'Ready' ;
157282 statusEl . className = 'ready' ;
158283 btnRun . disabled = false ;
284+ runtimeReady = true ;
285+ selectExample ( 0 ) ;
159286 }
160287 } ;
161288
162289 function runCode ( ) {
163290 var code = inputEl . value ;
164291 if ( ! code . trim ( ) ) { return ; }
165292
166- appendOutput ( '> Running...' , 'chai-output-line' ) ;
293+ outputEl . innerHTML = '' ;
167294 try {
168295 Module . eval ( code ) ;
169296 } catch ( e ) {
170297 appendOutput ( 'Error: ' + e . message , 'chai-output-error' ) ;
171298 }
172- appendOutput ( '' , 'chai-output-line' ) ;
299+ }
300+
301+ function scheduleLiveRun ( ) {
302+ if ( ! chkLive . checked || ! runtimeReady ) { return ; }
303+ if ( debounceTimer !== null ) {
304+ clearTimeout ( debounceTimer ) ;
305+ }
306+ debounceTimer = setTimeout ( function ( ) {
307+ debounceTimer = null ;
308+ runCode ( ) ;
309+ } , 500 ) ;
173310 }
174311
175312 btnRun . addEventListener ( 'click' , runCode ) ;
176313 btnClear . addEventListener ( 'click' , function ( ) {
177314 outputEl . innerHTML = '' ;
178315 } ) ;
179316
317+ inputEl . addEventListener ( 'input' , scheduleLiveRun ) ;
318+
180319 inputEl . addEventListener ( 'keydown' , function ( e ) {
181320 if ( e . ctrlKey && e . key === 'Enter' ) {
182321 e . preventDefault ( ) ;
@@ -190,6 +329,8 @@ <h3>Interactive Playground <span id="chai-status" class="loading">Loading&hellip
190329 this . selectionStart = this . selectionEnd = start + 2 ;
191330 }
192331 } ) ;
332+
333+ buildSidebar ( ) ;
193334</ script >
194335< script src ="/playground/chaiscript.js "> </ script >
195336
0 commit comments