// space.js, a full (not sparse data storage object) with some utilities. // This includes from/to fetch, write, files, and ad-hoc strings. [DONE] [DONE] [DONE] [DONE] [DONE] // It provides combination between Spaces. [DONE] // It also gives a search utility and a utility to grab an arbitrary section [DONE] [DONE] const fs = require('fs') const vec = require('./utils/vec'); function chop(string, n){ // chops a string into n-sized chunks. Assumed to be perfect multiple let arr = []; for (let sec = 0; sec < string.length; sec++){ arr.push(string.slice(sec*n,(sec+1)*n)); } return arr; } function replace(text, old, repl){ //replaces, in an array `text`, the instances of `old` with `repl` for (let i=0; i parseInt(linenum)) // list of included lines in the content let cont = chop(tile.content,16); let read = 0; //line of cont to read for (let line=0; line<8; line++){ let curline = line+8*tilerow; if (conform && incl.includes(line)){ for (let i=0; i<16; i++) this.data[curline].push(' '); } else { this.data[curline].push(...cont[read]); read++; } } } return this; } this.towrite = function(){ // Does no splitting or anything like that. Just returns a list of triplets for the write function if (this.loc[0] === undefined) throw "Space.towrite() requires valid loc"; let writes = []; for (let line = 0; line < this.data.length; line++) for (let chr = 0; chr < this.data[line].length; chr++){ if (this.data[line][chr] == '') continue; // Internal coding for "do not write" writes.push([[this.loc[0]+line, this.loc[1]+chr],this.data[line][chr]]); } return writes; } this.tofile = function(filename){ fs.writeFileSync(filename, this.print()); }; this.print = function(){ return this.data.map(row => replace(replace(replace(row.slice(),'&','\\&'),'\\','\\\\'),'','&').join('')).join('\n'); } this.fromfile = function(filename){ //Reads an external file into internal data this.adhoc(fs.readFileSync(filename,'utf8')); return this; } this.adhoc = function(text){ text = text.split('\n') text = text.map(row => row.split('')); this.data = text.map(row => { for (let i = 0; i 0) this.loc = vec.elem(this.loc, other.loc, (a,b) => Math.min(a,b)); } // offset is position of other relative to this, so these are mainly definitional. // Convert negative offsets of either sort into zero offsets with significant previous whitespace (translation) for (let i = 0; i < -offset[0]; i++) this.data.unshift([]); if (offset[0] < 0) offset[0] = 0; for (let row = 0; row < this.data.length; row++){ // offset[1] < 0 fix for (let i = 0; i < -offset[1]; i++) this.data[row].unshift(''); } if (offset[1] < 0) offset[1] = 0; // Parse over all relevant tiles and process them into usable chars (this.data is all relevant tiles due to padding) while (this.data.length < offset[0]+other.data.length) this.data.push([]); // Row padding for (let row = 0; row < this.data.length; row++){ let otherrow = other.data[row-offset[0]] || []; while (this.data[row].length < offset[1]+otherrow.length) this.data[row].push(''); // Character-wise padding for (let chr = 0; chr < this.data[row].length; chr++){ this.data[row][chr] = func(this.data[row][chr], otherrow[chr-offset[1]] || ''); } } return this; } this.search = function(other){ //Returns first instance of `other` subspace (prioritized vertically then horizontally) // Non-standard exclusion of this.loc let loc = []; for (let line=0; line<=this.data.length-other.data.length; line++){ for (let chr=0; chr<=this.data[line].length-other.data[0].length; chr++){ var match = true; for (let y=0; y { if (((data.length - ind) < lines.length)) return; let match; while ( (match = lines[0].exec(ln)) !== null){ let xdisp = match.index; let lnmatch = true; for (let i=1; lines[i] !== undefined; i+= 1){ let imatch = lines[i].exec(data[ind+i].slice(xdisp)); if (!imatch || imatch.index !== 0){ lnmatch = false; break; } } if (lnmatch){ loc.push([ind, xdisp]); } } }); return loc; } this.subsection = function(range){ // range is a coordinate pair if (range.length !== 2 || range[0].length !== 2) throw "not subsecting a coord pair"; // Similarly excludes this.loc newspace = new Space(); for (let line=range[0][0]; line row.slice()); // Deep copy newspace.loc = this.loc.slice(); return newspace; } } module.exports = Space