Skip to content

Commit 2fbdafe

Browse files
authored
Add JSON schemas and move snippets to JSON (#58)
- Add JSON schema for kernels.json with $schema field for editor completion - Create snippets/ directory with snippets.json and schema - Refactor src/snippets.rs to load from JSON at compile time - All 13 language snippets now editable without Rust knowledge
1 parent a369904 commit 2fbdafe

File tree

5 files changed

+550
-361
lines changed

5 files changed

+550
-361
lines changed

site/src/data/kernels.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "./kernels.schema.json",
23
"kernels": {
34
"python3": {
45
"implementation": "ipykernel",

site/src/data/kernels.schema.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "kernels.schema.json",
4+
"title": "Kernel Metadata",
5+
"description": "Static metadata about Jupyter kernels tested for protocol conformance",
6+
"type": "object",
7+
"properties": {
8+
"$schema": {
9+
"type": "string",
10+
"description": "JSON Schema reference"
11+
},
12+
"kernels": {
13+
"type": "object",
14+
"description": "Map of kernel names to their metadata",
15+
"additionalProperties": {
16+
"type": "object",
17+
"properties": {
18+
"implementation": {
19+
"type": "string",
20+
"description": "Name of the kernel implementation package"
21+
},
22+
"repository": {
23+
"type": "string",
24+
"format": "uri",
25+
"description": "URL to the kernel's source repository"
26+
},
27+
"description": {
28+
"type": "string",
29+
"description": "Short description of the kernel"
30+
},
31+
"documentation": {
32+
"type": "string",
33+
"format": "uri",
34+
"description": "URL to the kernel's documentation"
35+
}
36+
},
37+
"required": ["implementation", "repository"],
38+
"additionalProperties": false
39+
}
40+
}
41+
},
42+
"required": ["kernels"],
43+
"additionalProperties": false
44+
}

snippets/snippets.json

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
{
2+
"$schema": "./snippets.schema.json",
3+
"languages": {
4+
"python": {
5+
"print_hello": "print('hello')",
6+
"print_stderr": "import sys; print('error', file=sys.stderr)",
7+
"simple_expr": "1 + 1",
8+
"simple_expr_result": "2",
9+
"incomplete_code": "def foo(",
10+
"complete_code": "x = 1",
11+
"syntax_error": "def class",
12+
"input_prompt": "input('Enter: ')",
13+
"sleep_code": "import time; time.sleep(2)",
14+
"completion_var": "test_variable_for_completion",
15+
"completion_setup": "test_variable_for_completion = 42",
16+
"completion_prefix": "test_variable_for_",
17+
"display_data_code": "from IPython.display import display, HTML; display(HTML('<b>bold</b>'))",
18+
"update_display_data_code": "from IPython.display import display, HTML, update_display; dh = display(HTML('<b>initial</b>'), display_id=True); update_display(HTML('<b>updated</b>'), display_id=dh.display_id)",
19+
"rich_execute_result_code": "from IPython.display import HTML; HTML('<b>bold</b>')"
20+
},
21+
"r": {
22+
"print_hello": "cat('hello\\n')",
23+
"print_stderr": "cat('error\\n', file=stderr())",
24+
"simple_expr": "1 + 1",
25+
"simple_expr_result": "[1] 2",
26+
"incomplete_code": "function(",
27+
"complete_code": "x <- 1",
28+
"syntax_error": "function function",
29+
"input_prompt": "readline('Enter: ')",
30+
"sleep_code": "Sys.sleep(2)",
31+
"completion_var": "test_variable_for_completion",
32+
"completion_setup": "test_variable_for_completion <- 42",
33+
"completion_prefix": "test_variable_for_",
34+
"display_data_code": "plot(1:10)",
35+
"update_display_data_code": "plot(1:5); Sys.sleep(0.1); plot(6:10)",
36+
"rich_execute_result_code": "data.frame(x = 1:3, y = c('a', 'b', 'c'))"
37+
},
38+
"rust": {
39+
"print_hello": "println!(\"hello\");",
40+
"print_stderr": "eprintln!(\"error\");",
41+
"simple_expr": "1 + 1",
42+
"simple_expr_result": "2",
43+
"incomplete_code": "fn foo(",
44+
"complete_code": "let x = 1;",
45+
"syntax_error": "fn fn",
46+
"input_prompt": "// Rust kernel doesn't support stdin",
47+
"sleep_code": "std::thread::sleep(std::time::Duration::from_secs(2));",
48+
"completion_var": "test_variable_for_completion",
49+
"completion_setup": "let test_variable_for_completion = 42;",
50+
"completion_prefix": "test_variable_for_",
51+
"display_data_code": "// evcxr uses execute_result for rich output, not display_data",
52+
"update_display_data_code": "// evcxr doesn't support update_display_data (no display_id)",
53+
"rich_execute_result_code": "pub struct Html(pub &'static str);\nimpl Html {\n pub fn evcxr_display(&self) {\n println!(\"EVCXR_BEGIN_CONTENT text/html\\n{}\\nEVCXR_END_CONTENT\", self.0);\n }\n}\nHtml(\"<b>bold</b>\")"
54+
},
55+
"julia": {
56+
"print_hello": "println(\"hello\")",
57+
"print_stderr": "println(stderr, \"error\")",
58+
"simple_expr": "1 + 1",
59+
"simple_expr_result": "2",
60+
"incomplete_code": "function foo(",
61+
"complete_code": "x = 1",
62+
"syntax_error": "function function",
63+
"input_prompt": "readline()",
64+
"sleep_code": "sleep(2)",
65+
"completion_var": "test_variable_for_completion",
66+
"completion_setup": "test_variable_for_completion = 42",
67+
"completion_prefix": "test_variable_for_",
68+
"display_data_code": "display(\"text/html\", \"<b>bold</b>\")",
69+
"update_display_data_code": "# Julia update_display varies by environment",
70+
"rich_execute_result_code": "HTML(\"<b>bold</b>\")"
71+
},
72+
"typescript": {
73+
"print_hello": "console.log('hello')",
74+
"print_stderr": "console.error('error')",
75+
"simple_expr": "1 + 1",
76+
"simple_expr_result": "2",
77+
"incomplete_code": "const x = {",
78+
"complete_code": "const x = 1",
79+
"syntax_error": "function function",
80+
"input_prompt": "prompt('Enter: ')",
81+
"sleep_code": "await new Promise(r => setTimeout(r, 2000))",
82+
"completion_var": "testVariableForCompletion",
83+
"completion_setup": "const testVariableForCompletion = 42",
84+
"completion_prefix": "testVariableFor",
85+
"display_data_code": "await Deno.jupyter.broadcast(\"display_data\", { data: { \"text/html\": \"<b>bold</b>\" }, metadata: {}, transient: {} })",
86+
"update_display_data_code": "await Deno.jupyter.broadcast(\"display_data\", { data: { \"text/html\": \"<b>initial</b>\" }, metadata: {}, transient: { display_id: \"test_update\" } }); await Deno.jupyter.broadcast(\"update_display_data\", { data: { \"text/html\": \"<b>updated</b>\" }, metadata: {}, transient: { display_id: \"test_update\" } })",
87+
"rich_execute_result_code": "[{letter: \"A\", frequency: 0.08167}, {letter: \"B\", frequency: 0.01492}]"
88+
},
89+
"go": {
90+
"print_hello": "fmt.Println(\"hello\")",
91+
"print_stderr": "fmt.Fprintln(os.Stderr, \"error\")",
92+
"simple_expr": "1 + 1",
93+
"simple_expr_result": "2",
94+
"incomplete_code": "func foo(",
95+
"complete_code": "x := 1",
96+
"syntax_error": "func func",
97+
"input_prompt": "import \"github.com/janpfeifer/gonb/gonbui\"\ngonbui.RequestInput(\"Enter: \", false)",
98+
"sleep_code": "time.Sleep(2 * time.Second)",
99+
"completion_var": "testVariableForCompletion",
100+
"completion_setup": "testVariableForCompletion := 42",
101+
"completion_prefix": "testVariableFor",
102+
"display_data_code": "import \"github.com/janpfeifer/gonb/gonbui\"\ngonbui.DisplayHtml(\"<b>bold</b>\")",
103+
"update_display_data_code": "import \"github.com/janpfeifer/gonb/gonbui\"\nid := gonbui.UniqueId()\ngonbui.UpdateHtml(id, \"<b>initial</b>\")\ngonbui.UpdateHtml(id, \"<b>updated</b>\")",
104+
"rich_execute_result_code": "// Go uses display_data for rich output"
105+
},
106+
"scala": {
107+
"print_hello": "println(\"hello\")",
108+
"print_stderr": "System.err.println(\"error\")",
109+
"simple_expr": "1 + 1",
110+
"simple_expr_result": "2",
111+
"incomplete_code": "def foo(",
112+
"complete_code": "val x = 1",
113+
"syntax_error": "def def",
114+
"input_prompt": "scala.io.StdIn.readLine()",
115+
"sleep_code": "Thread.sleep(2000)",
116+
"completion_var": "testVariableForCompletion",
117+
"completion_setup": "val testVariableForCompletion = 42",
118+
"completion_prefix": "testVariableFor",
119+
"display_data_code": "kernel.publish.html(\"<b>bold</b>\")",
120+
"update_display_data_code": "val id = java.util.UUID.randomUUID().toString; kernel.publish.html(\"<b>initial</b>\", id); kernel.publish.updateHtml(\"<b>updated</b>\", id)",
121+
"rich_execute_result_code": "Html(\"<b>bold</b>\")"
122+
},
123+
"cpp": {
124+
"print_hello": "#include <iostream>\nstd::cout << \"hello\" << std::endl;",
125+
"print_stderr": "#include <iostream>\nstd::cerr << \"error\" << std::endl;",
126+
"simple_expr": "1 + 1",
127+
"simple_expr_result": "2",
128+
"incomplete_code": "int foo(",
129+
"complete_code": "int x = 1;",
130+
"syntax_error": "int int;",
131+
"input_prompt": "// C++ kernel stdin varies",
132+
"sleep_code": "#include <thread>\n#include <chrono>\nstd::this_thread::sleep_for(std::chrono::seconds(2));",
133+
"completion_var": "test_variable_for_completion",
134+
"completion_setup": "int test_variable_for_completion = 42;",
135+
"completion_prefix": "test_variable_for_",
136+
"display_data_code": "#include <string>\n#include \"xcpp/xdisplay.hpp\"\n\nstruct html_content {\n std::string content;\n};\n\n#include \"nlohmann/json.hpp\"\nnlohmann::json mime_bundle_repr(const html_content& h) {\n auto bundle = nlohmann::json::object();\n bundle[\"text/html\"] = h.content;\n return bundle;\n}\n\nhtml_content h{\"<b>bold</b>\"};\nxcpp::display(h);",
137+
"update_display_data_code": "// xeus-cling update_display_data requires display_id handling",
138+
"rich_execute_result_code": "// C++ uses display_data for rich output"
139+
},
140+
"sql": {
141+
"print_hello": "SELECT 'hello' AS message;",
142+
"print_stderr": "-- SQL doesn't have stderr; errors come from invalid queries",
143+
"simple_expr": "SELECT 1 + 1 AS result;",
144+
"simple_expr_result": "2",
145+
"incomplete_code": "SELECT * FROM",
146+
"complete_code": "SELECT 1;",
147+
"syntax_error": "SELEC * FORM table;",
148+
"input_prompt": "-- SQL kernel doesn't support stdin",
149+
"sleep_code": "-- SQL sleep varies by database backend",
150+
"completion_var": "test_table",
151+
"completion_setup": "CREATE TABLE IF NOT EXISTS test_table (id INTEGER);",
152+
"completion_prefix": "test_",
153+
"display_data_code": "SELECT 1 AS col1, 2 AS col2, 3 AS col3;",
154+
"update_display_data_code": "-- SQL doesn't support update_display_data",
155+
"rich_execute_result_code": "SELECT 1 AS col1, 2 AS col2, 3 AS col3;"
156+
},
157+
"lua": {
158+
"print_hello": "print('hello')",
159+
"print_stderr": "io.stderr:write('error\\n')",
160+
"simple_expr": "return 1 + 1",
161+
"simple_expr_result": "2",
162+
"incomplete_code": "function foo(",
163+
"complete_code": "x = 1",
164+
"syntax_error": "function function",
165+
"input_prompt": "io.read()",
166+
"sleep_code": "-- Lua sleep requires os.execute or socket",
167+
"completion_var": "test_variable_for_completion",
168+
"completion_setup": "test_variable_for_completion = 42",
169+
"completion_prefix": "test_variable_for_",
170+
"display_data_code": "ilua.display.html('<b>bold</b>')",
171+
"update_display_data_code": "-- Lua doesn't support update_display_data",
172+
"rich_execute_result_code": "// Lua uses display_data for rich output"
173+
},
174+
"haskell": {
175+
"print_hello": "putStrLn \"hello\"",
176+
"print_stderr": "import System.IO; hPutStrLn stderr \"error\"",
177+
"simple_expr": "1 + 1",
178+
"simple_expr_result": "2",
179+
"incomplete_code": "let x =",
180+
"complete_code": "let x = 1",
181+
"syntax_error": "let let",
182+
"input_prompt": "-- Haskell stdin varies by kernel",
183+
"sleep_code": "import Control.Concurrent; threadDelay 2000000",
184+
"completion_var": "testVariableForCompletion",
185+
"completion_setup": "let testVariableForCompletion = 42",
186+
"completion_prefix": "testVariableFor",
187+
"display_data_code": "putStrLn \"no rich display\"",
188+
"update_display_data_code": "-- Haskell doesn't support update_display_data",
189+
"rich_execute_result_code": "// Haskell doesn't support rich execute_result"
190+
},
191+
"octave": {
192+
"print_hello": "disp('hello')",
193+
"print_stderr": "fprintf(2, 'error\\n')",
194+
"simple_expr": "1 + 1",
195+
"simple_expr_result": "ans = 2",
196+
"incomplete_code": "if true",
197+
"complete_code": "x = 1;",
198+
"syntax_error": "1 +",
199+
"input_prompt": "% Octave stdin doesn't support Jupyter input protocol",
200+
"sleep_code": "pause(2)",
201+
"completion_var": "test_variable_for_completion",
202+
"completion_setup": "test_variable_for_completion = 42;",
203+
"completion_prefix": "test_variable_for_",
204+
"display_data_code": "% Octave plot() requires display - skip in headless CI",
205+
"update_display_data_code": "% Octave update_display varies by environment",
206+
"rich_execute_result_code": "// Octave uses display_data for rich output"
207+
},
208+
"ocaml": {
209+
"print_hello": "print_endline \"hello\"",
210+
"print_stderr": "prerr_endline \"error\"",
211+
"simple_expr": "1 + 1",
212+
"simple_expr_result": "2",
213+
"incomplete_code": "let foo (",
214+
"complete_code": "let x = 1",
215+
"syntax_error": "let let",
216+
"input_prompt": "read_line ()",
217+
"sleep_code": "Unix.sleep 2",
218+
"completion_var": "test_variable_for_completion",
219+
"completion_setup": "let test_variable_for_completion = 42",
220+
"completion_prefix": "test_variable_for_",
221+
"display_data_code": "#require \"jupyter.notebook\";; Jupyter_notebook.display \"text/html\" \"<b>bold</b>\"",
222+
"update_display_data_code": "(* OCaml jupyter doesn't support update_display_data *)",
223+
"rich_execute_result_code": "(* OCaml uses display_data for rich output *)"
224+
},
225+
"generic": {
226+
"print_hello": "print('hello')",
227+
"print_stderr": "print('error')",
228+
"simple_expr": "1 + 1",
229+
"simple_expr_result": "2",
230+
"incomplete_code": "(",
231+
"complete_code": "1",
232+
"syntax_error": "!@#$%",
233+
"input_prompt": "input()",
234+
"sleep_code": "// sleep not available",
235+
"completion_var": "x",
236+
"completion_setup": "x = 1",
237+
"completion_prefix": "x",
238+
"display_data_code": "1",
239+
"update_display_data_code": "// update_display not available",
240+
"rich_execute_result_code": "// rich execute_result not available"
241+
}
242+
}
243+
}

0 commit comments

Comments
 (0)