* word_wrap.js: Word wrapping functionality in it's own module

* Message.getQuoteLines()
This commit is contained in:
Bryan Ashby 2015-09-15 21:55:10 -06:00
parent a320a05c99
commit 4cba6f4c10
4 changed files with 146 additions and 77 deletions

View File

@ -607,8 +607,13 @@ function FullScreenEditorModule(options) {
// ...should not be too bad to do at all // ...should not be too bad to do at all
// ...probably do want quote markers in place here though, e.g. " Nu> Said some things" // ...probably do want quote markers in place here though, e.g. " Nu> Said some things"
// ...this could be handled via message.getQuoteLines(...) => [] // ...this could be handled via message.getQuoteLines(...) => []
//self.viewControllers.quoteBuilder.getView(3).setItems(['Someone said some shit', 'then they said more shit', 'and what not...', 'hurp durp']);
self.viewControllers.quoteBuilder.getView(3).setItems(['Someone said some shit', 'then they said more shit', 'and what not...', 'hurp durp']); var quoteView = self.viewControllers.quoteBuilder.getView(3);
var quoteWidth = quoteView.dimens.width;
console.log(quoteWidth)
var quoteLines = self.replyToMessage.getQuoteLines(quoteWidth);
console.log(quoteLines)
quoteView.setItems(quoteLines);
callback(null); callback(null);
}, },
function setViewFocus(callback) { function setViewFocus(callback) {

View File

@ -2,6 +2,7 @@
'use strict'; 'use strict';
var msgDb = require('./database.js').dbs.message; var msgDb = require('./database.js').dbs.message;
var wordWrapText = require('./word_wrap.js').wordWrapText;
var uuid = require('node-uuid'); var uuid = require('node-uuid');
var async = require('async'); var async = require('async');
@ -242,3 +243,28 @@ Message.prototype.persist = function(cb) {
} }
); );
}; };
Message.prototype.getQuoteLines = function(width) {
var quoteLines = [];
var origLines = this.message
.replace(/\b/g, '')
.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
var wrapOpts = {
width : width,
tabHandling : 'expand',
tabWidth : 4,
};
var wrapped;
var quotePrefix = 'Nu> '; // :TODO: build FTN style quote prefix
for(var i = 0; i < origLines.length; ++i) {
wrapped = wordWrapText(quotePrefix + origLines[i], wrapOpts).wrapped;
Array.prototype.push.apply(quoteLines, wrapped);
}
return quoteLines;
};

View File

