gwbasickernel 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eremey Valetov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ prune tests
2
+ include tests/test_kernel_package.py
@@ -0,0 +1,101 @@
1
+ Metadata-Version: 2.4
2
+ Name: gwbasickernel
3
+ Version: 0.1.0
4
+ Summary: Jupyter kernel for GW-BASIC 2026 with inline graphics
5
+ Author: Eremey Valetov
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/evvaletov/gw-basic-2026
8
+ Project-URL: Documentation, https://evvaletov.github.io/gw-basic-2026/
9
+ Project-URL: Issues, https://github.com/evvaletov/gw-basic-2026/issues
10
+ Classifier: Framework :: Jupyter
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Operating System :: MacOS
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: ipykernel>=6
18
+ Requires-Dist: jupyter_client>=8
19
+ Requires-Dist: pygments>=2
20
+ Dynamic: license-file
21
+
22
+ # GW-BASIC Jupyter kernel
23
+
24
+ Run GW-BASIC programs in JupyterLab or Notebook. Variables and program lines
25
+ persist between cells. The kernel converts the interpreter's Sixel output to
26
+ inline PNG images, so the notebook browser does not need Sixel support.
27
+
28
+ Requires Python 3.10 or later and the native
29
+ [GW-BASIC 2026 interpreter](https://github.com/evvaletov/gw-basic-2026)
30
+ on Linux or macOS. The Python package does not include that interpreter.
31
+ The DOS executables cannot be used as the notebook backend.
32
+
33
+ ## Install the interpreter
34
+
35
+ With Homebrew on Linux or macOS:
36
+
37
+ ```sh
38
+ brew tap evvaletov/gwbasic https://github.com/evvaletov/gw-basic-2026.git
39
+ brew install evvaletov/gwbasic/gwbasic
40
+ ```
41
+
42
+ The Homebrew formula builds from a pinned source revision. It includes the
43
+ interpreter and native compiler, with PulseAudio disabled.
44
+
45
+ Alternatively, build from source with a C11 compiler and CMake:
46
+
47
+ ```sh
48
+ git clone https://github.com/evvaletov/gw-basic-2026.git
49
+ cd gw-basic-2026
50
+ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
51
+ cmake --build build --parallel 2
52
+ export GWBASIC="$PWD/build/gwbasic"
53
+ ```
54
+
55
+ ## Install the kernel
56
+
57
+ Create a Python environment for the kernel and JupyterLab:
58
+
59
+ ```sh
60
+ python3 -m venv .venv
61
+ . .venv/bin/activate
62
+ python -m pip install gwbasickernel jupyterlab
63
+ gwbasickernel-install --sys-prefix
64
+ jupyter lab
65
+ ```
66
+
67
+ Choose **GW-BASIC 2026** when creating a notebook. The kernel looks for the
68
+ interpreter in `GWBASIC`, then on `PATH`. To save its location in the kernelspec,
69
+ use this command instead of the installer command above:
70
+
71
+ ```sh
72
+ gwbasickernel-install --sys-prefix --gwbasic /absolute/path/to/gwbasic
73
+ ```
74
+
75
+ If Jupyter runs in another Python environment, use `--user` to register the
76
+ kernel for your account. Keep the kernel's Python environment in place:
77
+ the kernelspec records its Python executable.
78
+
79
+ ## Try it
80
+
81
+ ```basic
82
+ 10 FOR N=1 TO 8
83
+ 20 PRINT N;N*N
84
+ 30 NEXT N
85
+ RUN
86
+ ```
87
+
88
+ For graphics, clear the previous program first:
89
+
90
+ ```basic
91
+ NEW
92
+ 10 SCREEN 1
93
+ 20 CIRCLE (160,100),80,2
94
+ RUN
95
+ ```
96
+
97
+ See the [executed graphics notebook](https://github.com/evvaletov/gw-basic-2026/blob/main/examples/graphics.ipynb)
98
+ and [demo guide](https://github.com/evvaletov/gw-basic-2026/blob/main/docs/demos.md).
99
+
100
+ `%new` clears the BASIC program; `%reset` starts a fresh interpreter process.
101
+ `%timeout 60` changes the output wait timeout from its default of 30 seconds.
@@ -0,0 +1,247 @@
1
+ # GW-BASIC 2026
2
+
3
+ A portable C reimplementation of Microsoft GW-BASIC, using the
4
+ [original 8088 assembly source](https://github.com/microsoft/GW-BASIC)
5
+ (released by Microsoft in 2020) as the authoritative reference.
6
+
7
+ The interpreter implements the language in C11 and aims to reproduce the
8
+ original behavior. Hardware access uses emulation or device stubs; see the
9
+ [language reference](docs/language-reference.md) for their limits.
10
+
11
+ ## Demos
12
+
13
+ ### FreeDOS editor
14
+
15
+ The 16-bit interpreter, installed with FreeDOS's FDINST package installer, listing and running [squares.bas](examples/squares.bas) in QEMU:
16
+
17
+ ![GW-BASIC full-screen editor in FreeDOS, showing the squares program and its output](docs/images/freedos-editor.png)
18
+
19
+ ### Native compilation
20
+
21
+ The same listing compiles through C to a native executable. These commands run from the repository root after building:
22
+
23
+ ```text
24
+ cp examples/squares.bas build/squares.bas
25
+ build/gwbasic-compile build/squares.bas -c --keep-c --runtime .
26
+ build/squares
27
+ ```
28
+
29
+ The executable prints the same table of squares as the interpreter. `build/squares.c` contains the generated C.
30
+
31
+ ### Notebook graphics
32
+
33
+ [graphics.ipynb](examples/graphics.ipynb) runs [circles.bas](examples/circles.bas) through the Jupyter kernel. The kernel converts the interpreter's Sixel output to inline PNG images. This preview shows the final frame from the executed notebook's HTML export:
34
+
35
+ ![Executed BASIC notebook with a SCREEN 1 program and its concentric circles](docs/images/notebook-graphics.png)
36
+
37
+ See [Reproducing the demos](docs/demos.md) for installation, commands, capture details and limitations.
38
+
39
+ ## Building
40
+
41
+ ```bash
42
+ mkdir -p build
43
+ (cd build && cmake ..)
44
+ cmake --build build
45
+ ```
46
+
47
+ The POSIX build requires a C11 compiler, CMake 3.12+, and `pkg-config`.
48
+ PulseAudio (`libpulse-simple`) is optional and detected at build time for
49
+ `SOUND`/`BEEP`/`PLAY` audio output.
50
+
51
+ Builds three targets:
52
+
53
+ - `gwbasic` -- the interpreter
54
+ - `gwbasic-compile` -- the ahead-of-time compiler
55
+ - `libgwrt.a` -- runtime library for compiled programs
56
+
57
+ ## Usage
58
+
59
+ Run these commands from the repository root. Interactive mode launches a
60
+ GW-BASIC-style full-screen editor:
61
+
62
+ ```
63
+ $ build/gwbasic
64
+ GW-BASIC 2026 0.18.2
65
+ (C) Eremey Valetov 2026. MIT License.
66
+ Based on Microsoft GW-BASIC assembly source.
67
+ Ok
68
+ PRINT 2+2
69
+ 4
70
+ Ok
71
+ ```
72
+
73
+ Run a program file (ASCII or binary tokenized):
74
+
75
+ <!-- docs-test: readme-run -->
76
+ ```bash
77
+ build/gwbasic tests/programs/prime_sieve.bas
78
+ ```
79
+
80
+ Compile to a native executable:
81
+
82
+ <!-- docs-test: readme-compile -->
83
+ ```bash
84
+ build/gwbasic-compile tests/programs/fibonacci.bas -c --runtime .
85
+ ```
86
+
87
+ ## Ahead-of-Time Compiler
88
+
89
+ `gwbasic-compile` translates ASCII BASIC programs to C source. With `-c`,
90
+ it invokes GCC to produce native executables linked against `libgwrt.a`.
91
+ GCC is required for this path even if the interpreter was built with Clang.
92
+
93
+ Pipeline: `.bas` → tokenizer → analysis → C codegen → `gcc` → native binary.
94
+
95
+ The compiler test harness compares eligible programs with the expected-output
96
+ files. It skips interactive, timing-dependent, and audio tests, plus helper
97
+ programs loaded by other tests. Passing that suite does not establish full
98
+ GW-BASIC compatibility; compiled timer and key event handlers are unsupported.
99
+
100
+ Save this example as `myprog.bas`:
101
+
102
+ <!-- docs-test: readme-program -->
103
+ ```basic
104
+ 10 PRINT "HELLO FROM BASIC"
105
+ 20 END
106
+ ```
107
+
108
+ <!-- docs-test: readme-compiler -->
109
+ ```bash
110
+ # Generate C source
111
+ build/gwbasic-compile myprog.bas -o myprog.c
112
+
113
+ # Compile to executable (automatic)
114
+ build/gwbasic-compile myprog.bas -c --runtime .
115
+ ```
116
+
117
+ ## VS Code extension
118
+
119
+ The [VS Code extension](editors/vscode/README.md) adds highlighting, snippets,
120
+ F5 Run, and native compilation in the integrated terminal. Install its VSIX
121
+ from the `vscode-extension-stable` CI artifact, then configure the interpreter and
122
+ compiler paths. The extension and runtime are packaged separately.
123
+
124
+ ## Homebrew
125
+
126
+ Install the interpreter and native compiler on Linux or macOS:
127
+
128
+ ```sh
129
+ brew tap evvaletov/gwbasic https://github.com/evvaletov/gw-basic-2026.git
130
+ brew install evvaletov/gwbasic/gwbasic
131
+ ```
132
+
133
+ The formula builds from a pinned source revision with PulseAudio disabled.
134
+ `gwbasic-compile program.bas -c` uses the installed runtime automatically.
135
+ Native compilation requires `gcc` on `PATH` (Apple's `gcc` command invokes
136
+ Clang on macOS).
137
+
138
+ ## Jupyter Kernel
139
+
140
+ A Jupyter notebook kernel for GW-BASIC with inline Sixel graphics
141
+ rendering, INPUT support, and Pygments syntax highlighting. Requires Python
142
+ 3.10 or later and the native interpreter on Linux or macOS.
143
+
144
+ ```bash
145
+ python3 -m venv .venv
146
+ . .venv/bin/activate
147
+ python -m pip install gwbasickernel jupyterlab
148
+ gwbasickernel-install --sys-prefix
149
+ jupyter lab # select "GW-BASIC 2026" kernel
150
+ ```
151
+
152
+ See the [kernel installation guide](gwbasickernel/README.md) for interpreter
153
+ setup and kernels installed in a different Python environment. To develop the
154
+ kernel from this checkout, use `python -m pip install -e .`.
155
+
156
+ ## What Works
157
+
158
+ The interpreter covers the language features below. Device-specific operations
159
+ include emulated ports, fixed return values, and unsupported machine-code calls.
160
+
161
+ Data types: INTEGER (%), SINGLE (!), DOUBLE (#), STRING ($)
162
+
163
+ Operators: `+ - * / ^ \ MOD AND OR XOR EQV IMP NOT < = > <= >= <>`
164
+
165
+ Statements:
166
+
167
+ | Category | Statements |
168
+ |----------|------------|
169
+ | Output | PRINT, LPRINT, LLIST, PRINT USING, WRITE, CLS |
170
+ | Variables | LET, DIM, ERASE, SWAP, DEFINT/SNG/DBL/STR |
171
+ | Control flow | GOTO, GOSUB/RETURN, FOR/NEXT, IF/THEN/ELSE, WHILE/WEND, ON...GOTO/GOSUB |
172
+ | Input | INPUT, LINE INPUT, DATA/READ/RESTORE, INKEY$ |
173
+ | Program | RUN, CONT, STOP, END, NEW, LIST, CLEAR, AUTO, RENUM, DELETE, EDIT |
174
+ | Sequential I/O | OPEN, CLOSE, PRINT#, WRITE#, INPUT#, LINE INPUT# |
175
+ | Random-access I/O | FIELD, LSET, RSET, PUT, GET, CVI/CVS/CVD, MKI$/MKS$/MKD$ |
176
+ | Program I/O | SAVE (binary/ASCII), LOAD (auto-detects), MERGE, CHAIN, COMMON |
177
+ | Event trapping | ON TIMER(n) GOSUB, TIMER ON/OFF/STOP, ON KEY(n) GOSUB |
178
+ | Error handling | ON ERROR GOTO, RESUME, ERROR, ERR, ERL |
179
+ | User functions | DEF FN, RANDOMIZE |
180
+ | File management | KILL, NAME, FILES, MKDIR, RMDIR, CHDIR, SHELL, ENVIRON |
181
+ | Date/time | DATE$, TIME$, TIMER |
182
+ | Screen | LOCATE, COLOR, WIDTH, SCREEN, KEY ON/OFF/LIST |
183
+ | Graphics | PSET, PRESET, LINE, CIRCLE, DRAW, PAINT, GET/PUT (sprites), VIEW, WINDOW, PALETTE, PMAP |
184
+ | Sound | SOUND, BEEP, PLAY (MML) |
185
+ | Memory | DEF SEG, PEEK, POKE, BSAVE, BLOAD |
186
+ | Hardware I/O | OUT, INP, WAIT, MOTOR, STICK, STRIG |
187
+
188
+ ## Tests
189
+
190
+ Run the regression suites from the repository root:
191
+
192
+ ```bash
193
+ python3 tests/test_harnesses.py # harness failure and timeout checks
194
+ bash tests/run_tests.sh # interpreter
195
+ bash tests/run_compiler_tests.sh # compiled programs
196
+ bash tests/run_corpus.sh --report corpus-matrix.json # curated compatibility cases
197
+ python3 -m gwbasickernel.test_kernel # Jupyter kernel
198
+ ```
199
+
200
+ For an interpreter run without audio playback:
201
+
202
+ ```bash
203
+ PULSE_SERVER=unix:/tmp/gwbasic-no-audio-server bash tests/run_tests.sh
204
+ ```
205
+
206
+ This points PulseAudio at an unavailable socket, as the interpreter CI step does.
207
+ Audio fixtures have a 30-second limit so they can also finish with a live server.
208
+ Output mismatches, execution failures, and timeouts fail the suites. See
209
+ [Development](docs/development.md) for timeout settings and test coverage.
210
+
211
+ The [compatibility corpus](tests/corpus/README.md) contains 98 original BASIC
212
+ Computer Games listings. Its automated runtime suite checks 53 fixed-input cases
213
+ from twenty-six listings against Microsoft GW-BASIC transcripts and compares six
214
+ compiler modes with the interpreter. The other listings have build-audit
215
+ coverage only. Awari and Checkers compile; Super Star Trek is rejected for an
216
+ unspaced `TO` expression that Microsoft GW-BASIC also rejects.
217
+
218
+ ## DOS / FreeDOS
219
+
220
+ Cross-compiles to DOS with OpenWatcom V2:
221
+
222
+ ```bash
223
+ wmake -f Makefile.dos16 # 16-bit real mode, no extender
224
+ wmake -f Makefile.dos # 32-bit DOS/4GW, requires DOS4GW.EXE
225
+ ```
226
+
227
+ The 16-bit build runs on FreeDOS, MS-DOS, and compatible systems without
228
+ a DOS extender. See [Getting Started](docs/getting-started.md) for details.
229
+
230
+ ## Release archives
231
+
232
+ The v0.18.2 [release notes](RELEASE_NOTES.md) describe the Linux and DOS archives,
233
+ checksums, and validation limits. CI builds archives after its checks pass;
234
+ publication is a separate step.
235
+
236
+ ## Documentation
237
+
238
+ Full Sphinx documentation in `docs/`:
239
+
240
+ ```bash
241
+ cd docs && pip install -r requirements.txt && make html
242
+ ```
243
+
244
+ ## License
245
+
246
+ The implementation uses the [MIT License](LICENSE). The vendored BASIC Computer
247
+ Games listings in `tests/corpus/` use the upstream [Unlicense](tests/corpus/LICENSE).
@@ -0,0 +1,80 @@
1
+ # GW-BASIC Jupyter kernel
2
+
3
+ Run GW-BASIC programs in JupyterLab or Notebook. Variables and program lines
4
+ persist between cells. The kernel converts the interpreter's Sixel output to
5
+ inline PNG images, so the notebook browser does not need Sixel support.
6
+
7
+ Requires Python 3.10 or later and the native
8
+ [GW-BASIC 2026 interpreter](https://github.com/evvaletov/gw-basic-2026)
9
+ on Linux or macOS. The Python package does not include that interpreter.
10
+ The DOS executables cannot be used as the notebook backend.
11
+
12
+ ## Install the interpreter
13
+
14
+ With Homebrew on Linux or macOS:
15
+
16
+ ```sh
17
+ brew tap evvaletov/gwbasic https://github.com/evvaletov/gw-basic-2026.git
18
+ brew install evvaletov/gwbasic/gwbasic
19
+ ```
20
+
21
+ The Homebrew formula builds from a pinned source revision. It includes the
22
+ interpreter and native compiler, with PulseAudio disabled.
23
+
24
+ Alternatively, build from source with a C11 compiler and CMake:
25
+
26
+ ```sh
27
+ git clone https://github.com/evvaletov/gw-basic-2026.git
28
+ cd gw-basic-2026
29
+ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
30
+ cmake --build build --parallel 2
31
+ export GWBASIC="$PWD/build/gwbasic"
32
+ ```
33
+
34
+ ## Install the kernel
35
+
36
+ Create a Python environment for the kernel and JupyterLab:
37
+
38
+ ```sh
39
+ python3 -m venv .venv
40
+ . .venv/bin/activate
41
+ python -m pip install gwbasickernel jupyterlab
42
+ gwbasickernel-install --sys-prefix
43
+ jupyter lab
44
+ ```
45
+
46
+ Choose **GW-BASIC 2026** when creating a notebook. The kernel looks for the
47
+ interpreter in `GWBASIC`, then on `PATH`. To save its location in the kernelspec,
48
+ use this command instead of the installer command above:
49
+
50
+ ```sh
51
+ gwbasickernel-install --sys-prefix --gwbasic /absolute/path/to/gwbasic
52
+ ```
53
+
54
+ If Jupyter runs in another Python environment, use `--user` to register the
55
+ kernel for your account. Keep the kernel's Python environment in place:
56
+ the kernelspec records its Python executable.
57
+
58
+ ## Try it
59
+
60
+ ```basic
61
+ 10 FOR N=1 TO 8
62
+ 20 PRINT N;N*N
63
+ 30 NEXT N
64
+ RUN
65
+ ```
66
+
67
+ For graphics, clear the previous program first:
68
+
69
+ ```basic
70
+ NEW
71
+ 10 SCREEN 1
72
+ 20 CIRCLE (160,100),80,2
73
+ RUN
74
+ ```
75
+
76
+ See the [executed graphics notebook](https://github.com/evvaletov/gw-basic-2026/blob/main/examples/graphics.ipynb)
77
+ and [demo guide](https://github.com/evvaletov/gw-basic-2026/blob/main/docs/demos.md).
78
+
79
+ `%new` clears the BASIC program; `%reset` starts a fresh interpreter process.
80
+ `%timeout 60` changes the output wait timeout from its default of 30 seconds.
@@ -0,0 +1,3 @@
1
+ """Jupyter kernel for GW-BASIC 2026."""
2
+
3
+ __version__ = '0.1.0'
@@ -0,0 +1,4 @@
1
+ from ipykernel.kernelapp import IPKernelApp
2
+ from .kernel import GWBasicKernel
3
+
4
+ IPKernelApp.launch_instance(kernel_class=GWBasicKernel)
@@ -0,0 +1,79 @@
1
+ """Pygments lexer for GW-BASIC."""
2
+
3
+ from pygments.lexer import RegexLexer
4
+ from pygments.token import (
5
+ Comment, Keyword, Name, Number, Operator, Punctuation, String, Text,
6
+ )
7
+
8
+
9
+ class GWBasicLexer(RegexLexer):
10
+ name = 'GW-BASIC'
11
+ aliases = ['gwbasic', 'basic']
12
+ filenames = ['*.bas', '*.BAS']
13
+ mimetypes = ['text/x-basic']
14
+
15
+ tokens = {
16
+ 'root': [
17
+ # REM comments (to end of line)
18
+ (r"(?i)\bREM\b.*$", Comment.Single),
19
+ # Single-quote comments
20
+ (r"'.*$", Comment.Single),
21
+
22
+ # String literals
23
+ (r'"[^"]*"', String.Double),
24
+
25
+ # Line numbers at start of line
26
+ (r'^\s*\d+', Name.Label),
27
+
28
+ # Hex and octal literals
29
+ (r'&[Hh][0-9A-Fa-f]+', Number.Hex),
30
+ (r'&[Oo]?[0-7]+', Number.Oct),
31
+
32
+ # Floating point
33
+ (r'\d+\.\d*([eEdD][+-]?\d+)?[!#]?', Number.Float),
34
+ (r'\d+[eEdD][+-]?\d+[!#]?', Number.Float),
35
+
36
+ # Integer
37
+ (r'\d+[%!#]?', Number.Integer),
38
+
39
+ # Statements / keywords
40
+ (r'(?i)\b(AUTO|BEEP|BLOAD|BSAVE|CALL|CALLS|CHAIN|CHDIR|CIRCLE'
41
+ r'|CLEAR|CLOSE|CLS|COLOR|COM|COMMON|CONT|DATA|DEF\s+SEG'
42
+ r'|DEF\s+FN|DEFDBL|DEFINT|DEFSNG|DEFSTR|DELETE|DIM|DRAW'
43
+ r'|EDIT|ELSE|END|ENVIRON|ERASE|ERROR|FIELD|FILES|FOR|GET'
44
+ r'|GOSUB|GOTO|IF|INPUT|KEY|KILL|LCOPY|LET|LINE\s+INPUT'
45
+ r'|LINE|LIST|LLIST|LOAD|LOCATE|LPRINT|LSET|MERGE|MKDIR'
46
+ r'|MOTOR|NAME|NEW|NEXT|ON|OPEN|OPTION\s+BASE|OUT|PAINT'
47
+ r'|PALETTE|PLAY|POKE|PRESET|PRINT|PSET|PUT|RANDOMIZE'
48
+ r'|READ|REM|RENUM|RESET|RESTORE|RESUME|RETURN|RMDIR|RSET'
49
+ r'|RUN|SAVE|SCREEN|SHELL|SOUND|STOP|SWAP|SYSTEM|THEN|TIMER'
50
+ r'|TO|TRON|TROFF|USING|VIEW|WAIT|WEND|WHILE|WIDTH|WINDOW'
51
+ r'|WRITE)\b', Keyword),
52
+
53
+ # Built-in functions
54
+ (r'(?i)\b(ABS|ASC|ATN|CDBL|CHR\$|CINT|COS|CSNG|CSRLIN'
55
+ r'|CVD|CVI|CVS|DATE\$|EOF|ENVIRON\$|ERDEV\$?|ERL|ERR'
56
+ r'|EXP|FIX|FN|FRE|HEX\$|INKEY\$|INP|INPUT\$|INSTR|INT'
57
+ r'|IOCTL\$|LEFT\$|LEN|LOC|LOF|LOG|LPOS|MID\$|MKD\$'
58
+ r'|MKI\$|MKS\$|OCT\$|PEEK|PEN|PMAP|POINT|POS|RIGHT\$'
59
+ r'|RND|SGN|SIN|SPACE\$|SPC|SQR|STICK|STR\$|STRIG'
60
+ r'|STRING\$|TAB|TAN|TIME\$|TIMER|USR|VAL|VARPTR\$?)\b',
61
+ Name.Builtin),
62
+
63
+ # Logical / arithmetic operators as keywords
64
+ (r'(?i)\b(AND|EQV|IMP|MOD|NOT|OR|XOR|STEP)\b', Operator.Word),
65
+
66
+ # Operators
67
+ (r'[+\-*/\\^<>=]', Operator),
68
+ (r'<>|<=|>=', Operator),
69
+
70
+ # Punctuation
71
+ (r'[(),;:#]', Punctuation),
72
+
73
+ # Identifiers (variable names)
74
+ (r'[A-Za-z][A-Za-z0-9]*[%!#$]?', Name),
75
+
76
+ # Whitespace
77
+ (r'\s+', Text),
78
+ ],
79
+ }
@@ -0,0 +1,60 @@
1
+ """Install the GW-BASIC kernel into Jupyter."""
2
+
3
+ import argparse
4
+ import json
5
+ import shutil
6
+ import sys
7
+ import tempfile
8
+ from pathlib import Path
9
+
10
+
11
+ def install_kernel(user=True, prefix=None, gwbasic=None):
12
+ from jupyter_client.kernelspec import KernelSpecManager
13
+
14
+ spec = json.loads((Path(__file__).parent / 'kernel.json').read_text())
15
+ spec['argv'][0] = sys.executable
16
+ if gwbasic is not None:
17
+ binary = shutil.which(str(gwbasic))
18
+ if binary is None:
19
+ raise ValueError(f'GW-BASIC executable not found: {gwbasic}')
20
+ spec['env'] = {'GWBASIC': str(Path(binary).absolute())}
21
+
22
+ with tempfile.TemporaryDirectory() as td:
23
+ dest = Path(td) / 'gwbasic'
24
+ dest.mkdir()
25
+ (dest / 'kernel.json').write_text(json.dumps(spec, indent=2) + '\n')
26
+
27
+ ksm = KernelSpecManager()
28
+ ksm.install_kernel_spec(
29
+ str(dest), kernel_name='gwbasic', user=user, prefix=prefix,
30
+ )
31
+
32
+ print('GW-BASIC kernel installed successfully.')
33
+ print('Run "jupyter kernelspec list" to verify.')
34
+
35
+
36
+ def main():
37
+ parser = argparse.ArgumentParser(description='Install the GW-BASIC Jupyter kernel')
38
+ location = parser.add_mutually_exclusive_group()
39
+ location.add_argument('--user', action='store_true',
40
+ help='Install for the current user (default)')
41
+ location.add_argument('--sys-prefix', action='store_true',
42
+ help='Install into sys.prefix (for virtualenvs)')
43
+ location.add_argument('--prefix', type=str, default=None,
44
+ help='Install into a specific prefix')
45
+ parser.add_argument('--gwbasic', help='Interpreter executable to save in the kernelspec')
46
+ args = parser.parse_args()
47
+
48
+ try:
49
+ if args.sys_prefix:
50
+ install_kernel(user=False, prefix=sys.prefix, gwbasic=args.gwbasic)
51
+ elif args.prefix:
52
+ install_kernel(user=False, prefix=args.prefix, gwbasic=args.gwbasic)
53
+ else:
54
+ install_kernel(gwbasic=args.gwbasic)
55
+ except ValueError as exc:
56
+ parser.error(str(exc))
57
+
58
+
59
+ if __name__ == '__main__':
60
+ main()
@@ -0,0 +1,8 @@
1
+ {
2
+ "argv": ["python", "-m", "gwbasickernel", "-f", "{connection_file}"],
3
+ "display_name": "GW-BASIC 2026",
4
+ "language": "basic",
5
+ "metadata": {
6
+ "debugger": false
7
+ }
8
+ }