<commit_before>designApp.controller("designCtrl", function($scope) {
	var self = this;

	self.models = {
        selected: null,
        templates: [
            {
            	type: "feature",
        		typ: "http://purl.obolibrary.org/obo/SO_0000167",
        		id: 1,
        		name: "promoter",
                temp_params: {
                   fixed: true
                }
            },
            {
            	type: "feature",
                typ: "http://purl.obolibrary.org/obo/SO_0000139",
                id: 2,
                name:"ribosome entry site",
                end: 60,
                parameters: {
                   "TIR target": 15000
                },
                temp_params: {
                   fixed: false
                }
            },
            {
            	type: "feature",
            	typ: "http://purl.obolibrary.org/obo/SO_0000316",
                id: 3,
                name: "coding sequence",
                options: [
                   {
                      typ: "http://purl.obolibrary.org/obo/SO_0000316",
                      name: "coding sequence",
                      temp_params: {
                         fixed: false
                      }
                   }
                ]
            },
        	{
        		type: "feature",
        		typ: "http://purl.obolibrary.org/obo/SO_0000141",
        		id: 4,
        		name: "terminator",
                temp_params: {
                   fixed: true
                }
            }
        ],
        designs: [
        	{
        		type: "design",
        		id: 1,
            	name: "Design",
                desc: "Design",
            	features: []
        	}
        ]
    };

	self.modelAsJson = angular.toJson(self.models, true)

	$scope.$watch(function() {
		return self.models;
	},
	function(values) {
		self.modelAsJson = angular.toJson(self.models, true)
	}, true);
});<commit_msg>Added more templates.<commit_after>designApp.controller("designCtrl", function($scope) {
	var self = this;

	self.models = {
			selected: null,
			templates: [
				{
					typ: "http://purl.obolibrary.org/obo/SO_0001416",
					name: "5' flanking region",
					temp_params: {
						fixed: true
					}
				},
				{
					typ: "http://purl.obolibrary.org/obo/SO_0000143",
					name: "assembly component",
					temp_params: {
						fixed: true
					}
				},
				{
					type: "feature",
					typ: "http://purl.obolibrary.org/obo/SO_0000167",
					id: 1,
					name: "promoter",
					temp_params: {
						fixed: true
					}
				},
				{
					type: "feature",
					typ: "http://purl.obolibrary.org/obo/SO_0000139",
					id: 2,
					name:"ribosome entry site",
					end: 60,
					parameters: {
						"TIR target": 15000
					},
					temp_params: {
						fixed: false
					}
				},
				{
					type: "feature",
					typ: "http://purl.obolibrary.org/obo/SO_0000316",
					id: 3,
					name: "coding sequence",
					options: [
						{
							typ: "http://purl.obolibrary.org/obo/SO_0000316",
							name: "coding sequence",
							temp_params: {
								fixed: false
							}
						}
						]
				},
				{
					type: "feature",
					typ: "http://purl.obolibrary.org/obo/SO_0000141",
					id: 4,
					name: "terminator",
					temp_params: {
						fixed: true
					}
				},
				{
					typ: "http://purl.obolibrary.org/obo/SO_0000449",
					end: 100,
					name: "random region",
					temp_params: {
						fixed: false
					}
				},
				{
					typ: "http://purl.obolibrary.org/obo/SO_0001417",
					name: "3' flanking region",
					temp_params: {
						fixed: true
					}
				}
				],
				designs: [
					{
						type: "design",
						id: 1,
						name: "Design",
						desc: "Design",
						features: []
					}
					]
	};

	self.modelAsJson = angular.toJson(self.models, true)

	$scope.$watch(function() {
		return self.models;
	},
	function(values) {
		self.modelAsJson = angular.toJson(self.models, true)
	}, true);
});<|endoftext|>


<commit_before>// @flow

import childProcess from 'child_process';
import glob from 'glob';

import formattedToRegex from './formattedToRegex';

function findMatchingFilesWithFind(
  lookupPath: string,
  validFilesRegex: string
): Array<string> {
  const findCommand = [
    `find ${lookupPath}`,
    '-name "**.js*"',
    '-not -path "./node_modules/*"',
  ].join(' ');
  const command = `${findCommand} | egrep -i \"${validFilesRegex}\"`;

  // TODO switch to spawn so we can start processing the stream as it comes
  // in.
  let out = '';
  let err = '';
  try {
    out = String(childProcess.execSync(command));
  } catch (error) {
    err = String(error.stderr);
  }

  if (err !== '') {
    throw new Error(err);
  }

  // Filter out empty lines before returning
  return out.split('\n').filter((file: string): boolean => !!file);
}

function findMatchingFilesWithNode(
  lookupPath: string,
  validFilesRegex: string
): Array<string> {
  return glob.sync(`${lookupPath}/**/*.js*`, {
    ignore: './node_modules/**/*',
  }).filter((filePath: string): bool =>
    new RegExp(validFilesRegex, 'i').test(filePath));
}

/**
 * Finds files from the local file system matching the variable name.
 */
export default function findMatchingFiles(
  lookupPath: string,
  variableName: string
): Array<string> {
  if (lookupPath === '') {
    // If lookupPath is an empty string, the `find` command will not work
    // as desired so we bail early.
    throw new Error(`lookup path cannot be empty (${lookupPath})`);
  }

  const formattedVarName = formattedToRegex(variableName);
  const validFilesRegex = `(/|^)${formattedVarName}(/index)?(/package)?\\.js.*`;

  if (/^win/.test(process.platform)) {
    return findMatchingFilesWithNode(lookupPath, validFilesRegex);
  }
  return findMatchingFilesWithFind(lookupPath, validFilesRegex);
}
<commit_msg>Speed up findMatchingFilesWithNode by changing ignore pattern<commit_after>// @flow

import childProcess from 'child_process';
import glob from 'glob';

import formattedToRegex from './formattedToRegex';

function findMatchingFilesWithFind(
  lookupPath: string,
  validFilesRegex: string
): Array<string> {
  const findCommand = [
    `find ${lookupPath}`,
    '-name "**.js*"',
    '-not -path "./node_modules/*"',
  ].join(' ');
  const command = `${findCommand} | egrep -i \"${validFilesRegex}\"`;

  // TODO switch to spawn so we can start processing the stream as it comes
  // in.
  let out = '';
  let err = '';
  try {
    out = String(childProcess.execSync(command));
  } catch (error) {
    err = String(error.stderr);
  }

  if (err !== '') {
    throw new Error(err);
  }

  // Filter out empty lines before returning
  return out.split('\n').filter((file: string): boolean => !!file);
}

function findMatchingFilesWithNode(
  lookupPath: string,
  validFilesRegex: string
): Array<string> {
  return glob.sync(`${lookupPath}/**/*.js*`, {
    ignore: './node_modules/**',
  }).filter((filePath: string): bool =>
    new RegExp(validFilesRegex, 'i').test(filePath));
}

/**
 * Finds files from the local file system matching the variable name.
 */
export default function findMatchingFiles(
  lookupPath: string,
  variableName: string
): Array<string> {
  if (lookupPath === '') {
    // If lookupPath is an empty string, the `find` command will not work
    // as desired so we bail early.
    throw new Error(`lookup path cannot be empty (${lookupPath})`);
  }

  const formattedVarName = formattedToRegex(variableName);
  const validFilesRegex = `(/|^)${formattedVarName}(/index)?(/package)?\\.js.*`;

  if (/^win/.test(process.platform)) {
    return findMatchingFilesWithNode(lookupPath, validFilesRegex);
  }
  return findMatchingFilesWithFind(lookupPath, validFilesRegex);
}
<|endoftext|>


<commit_before>import Net from 'net';
import Store from './store';
import { Parser } from './parser';
import ParserError from './parser_error';
import StoreError from './store_error';
import FS from "fs";

const DEFAULT_PORT = 6379;
const DEFAULT_HOST = '127.0.0.1';
const WRITE_COMMANDS = {
  SET: true, // always write to AOF
  APPEND: true, // always write to AOF when returning integer
  TOUCH: true, // write to AOF when return val integer NOT 0 X
  INCR: true, // always write to AOF when returning integer
  DECR: true, // always write to AOF when returning integer
  RENAME: true, // write to AOF when returning OK
  RENAMENX: true, // write to AOF when returns 1 or 0
  DEL: true, // write for any integer greater than 0 X
  LREM: true, // write for any integer greater than 0 X
  LPUSH: true, // write for any integer value
  RPUSH: true, // write for any integer value
  LPOP: true, // write when not nil X
  RPOP: true, // write when not nil X
  LSET: true, // write when returning OK
  HSET: true, // write for 1 or 0
  HMSET: true, // write when returning OK
  HDEL: true, // write for any integer value
  HSETNX: true, // write for 1 or 0
  HINCRBY: true, // write for any float
  ZINTERSTORE: true, // write for any integer value
  ZUNIONSTORE: true, // write for any integer value
  ZADD: true, // write for integer or bulk string reply
  ZREM: true, // write for any integer value
  ZINCRBY: true, // bulk string reply
};
const DEF_OPTIONS = {
  aofWritePath: 'corvoAOF.aof',
  aofPersistence: true
};

class CorvoServer {
  constructor(options=DEF_OPTIONS) {
    this.store = new Store();
    this.storeCommandMap = {
      'GET': this.store.getString,
      'APPEND': this.store.appendString,
      'STRLEN': this.store.getStrLen,
      'TOUCH': this.store.touch,
      'INCR': this.store.strIncr,
      'DECR': this.store.strDecr,
      'EXISTS': this.store.exists,
      'RENAME': this.store.rename,
      'RENAMENX': this.store.renameNX,
      'TYPE': this.store.type,
      'DEL': this.store.del,
      'LINDEX': this.store.lindex,
      'LREM': this.store.lrem,
      'LLEN': this.store.llen,
      'LPUSH': this.store.lpush,
      'RPUSH': this.store.rpush,
      'LPOP': this.store.lpop,
      'RPOP': this.store.rpop,
      'LSET': this.store.lset,
      'HSET': this.store.hset,
      'HVALS': this.store.hvals,
      'HSTRLEN': this.store.hstrlen,
      'HKEYS': this.store.hkeys,
      'HMSET': this.store.hmset,
      'HDEL': this.store.hdel,
      'HGET': this.store.hget,
      'HGETALL': this.store.hGetAll,
      'HLEN': this.store.hlen,
      'HSETNX': this.store.hsetnx,
      'HMGET': this.store.hmget,
      'HINCRBY': this.store.hincrby,
      'ZINTERSTORE': this.store.zinterstore,
      'ZUNIONSTORE': this.store.zunionstore,
      'ZADD': this.store.zadd,
      'ZREM': this.store.zrem,
      'ZCARD': this.store.zcard,
      'ZINCRBY': this.store.zincrby,
      'ZSCORE': this.store.zscore,
    };
    this.aofWritePath = options.aofWritePath;
    this.persist = options.aofPersistence;
    if (this.persist) {
      this.writer = FS.createWriteStream(options.aofWritePath, {'flags': 'a' });
    }
  }

