Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

# Matches multiple files with brace expansion notation
# Set default charset
[*.{js}]
charset = utf-8

# Indentation override for all JS under lib directory
[lib/**.js]
indent_style = tab
indent_size = 2

# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
170 changes: 112 additions & 58 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,35 @@ const loadLesson = filename => {
return lines;
};

const start = file => {
const lines = loadLesson(file);
beginLesson(lines);
const start = (file, list, index) => {
let callback;
if (index === list.length - 1) {
callback = () => {
console.log('Well done!');
process.stdin.pause();
}
} else {
callback = () => {
const nextIndex = parseInt(index) + 1;
const nextFile = list[nextIndex];
start(nextFile, list, nextIndex);
}
}
const lines = loadLesson(file.path);
beginLesson(lines, callback);
};

function beginLesson (lines) {
var fail = clc.bgRed.white.bold.underline;
function beginLesson (lines, callback) {
var fail = clc.bgRed.white;
var pass = clc.green;
var complete = clc.green.underline;
var white = clc;
let dim = clc.magenta;
var green = clc.green;
var titleStyle = clc.underline;
var titleStyle = clc.cyan.underline;

// Extra line so test ends in correct place
lines.push('');

// Log the lesson title
const firstLine = `${lines[0]}`;
Expand All @@ -210,13 +227,13 @@ function beginLesson (lines) {
// Remove the lesson title from the lesson lines
lines.shift();

var cursorLine = 0;
var currentLine;
var cursorColumn = 0;
var lineErrors= 0;
var trace = '';
var totalErrors = 0;
var start = (+ new Date());
let cursorLine = 0;
let currentLine;
let cursorColumn = 0;
let lineErrors= 0;
let trace = '';
let totalErrors = 0;
let start = (+ new Date());

// Load the first line
nextLine();
Expand All @@ -226,34 +243,40 @@ function beginLesson (lines) {
cursorColumn = 0;
trace = '';
currentLine = lines[cursorLine];
console.log(white('\n' + currentLine));
console.log(white('\n' + currentLine.replace(/\s/g, dim('⠐')) + dim('¬')));

process.stdout.write(dim('_'));

if (cursorLine === lines.length-1) {
//if (cursorLine === 1) {
lessonComplete();
}
cursorLine +=1;
}

function lessonComplete () {
var end = (+ new Date());
var time = end - start;
var wordCount = lines.join(' ').split(' ').length - 1;
var msPerWord = time / wordCount;
var wpm = (60 * 1000 / msPerWord).toFixed(2);

var end = (+ new Date());
var time = end - start;
var wordCount = lines.join(' ').split(' ').length - 1;
var msPerWord = time / wordCount;
var wpm = (60 * 1000 / msPerWord).toFixed(2);

console.log();
console.log(complete('Lesson complete!'));
console.log(white('Total errors: ' + totalErrors));
console.log(white('Words Per Minute: ' + wpm));
console.log();
process.stdin.pause();
console.log();
process.stdin.removeListener('keypress', onKeyPress);
callback();
}

// Begin reading keys
keypress(process.stdin);

process.stdin.on('keypress', function (ch, key) {
if (key && key.hasOwnProperty('name')) {
// Begin reading keys
keypress(process.stdin);
function onKeyPress (ch, key) {
const cols = process.stdout.columns;
const atEdge = cursorColumn > 0 && cursorColumn % cols >= cols -1;
//atEdge && console.log('edge');
if (key && key.hasOwnProperty('name')) {

// Quit on Ctrl+C
if (key && key.ctrl && key.name == 'c') {
Expand All @@ -264,34 +287,62 @@ function beginLesson (lines) {

// Ignore keys
// if (key.name === 'return' || key.name === 'tab') {
if ( key.name === 'tab') {
if (key.name === 'tab') {
return;
}

const modCol = cursorColumn % cols;
const byEdge = cursorColumn > 0 && modCol > cols -2;
const edge = cursorColumn > 0 && modCol === 0;
const preEdge = cursorColumn > 0 && modCol < cols;
//edge && console.log('edge');
//adEdge && console.log('atEdge');
//byEdge && console.log('byEdge');
if (key.name === 'backspace') {
if (cursorColumn > 0) {
process.stdout.write(clc.move.left(1));
process.stdout.write(clc.erase.lineRight);
if (byEdge) {
process.stdout.write(clc.move.left(1));
process.stdout.write(clc.erase.lineRight);
process.stdout.write(dim('_'));
} else if (atEdge) {
process.stdout.write(clc.move.left(1));
} else if (preEdge) {
process.stdout.write(clc.move.left(2));
process.stdout.write(clc.erase.lineRight);
process.stdout.write(clc.erase.lineRight);
process.stdout.write(dim('_'));
}
}

cursorColumn -= 1;
if (trace[cursorColumn] === '0') {
if (trace[cursorColumn] === '0') {
lineErrors-=1;
}
trace = trace.substr(0, trace.length-1);
}


return;
}
}

if (ch === currentLine[cursorColumn]) {
if (!returned) {
process.stdout.write(pass(ch));
if (cursorColumn % process.stdout.columns === 0 &&
cursorColumn > 0) {
process.stdout.write('\n');
}
!atEdge && process.stdout.write(clc.move.left(1));
process.stdout.write(clc.erase.lineRight);
process.stdout.write(pass(ch).replace(/\s/, dim('⠐')));
!atEdge && process.stdout.write(dim('_'));
trace += '1';
}
} else {
if (!returned) {
process.stdout.write('\u0007');
process.stdout.write(clc.move.left(1));
process.stdout.write(clc.erase.lineRight);
process.stdout.write(fail(ch));
process.stdout.write(dim('_'));
lineErrors += 1;
totalErrors += 1;
trace += '0';
Expand All @@ -301,19 +352,21 @@ function beginLesson (lines) {
cursorColumn += 1;
}

// console.log(cursorColumn, currentLine.length, returned);
if (cursorColumn >= currentLine.length && !lineErrors && returned) {
nextLine();
}
});

if (typeof process.stdin.setRawMode == 'function') {
process.stdin.setRawMode(true);
} else {
tty.setRawMode(true);
}

process.stdin.resume();
if (cursorColumn >= currentLine.length && !lineErrors && returned) {
process.stdout.write(clc.move.left(1));
process.stdout.write(clc.erase.lineRight);
process.stdout.write(dim('¬'));
nextLine();
}
};
process.stdin.on('keypress', onKeyPress);
if (typeof process.stdin.setRawMode == 'function') {
process.stdin.setRawMode(true);
} else {
tty.setRawMode(true);
}

process.stdin.resume();
}

const generateTOC = () => new Promise((resolve, reject) => {
Expand Down Expand Up @@ -363,10 +416,10 @@ const menu = {
sub: async list => {
const choices = [];

list.forEach(file => {
list.forEach((file, idx) => {
choices.push({
message: file.title,
name: file.path
name: String(idx)
});
});

Expand All @@ -375,10 +428,11 @@ const menu = {
message: 'Choose your beginning',
limit: 5,
choices
});
});

const answer = await prompt.run();
return answer;
const idx = await prompt.run();
const file = list[idx];
return [file, idx];
},

help: () => program.outputHelp(),
Expand All @@ -395,11 +449,11 @@ const startWithMenu = () => generateTOC()
if (Reflect.has(menu, type)) {
return menu[type]();
}

const list = type === 'lessons' ? TOC.lessons : TOC.katas[type];
menu.sub(list).then(file => {
start(file);

menu.sub(list).then(([file, idx]) => {
start(file, list, idx);
})
});

Expand All @@ -409,4 +463,4 @@ const startWithFile = () => {}
program.keyboard && drawKeyboard();
fileToLoad &&
startWithFile(fileToLoad) ||
startWithMenu();
startWithMenu();
2 changes: 1 addition & 1 deletion kata/tao-te-ching/chapter-07
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ Hence, they are long lived.
Thus, although the saint puts himself last, finds himself in the lead.
Although he is not self-concerned, finds himself accomplished.
It is because he is not focused on self-interests and hence can fulfill his true nature.
he Way of a saint is to act naturally without contention.
The Way of a saint is to act naturally without contention.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dvorak-programmers-tutorial",
"version": "2.0.4",
"version": "2.0.5",
"description": "Dvorak Programmer CLI Tutorial",
"bin": {
"dvorak": "index.js"
Expand Down
Loading