Skip to content

Commit

Permalink
[Aviraj] Using class based approach
Browse files Browse the repository at this point in the history
  • Loading branch information
avirajkhare00 committed Feb 9, 2025
1 parent f43c2dd commit 9349f8b
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 72 deletions.
20 changes: 20 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
var Module = {
preRun: [],
postRun: [],
print: function(text) {
console.log(text);
if (window.terminal && window.terminal.isInitialized) {
window.terminal.writeToTerminal(text + '\n');
}
},
printErr: function(text) {
console.error(text);
if (window.terminal && window.terminal.isInitialized) {
window.terminal.writeToTerminal('Error: ' + text + '\n');
}
},
canvas: (function() {
var canvas = document.getElementById('terminal');
return canvas;
})()
};
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,25 @@
#terminal {
border: none;
}
#loading {
color: #00ff00;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div id="terminal-container">
<canvas id="terminal" width="800" height="480"></canvas>
<div id="loading">Loading WebAssembly Terminal...</div>
</div>
<!-- Module configuration must be loaded first -->
<script src="config.js"></script>
<!-- Then load the Emscripten generated code -->
<script src="terminal.generated.js"></script>
<!-- Finally load our terminal implementation -->
<script src="terminal.js"></script>
</body>
</html>
203 changes: 131 additions & 72 deletions terminal.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,142 @@
let Module = {
onRuntimeInitialized: function() {
initTerminal();
class Terminal {
constructor() {
this.CHAR_WIDTH = 10;
this.CHAR_HEIGHT = 20;
this.TERM_WIDTH = 80;
this.TERM_HEIGHT = 24;
this.isInitialized = false;
this.canvas = null;
this.ctx = null;

// Bind methods to this instance
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.render = this.render.bind(this);

// Wait for Emscripten to be ready
if (Module.ready) {
this.init();
} else {
Module.onRuntimeInitialized = () => {
console.log('WebAssembly Runtime Initialized');
this.init();
};
}
}
};

const CHAR_WIDTH = 10;
const CHAR_HEIGHT = 20;
const TERM_WIDTH = 80;
const TERM_HEIGHT = 24;

let canvas, ctx;

function initTerminal() {
canvas = document.getElementById('terminal');
ctx = canvas.getContext('2d');

// Set up canvas for terminal rendering
ctx.font = `${CHAR_HEIGHT}px monospace`;
ctx.textBaseline = 'top';
ctx.fillStyle = '#00ff00'; // Classic green terminal text

// Initialize the terminal buffer in WebAssembly
Module._init_terminal();

// Write some initial text
writeToTerminal("WebAssembly Terminal v1.0\n> ");
init() {
// Hide loading message
const loading = document.getElementById('loading');
if (loading) loading.style.display = 'none';

this.canvas = document.getElementById('terminal');
this.ctx = this.canvas.getContext('2d');

// Set up canvas for terminal rendering
this.ctx.font = `${this.CHAR_HEIGHT}px monospace`;
this.ctx.textBaseline = 'top';
this.ctx.fillStyle = '#00ff00'; // Classic green terminal text

// Initialize the terminal buffer in WebAssembly
Module._init_terminal();
this.isInitialized = true;

// Write some initial text
this.writeToTerminal('WebAssembly Terminal v1.0\n');
this.writeToTerminal('Ready...\n> ');

// Set up keyboard input
document.addEventListener('keydown', this.handleKeyDown);
document.addEventListener('keypress', this.handleKeyPress);

// Start the render loop
requestAnimationFrame(this.render);
}

// Set up keyboard input
document.addEventListener('keypress', handleKeyPress);
writeToTerminal(text) {
if (!this.isInitialized) return;

try {
const textPtr = Module.stringToNewUTF8(text);
Module._write_text(textPtr);
Module._free(textPtr);
} catch (e) {
console.error('Error writing to terminal:', e);
}
}

// Start the render loop
requestAnimationFrame(render);
}

function writeToTerminal(text) {
const textPtr = Module.stringToNewUTF8(text);
Module._write_text(textPtr);
Module._free(textPtr);
}

function handleKeyPress(event) {
const char = String.fromCharCode(event.charCode);
writeToTerminal(char);
if (event.key === 'Enter') {
writeToTerminal('\n> ');
handleKeyDown(event) {
// Handle special keys
switch (event.key) {
case 'Backspace':
event.preventDefault();
// TODO: Implement backspace
break;
case 'Tab':
event.preventDefault();
this.writeToTerminal(' '); // 4 spaces
break;
}
}
}

function render() {
// Clear the canvas
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#00ff00';

// Render each line
for (let y = 0; y < TERM_HEIGHT; y++) {
const linePtr = Module._get_line(y);
if (linePtr) {
const line = Module.UTF8ToString(linePtr, TERM_WIDTH);
for (let x = 0; x < TERM_WIDTH; x++) {
ctx.fillText(
line[x],
x * CHAR_WIDTH,
y * CHAR_HEIGHT
);
}
handleKeyPress(event) {
event.preventDefault();
const char = String.fromCharCode(event.charCode);
this.writeToTerminal(char);
if (event.key === 'Enter') {
this.writeToTerminal('\n> ');
}
}

// Draw cursor
const cursorX = Module._get_cursor_x();
const cursorY = Module._get_cursor_y();
ctx.fillStyle = '#00ff00';
ctx.fillRect(
cursorX * CHAR_WIDTH,
cursorY * CHAR_HEIGHT,
CHAR_WIDTH,
2
);
render() {
if (!this.isInitialized) {
requestAnimationFrame(this.render);
return;
}

requestAnimationFrame(render);
try {
// Clear the canvas
this.ctx.fillStyle = '#000000';
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.fillStyle = '#00ff00';

// Render each line
for (let y = 0; y < this.TERM_HEIGHT; y++) {
const linePtr = Module._get_line(y);
if (linePtr) {
const line = Module.UTF8ToString(linePtr, this.TERM_WIDTH);
for (let x = 0; x < this.TERM_WIDTH; x++) {
if (line[x] && line[x] !== ' ') {
this.ctx.fillText(
line[x],
x * this.CHAR_WIDTH,
y * this.CHAR_HEIGHT
);
}
}
}
}

// Draw cursor
const cursorX = Module._get_cursor_x();
const cursorY = Module._get_cursor_y();
this.ctx.fillStyle = '#00ff00';
this.ctx.fillRect(
cursorX * this.CHAR_WIDTH,
cursorY * this.CHAR_HEIGHT,
this.CHAR_WIDTH,
2
);
} catch (e) {
console.error('Render error:', e);
}

requestAnimationFrame(this.render);
}
}

// Initialize terminal when the page loads
document.addEventListener('DOMContentLoaded', () => {
window.terminal = new Terminal();
});

0 comments on commit 9349f8b

Please sign in to comment.