  prepareRespReturn(result, isError=false) {
    // handle error
    if (isError) {
      return "-" + result + "\r\n";
    }

    // handle null
    if (result === null) {
      return "$-1\r\n";
    }

    // handle array
    if (result instanceof Array) {
      let respResult = "*" + result.length + "\r\n";

      result.forEach((elem) => {
        if (elem === null) {
          respResult += "$-1\r\n";
        } else if (typeof elem === 'string') {
          respResult += "$" + elem.length + "\r\n" + elem + "\r\n";
        } else if (typeof elem === 'number') {
          respResult += ":" + elem + "\r\n";
        }
      });

      return respResult;
    }

    // handle string
    if (typeof result === 'string') {
      let respResult;
      if (result.length === 0) {
        respResult = "$0\r\n\r\n";
      } else {
        respResult = "+" + result + "\r\n";
      }

      return respResult;
    }

    // handle number
    if (typeof result === 'number') {
      return ":" + result + "\r\n";;
    }

  }

  startServer(port=DEFAULT_PORT, host=DEFAULT_HOST) {
    const server = Net.createServer();
    server.on('connection', this.handleConnection.bind(this));

    if (this.persist) { this.aofLoadFile(this.aofWritePath); }
    server.listen(port, host, function() {
      console.log('server listening to %j', server.address());
    });
  }

  handleConnection(conn) {
    conn.setEncoding('utf8');
    conn.on('data', function(data) {
      console.log("data =", data);
      try {
        const tokens = Parser.processIncomingString(data);
        const command = tokens[0].toUpperCase();
        let result;

        if (command === 'SET') {
          if (tokens.length > 3) {
            // add code to accommodate expiry later
            const flag = tokens[tokens.length - 1];

            if (flag === 'NX') {
              result = this.store.setStringNX(...tokens.slice(1));
            } else if (flag === 'XX') {
              result = this.store.setStringX(...tokens.slice(1));
            }
          } else {
            result = this.store.setString(...tokens.slice(1));
          }
        } else if (command === 'LINSERT') {
          const flag = tokens[2];

          if (flag === 'BEFORE') {
            result = this.store.linsertBefore(...tokens.slice(1));
          } else if (flag === 'AFTER') {
            result = this.store.linsertAfter(...tokens.slice(1));
          }

        } else if (this.storeCommandMap[command]) {
          console.log("TOKENS", tokens);
          result = this.storeCommandMap[command].apply(this.store, tokens.slice(1));
        } else {
          result = "ServerError: Command not found in storeCommandMap.";
        }

        // write to AOF file if command and return val are correct
        if (WRITE_COMMANDS[command]) {
          if (this.persist) {
            this.aofCheckAndWrite(data, command, result);
          }
        }

        const stringToReturn = this.prepareRespReturn(result);
        conn.write(stringToReturn);
      } catch(err) {
        if (err instanceof ParserError || err instanceof StoreError) {
          const stringToReturn = this.prepareRespReturn(err.message, true);
          conn.write(stringToReturn);
        } else {
          throw err;
        }
      }
    }.bind(this));
  };

  aofCheckAndWrite(data, command, result) {
    if (command === 'TOUCH' && result === 0) {
      return;
    } else if (command === 'DEL' && result === 0) {
      return;
    } else if (command === 'LPOP' && result === null) {
      return;
    } else if (command === 'RPOP' && result === null) {
      return;
    } else if (command === 'LREM' && result === 0) {
      return;
    } else {
      console.log("WRITING TO AOF FILE!");
      this.writer.write(data, 'UTF8');
    }
  }

  aofLoadFile(fileName) {
    // const CHUNK_SIZE = 1024;
    const CHUNK_SIZE = 391;
    const buf = new Buffer(CHUNK_SIZE);

    console.log("Going to open an existing file");
    const self = this;
    this.prependString = "";
    FS.open(fileName, 'r', function(err, fd) {
      if (err) {
        return console.error(err);
      }
      console.log("File opened successfully!");
      console.log("Going to read the file");
      function readNextChunk() {
        FS.read(fd, buf, 0, CHUNK_SIZE, 0, function(err, bytes){
          if (err){
            console.log(err);
          }
          console.log(bytes + " bytes read");

          // Print only read bytes to avoid junk.
          if (bytes === 0){
            // done reading file
            FS.close(fd, function(err) {
              if (err) {
                throw err;
              }
              return - 1;
            });
          }

          console.log(buf.slice(0, bytes).toString());
          let dataToProcess;

          const dataReceived = buf.slice(0, bytes).toString();
          if (bytes < CHUNK_SIZE) {
            dataToProcess = self.prependString + dataReceived;
          } else {
console.log("here in else");
            const bytesToChop = self.getTrailingCommandBytes(dataReceived);
console.log("bytesToChop = ", bytesToChop);
console.log("prependString = ", self.prependString);
console.log("chopped dataReceived = ", dataReceived.slice(0, -bytesToChop));
            dataToProcess = self.prependString + dataReceived.slice(0, -bytesToChop);
            self.prependString = dataReceived.slice(-bytesToChop);
          }
          let inputDataTokens = dataToProcess.split('\r\n').slice(0, -1);
          console.log("inputDataTokens.length=", inputDataTokens.length);
          console.log("inputDataTokens[0]=", inputDataTokens[0], ":");
          console.log("inputDataTokens[1]=", inputDataTokens[1], ":");
          while (inputDataTokens.length) {
            let countToken = inputDataTokens.shift();
            let count = parseInt(countToken.slice(1), 10);
            // extract one command
            let tokens = self.extractOneCommand(count, inputDataTokens);

            // apply that command
            self.aofCallStoreCommands(tokens);
          }
        });
        console.log("after FS.read");
      }
      readNextChunk();
      console.log("after call to readNextChunk");
    });
  }

  getTrailingCommandBytes(dataReceived) {
    let count = 0;
    let idx = dataReceived.length - 1;

    while (idx >= 0) {
      count += 1;
      if (dataReceived[idx] === '*') {
        return count;
      }
      idx -= 1;
    }
  }

  extractOneCommand(count, inputDataTokens) {
    const tokens = [];
    for (let i = 0; i < count; i += 1) {
      inputDataTokens.shift();
      tokens.push(inputDataTokens.shift());
    }

    return tokens;
  }

  aofCallStoreCommands(tokens) {
    try {
      const command = tokens[0].toUpperCase();
      let result;

      if (command === 'SET') {
        if (tokens.length > 3) {
          // add code to accommodate expiry later
          const flag = tokens[tokens.length - 1];

          if (flag === 'NX') {
            result = this.store.setStringNX(...tokens.slice(1));
          } else if (flag === 'XX') {
            result = this.store.setStringX(...tokens.slice(1));
          }
        } else {
          result = this.store.setString(...tokens.slice(1));
        }
      } else if (command === 'LINSERT') {
        const flag = tokens[2];

        if (flag === 'BEFORE') {
          result = this.store.linsertBefore(...tokens.slice(1));
        } else if (flag === 'AFTER') {
          result = this.store.linsertAfter(...tokens.slice(1));
        }

      } else if (this.storeCommandMap[command]) {
        console.log("TOKENS", tokens);
        result = this.storeCommandMap[command].apply(this.store, tokens.slice(1));
      } else {
        result = "ServerError: Command not found in storeCommandMap.";
      }

    } catch(err) {
      throw err;
    }
  }

  static parseCommandLineIntoOptions(args) {
    const options = {};

    while (args.length) {
      const token = args.shift();
      if (token === '--maxMemory') {
        const maxMemory = +args.shift();

        if (isNaN(maxMemory)) {
          throw new Error("Invalid option value for maxMemory.");
        }

        options['maxMemory'] = maxMemory;
      } else if (token === '--aofWritePath') {
        const path = args.shift();

        if (!path.match(/.+\.aof$/i)) {
          throw new Error("Invalid option value for aofWritePath.");
        }

        options['aofWritePath'] = path
      } else if (token === '--aofPersistence') {
        let persistenceBool = args.shift();

        if (persistenceBool !== 'true' && persistenceBool !== 'false') {
          throw new Error("Invalid option value for aofPersistence.");
        }

        persistenceBool = persistenceBool === 'true';

        options['aofPersistence'] = persistenceBool;
      }
    };

    return options;
  }
}

export default CorvoServer;
<commit_msg>Read file using stream<commit_after>import Net from 'net';
import Store from './store';
import { Parser } from './parser';
import ParserError from './parser_error';
import StoreError from './store_error';
import FS from "fs";

const DEFAULT_PORT = 6379;
const DEFAULT_HOST = '127.0.0.1';
const WRITE_COMMANDS = {
  SET: true, // always write to AOF
  APPEND: true, // always write to AOF when returning integer
  TOUCH: true, // write to AOF when return val integer NOT 0 X
  INCR: true, // always write to AOF when returning integer
  DECR: true, // always write to AOF when returning integer
  RENAME: true, // write to AOF when returning OK
  RENAMENX: true, // write to AOF when returns 1 or 0
  DEL: true, // write for any integer greater than 0 X
  LREM: true, // write for any integer greater than 0 X
  LPUSH: true, // write for any integer value
  RPUSH: true, // write for any integer value
  LPOP: true, // write when not nil X
  RPOP: true, // write when not nil X
  LSET: true, // write when returning OK
  HSET: true, // write for 1 or 0
  HMSET: true, // write when returning OK
  HDEL: true, // write for any integer value
  HSETNX: true, // write for 1 or 0
  HINCRBY: true, // write for any float
  ZINTERSTORE: true, // write for any integer value
  ZUNIONSTORE: true, // write for any integer value
  ZADD: true, // write for integer or bulk string reply
  ZREM: true, // write for any integer value
  ZINCRBY: true, // bulk string reply
};
const DEF_OPTIONS = {
  aofWritePath: 'corvoAOF.aof',
  aofPersistence: true
};