@ -6,6 +6,7 @@ var miscUtil = require('./misc_util.js');
var strUtil = require('./string_util.js'); var strUtil = require('./string_util.js');
var ansi = require('./ansi_term.js'); var ansi = require('./ansi_term.js');
var colorCodes = require('./color_codes.js'); var colorCodes = require('./color_codes.js');
var wordWrapText = require('./word_wrap.js').wordWrapText;
var assert = require('assert'); var assert = require('assert');
var _ = require('lodash'); var _ = require('lodash');
@ -492,84 +493,16 @@ function MultiLineEditTextView(options) {
}; };
this.wordWrapSingleLine = function(s, tabHandling, width) { this.wordWrapSingleLine = function(s, tabHandling, width) {
tabHandling = tabHandling || 'expandTabs';
if(!_.isNumber(width)) { if(!_.isNumber(width)) {
width = self.dimens.width; width = self.dimens.width;
} }
// return wordWrapText(
// Notes s, {
// * Sublime Text 3 for example considers spaces after a word width : width,
// part of said word. For example, "word " would be wraped tabHandling : tabHandling || 'expand',
// in it's entirity. tabWidth : self.tabWidth,
//
// * Tabs in Sublime Text 3 are also treated as a word, so, e.g.
// "\t" may resolve to " " and must fit within the space.
//
// * If a word is ultimately too long to fit, break it up until it does.
//
// RegExp below is JavaScript '\s' minus the '\t'
//
var re = new RegExp(
'\t|[ \f\n\r\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006' +
'\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]', 'g');
var m;
var wordStart = 0;
var results = { wrapped : [ '' ] };
var i = 0;
var word;
var wordLen;
function addWord() {
word.match(new RegExp('.{0,' + width + '}', 'g')).forEach(function wrd(w) {
wordLen = self.getStringLength(w);
if(results.wrapped[i].length + w.length > width) {
//if(results.wrapped[i].length + wordLen > width) {
if(0 === i) {
results.firstWrapRange = { start : wordStart, end : wordStart + w.length };
//results.firstWrapRange = { start : wordStart, end : wordStart + wordLen };
}
results.wrapped[++i] = w;
} else {
results.wrapped[i] += w;
}
}); });
}
while((m = re.exec(s)) !== null) {
word = s.substring(wordStart, re.lastIndex - 1);
switch(m[0].charAt(0)) {
case ' ' :
word += m[0];
break;
case '\t' :
//
// Expand tab given position
//
// Nice info here: http://c-for-dummies.com/blog/?p=424
//
if('expandTabs' === tabHandling) {
word += self.expandTab(results.wrapped[i].length + word.length, '\t') + '\t';
} else {
word += m[0];
}
break;
}
addWord();
wordStart = re.lastIndex + m[0].length - 1;
}
//
// Remainder
//
word = s.substring(wordStart);
addWord();
return results;
}; };
// :TODO: rename to insertRawText() // :TODO: rename to insertRawText()
@ -1059,7 +992,7 @@ MultiLineEditTextView.prototype.setFocus = function(focused) {
MultiLineEditTextView.prototype.setText = function(text) { MultiLineEditTextView.prototype.setText = function(text) {
//text = require('fs').readFileSync('/home/nuskooler/Downloads/test_text.txt', { encoding : 'utf-8'}); //text = require('fs').readFileSync('/home/nuskooler/Downloads/test_text.txt', { encoding : 'utf-8'});
//this.textLines = [ ]; this.textLines = [ ];
this.insertRawText(text); this.insertRawText(text);
if(this.isEditMode()) { if(this.isEditMode()) {

105
core/word_wrap.js Normal file
View File

@ -0,0 +1,105 @@
/* jslint node: true */
'use strict';
var assert = require('assert');
var _ = require('lodash');
exports.wordWrapText = wordWrapText;
function wordWrapText(text, options) {
//
// options.*:
// width : word wrap width
// tabHandling : expand (default=expand)
// tabWidth : tab width if tabHandling is 'expand' (default=4)
//
assert(_.isObject(options), 'Missing options!');
assert(_.isNumber(options.width), 'Missing options.width!');
options.tabHandling = options.tabHandling || 'expand';
if(!_.isNumber(options.tabWidth)) {
options.tabWidth = 4;
}
//
// Notes
// * Sublime Text 3 for example considers spaces after a word
// part of said word. For example, "word " would be wraped
// in it's entirity.
//
// * Tabs in Sublime Text 3 are also treated as a word, so, e.g.
// "\t" may resolve to " " and must fit within the space.
//
// * If a word is ultimately too long to fit, break it up until it does.
//
// RegExp below is JavaScript '\s' minus the '\t'
//
var re = new RegExp(
'\t|[ \f\n\r\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006' +
'\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]', 'g');
var m;
var wordStart = 0;
var results = { wrapped : [ '' ] };
var i = 0;
var word;
var wordLen;
function expandTab(col) {
var remainWidth = options.tabWidth - (col % options.tabWidth);
return new Array(remainWidth).join('\t');
}
// :TODO: support wrapping pipe code text (e.g. ignore color codes, expand MCI codes)
function addWord() {
word.match(new RegExp('.{0,' + options.width + '}', 'g')).forEach(function wrd(w) {
//wordLen = self.getStringLength(w);
if(results.wrapped[i].length + w.length > options.width) {
//if(results.wrapped[i].length + wordLen > width) {
if(0 === i) {
results.firstWrapRange = { start : wordStart, end : wordStart + w.length };
//results.firstWrapRange = { start : wordStart, end : wordStart + wordLen };
}
results.wrapped[++i] = w;
} else {
results.wrapped[i] += w;
}
});
}
while((m = re.exec(text)) !== null) {
word = text.substring(wordStart, re.lastIndex - 1);
switch(m[0].charAt(0)) {
case ' ' :
word += m[0];
break;
case '\t' :
//
// Expand tab given position
//
// Nice info here: http://c-for-dummies.com/blog/?p=424
//
if('expand' === options.tabHandling) {
word += expandTab(results.wrapped[i].length + word.length) + '\t';
} else {
word += m[0];
}
break;
}
addWord();
wordStart = re.lastIndex + m[0].length - 1;
}
//
// Remainder
//
word = text.substring(wordStart);
addWord();
return results;
}