Menu
CoddyTech

Reading Input

Part of the Node.js Basics section of Coddy's Node.js journey. Lesson 30 of 33.

Adding notes one command at a time is slow when the list already exists somewhere else.

A program can also read input from stdin: text typed at the keyboard, or sent in from a file. On a laptop, cat numbers.txt | node sum.js sends a file into stdin; the | is called a pipe. for await (const chunk of process.stdin) reads it piece by piece until it ends. Join the pieces, then split them into lines.

// cat numbers.txt | node sum.js
let input = '';
for await (const chunk of process.stdin) {
    input += chunk;
}
const numbers = input.split('\n').filter((line) => line !== '').map(Number);
console.log(numbers.reduce((a, b) => a + b, 0));

Here the terminal's Input box fills stdin. Text usually ends with a newline, so the last line is empty: drop empty lines.

challenge icon

Challenge

Easy

Typing notes one add at a time is slow when you already have a list somewhere. Add an import command that reads many notes at once from the program's input, stdin.

  1. In notes.js, add an import command. Read all of stdin into one string with for await, as the lesson shows.
  2. Split the text into lines. Trim the spaces at the start and end of each line, and skip lines that are empty after trimming.
  3. Add each remaining line as a note with store.add, waiting for each one. Your added listener still prints a Saved note line for every note. That is expected.
  4. Last, print Imported , the number of notes added, and notes.. With this input:
    Buy bread
    Call the bank
    
    Water the plants
    node notes.js import saves the three lines as notes. It prints three Saved note lines, then, last:
    Imported 3 notes.
    With no input at all, it prints only:
    Imported 0 notes.

Try it: click the Input button next to Run. A box opens under the arguments. Type three lines in it, with an empty line between two of them. Type import in the box after $ node notes.js and press Enter. Then empty the Input box and run import again: you see Imported 0 notes..

Try it yourself

// Your notes tool starts here.
import { rmSync } from 'node:fs';
import path from 'node:path';
import { formatNote } from './format.js';
import stats from './legacy/stats.cjs';
import store from './store.js';

const [command, ...words] = process.argv.slice(2);
const text = words.join(' ');

store.on('added', (note, n) => {
    console.log(`Saved note ${n}.`);
});

const noteNumber = (word) => {
    const n = Number(word);
    if (!Number.isInteger(n) || n < 1 || n > store.notes.length) {
        console.error(`No note ${word}`);
        process.exit(1);
    }
    return n;
};

if (command === 'add') {
    await store.add(text);
} else if (command === 'list') {
    const owner = process.env.NOTES_OWNER ?? 'you';
    console.log(`Notes for ${owner}`);
    if (store.notes.length === 0) {
        console.log('No notes yet');
    }
    const lines = store.notes.map((note, i) => formatNote(i + 1, note));
    if (store.settings.sort === 'newest') {
        lines.reverse();
    }
    lines.forEach((line) => console.log(line));
} else if (command === 'where') {
    const file = path.join(process.cwd(), 'notes.json');
    console.log(file);
    console.log(path.basename(file));
} else if (command === 'stats') {
    console.log(`${store.notes.length} notes, ${stats.countWords(store.notes)} words`);
} else if (command === 'done') {
    const removed = await store.remove(noteNumber(words[0]));
    console.log(`Done: ${removed}`);
} else if (command === 'remind') {
    const note = store.notes[noteNumber(words[0]) - 1];
    let count = 3;
    const timer = setInterval(() => {
        if (count > 0) {
            console.log(count);
            count -= 1;
        } else {
            console.log(note);
            clearInterval(timer);
        }
    }, 200);
} else if (command === 'clear') {
    rmSync('notes.json', { force: true });
    console.log('Deleted notes.json');
} else {
    if (command) {
        console.error(`Unknown command: ${command}`);
    }
    console.error('Usage: node notes.js <command> [words]');
    process.exit(1);
}

All lessons in Node.js Basics

Practice on your own: Express playground