class CorvoServer {
  constructor(options=DEF_OPTIONS) {
    this.store = new Store();
    this.storeCommandMap = {
      'GET': this.store.getString,
      'APPEND': this.store.appendString,
      'STRLEN': this.store.getStrLen,
      'TOUCH': this.store.touch,
      'INCR': this.store.strIncr,
      'DECR': this.store.strDecr,
      'EXISTS': this.store.exists,
      'RENAME': this.store.rename,
      'RENAMENX': this.store.renameNX,
      'TYPE': this.store.type,
      'DEL': this.store.del,
      'LINDEX': this.store.lindex,
      'LREM': this.store.lrem,
      'LLEN': this.store.llen,
      'LPUSH': this.store.lpush,
      'RPUSH': this.store.rpush,
      'LPOP': this.store.lpop,
      'RPOP': this.store.rpop,
      'LSET': this.store.lset,
      'HSET': this.store.hset,
      'HVALS': this.store.hvals,
      'HSTRLEN': this.store.hstrlen,
      'HKEYS': this.store.hkeys,
      'HMSET': this.store.hmset,
      'HDEL': this.store.hdel,
      'HGET': this.store.hget,
      'HGETALL': this.store.hGetAll,
      'HLEN': this.store.hlen,
      'HSETNX': this.store.hsetnx,
      'HMGET': this.store.hmget,
      'HINCRBY': this.store.hincrby,
      'ZINTERSTORE': this.store.zinterstore,
      'ZUNIONSTORE': this.store.zunionstore,
      'ZADD': this.store.zadd,
      'ZREM': this.store.zrem,
      'ZCARD': this.store.zcard,
      'ZINCRBY': this.store.zincrby,
      'ZSCORE': this.store.zscore,
    };
    this.aofWritePath = options.aofWritePath;
    this.persist = options.aofPersistence;
    if (this.persist) {
      this.writer = FS.createWriteStream(options.aofWritePath, {'flags': 'a' });
    }
  }

  prepareRespReturn(result, isError=false) {
    // handle error
    if (isError) {
      return "-" + result + "\r\n";
    }

    // handle null
    if (result === null) {
      return "$-1\r\n";
    }

    // handle array
    if (result instanceof Array) {
      let respResult = "*" + result.length + "\r\n";

      result.forEach((elem) => {
        if (elem === null) {
          respResult += "$-1\r\n";
        } else if (typeof elem === 'string') {
          respResult += "$" + elem.length + "\r\n" + elem + "\r\n";
        } else if (typeof elem === 'number') {
          respResult += ":" + elem + "\r\n";
        }
      });

      return respResult;
    }

    // handle string
    if (typeof result === 'string') {
      let respResult;
      if (result.length === 0) {
        respResult = "$0\r\n\r\n";
      } else {
        respResult = "+" + result + "\r\n";
      }

      return respResult;
    }

    // handle number
    if (typeof result === 'number') {
      return ":" + result + "\r\n";;
    }

  }

  startServer(port=DEFAULT_PORT, host=DEFAULT_HOST) {
    const server = Net.createServer();
    server.on('connection', this.handleConnection.bind(this));

    if (this.persist) { this.aofLoadFile(this.aofWritePath); }
    server.listen(port, host, function() {
      console.log('server listening to %j', server.address());
    });
  }

  handleConnection(conn) {
    conn.setEncoding('utf8');
    conn.on('data', function(data) {
      console.log("data =", data);
      try {
        const tokens = Parser.processIncomingString(data);
        const command = tokens[0].toUpperCase();
        let result;

        if (command === 'SET') {
          if (tokens.length > 3) {
            // add code to accommodate expiry later
            const flag = tokens[tokens.length - 1];

            if (flag === 'NX') {
              result = this.store.setStringNX(...tokens.slice(1));
            } else if (flag === 'XX') {
              result = this.store.setStringX(...tokens.slice(1));
            }
          } else {
            result = this.store.setString(...tokens.slice(1));
          }
        } else if (command === 'LINSERT') {
          const flag = tokens[2];

          if (flag === 'BEFORE') {
            result = this.store.linsertBefore(...tokens.slice(1));
          } else if (flag === 'AFTER') {
            result = this.store.linsertAfter(...tokens.slice(1));
          }

        } else if (this.storeCommandMap[command]) {
          console.log("TOKENS", tokens);
          result = this.storeCommandMap[command].apply(this.store, tokens.slice(1));
        } else {
          result = "ServerError: Command not found in storeCommandMap.";
        }

        // write to AOF file if command and return val are correct
        if (WRITE_COMMANDS[command]) {
          if (this.persist) {
            this.aofCheckAndWrite(data, command, result);
          }
        }

        const stringToReturn = this.prepareRespReturn(result);
        conn.write(stringToReturn);
      } catch(err) {
        if (err instanceof ParserError || err instanceof StoreError) {
          const stringToReturn = this.prepareRespReturn(err.message, true);
          conn.write(stringToReturn);
        } else {
          throw err;
        }
      }
    }.bind(this));
  };

  aofCheckAndWrite(data, command, result) {
    if (command === 'TOUCH' && result === 0) {
      return;
    } else if (command === 'DEL' && result === 0) {
      return;
    } else if (command === 'LPOP' && result === null) {
      return;
    } else if (command === 'RPOP' && result === null) {
      return;
    } else if (command === 'LREM' && result === 0) {
      return;
    } else {
      console.log("WRITING TO AOF FILE!");
      this.writer.write(data, 'UTF8');
    }
  }

  aofLoadFile(fileName) {
    // const CHUNK_SIZE = 1024;
    const CHUNK_SIZE = 391;

    console.log("Going to open an existing file");
    const self = this;
    this.prependString = "";
    const readStream = FS.createReadStream(fileName, {encoding: 'utf8', highWaterMark: CHUNK_SIZE});
    readStream.on('data', function(chunk) {
          console.log("chunk = ", chunk.toString());
          console.log("chunksize = ", chunk.length);
          let bytes = chunk.length;

          let dataToProcess;

          const dataReceived = chunk;
          if (bytes < CHUNK_SIZE) {
            dataToProcess = self.prependString + dataReceived;
          } else {
console.log("here in else");
            const bytesToChop = self.getTrailingCommandBytes(dataReceived);
console.log("bytesToChop = ", bytesToChop);
console.log("prependString = ", self.prependString);
console.log("chopped dataReceived = ", dataReceived.slice(0, -bytesToChop));
            dataToProcess = self.prependString + dataReceived.slice(0, -bytesToChop);
            self.prependString = dataReceived.slice(-bytesToChop);
          }
          let inputDataTokens = dataToProcess.split('\r\n').slice(0, -1);
          console.log("inputDataTokens.length=", inputDataTokens.length);
          console.log("inputDataTokens[0]=", inputDataTokens[0], ":");
          console.log("inputDataTokens[1]=", inputDataTokens[1], ":");
          while (inputDataTokens.length) {
            let countToken = inputDataTokens.shift();
            let count = parseInt(countToken.slice(1), 10);
            // extract one command
            let tokens = self.extractOneCommand(count, inputDataTokens);

            // apply that command
            self.aofCallStoreCommands(tokens);
          }
      }).on('end', function() {
        console.log("end of data reached");
      });
  }

  getTrailingCommandBytes(dataReceived) {
    let count = 0;
    let idx = dataReceived.length - 1;

    while (idx >= 0) {
      count += 1;
      if (dataReceived[idx] === '*') {
        return count;
      }
      idx -= 1;
    }
  }

  extractOneCommand(count, inputDataTokens) {
    const tokens = [];
    for (let i = 0; i < count; i += 1) {
      inputDataTokens.shift();
      tokens.push(inputDataTokens.shift());
    }

    return tokens;
  }

  aofCallStoreCommands(tokens) {
    try {
      const command = tokens[0].toUpperCase();
      let result;

      if (command === 'SET') {
        if (tokens.length > 3) {
          // add code to accommodate expiry later
          const flag = tokens[tokens.length - 1];

          if (flag === 'NX') {
            result = this.store.setStringNX(...tokens.slice(1));
          } else if (flag === 'XX') {
            result = this.store.setStringX(...tokens.slice(1));
          }
        } else {
          result = this.store.setString(...tokens.slice(1));
        }
      } else if (command === 'LINSERT') {
        const flag = tokens[2];

        if (flag === 'BEFORE') {
          result = this.store.linsertBefore(...tokens.slice(1));
        } else if (flag === 'AFTER') {
          result = this.store.linsertAfter(...tokens.slice(1));
        }

      } else if (this.storeCommandMap[command]) {
        console.log("TOKENS", tokens);
        result = this.storeCommandMap[command].apply(this.store, tokens.slice(1));
      } else {
        result = "ServerError: Command not found in storeCommandMap.";
      }

    } catch(err) {
      throw err;
    }
  }

  static parseCommandLineIntoOptions(args) {
    const options = {};

    while (args.length) {
      const token = args.shift();
      if (token === '--maxMemory') {
        const maxMemory = +args.shift();

        if (isNaN(maxMemory)) {
          throw new Error("Invalid option value for maxMemory.");
        }

        options['maxMemory'] = maxMemory;
      } else if (token === '--aofWritePath') {
        const path = args.shift();

        if (!path.match(/.+\.aof$/i)) {
          throw new Error("Invalid option value for aofWritePath.");
        }

        options['aofWritePath'] = path
      } else if (token === '--aofPersistence') {
        let persistenceBool = args.shift();

        if (persistenceBool !== 'true' && persistenceBool !== 'false') {
          throw new Error("Invalid option value for aofPersistence.");
        }

        persistenceBool = persistenceBool === 'true';

        options['aofPersistence'] = persistenceBool;
      }
    };

    return options;
  }
}

export default CorvoServer;
<|endoftext|>


<commit_before>/** @babel */

import {Point, CompositeDisposable} from 'atom'
import fs from 'fs-plus'
import fuzzaldrin from 'fuzzaldrin'
import fuzzaldrinPlus from 'fuzzaldrin-plus'
import path from 'path'
import SelectListView from 'atom-select-list'

import {repositoryForPath} from './helpers'
import FileIcons from './file-icons'

