Skip to content

Instantly share code, notes, and snippets.

@ryanwitt
Created September 8, 2012 19:51
Show Gist options
  • Save ryanwitt/3679155 to your computer and use it in GitHub Desktop.
Save ryanwitt/3679155 to your computer and use it in GitHub Desktop.
Textphile interative introduction
// requires ace editor + https://github.com/creationix/step
/* INTERACTIVE INTRODUCTION */
var sec = 600;
var typewriter_pauses = [
{match:/[,\-(]/, pause:0.2*sec}
, {match:/[.!?:]/, pause:0.4*sec}
, {match:/[\t]/, pause:0.8*sec}
, {match:/[\n]/, pause:0.4*sec}
, {match:/.*/, pause:0.035*sec}
];
var last_cursor; // used also by get_yesno
var typewriter = function(text, callback) {
var i = 0, callback = callback || function(){};
editor.setReadOnly(true);
if (last_cursor) {
editor.moveCursorTo(last_cursor.row, last_cursor.column);
var e = last_cursor; editor.selection.setRange(new Range(e.row, e.column, e.row, e.column));
}
var typeit = function() {
var letter = text[i++];
editor.insert(letter);
if (i < text.length) {
var matching_timeouts = $.map(typewriter_pauses, function (v,k) {
if (letter.match(v.match)) return v.pause;
});
setTimeout(typeit, matching_timeouts[0]);
} else {
editor.setReadOnly(false);
last_cursor = editor.selection.getCursor();
callback();
}
};
typeit();
};
/* USER ANSWER DETECTION */
var yes_exact = RegExp('^(' + words_for_yes + '|' + yes_in_languages + ')$', 'i');
var yes_soft = RegExp(words_for_yes, 'ig');
var no_exact = RegExp('^(' + words_for_no + '|' + no_in_languages + ')$', 'i');
var no_soft = RegExp(words_for_no, 'ig');
var is_yes = function(text) {
if (text.match(yes_exact)) return true;
if (text.match(no_exact)) return false;
if (text.match(yes_soft)) return true;
if (text.match(no_soft)) return false;
};
var last_answer = '';
var get_yesno = function(callback) {
var callback = callback || function(){};
return function() {
var start = editor.selection.getCursor();
editor.focus();
console.log('start', start);
var check_timeout, check = function () {
var end = editor.selection.getCursor();
var text = last_answer = editor.session.getTextRange(new Range(start.row, start.column, end.row, end.column));
var result = is_yes(text);
console.log('text', text);
console.log('result', result);
if (result === true || result === false) {
$(editor.session).unbind('change', change);
console.log(result);
last_cursor = editor.selection.getCursor();
callback(result);
}
};
var change = function(e){
clearTimeout(check_timeout);
check_timeout = setTimeout(check, 1400);
}
$(editor.session).on('change', change);
}
};
var pause = function(callback, time) {
callback = callback || function() {};
return function() {setTimeout(function(){callback()}, time)};
}
var stop_intro = function() {
pause_change = false;
editor.setReadOnly(true);
};
var intro = function () {
var anchor = editor.selection.getCursor();
pause_change = true;
editor.setReadOnly(true);
Step(function () {
editor.insert(' ');
typewriter(' ', this);
}, function() {
last_cursor.column = 0;
typewriter('Hi! Welcome to Textphile!\n\n', this);
}, function() {
anchor = {row:last_cursor.row,column:last_cursor.column};
typewriter('Do you love text? (type your answer here): ', get_yesno(this));
}, function (result) {
console.log('result', result);
if (result) {
typewriter('\n'.repeat(Math.max(0, 2-(last_answer.match(/\n/g)||[]).length)) + 'Cool! I do too. ', pause(this, sec));
} else {
var rejoin = this;
typewriter('\n\nNo prob, Bob. You might like Asana (by Dustin Moskovitz) or Trello (by Joel Spolsky). Google them.',
function() {
Step(function() {
setTimeout(this, 2*sec);
}, function() {
typewriter('\n\nDo you want to learn more about Textphile? ', get_yesno(this));
}, function(result) {
var newlines = '\n'.repeat(Math.max(0, 2-(last_answer.match(/\n/g)||[]).length));
if (result) typewriter(newlines, rejoin);
else typewriter(newlines + 'Bye!', pause(function () {
window.location = 'http://nyan.cat/original.php';
}, sec));
});
});
}
}, function() {
editor.selection.setRange(new Range(anchor.row, anchor.column, last_cursor.row, last_cursor.column));
pause(this, 1*sec)();
}, function() {
editor.insert('');
var rejoin = this;
typewriter("This is a text file", pause(function() {
typewriter(" with extra powers.", pause(rejoin, 3*sec));
}, 0.5*sec));
}, function() {
anchor = {row:last_cursor.row,column:last_cursor.column};
typewriter(" For example, I'm working with @carolyn, so I can mention her a few times.", pause(this, 1*sec));
}, function() {
update_people();
editor.selection.setRange(new Range(anchor.row, anchor.column, last_cursor.row, last_cursor.column));
pause(this, 1*sec)();
}, function() {
editor.insert('');
typewriter("\n\nProject X:\ncode new design from @carolyn\nemail beta users"+
"\nadjust syntax highlighting\ntuesday release\nget highlighting feedback from @carolyn\nmargarita time!", pause(this, 3*sec));
}, function() {
typewriter("\n\n", this);
}, function() {
last_cursor.column = 0;
anchor = {row:last_cursor.row,column:last_cursor.column};
typewriter("To quickly see lines that mention @carolyn, click her link on the left.", this);
}, function() {
$('#person_carolyn').one('click', pause(this, 2*sec));
}, function() {
typewriter("\nGreat! Leave this view by clicking 'All' or pressing Esc.", this);
}, function() {
$('#all li a').one('click', pause(this, 1*sec));
}, function() {
typewriter(' Good!', pause(this, 2*sec));
}, function() {
update_tags()
editor.selection.setRange(new Range(anchor.row, anchor.column, last_cursor.row, last_cursor.column));
pause(this, 1*sec)();
}, function() {
editor.insert('');
typewriter("Much like @people, you can also use #tags.", pause(this, 1*sec));
}, function() {
typewriter(" Let's make an #email tag.\n", pause(this, 1*sec));
}, function() {
update_tags();
var anchor = editor.find('email beta users'); last_cursor = anchor.start;
pause(this, 1*sec)();
}, function() {
var s = last_cursor; editor.selection.setRange(new Range(s.row, s.column, s.row, s.column));
typewriter("#", pause(this, 1*sec));
}, function() {
var anchor = editor.find('get highlighting feedback from @carolyn'); last_cursor = anchor.end;
pause(this, 1*sec)();
}, function() {
var e = last_cursor; editor.selection.setRange(new Range(e.row, e.column, e.row, e.column));
typewriter(" #email", pause(this, 2*sec));
}, function() {
var anchor = editor.find("Let's make an #email tag."); last_cursor = anchor.end;
var e = last_cursor; editor.selection.setRange(new Range(e.row, e.column, e.row, e.column));
typewriter("\nI try to write emails all at once, rather than being interrupted every few minutes.\nNext time I have my email open, I can click the #email link on the left to help remember what to write. Try it!", this);
}, function() {
$('#tag_email').one('click', pause(this, 1*sec));
}, function() {
typewriter(' Great! Now get out of this view again.', pause(this, 1*sec));
}, function() {
$('#all li a').one('click', pause(this, 1*sec));
}, function() {
update_headings();
editor.selection.setRange(new Range(anchor.row, anchor.column, last_cursor.row, last_cursor.column));
pause(this, 1*sec)();
}, function() {
editor.insert('');
typewriter("Cool. One more thing. Did you notice Project X automatically became a heading?\n", pause(this, 3*sec));
}, function() {
editor.selection.setRange(new Range(anchor.row, anchor.column, last_cursor.row, last_cursor.column));
pause(this, 1*sec)();
}, function() {
editor.insert('');
last_cursor.column = 0;
typewriter("Headings:\nThey help you organize things that belong together.\nGood for:\nOutlining\nProjects\nLists\nBeing cool:\n1. ( •_•)>⌐■-■\n2. (⌐■_■)\n", pause(this, 3*sec));
}, function() {
update_headings();
last_cursor.column = 0;
anchor = {row:last_cursor.row,column:last_cursor.column};
typewriter("\nWhy don't you focus on being cool?", this);
}, function() {
$('#heading_Beingcool').one('click', pause(this, 1*sec));
}, function() {
typewriter(" You got it! So cool.", pause(this, 2*sec));
}, function() {
typewriter(" Alright, enough with the cool. Escape.", pause(this, 1*sec));
}, function() {
$('#all li a').one('click', pause(this, 1*sec));
}, function() {
editor.selection.setRange(new Range(anchor.row, anchor.column, last_cursor.row, last_cursor.column));
pause(this, 1*sec)();
}, function() {
editor.insert('');
typewriter("\nThat's it! Textphile takes care of saving the file, (even when you're offline).\n"+
"It also keeps track of your changes, so you can review them later.", pause(this, 3*sec));
}, function() {
editor.selection.setRange(new Range(anchor.row, anchor.column, last_cursor.row, last_cursor.column));
pause(this, 2*sec)();
}, function() {
editor.insert('');
typewriter('\nTodo:\nlearn about @people\nlearn about #tags\nlearn about headings', pause(this, 1*sec));
}, function() {
update_headings();
var anchor = editor.find('learn about @people'); last_cursor = anchor.start;
typewriter('x ', pause(this, 1*sec));
}, function() {
var anchor = editor.find('learn about #tags'); last_cursor = anchor.start;
typewriter('x ', pause(this, 1*sec));
}, function() {
var anchor = editor.find('learn about headings'); last_cursor = anchor.start;
typewriter('x ', pause(this, 1*sec));
}, function() {
var anchor = editor.find('learn about headings'); last_cursor = anchor.end;
typewriter('\n1. Select all text and hit the "Mail" button, as a record of this tutorial.\n2. Replace this your own text!\n3. Try typing "hint" on a line by itself :)\n', pause(this, 2*sec));
}, function() {
pause_change = false;
last_cursor.column = 0;
typewriter("\nHave fun being productive! It's all yours now.", this);
}, function() {
editor.setReadOnly(false);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment