diff --git a/00_Common/javascript/WebTerminal/HtmlTerminal.js b/00_Common/javascript/WebTerminal/HtmlTerminal.js
index 4a095c87..c8d529d9 100644
--- a/00_Common/javascript/WebTerminal/HtmlTerminal.js
+++ b/00_Common/javascript/WebTerminal/HtmlTerminal.js
@@ -96,9 +96,18 @@ class HtmlTerminal {
this.#inputCallback = undefined;
} else if (e.keyCode === 8 /* BACKSPACE */) {
this.#$prompt.innerText = this.#$prompt.innerText.slice(0, -1);
+ } else if (
+ e.keyCode == 16 // "Shift"
+ || e.keyCode == 17 // "Control"
+ || e.keyCode == 20 // "CapsLock"
+ || !e.key.match(/^[a-z0-9!"ยง#$%&'()*+,.\/:;<=>?@\[\] ^_`{|}~-]$/i)
+ ) {
+ // ignore non-visible characters
+ return e;
} else {
this.#$prompt.innerHtml = '';
- this.#$prompt.innerText = this.#$prompt.innerText + e.key;
+ const key = e.shiftKey ? e.key.toUpperCase() : e.key;
+ this.#$prompt.innerText = this.#$prompt.innerText + key;
}
}
@@ -135,27 +144,23 @@ class HtmlTerminal {
* @param {string} text
*/
write(text) {
- if (text.match(/^\n*$/)) {
- // empty new line
- text.match(/\n/g).forEach(() => {
- const $br = document.createElement("br");
- this.$output.appendChild($br);
- });
- } else if (text && text.length && text.includes("\n")) {
+ if (!text || text.length <= 0) {
+ // empty line
+ this.$output.appendChild(document.createElement("br"));
+ } else if (text.endsWith("\n")) {
+ // single line with linebrank
+ const $lineNode = this.#newLine(text);
+ this.$output.appendChild(this.#newLine(text));
+ this.$output.appendChild(document.createElement("br"));
+ } else if (text.includes("\n")) {
+ // multible lines
const lines = text.split("\n");
lines.forEach((line) => {
- if (line.length === 0 || line.match(/^\s*$/)) {
- this.$output.appendChild(document.createElement("br"));
- } else {
- const $lineNode = this.#newLine(line);
- this.$output.appendChild($lineNode);
- //this.$node.appendChild(document.createElement("br"));
- }
+ this.write(line);
});
- } else if (text && text.length) {
- // simple line
- const $lineNode = this.#newLine(text);
- this.$output.appendChild($lineNode);
+ } else {
+ // single line
+ this.$output.appendChild(this.#newLine(text));
}
// scroll to the buttom of the page
diff --git a/00_Common/javascript/WebTerminal/terminal_tests.mjs b/00_Common/javascript/WebTerminal/terminal_tests.mjs
index 804de3f2..d2470c95 100644
--- a/00_Common/javascript/WebTerminal/terminal_tests.mjs
+++ b/00_Common/javascript/WebTerminal/terminal_tests.mjs
@@ -3,21 +3,21 @@
import { print, println, tab, input } from '../common.mjs';
async function main() {
- println(tab(20), "Minimal node.js terminal 2");
- println("");
+ println(tab(30), "Minimal node.js terminal emulator");
+ println();
println(tab(0), "tab 0");
println(tab(5), "tab 5");
println(tab(10), "tab 10");
println(tab(15), "tab 15");
println(tab(20), "tab 20");
println(tab(25), "tab 25");
- println("");
- println("1234567890", " ", "ABCDEFGHIJKLMNOPRSTUVWXYZ");
- println("");
+ println();
+ println("1234567890", " _ ", "ABCDEFGHIJKLMNOPRSTUVWXYZ");
+ println();
print("\nHallo"); print(" "); print("Welt!\n");
println("");
- print("Line 1\nLine 2\nLine 3\nLine 4");
- println("");
+ println("Line 1\nLine 2\nLine 3\nLine 4");
+ println("----------------------------------------------");
const value = await input("input");
println(`input value was "${value}"`);
diff --git a/00_Common/javascript/common.mjs b/00_Common/javascript/common.mjs
index 3fcc4212..765f5cc2 100644
--- a/00_Common/javascript/common.mjs
+++ b/00_Common/javascript/common.mjs
@@ -1,21 +1,67 @@
-
+/**
+ * Print multible strings to the terminal.
+ * Strings get concatinated (add together) without any space betweent them.
+ * There will be no newline at the end!
+ * If you want a linebrak at the end use `println`.
+ *
+ * This function is normally used if you want to put something on the screen
+ * and later add some content to the same line.
+ * For normal output (similar to `console.log`) use `println`!
+ *
+ * @param {...string} messages - the strings to print to the terminal.
+ */
export function print(...messages) {
- process.stdout.write(messages.join(""));
+ process.stdout.write(messages.join(""));
}
+/**
+ * Add multible strings as a new line to the terminal.
+ * Strings get concatinated (add together) without any space betweent them.
+ * There will be a newline at the end!
+ * If you want the terminal to stay active on the current line use `print`.
+ *
+ * @param {...any} messages - the strings to print to the terminal.
+ */
export function println(...messages) {
- process.stdout.write(messages.join("") + "\n");
+ process.stdout.write(messages.join("") + "\n");
}
-export function tab(count) {
- return " ".repeat(count);
+/**
+ * Create an empty string with a given length
+ *
+ * @param {number} length - the length of the string in space-characters.
+ * @returns {string} returns a string containing only ampty spaces with a length of `count`.
+ */
+export function tab(length) {
+ return " ".repeat(length);
}
-export async function input(message = "") {
- process.stdout.write(message + ' ');
- return new Promise(resolve => {
- process.stdin.on('data', (input) => {
- resolve(input.toString().replace('\n', ''));
- });
- });
+/**
+ * Read input from the keyboard and return it as a string.
+ * TODO: to would be very helpfull to only allow a certain class of input (numbers, letters)
+ * TODO: also we could convert all inputs to uppercase (where it makes sence).
+ *
+ * @param {string=''} message - a message or question to print befor the input.
+ * @returns {Promise} - returns the entered text as a string
+ * @async
+ */
+export async function input(message = '') {
+ /* First we need to print the mesage
+ * We append a space by default to seperate the message from the imput.
+ * TODO: If the message already contains a space at the end this is not needed! */
+ process.stdout.write(message + ' ');
+
+ return new Promise(resolve => {
+ process.stdin.on('data', (input) => {
+ /* onData returns a Buffer.
+ * First we need to convert it into a string. */
+ const data = input.toString();
+
+ /* The result fo onData is a string ending with an `\n`.
+ * We just need the actual content so let's remove the newline at the end: */
+ const content = data[data.length] === '\n' ? data.slice(0, -1) : data;
+
+ resolve(content);
+ });
+ });
}
diff --git a/00_Utilities/build-index.js b/00_Utilities/build-index.js
index 20af363e..1ed862ef 100644
--- a/00_Utilities/build-index.js
+++ b/00_Utilities/build-index.js
@@ -103,10 +103,7 @@ function findJSFilesInFolder(folder) {
...htmlFiles,
...mjsFiles
].filter(file => !IGNORE_FILES.includes(file));
- console.log(entries);
-
-
if (entries.length == 0) {
throw new Error(`Game "${folder}" is missing a HTML or node.js file in the folder "${folder}/${JAVASCRIPT_FOLDER}"`);
}
diff --git a/96_Word/javascript/word.js b/96_Word/javascript/word.js
deleted file mode 100644
index 3d7e3a5a..00000000
--- a/96_Word/javascript/word.js
+++ /dev/null
@@ -1,148 +0,0 @@
-// WORD
-//
-// Converted from BASIC to Javascript by Oscar Toledo G. (nanochess)
-//
-
-function print(str)
-{
- document.getElementById("output").appendChild(document.createTextNode(str));
-}
-
-function input()
-{
-
- return new Promise(function (resolve) {
- const input_element = document.createElement("INPUT");
-
- print("? ");
- input_element.setAttribute("type", "text");
- input_element.setAttribute("length", "50");
- document.getElementById("output").appendChild(input_element);
- input_element.focus();
- input_element.addEventListener("keydown", function (event) {
- if (event.keyCode === 13) {
- const input_str = input_element.value;
- document.getElementById("output").removeChild(input_element);
- print(input_str);
- print("\n");
- resolve(input_str);
- }
- });
- });
-}
-
-function tab(space)
-{
- let str = "";
- while (space-- > 0)
- str += " ";
- return str;
-}
-
-// These are the words that the game knows about> If you want a bigger challenge you could add more words to the array
-const WORDS = ["DINKY", "SMOKE", "WATER", "GLASS", "TRAIN",
- "MIGHT", "FIRST", "CANDY", "CHAMP", "WOULD",
- "CLUMP", "DOPEY"];
-const WORD_COUNT = WORDS.length;
-
-// Main control section
-async function main()
-{
- print(tab(33) + "WORD\n");
- print(tab(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n");
- print("\n");
- print("\n");
- print("\n");
- print("I AM THINKING OF A WORD -- YOU GUESS IT. I WILL GIVE YOU\n");
- print("CLUES TO HELP YOU GET IT. GOOD LUCK!!\n");
- print("\n");
- print("\n");
- outer: while (1) {
- print("\n");
- print("\n");
- print("YOU ARE STARTING A NEW GAME...\n");
-
- const secretWord = WORDS[Math.floor(Math.random() * WORD_COUNT)];
-
- let guessCount = 0;
- // This array holds the letters which have been found in the correct position across all guesses
- // For instance if the word is "PLAIN" and the guesses so far are
- // "SHALL" ("A" correct) and "CLIMB" ("L" correct) then it will hold "-LA--"
- const knownLetters = [];
- for (let i = 0; i < 5; i++)
- knownLetters[i] = "-";
-
- let guess = undefined;
- while (1) {
- print("GUESS A FIVE LETTER WORD");
- guess = (await input()).toUpperCase();
- guessCount++;
- if (secretWord === guess) {
- // The player has guessed correctly
- break;
- }
-
- if (guess.charAt(0) === "?") {
- // Player has given up
- print("THE SECRET WORD IS " + secretWord + "\n");
- print("\n");
- // Start a new game by going to the start of the outer while loop
- continue outer;
- }
-
- if (guess.length !== 5) {
- print("YOU MUST GUESS A 5 LETTER WORD. START AGAIN.\n");
- print("\n");
- guessCount--;
- continue;
- }
-
- // Two things happen in this double loop:
- // 1. Letters which are in both the guessed and secret words are put in the lettersInCommon array
- // 2. Letters which are in the correct position in the guessed word are added to the knownLetters array
- let lettersInCommonCount = 0;
- const lettersInCommon = [];
- for (let i = 0; i < 5; i++) {// loop round characters in secret word
- let secretWordCharacter = secretWord.charAt(i);
- for (let j = 0; j < 5; j++) {// loop round characters in guessed word
- let guessedWordCharacter = guess.charAt(j);
- if (secretWordCharacter === guessedWordCharacter) {
- lettersInCommon[lettersInCommonCount] = guessedWordCharacter;
- if (i === j) {
- // Letter is in the exact position so add to the known letters array
- knownLetters[j] = guessedWordCharacter;
- }
- lettersInCommonCount++;
- }
- }
- }
-
- const lettersInCommonText = lettersInCommon.join("");
- print("THERE WERE " + lettersInCommonCount + " MATCHES AND THE COMMON LETTERS WERE... " + lettersInCommonText + "\n");
-
- const knownLettersText = knownLetters.join("");
- print("FROM THE EXACT LETTER MATCHES, YOU KNOW............ " + knownLettersText + "\n");
-
- if (knownLettersText === secretWord) {
- guess = knownLettersText;
- break;
- }
-
- if (lettersInCommonCount <= 1) {
- print("\n");
- print("IF YOU GIVE UP, TYPE '?' FOR YOUR NEXT GUESS.\n");
- print("\n");
- }
- }
-
- print("YOU HAVE GUESSED THE WORD. IT TOOK " + guessCount + " GUESSES!\n");
- print("\n");
-
- print("WANT TO PLAY AGAIN");
- const playAgainResponse = (await input()).toUpperCase();
- if (playAgainResponse !== "YES")
- break;
- }
-}
-
-main();