export default class FuzzyFinderView {
  constructor () {
    this.previousQueryWasLineJump = false
    this.items = []
    this.selectListView = new SelectListView({
      items: this.items,
      maxResults: 10,
      emptyMessage: this.getEmptyMessage(),
      filterKeyForItem: (item) => item.projectRelativePath,
      filterQuery: (query) => {
        const colon = query.indexOf(':')
        if (colon !== -1) {
          query = query.slice(0, colon)
        }
        // Normalize to backslashes on Windows
        if (process.platform === 'win32') {
          query = query.replace(/\//g, '\\')
        }

        return query
      },
      didCancelSelection: () => { this.cancel() },
      didConfirmSelection: (item) => {
        this.confirm(item, {searchAllPanes: atom.config.get('fuzzy-finder.searchAllPanes')})
      },
      didConfirmEmptySelection: () => {
        this.confirm()
      },
      didChangeQuery: () => {
        const isLineJump = this.isQueryALineJump()
        if (!this.previousQueryWasLineJump && isLineJump) {
          this.previousQueryWasLineJump = true
          this.selectListView.update({
            items: [],
            emptyMessage: 'Jump to line in active editor'
          })
        } else if (this.previousQueryWasLineJump && !isLineJump) {
          this.previousQueryWasLineJump = false
          this.selectListView.update({
            items: this.items,
            emptyMessage: this.getEmptyMessage()
          })
        }
      },
      elementForItem: ({filePath, projectRelativePath}) => {
        const filterQuery = this.selectListView.getFilterQuery()
        const matches = this.useAlternateScoring
          ? fuzzaldrinPlus.match(projectRelativePath, filterQuery)
          : fuzzaldrin.match(projectRelativePath, filterQuery)

        const li = document.createElement('li')
        li.classList.add('two-lines')

        const repository = repositoryForPath(filePath)
        if (repository) {
          const status = repository.getCachedPathStatus(filePath)
          if (repository.isStatusNew(status)) {
            const div = document.createElement('div')
            div.classList.add('status', 'status-added', 'icon', 'icon-diff-added')
            li.appendChild(div)
          } else if (repository.isStatusModified(status)) {
            const div = document.createElement('div')
            div.classList.add('status', 'status-modified', 'icon', 'icon-diff-modified')
            li.appendChild(div)
          }
        }

        const iconClasses = FileIcons.getService().iconClassForPath(filePath, 'fuzzy-finder')
        let classList
        if (Array.isArray(iconClasses)) {
          classList = iconClasses
        } else if (iconClasses) {
          classList = iconClasses.toString().split(/\s+/g)
        } else {
          classList = []
        }

        const fileBasename = path.basename(filePath)
        const baseOffset = projectRelativePath.length - fileBasename.length
        const primaryLine = document.createElement('div')
        primaryLine.classList.add('primary-line', 'file', 'icon', ...classList)
        primaryLine.dataset.name = fileBasename
        primaryLine.dataset.path = projectRelativePath
        primaryLine.appendChild(highlight(fileBasename, matches, baseOffset))
        li.appendChild(primaryLine)

        const secondaryLine = document.createElement('div')
        secondaryLine.classList.add('secondary-line', 'path', 'no-icon')
        secondaryLine.appendChild(highlight(projectRelativePath, matches, 0))
        li.appendChild(secondaryLine)

        return li
      }
    })
    this.selectListView.element.classList.add('fuzzy-finder')

    const splitLeft = () => { this.splitOpenPath((pane) => pane.splitLeft.bind(pane)) }
    const splitRight = () => { this.splitOpenPath((pane) => pane.splitRight.bind(pane)) }
    const splitUp = () => { this.splitOpenPath((pane) => pane.splitUp.bind(pane)) }
    const splitDown = () => { this.splitOpenPath((pane) => pane.splitDown.bind(pane)) }
    atom.commands.add(this.selectListView.element, {
      'pane:split-left': splitLeft,
      'pane:split-left-and-copy-active-item': splitLeft,
      'pane:split-left-and-move-active-item': splitLeft,
      'pane:split-right': splitRight,
      'pane:split-right-and-copy-active-item': splitRight,
      'pane:split-right-and-move-active-item': splitRight,
      'pane:split-up': splitUp,
      'pane:split-up-and-copy-active-item': splitUp,
      'pane:split-up-and-move-active-item': splitUp,
      'pane:split-down': splitDown,
      'pane:split-down-and-copy-active-item': splitDown,
      'pane:split-down-and-move-active-item': splitDown,
      'fuzzy-finder:invert-confirm': () => {
        this.confirm(
          this.selectListView.getSelectedItem(),
          {searchAllPanes: !atom.config.get('fuzzy-finder.searchAllPanes')}
        )
      }
    })

    this.subscriptions = new CompositeDisposable()
    this.subscriptions.add(
      atom.config.observe('fuzzy-finder.useAlternateScoring', (newValue) => {
        this.useAlternateScoring = newValue
        if (this.useAlternateScoring) {
          this.selectListView.update({
            filter: (items, query) => {
              return query ? fuzzaldrinPlus.filter(items, query, {key: 'projectRelativePath'}) : items
            }
          })
        } else {
          this.selectListView.update({filter: null})
        }
      })
    )
  }

  get element () {
    return this.selectListView.element
  }

  destroy () {
    if (this.panel) {
      this.panel.destroy()
    }

    if (this.subscriptions) {
      this.subscriptions.dispose()
      this.subscriptions = null
    }

    return this.selectListView.destroy()
  }

  cancel () {
    if (atom.config.get('fuzzy-finder.preserveLastSearch')) {
      this.selectListView.refs.queryEditor.selectAll()
    } else {
      this.selectListView.reset()
    }

    this.hide()
  }

  confirm ({filePath} = {}, openOptions) {
    if (atom.workspace.getActiveTextEditor() && this.isQueryALineJump()) {
      const lineNumber = this.getLineNumber()
      this.cancel()
      this.moveToLine(lineNumber)
    } else if (!filePath) {
      this.cancel()
    } else if (fs.isDirectorySync(filePath)) {
      this.selectListView.update({errorMessage: 'Selected path is a directory'})
      setTimeout(() => { this.selectListView.update({errorMessage: null}) }, 2000)
    } else {
      const lineNumber = this.getLineNumber()
      this.cancel()
      this.openPath(filePath, lineNumber, openOptions)
    }
  }

  getEditorSelection() {
    const editor = atom.workspace.getActiveTextEditor()
    if (!editor) {
      return
    }
    const selectedText = editor.getSelectedText()
    if (/\n/m.test(selectedText)) {
      return
    }
    return selectedText
  }

  prefillQueryFromSelection() {
    const selectedText = this.getEditorSelection()
    if (selectedText) {
      this.selectListView.refs.queryEditor.setText(selectedText)
      textLength = selectedText.length
      this.selectListView.refs.queryEditor.setSelectedBufferRange([[0, 0], [0, textLength]])
    }
  }

  show () {
    this.previouslyFocusedElement = document.activeElement
    if (!this.panel) {
      this.panel = atom.workspace.addModalPanel({item: this})
    }
    this.panel.show()
    if (atom.config.get('fuzzy-finder.prefillFromSelection') === true) {
      this.prefillQueryFromSelection()
    }
    this.selectListView.focus()
  }

  hide () {
    if (this.panel) {
      this.panel.hide()
    }

    if (this.previouslyFocusedElement) {
      this.previouslyFocusedElement.focus()
      this.previouslyFocusedElement = null
    }
  }

  async openPath (filePath, lineNumber, openOptions) {
    if (filePath) {
      await atom.workspace.open(filePath, openOptions)
      this.moveToLine(lineNumber)
    }
  }

  moveToLine (lineNumber = -1) {
    if (lineNumber < 0) {
      return
    }

    const editor = atom.workspace.getActiveTextEditor()
    if (editor) {
      const position = new Point(lineNumber, 0)
      editor.scrollToBufferPosition(position, {center: true})
      editor.setCursorBufferPosition(position)
      editor.moveToFirstCharacterOfLine()
    }
  }

  splitOpenPath (splitFn) {
    const {filePath} = this.selectListView.getSelectedItem() || {}
    const lineNumber = this.getLineNumber()
    const editor = atom.workspace.getActiveTextEditor()
    const activePane = atom.workspace.getActivePane()

    if (this.isQueryALineJump() && editor) {
      this.previouslyFocusedElement = null
      splitFn(activePane)({copyActiveItem: true})
      this.moveToLine(lineNumber)
    } else if (!filePath) {
      return // eslint-disable-line no-useless-return
    } else if (activePane) {
      this.previouslyFocusedElement = null
      splitFn(activePane)()
      this.openPath(filePath, lineNumber)
    } else {
      this.previouslyFocusedElement = null
      this.openPath(filePath, lineNumber)
    }
  }

  isQueryALineJump () {
    return (
      this.selectListView.getFilterQuery().trim() === '' &&
      this.selectListView.getQuery().indexOf(':') !== -1
    )
  }

  getLineNumber () {
    const query = this.selectListView.getQuery()
    const colon = query.indexOf(':')
    if (colon === -1) {
      return -1
    } else {
      return parseInt(query.slice(colon + 1)) - 1
    }
  }

  setItems (filePaths) {
    this.items = this.projectRelativePathsForFilePaths(filePaths)
    if (this.isQueryALineJump()) {
      return this.selectListView.update({items: [], loadingMessage: null, loadingBadge: null})
    } else {
      return this.selectListView.update({items: this.items, loadingMessage: null, loadingBadge: null})
    }
  }

  projectRelativePathsForFilePaths (filePaths) {
    // Don't regenerate project relative paths unless the file paths have changed
    if (filePaths !== this.filePaths) {
      const projectHasMultipleDirectories = atom.project.getDirectories().length > 1
      this.filePaths = filePaths
      this.projectRelativePaths = this.filePaths.map((filePath) => {
        let [rootPath, projectRelativePath] = atom.project.relativizePath(filePath)
        if (rootPath && projectHasMultipleDirectories) {
          projectRelativePath = path.join(path.basename(rootPath), projectRelativePath)
        }
        return {filePath, projectRelativePath}
      })
    }

    return this.projectRelativePaths
  }
}

function highlight (path, matches, offsetIndex) {
  let lastIndex = 0
  let matchedChars = []
  const fragment = document.createDocumentFragment()
  for (let matchIndex of matches) {
    matchIndex -= offsetIndex
    // If marking up the basename, omit path matches
    if (matchIndex < 0) {
      continue
    }
    const unmatched = path.substring(lastIndex, matchIndex)
    if (unmatched) {
      if (matchedChars.length > 0) {
        const span = document.createElement('span')
        span.classList.add('character-match')
        span.textContent = matchedChars.join('')
        fragment.appendChild(span)
        matchedChars = []
      }

      fragment.appendChild(document.createTextNode(unmatched))
    }

    matchedChars.push(path[matchIndex])
    lastIndex = matchIndex + 1
  }

  if (matchedChars.length > 0) {
    const span = document.createElement('span')
    span.classList.add('character-match')
    span.textContent = matchedChars.join('')
    fragment.appendChild(span)
  }

  // Remaining characters are plain text
  fragment.appendChild(document.createTextNode(path.substring(lastIndex)))
  return fragment
}
<commit_msg>:shirt: standard<commit_after>/** @babel */

import {Point, CompositeDisposable} from 'atom'
import fs from 'fs-plus'
import fuzzaldrin from 'fuzzaldrin'
import fuzzaldrinPlus from 'fuzzaldrin-plus'
import path from 'path'
import SelectListView from 'atom-select-list'

import {repositoryForPath} from './helpers'
import FileIcons from './file-icons'

export default class FuzzyFinderView {
  constructor () {
    this.previousQueryWasLineJump = false
    this.items = []
    this.selectListView = new SelectListView({
      items: this.items,
      maxResults: 10,
      emptyMessage: this.getEmptyMessage(),
      filterKeyForItem: (item) => item.projectRelativePath,
      filterQuery: (query) => {
        const colon = query.indexOf(':')
        if (colon !== -1) {
          query = query.slice(0, colon)
        }
        // Normalize to backslashes on Windows
        if (process.platform === 'win32') {
          query = query.replace(/\//g, '\\')
        }

        return query
      },
      didCancelSelection: () => { this.cancel() },
      didConfirmSelection: (item) => {
        this.confirm(item, {searchAllPanes: atom.config.get('fuzzy-finder.searchAllPanes')})
      },
      didConfirmEmptySelection: () => {
        this.confirm()
      },
      didChangeQuery: () => {
        const isLineJump = this.isQueryALineJump()
        if (!this.previousQueryWasLineJump && isLineJump) {
          this.previousQueryWasLineJump = true
          this.selectListView.update({
            items: [],
            emptyMessage: 'Jump to line in active editor'
          })
        } else if (this.previousQueryWasLineJump && !isLineJump) {
          this.previousQueryWasLineJump = false
          this.selectListView.update({
            items: this.items,
            emptyMessage: this.getEmptyMessage()
          })
        }
      },
      elementForItem: ({filePath, projectRelativePath}) => {
        const filterQuery = this.selectListView.getFilterQuery()
        const matches = this.useAlternateScoring
          ? fuzzaldrinPlus.match(projectRelativePath, filterQuery)
          : fuzzaldrin.match(projectRelativePath, filterQuery)

        const li = document.createElement('li')
        li.classList.add('two-lines')

        const repository = repositoryForPath(filePath)
        if (repository) {
          const status = repository.getCachedPathStatus(filePath)
          if (repository.isStatusNew(status)) {
            const div = document.createElement('div')
            div.classList.add('status', 'status-added', 'icon', 'icon-diff-added')
            li.appendChild(div)
          } else if (repository.isStatusModified(status)) {
            const div = document.createElement('div')
            div.classList.add('status', 'status-modified', 'icon', 'icon-diff-modified')
            li.appendChild(div)
          }
        }

        const iconClasses = FileIcons.getService().iconClassForPath(filePath, 'fuzzy-finder')
        let classList
        if (Array.isArray(iconClasses)) {
          classList = iconClasses
        } else if (iconClasses) {
          classList = iconClasses.toString().split(/\s+/g)
        } else {
          classList = []
        }

        const fileBasename = path.basename(filePath)
        const baseOffset = projectRelativePath.length - fileBasename.length
        const primaryLine = document.createElement('div')
        primaryLine.classList.add('primary-line', 'file', 'icon', ...classList)
        primaryLine.dataset.name = fileBasename
        primaryLine.dataset.path = projectRelativePath
        primaryLine.appendChild(highlight(fileBasename, matches, baseOffset))
        li.appendChild(primaryLine)

        const secondaryLine = document.createElement('div')
        secondaryLine.classList.add('secondary-line', 'path', 'no-icon')
        secondaryLine.appendChild(highlight(projectRelativePath, matches, 0))
        li.appendChild(secondaryLine)

        return li
      }
    })
    this.selectListView.element.classList.add('fuzzy-finder')

    const splitLeft = () => { this.splitOpenPath((pane) => pane.splitLeft.bind(pane)) }
    const splitRight = () => { this.splitOpenPath((pane) => pane.splitRight.bind(pane)) }
    const splitUp = () => { this.splitOpenPath((pane) => pane.splitUp.bind(pane)) }
    const splitDown = () => { this.splitOpenPath((pane) => pane.splitDown.bind(pane)) }
    atom.commands.add(this.selectListView.element, {
      'pane:split-left': splitLeft,
      'pane:split-left-and-copy-active-item': splitLeft,
      'pane:split-left-and-move-active-item': splitLeft,
      'pane:split-right': splitRight,
      'pane:split-right-and-copy-active-item': splitRight,
      'pane:split-right-and-move-active-item': splitRight,
      'pane:split-up': splitUp,
      'pane:split-up-and-copy-active-item': splitUp,
      'pane:split-up-and-move-active-item': splitUp,
      'pane:split-down': splitDown,
      'pane:split-down-and-copy-active-item': splitDown,
      'pane:split-down-and-move-active-item': splitDown,
      'fuzzy-finder:invert-confirm': () => {
        this.confirm(
          this.selectListView.getSelectedItem(),
          {searchAllPanes: !atom.config.get('fuzzy-finder.searchAllPanes')}
        )
      }
    })

    this.subscriptions = new CompositeDisposable()
    this.subscriptions.add(
      atom.config.observe('fuzzy-finder.useAlternateScoring', (newValue) => {
        this.useAlternateScoring = newValue
        if (this.useAlternateScoring) {
          this.selectListView.update({
            filter: (items, query) => {
              return query ? fuzzaldrinPlus.filter(items, query, {key: 'projectRelativePath'}) : items
            }
          })
        } else {
          this.selectListView.update({filter: null})
        }
      })
    )
  }

  get element () {
    return this.selectListView.element
  }

  destroy () {
    if (this.panel) {
      this.panel.destroy()
    }

    if (this.subscriptions) {
      this.subscriptions.dispose()
      this.subscriptions = null
    }

    return this.selectListView.destroy()
  }

  cancel () {
    if (atom.config.get('fuzzy-finder.preserveLastSearch')) {
      this.selectListView.refs.queryEditor.selectAll()
    } else {
      this.selectListView.reset()
    }

    this.hide()
  }

  confirm ({filePath} = {}, openOptions) {
    if (atom.workspace.getActiveTextEditor() && this.isQueryALineJump()) {
      const lineNumber = this.getLineNumber()
      this.cancel()
      this.moveToLine(lineNumber)
    } else if (!filePath) {
      this.cancel()
    } else if (fs.isDirectorySync(filePath)) {
      this.selectListView.update({errorMessage: 'Selected path is a directory'})
      setTimeout(() => { this.selectListView.update({errorMessage: null}) }, 2000)
    } else {
      const lineNumber = this.getLineNumber()
      this.cancel()
      this.openPath(filePath, lineNumber, openOptions)
    }
  }

  getEditorSelection () {
    const editor = atom.workspace.getActiveTextEditor()
    if (!editor) {
      return
    }
    const selectedText = editor.getSelectedText()
    if (/\n/m.test(selectedText)) {
      return
    }
    return selectedText
  }

  prefillQueryFromSelection () {
    const selectedText = this.getEditorSelection()
    if (selectedText) {
      this.selectListView.refs.queryEditor.setText(selectedText)
      const textLength = selectedText.length
      this.selectListView.refs.queryEditor.setSelectedBufferRange([[0, 0], [0, textLength]])
    }
  }

  show () {
    this.previouslyFocusedElement = document.activeElement
    if (!this.panel) {
      this.panel = atom.workspace.addModalPanel({item: this})
    }
    this.panel.show()
    if (atom.config.get('fuzzy-finder.prefillFromSelection') === true) {
      this.prefillQueryFromSelection()
    }
    this.selectListView.focus()
  }

  hide () {
    if (this.panel) {
      this.panel.hide()
    }

    if (this.previouslyFocusedElement) {
      this.previouslyFocusedElement.focus()
      this.previouslyFocusedElement = null
    }
  }

  async openPath (filePath, lineNumber, openOptions) {
    if (filePath) {
      await atom.workspace.open(filePath, openOptions)
      this.moveToLine(lineNumber)
    }
  }

  moveToLine (lineNumber = -1) {
    if (lineNumber < 0) {
      return
    }

    const editor = atom.workspace.getActiveTextEditor()
    if (editor) {
      const position = new Point(lineNumber, 0)
      editor.scrollToBufferPosition(position, {center: true})
      editor.setCursorBufferPosition(position)
      editor.moveToFirstCharacterOfLine()
    }
  }

  splitOpenPath (splitFn) {
    const {filePath} = this.selectListView.getSelectedItem() || {}
    const lineNumber = this.getLineNumber()
    const editor = atom.workspace.getActiveTextEditor()
    const activePane = atom.workspace.getActivePane()

    if (this.isQueryALineJump() && editor) {
      this.previouslyFocusedElement = null
      splitFn(activePane)({copyActiveItem: true})
      this.moveToLine(lineNumber)
    } else if (!filePath) {
      return // eslint-disable-line no-useless-return
    } else if (activePane) {
      this.previouslyFocusedElement = null
      splitFn(activePane)()
      this.openPath(filePath, lineNumber)
    } else {
      this.previouslyFocusedElement = null
      this.openPath(filePath, lineNumber)
    }
  }

  isQueryALineJump () {
    return (
      this.selectListView.getFilterQuery().trim() === '' &&
      this.selectListView.getQuery().indexOf(':') !== -1
    )
  }

  getLineNumber () {
    const query = this.selectListView.getQuery()
    const colon = query.indexOf(':')
    if (colon === -1) {
      return -1
    } else {
      return parseInt(query.slice(colon + 1)) - 1
    }
  }

  setItems (filePaths) {
    this.items = this.projectRelativePathsForFilePaths(filePaths)
    if (this.isQueryALineJump()) {
      return this.selectListView.update({items: [], loadingMessage: null, loadingBadge: null})
    } else {
      return this.selectListView.update({items: this.items, loadingMessage: null, loadingBadge: null})
    }
  }

  projectRelativePathsForFilePaths (filePaths) {
    // Don't regenerate project relative paths unless the file paths have changed
    if (filePaths !== this.filePaths) {
      const projectHasMultipleDirectories = atom.project.getDirectories().length > 1
      this.filePaths = filePaths
      this.projectRelativePaths = this.filePaths.map((filePath) => {
        let [rootPath, projectRelativePath] = atom.project.relativizePath(filePath)
        if (rootPath && projectHasMultipleDirectories) {
          projectRelativePath = path.join(path.basename(rootPath), projectRelativePath)
        }
        return {filePath, projectRelativePath}
      })
    }

    return this.projectRelativePaths
  }
}

function highlight (path, matches, offsetIndex) {
  let lastIndex = 0
  let matchedChars = []
  const fragment = document.createDocumentFragment()
  for (let matchIndex of matches) {
    matchIndex -= offsetIndex
    // If marking up the basename, omit path matches
    if (matchIndex < 0) {
      continue
    }
    const unmatched = path.substring(lastIndex, matchIndex)
    if (unmatched) {
      if (matchedChars.length > 0) {
        const span = document.createElement('span')
        span.classList.add('character-match')
        span.textContent = matchedChars.join('')
        fragment.appendChild(span)
        matchedChars = []
      }

      fragment.appendChild(document.createTextNode(unmatched))
    }

    matchedChars.push(path[matchIndex])
    lastIndex = matchIndex + 1
  }

  if (matchedChars.length > 0) {
    const span = document.createElement('span')
    span.classList.add('character-match')
    span.textContent = matchedChars.join('')
    fragment.appendChild(span)
  }

  // Remaining characters are plain text
  fragment.appendChild(document.createTextNode(path.substring(lastIndex)))
  return fragment
}
<|endoftext|>


<commit_before>/* @flow */
'use strict';

export default class Logger {
    start: number;

    constructor() {
        this.start = Date.now();
    }

    // eslint-disable-next-line flowtype/no-weak-types
    log(...args: any) {
        Function.prototype.bind
            .call(window.console.log, window.console)
            .apply(
                window.console,
                [Date.now() - this.start + 'ms', 'html2canvas:'].concat([].slice.call(args, 0))
            );
    }

    // eslint-disable-next-line flowtype/no-weak-types
    error(...args: any) {
        Function.prototype.bind
            .call(window.console.error, window.console)
            .apply(
                window.console,
                [Date.now() - this.start + 'ms', 'html2canvas:'].concat([].slice.call(args, 0))
            );
    }
}
<commit_msg>Check availability of console before using it (Fix IE9)<commit_after>/* @flow */
'use strict';

export default class Logger {
    start: number;

    constructor() {
        this.start = Date.now();
    }

    // eslint-disable-next-line flowtype/no-weak-types
    log(...args: any) {
        if (window.console && window.console.log) {
            Function.prototype.bind
                .call(window.console.log, window.console)
                .apply(
                    window.console,
                    [Date.now() - this.start + 'ms', 'html2canvas:'].concat([].slice.call(args, 0))
                );
        }
    }

    // eslint-disable-next-line flowtype/no-weak-types
    error(...args: any) {
        if (window.console && window.console.error) {
            Function.prototype.bind
                .call(window.console.error, window.console)
                .apply(
                    window.console,
                    [Date.now() - this.start + 'ms', 'html2canvas:'].concat([].slice.call(args, 0))
                );
        }
    }
}
<|endoftext|>


<commit_before>require(['jquery', 'EpubLibrary', 'EpubReader'], function($, EpubLibrary, EpubReader){

	var getEpubQueryParam = function(){
        var query = window.location.search;
        if (query && query.length){
            query = query.substring(1);
        }
        if (query.length){
            var keyParams = query.split('&');
            for (var x = 0; x < keyParams.length; x++)
            {
                var keyVal = keyParams[x].split('=');
                if (keyVal[0] == 'epub' && keyVal.length == 2){
                    return keyVal[1];
                }
            }

        }
        return null;
    }

	var initialLoad = function(){
		var epubUrl = getEpubQueryParam();
		if (epubUrl){
			EpubReader.loadUI({epub: decodeURIComponent(epubUrl)});
		}
		else{
			EpubLibrary.loadUI();
		}

		$(document.body).on('click', function()
        {
            $(document.body).removeClass("keyboard");
        });

		$(document).on('keyup', function(e)
        {
            $(document.body).addClass("keyboard");
        });
	}

	$(initialLoad);

	var pushState = $.noop;
	if (window.history && window.history.pushState){
		$(window).on('popstate', function(){
			var state = history.state;
			if (state && state.epub){
				EpubLibrary.unloadUI();
				EpubReader.loadUI({epub: state.epub});
			}
			else{
				EpubReader.unloadUI();
				EpubLibrary.loadUI();
			}
		});
		pushState = function(data, title, url){
			history.pushState(data, title, url);
		};
	}

	$(window).on('readepub', function(e, url){
		EpubLibrary.unloadUI();
		EpubReader.loadUI({epub: url});
		pushState({epub: url}, "Readium Viewer", '?epub=' + encodeURIComponent(url));
	});

	$(window).on('loadlibrary', function(e){
		EpubReader.unloadUI();
		EpubLibrary.loadUI();
		pushState(null, "Readium Library", 'index.html');
	});
});<commit_msg>Fixes #155, adds bootstrap tooltips to nav buttons<commit_after>require(['jquery', 'EpubLibrary', 'EpubReader'], function($, EpubLibrary, EpubReader){

	var getEpubQueryParam = function(){
        var query = window.location.search;
        if (query && query.length){
            query = query.substring(1);
        }
        if (query.length){
            var keyParams = query.split('&');
            for (var x = 0; x < keyParams.length; x++)
            {
                var keyVal = keyParams[x].split('=');
                if (keyVal[0] == 'epub' && keyVal.length == 2){
                    return keyVal[1];
                }
            }

        }
        return null;
    }

	var initialLoad = function(){
		var epubUrl = getEpubQueryParam();
		if (epubUrl){
			EpubReader.loadUI({epub: decodeURIComponent(epubUrl)});
		}
		else{
			EpubLibrary.loadUI();
		}

		$(document.body).on('click', function()
        {
            $(document.body).removeClass("keyboard");
        });

		$(document).on('keyup', function(e)
        {
            $(document.body).addClass("keyboard");
        });
	}

	$(initialLoad);

	var pushState = $.noop;
	if (window.history && window.history.pushState){
		$(window).on('popstate', function(){
			var state = history.state;
			if (state && state.epub){
				readerView(state.epub);
			}
			else{
				libraryView();
			}
		});
		pushState = function(data, title, url){
			history.pushState(data, title, url);
		};
	}

	var tooltipSelector = 'nav *[title]';
	var libraryView = function(){
		$(tooltipSelector).tooltip('destroy');
		EpubReader.unloadUI();
		EpubLibrary.loadUI();
	}

	var readerView = function(url){
		$(tooltipSelector).tooltip('destroy');
		EpubLibrary.unloadUI();
		EpubReader.loadUI({epub: url});
	}

	$(window).on('readepub', function(e, url){
		readerView(url);
		pushState({epub: url}, "Readium Viewer", '?epub=' + encodeURIComponent(url));
	});

	$(window).on('loadlibrary', function(e){
		libraryView();
		pushState(null, "Readium Library", 'index.html');
	});

	$(document.body).tooltip({
		selector : tooltipSelector,
		placement: 'auto',
		container: 'body' // do this to prevent weird navbar re-sizing issue when the tooltip is inserted
	}).on('show.bs.tooltip', function(e){
		$(tooltipSelector).not(e.target).tooltip('destroy');
	});

});<|endoftext|>


<commit_before>/*
 *  This file is part of SYZOJ.
 *
 *  Copyright (c) 2016 Menci <huanghaorui301@gmail.com>
 *
 *  SYZOJ is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  SYZOJ is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public
 *  License along with SYZOJ. If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

Array.prototype.forEachAsync = Array.prototype.mapAsync = async function (fn) {
  return Promise.all(this.map(fn));
};

Array.prototype.filterAsync = async function (fn) {
  let a = await this.mapAsync(fn);
  return this.filter((x, i) => a[i]);
};

global.ErrorMessage = class ErrorMessage {
  constructor(message, nextUrls, details) {
    this.message = message;
    this.nextUrls = nextUrls || {};
    this.details = details;
  }
};

let path = require('path');
let util = require('util');
let renderer = require('moemark-renderer');
let moment = require('moment');
let url = require('url');
let querystring = require('querystring');
let pygmentize = require('pygmentize-bundled-cached');
let gravatar = require('gravatar');
let AdmZip = require('adm-zip');
let filesize = require('file-size');
let AsyncLock = require('async-lock');

function escapeHTML(s) {
  // Code from http://stackoverflow.com/questions/5251520/how-do-i-escape-some-html-in-javascript/5251551
  return s.replace(/[^0-9A-Za-z ]/g, (c) => {
    return "&#" + c.charCodeAt(0) + ";";
  });
}

function highlightPygmentize(code, lang, cb) {
  pygmentize({
    lang: lang,
    format: 'html',
    options: {
      nowrap: true,
      classprefix: 'pl-'
    }
  }, code, (err, res) => {
    if (err || res.toString() === 'undefined') {
      cb(escapeHTML(code));
    } else {
      cb(res);
    }
  });
}

renderer.config.highlight = highlightPygmentize;

module.exports = {
  resolvePath(s) {
    let a = Array.from(arguments);
    a.unshift(__dirname);
    return path.resolve.apply(null, a);
  },
  markdown(obj, keys, noReplaceUI) {
    let XSS = require('xss');
    let CSSFilter = require('cssfilter');
    let whiteList = Object.assign({}, require('xss/lib/default').whiteList);
    delete whiteList.audio;
    delete whiteList.video;
    for (let tag in whiteList) whiteList[tag] = whiteList[tag].concat(['id', 'style', 'class']);
    let xss = new XSS.FilterXSS({
      css: {
        whiteList: Object.assign({}, require('cssfilter/lib/default').whiteList, {
          'vertical-align': true,
          top: true,
          bottom: true,
          left: true,
          right: true
        })
      },
      whiteList: whiteList,
      stripIgnoreTag: true
    });
    let replaceXSS = s => {
      return xss.process(s);
    };
    let replaceUI = s => {
      if (noReplaceUI) return s;

      s = s.split('
').join('

').split('
').join('

')
           .split('
').join('
')
           .split('
').join('
').split('
').join('
');

      let cheerio = require('cheerio');
      let $ = cheerio.load(s);

      let a = $('img:only-child');
      for (let img of Array.from(a)) {
        if (!img.prev && !img.next) {
          $(img).css('display', 'block');
          $(img).css('margin', '0 auto');
        }
      }

      return $.html();
    };
    return new Promise((resolve, reject) => {
      if (!keys) {
        if (!obj || !obj.trim()) resolve("");
        else renderer(obj, { mathjaxUseHtml: true }, s => {
            resolve(replaceUI(replaceXSS(s)));
        });
      } else {
        let res = obj, cnt = keys.length;
        for (let key of keys) {
          renderer(res[key], { mathjaxUseHtml: true }, (s) => {
            res[key] = replaceUI(replaceXSS(s));
            if (!--cnt) resolve(res);
          });
        }
      }
    });
  },
  formatDate(ts, format) {
    let m = moment(ts * 1000);
    m.locale('eu');
    return m.format(format || 'L H:mm:ss');
  },
  formatTime(x) {
    let sgn = x < 0 ? '-' : '';
    x = Math.abs(x);
    function toStringWithPad(x) {
      x = parseInt(x);
      if (x < 10) return '0' + x.toString();
      else return x.toString();
    }
    return sgn + util.format('%s:%s:%s', toStringWithPad(x / 3600), toStringWithPad(x / 60 % 60), toStringWithPad(x % 60));
  },
  formatSize(x) {
    let res = filesize(x, { fixed: 1 }).calculate();
    if (res.result === parseInt(res.result)) res.fixed = res.result.toString();
    if (res.suffix.startsWith('Byte')) res.suffix = 'B';
    else res.suffix = res.suffix.replace('iB', '');
    return res.fixed + ' ' + res.suffix;
  },
  parseDate(s) {
    return parseInt(+new Date(s) / 1000);
  },
  getCurrentDate() {
    return parseInt(+new Date / 1000);
  },
  makeUrl(req_params, form) {
    let res = '';
    if (!req_params) res = '/';
    else if (req_params.originalUrl) {
      let u = url.parse(req_params.originalUrl);
      res = u.pathname;
    } else {
      if (!Array.isArray(req_params)) req_params = [req_params];
      for (let param of req_params) res += '/' + param;
    }
    let encoded = querystring.encode(form);
    if (encoded) res += '?' + encoded;
    return res;
  },
  escapeHTML: escapeHTML,
  highlight(code, lang) {
    return new Promise((resolve, reject) => {
      highlightPygmentize(code, lang, res => {
        resolve(res);
      });
    });
  },
  gravatar(email, size) {
    return gravatar.url(email, { s: size, d: 'mm' }).replace('www', 'cn');
  },
  parseTestData(filename) {
    let zip = new AdmZip(filename);
    let list = zip.getEntries().filter(e => !e.isDirectory).map(e => e.entryName);
    let res = [];
    if (!list.includes('data_rule.txt')) {
      res[0] = {};
      res[0].cases = [];
      for (let file of list) {
        let parsedName = path.parse(file);
        if (parsedName.ext === '.in') {
          if (list.includes(`${parsedName.name}.out`)) {
            res[0].cases.push({
              input: file,
              output: `${parsedName.name}.out`
            });
          }

          if (list.includes(`${parsedName.name}.ans`)) {
            res[0].cases.push({
              input: file,
              output: `${parsedName.name}.ans`
            });
          }
        }
      }

      res[0].type = 'sum';
      res[0].score = 100;
      res[0].cases.sort((a, b) => {
        function getLastInteger(s) {
          let re = /(\d+)\D*$/;
          let x = re.exec(s);
          if (x) return parseInt(x[1]);
          else return -1;
        }

        return getLastInteger(a.input) - getLastInteger(b.input);
      });
    } else {
      let lines = zip.readAsText('data_rule.txt').split('\r').join('').split('\n').filter(x => x.length !== 0);

      if (lines.length < 3) throw '无效的数据配置文件（data_rule.txt）。';

      let input = lines[lines.length - 2];
      let output = lines[lines.length - 1];

      for (let s = 0; s < lines.length - 2; ++s) {
        res[s] = {};
        res[s].cases = [];
        let numbers = lines[s].split(' ').filter(x => x);
        if (numbers[0].includes(':')) {
          let tokens = numbers[0].split(':');
          res[s].type = tokens[0] || 'sum';
          res[s].score = parseFloat(tokens[1]) || (100 / (lines.length - 2));
          numbers.shift();
        } else {
          res[s].type = 'sum';
          res[s].score = 100;
        }
        for (let i of numbers) {
          let testcase = {
            input: input.replace('#', i),
            output: output.replace('#', i)
          };

          if (!list.includes(testcase.input)) throw `找不到文件 ${testcase.input}`;
          if (!list.includes(testcase.output)) throw `找不到文件 ${testcase.output}`;
          res[s].cases.push(testcase);
        }
      }

      res = res.filter(x => x.cases && x.cases.length !== 0);
    }

    res.spj = list.includes('spj.js') || list.some(s => s.startsWith('spj_'));
    return res;
  },
  ansiToHTML(s) {
    let Convert = require('ansi-to-html');
    let convert = new Convert({ escapeXML: true });
    return convert.toHtml(s);
  },
  paginate(count, currPage, perPage) {
    currPage = parseInt(currPage);
    if (!currPage || currPage < 1) currPage = 1;

    let pageCnt = Math.ceil(count / perPage);
    if (currPage > pageCnt) currPage = pageCnt;

    return {
      currPage: currPage,
      perPage: perPage,
      pageCnt: pageCnt,
      toSQL: () => {
        if (!pageCnt) return '';
        else return ` LIMIT ${(currPage - 1) * perPage},${perPage}`
      }
    };
  },
  removeTitleTag(s) {
    return s.replace(/「[\S\s]+?」/, '');
  },
  md5(data) {
    let crypto = require('crypto');
    let md5 = crypto.createHash('md5');
    md5.update(data);
    return md5.digest('hex');
  },
  async hitokoto() {
    try {
      let request = require('request-promise');
      let res = await request({
        uri: 'http://api.hitokoto.us/rand',
        timeout: 1500,
        qs: {
          encode: 'json',
          cat: 'a'
        },
        json: true
      });
      if (!res.hitokoto) return null;
      else return res;
    } catch (e) {
      return null;
    }
  },
  isValidUsername(s) {
    return /^[a-zA-Z0-9\-\_]+$/.test(s);
  },
  locks: [],
  lock(key, cb) {
    let s = JSON.stringify(key);
    if (!this.locks[s]) this.locks[s] = new AsyncLock();
    return this.locks[s].acquire(s, cb);
  }
};
<commit_msg>Fix markdown rendering return  tag<commit_after>/*
 *  This file is part of SYZOJ.
 *
 *  Copyright (c) 2016 Menci <huanghaorui301@gmail.com>
 *
 *  SYZOJ is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  SYZOJ is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public
 *  License along with SYZOJ. If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

Array.prototype.forEachAsync = Array.prototype.mapAsync = async function (fn) {
  return Promise.all(this.map(fn));
};

Array.prototype.filterAsync = async function (fn) {
  let a = await this.mapAsync(fn);
  return this.filter((x, i) => a[i]);
};

global.ErrorMessage = class ErrorMessage {
  constructor(message, nextUrls, details) {
    this.message = message;
    this.nextUrls = nextUrls || {};
    this.details = details;
  }
};

let path = require('path');
let util = require('util');
let renderer = require('moemark-renderer');
let moment = require('moment');
let url = require('url');
let querystring = require('querystring');
let pygmentize = require('pygmentize-bundled-cached');
let gravatar = require('gravatar');
let AdmZip = require('adm-zip');
let filesize = require('file-size');
let AsyncLock = require('async-lock');

function escapeHTML(s) {
  // Code from http://stackoverflow.com/questions/5251520/how-do-i-escape-some-html-in-javascript/5251551
  return s.replace(/[^0-9A-Za-z ]/g, (c) => {
    return "&#" + c.charCodeAt(0) + ";";
  });
}

function highlightPygmentize(code, lang, cb) {
  pygmentize({
    lang: lang,
    format: 'html',
    options: {
      nowrap: true,
      classprefix: 'pl-'
    }
  }, code, (err, res) => {
    if (err || res.toString() === 'undefined') {
      cb(escapeHTML(code));
    } else {
      cb(res);
    }
  });
}

renderer.config.highlight = highlightPygmentize;

module.exports = {
  resolvePath(s) {
    let a = Array.from(arguments);
    a.unshift(__dirname);
    return path.resolve.apply(null, a);
  },
  markdown(obj, keys, noReplaceUI) {
    let XSS = require('xss');
    let CSSFilter = require('cssfilter');
    let whiteList = Object.assign({}, require('xss/lib/default').whiteList);
    delete whiteList.audio;
    delete whiteList.video;
    for (let tag in whiteList) whiteList[tag] = whiteList[tag].concat(['id', 'style', 'class']);
    let xss = new XSS.FilterXSS({
      css: {
        whiteList: Object.assign({}, require('cssfilter/lib/default').whiteList, {
          'vertical-align': true,
          top: true,
          bottom: true,
          left: true,
          right: true
        })
      },
      whiteList: whiteList,
      stripIgnoreTag: true
    });
    let replaceXSS = s => {
      return xss.process(s);
    };
    let replaceUI = s => {
      if (noReplaceUI) return s;

      s = s.split('
').join('

').split('
').join('

')
           .split('
').join('
')
           .split('
').join('
').split('
').join('
');

      let cheerio = require('cheerio');
      let $ = cheerio.load('');
      let body = $('body');
      body.html(s);

      let a = $('img:only-child');
      for (let img of Array.from(a)) {
        if (!img.prev && !img.next) {
          $(img).css('display', 'block');
          $(img).css('margin', '0 auto');
        }
      }

      return body.html();
    };
    return new Promise((resolve, reject) => {
      if (!keys) {
        if (!obj || !obj.trim()) resolve("");
        else renderer(obj, { mathjaxUseHtml: true }, s => {
            resolve(replaceUI(replaceXSS(s)));
        });
      } else {
        let res = obj, cnt = keys.length;
        for (let key of keys) {
          renderer(res[key], { mathjaxUseHtml: true }, (s) => {
            res[key] = replaceUI(replaceXSS(s));
            if (!--cnt) resolve(res);
          });
        }
      }
    });
  },
  formatDate(ts, format) {
    let m = moment(ts * 1000);
    m.locale('eu');
    return m.format(format || 'L H:mm:ss');
  },
  formatTime(x) {
    let sgn = x < 0 ? '-' : '';
    x = Math.abs(x);
    function toStringWithPad(x) {
      x = parseInt(x);
      if (x < 10) return '0' + x.toString();
      else return x.toString();
    }
    return sgn + util.format('%s:%s:%s', toStringWithPad(x / 3600), toStringWithPad(x / 60 % 60), toStringWithPad(x % 60));
  },
  formatSize(x) {
    let res = filesize(x, { fixed: 1 }).calculate();
    if (res.result === parseInt(res.result)) res.fixed = res.result.toString();
    if (res.suffix.startsWith('Byte')) res.suffix = 'B';
    else res.suffix = res.suffix.replace('iB', '');
    return res.fixed + ' ' + res.suffix;
  },
  parseDate(s) {
    return parseInt(+new Date(s) / 1000);
  },
  getCurrentDate() {
    return parseInt(+new Date / 1000);
  },
  makeUrl(req_params, form) {
    let res = '';
    if (!req_params) res = '/';
    else if (req_params.originalUrl) {
      let u = url.parse(req_params.originalUrl);
      res = u.pathname;
    } else {
      if (!Array.isArray(req_params)) req_params = [req_params];
      for (let param of req_params) res += '/' + param;
    }
    let encoded = querystring.encode(form);
    if (encoded) res += '?' + encoded;
    return res;
  },
  escapeHTML: escapeHTML,
  highlight(code, lang) {
    return new Promise((resolve, reject) => {
      highlightPygmentize(code, lang, res => {
        resolve(res);
      });
    });
  },
  gravatar(email, size) {
    return gravatar.url(email, { s: size, d: 'mm' }).replace('www', 'cn');
  },
  parseTestData(filename) {
    let zip = new AdmZip(filename);
    let list = zip.getEntries().filter(e => !e.isDirectory).map(e => e.entryName);
    let res = [];
    if (!list.includes('data_rule.txt')) {
      res[0] = {};
      res[0].cases = [];
      for (let file of list) {
        let parsedName = path.parse(file);
        if (parsedName.ext === '.in') {
          if (list.includes(`${parsedName.name}.out`)) {
            res[0].cases.push({
              input: file,
              output: `${parsedName.name}.out`
            });
          }

          if (list.includes(`${parsedName.name}.ans`)) {
            res[0].cases.push({
              input: file,
              output: `${parsedName.name}.ans`
            });
          }
        }
      }

      res[0].type = 'sum';
      res[0].score = 100;
      res[0].cases.sort((a, b) => {
        function getLastInteger(s) {
          let re = /(\d+)\D*$/;
          let x = re.exec(s);
          if (x) return parseInt(x[1]);
          else return -1;
        }

        return getLastInteger(a.input) - getLastInteger(b.input);
      });
    } else {
      let lines = zip.readAsText('data_rule.txt').split('\r').join('').split('\n').filter(x => x.length !== 0);

      if (lines.length < 3) throw '无效的数据配置文件（data_rule.txt）。';

      let input = lines[lines.length - 2];
      let output = lines[lines.length - 1];

      for (let s = 0; s < lines.length - 2; ++s) {
        res[s] = {};
        res[s].cases = [];
        let numbers = lines[s].split(' ').filter(x => x);
        if (numbers[0].includes(':')) {
          let tokens = numbers[0].split(':');
          res[s].type = tokens[0] || 'sum';
          res[s].score = parseFloat(tokens[1]) || (100 / (lines.length - 2));
          numbers.shift();
        } else {
          res[s].type = 'sum';
          res[s].score = 100;
        }
        for (let i of numbers) {
          let testcase = {
            input: input.replace('#', i),
            output: output.replace('#', i)
          };

          if (!list.includes(testcase.input)) throw `找不到文件 ${testcase.input}`;
          if (!list.includes(testcase.output)) throw `找不到文件 ${testcase.output}`;
          res[s].cases.push(testcase);
        }
      }

      res = res.filter(x => x.cases && x.cases.length !== 0);
    }

    res.spj = list.includes('spj.js') || list.some(s => s.startsWith('spj_'));
    return res;
  },
  ansiToHTML(s) {
    let Convert = require('ansi-to-html');
    let convert = new Convert({ escapeXML: true });
    return convert.toHtml(s);
  },
  paginate(count, currPage, perPage) {
    currPage = parseInt(currPage);
    if (!currPage || currPage < 1) currPage = 1;

    let pageCnt = Math.ceil(count / perPage);
    if (currPage > pageCnt) currPage = pageCnt;

    return {
      currPage: currPage,
      perPage: perPage,
      pageCnt: pageCnt,
      toSQL: () => {
        if (!pageCnt) return '';
        else return ` LIMIT ${(currPage - 1) * perPage},${perPage}`
      }
    };
  },
  removeTitleTag(s) {
    return s.replace(/「[\S\s]+?」/, '');
  },
  md5(data) {
    let crypto = require('crypto');
    let md5 = crypto.createHash('md5');
    md5.update(data);
    return md5.digest('hex');
  },
  async hitokoto() {
    try {
      let request = require('request-promise');
      let res = await request({
        uri: 'http://api.hitokoto.us/rand',
        timeout: 1500,
        qs: {
          encode: 'json',
          cat: 'a'
        },
        json: true
      });
      if (!res.hitokoto) return null;
      else return res;
    } catch (e) {
      return null;
    }
  },
  isValidUsername(s) {
    return /^[a-zA-Z0-9\-\_]+$/.test(s);
  },
  locks: [],
  lock(key, cb) {
    let s = JSON.stringify(key);
    if (!this.locks[s]) this.locks[s] = new AsyncLock();
    return this.locks[s].acquire(s, cb);
  }
};
<|endoftext|>


<commit_before>var assert = require('assert');
var { URL_PREFIX, ADMIN_USER, TEST_USER } = require('../fixtures.js');
const webUI = require('../web-ui.js');

const WAIT_DURATION = 10000;

require('../acceptance-cmds.js'); // also checks that openwhyd/whydjs server is tested against the test database
// TODO: make sure that DB was reset before starting the whydJS app server

describe('bookmarklet - adding from a youtube track', function() {

  it(`user login`, webUI.loginAs(ADMIN_USER));

  it(`should load a youtube page`, function() {
    browser.url('https://www.youtube.com/watch?v=-F9vo4Z5lO4');
    browser.waitForContent(/1sec/);
  });

  it('should load the bookmarklet', function () {
    browser.injectJS(`${URL_PREFIX}/js/bookmarklet.js`);
  });

  it(`should have the bookmarklet loaded`, function() {
    function getBookmarklet() {
      return window._initWhydBk;
    }
    return !!browser.execute(getBookmarklet).value;
    // TODO: create a re-usable waitForSymbol() wdio command
  });

  it(`should find the page's track in the list`, function() {
    browser.waitForExist('.whydThumb');
  });

  /*
  // this code was useful to detect that chrome was not loading insecure/mixed content
  it(`should output browser log`, function () {
    console.log('browser log:', browser.log('browser').value.filter(i => i.level === 'SEVERE'));
    //console.log('driver log:', browser.log('driver').value.slice(-10));
    //console.log('client log:', browser.log('client').value.slice(-10));
    //console.log('server log:', browser.log('server').value.slice(-10));
    // TODO: create a re-usable displayLogs() wdio command
  });
  */

  // TODO: check that adding the track works

  //webUI.logout();
});

// Webdriver API documentation: http://webdriver.io/api.html
<commit_msg>failing test for https://github.com/openwhyd/openwhyd/issues/67#issuecomment-330033963<commit_after>var assert = require('assert');
var { URL_PREFIX, ADMIN_USER, TEST_USER } = require('../fixtures.js');
const webUI = require('../web-ui.js');

const WAIT_DURATION = 10000;

require('../acceptance-cmds.js'); // also checks that openwhyd/whydjs server is tested against the test database
// TODO: make sure that DB was reset before starting the whydJS app server

describe('bookmarklet - adding from a youtube track', function() {

  it(`user login`, webUI.loginAs(ADMIN_USER));

  it(`should load a youtube page`, function() {
    browser.url('https://www.youtube.com/watch?v=-F9vo4Z5lO4');
    browser.waitForContent(/1sec/);
  });

  it('should load the bookmarklet', function () {
    browser.injectJS(`${URL_PREFIX}/js/bookmarklet.js`);
  });

  it(`should have the bookmarklet loaded`, function() {
    function getBookmarklet() {
      return window._initWhydBk;
    }
    return !!browser.execute(getBookmarklet).value;
    // TODO: create a re-usable waitForSymbol() wdio command
  });

  it(`should find the page's track in the list`, function() {
    browser.waitForExist('.whydThumb');
  });

  /*
  // this code was useful to detect that chrome was not loading insecure/mixed content
  it(`should output browser log`, function () {
    console.log('browser log:', browser.log('browser').value.filter(i => i.level === 'SEVERE'));
    //console.log('driver log:', browser.log('driver').value.slice(-10));
    //console.log('client log:', browser.log('client').value.slice(-10));
    //console.log('server log:', browser.log('server').value.slice(-10));
    // TODO: create a re-usable displayLogs() wdio command
  });
  */

});

describe('bookmarklet - adding a second time from same youtube page', function() {

  it('should close the bookmarklet', function() {
    $('#whydHeader div').click();
  });

  it('should load the bookmarklet', function () {
    browser.injectJS(`${URL_PREFIX}/js/bookmarklet.js`);
  });

  it(`should find the page's track in the list`, function() {
    browser.waitForExist('.whydThumb');
  });

  it(`should output browser log`, function () {
    console.log('browser log:', browser.log('browser').value.slice(-30));
    // TODO: create a re-usable displayLogs() wdio command
  });

  // TODO: check that adding the track works

  //webUI.logout();

});

// Webdriver API documentation: http://webdriver.io/api.html
<|endoftext|>