diff --git a/bin/fanyi b/bin/fanyi index 22236d7..99671fa 100755 --- a/bin/fanyi +++ b/bin/fanyi @@ -4,15 +4,44 @@ const program = require('commander'); const chalk = require('chalk'); const updateNotifier = require('update-notifier'); const pkg = require('../package.json'); +const config = require('../lib/config'); updateNotifier({ pkg }).notify(); program - .option('-C, --nocolor', 'Output without color.') - // .option('-I, --iciba', 'Just output iciba.com\'s translate result.') - // .option('-Y, --youdao', 'Just output fanyi.youdao.com\'s translate result.') - // .option('-D, --dictionaryapi', 'Just output dictionaryapi.com\'s translate result.') - .version(pkg.version); + .version(pkg.version) + .option('-s, --say', 'Turn on the pronunciation') + .option('-S, --no-say', 'Turn off the pronunciation') + .action(args => { + const {say} = args; + const options = resolveOptions({ say }); + return runFY(options); + }) + + +program + .command('config') + .description('Set the global options') + .option('-c, --color', 'Output with color') + .option('-C, --no-color', 'Output without color') + .option('-i, --iciba', 'Enable the iciba translation engine') + .option('-I, --no-iciba', 'Disable the iciba translation engine') + .option('-y, --youdao', 'Enable the youdao translation engine') + .option('-Y, --no-youdao', 'Disable the youdao translation engine') + .option('-d, --dictionaryapi', 'Enable the dictionary translation engine') + .option('-D, --no-dictionaryapi', 'Disable the dictionary translation engine') + .option('-s, --say', 'Turn on the pronunciation') + .option('-S, --no-say', 'Turn off the pronunciation') + .action(args => { + // hack + // If the input is "fanyi config", then translate the word config. + if (process.argv.length === 3) { + return runFY(); + } + const {color, iciba, youdao, dictionaryapi, say} = args + const options = resolveOptions({ color, iciba, youdao, dictionaryapi, say }); + return config.write(options); + }); program.on('--help', function () { console.log(''); @@ -29,12 +58,22 @@ if (!process.argv.slice(2).length) { program.outputHelp(); } -const fanyi = require('..'); -const nocolor = program.nocolor; -if (nocolor) { - chalk = new chalk.constructor({ enabled: false }); +async function runFY(options = {}) { + const defaultOptions = await config.load(); + const mergedOptions = {...defaultOptions, ...options} + const fanyi = require('..'); + fanyi(program.args.join(' '), mergedOptions) } -fanyi(program.args.join(' '), { - nocolor, -}); +function resolveOptions(options) { + const opts = {} + Object.keys(options) + .filter(key => isBoolean(options[key])) + .map(key => opts[key] = options[key]); + + return opts; +} + +function isBoolean(val) { + return typeof val === 'boolean'; +} \ No newline at end of file diff --git a/index.js b/index.js index b0ef292..330993c 100644 --- a/index.js +++ b/index.js @@ -9,10 +9,13 @@ const ora = require('ora'); module.exports = function (word, options, callback) { console.log(''); + const { say, iciba, youdao, dictionaryapi } = options; + const requestCounts = [iciba, youdao, dictionaryapi].filter(isTrueOrUndefined).length; const spinner = ora().start(); + // say it try { - if (!process.env.CI) { + if (!process.env.CI && isTrueOrUndefined(say)) { require('say').speak(word, isChinese(word) ? 'Ting-Ting' : null); } } catch (e) { @@ -22,7 +25,7 @@ module.exports = function (word, options, callback) { let count = 0; const callbackAll = () => { count += 1; - if (count >= 3) { + if (count >= requestCounts) { spinner.stop(); callback && callback(); } @@ -31,47 +34,54 @@ module.exports = function (word, options, callback) { word = encodeURIComponent(word); // iciba - request.get(SOURCE.iciba.replace('${word}', word), function (error, response, body) { - if (!error && response.statusCode == 200) { - parseString(body, function (err, result) { - if (err) { - return; - } - print.iciba(result.dict, options); - }); - } - callbackAll(); - }); + isTrueOrUndefined(iciba) && + request.get(SOURCE.iciba.replace('${word}', word), function (error, response, body) { + if (!error && response.statusCode == 200) { + parseString(body, function (err, result) { + if (err) { + return; + } + print.iciba(result.dict, options); + }); + } + callbackAll(); + }); // youdao - request.get(SOURCE.youdao.replace('${word}', word), function (error, response, body) { - if (!error && response.statusCode == 200) { - try { - const data = JSON.parse(entities.decode(body)); - print.youdao(data, options); - } catch (e) { - // 来自您key的翻译API请求异常频繁,为保护其他用户的正常访问,只能暂时禁止您目前key的访问 + isTrueOrUndefined(youdao) && + request.get(SOURCE.youdao.replace('${word}', word), function (error, response, body) { + if (!error && response.statusCode == 200) { + try { + const data = JSON.parse(entities.decode(body)); + print.youdao(data, options); + } catch (e) { + // 来自您key的翻译API请求异常频繁,为保护其他用户的正常访问,只能暂时禁止您目前key的访问 + } } - } - callbackAll(); - }); + callbackAll(); + }); // dictionaryapi - request.get(SOURCE.dictionaryapi.replace('${word}', word), { timeout: 6000 }, function ( - error, - response, - body, - ) { - if (error) { - return callbackAll(); - } - if (response.statusCode == 200) { - parseString(body, function (err, result) { - if (!err) { - print.dictionaryapi(result.entry_list.entry, word, options); + isTrueOrUndefined(dictionaryapi) && + request.get( + SOURCE.dictionaryapi.replace('${word}', word), + { timeout: 6000 }, + function (error, response, body) { + if (error) { + return callbackAll(); } - }); - } - callbackAll(); - }); + if (response.statusCode == 200) { + parseString(body, function (err, result) { + if (!err) { + print.dictionaryapi(result.entry_list.entry, word, options); + } + }); + } + callbackAll(); + }, + ); }; + +function isTrueOrUndefined(val) { + return val === true || val === undefined; +} diff --git a/lib/config.js b/lib/config.js new file mode 100644 index 0000000..ee8de3b --- /dev/null +++ b/lib/config.js @@ -0,0 +1,28 @@ +const homedir = process.env.HOME || require('os').homedir(); +const path = require('path'); +const fs = require('fs'); +const configPath = path.resolve(homedir, '.fanyirc'); + +const config = { + async load(path = configPath) { + const emptyObj = {}; + if (fs.existsSync(path) && fs.statSync(path).isFile()) { + const content = fs.readFileSync(path, 'utf-8'); + try { + return JSON.parse(content.toString()); + } catch (e) { + return emptyObj; + } + } else { + return emptyObj; + } + }, + async write(options = {}, path = configPath) { + const defaultOptions = await config.load(path); + const mergedOptions = { ...defaultOptions, ...options }; + const content = JSON.stringify(mergedOptions); + return fs.writeFileSync(path, content); + }, +}; + +module.exports = config; diff --git a/lib/print.js b/lib/print.js index 1cdac42..ca5b5e6 100644 --- a/lib/print.js +++ b/lib/print.js @@ -1,8 +1,8 @@ -const chalk = require('chalk'); +let chalk = require('chalk'); -exports.iciba = function (data, options) { - if (options && options.nocolor) { - chalk = new chalk.constructor({ enabled: false }); +exports.iciba = function (data, options = {}) { + if (options.color === false) { + chalk = initChalkWithNoColor(); } let firstLine = ''; @@ -62,8 +62,8 @@ exports.iciba = function (data, options) { }; exports.youdao = function (data, options) { - if (options && options.nocolor) { - chalk = new chalk.constructor({ enabled: false }); + if (options.color === false) { + chalk = initChalkWithNoColor(); } let firstLine = ''; @@ -101,8 +101,8 @@ exports.youdao = function (data, options) { }; exports.dictionaryapi = function (data, word, options) { - if (options && options.nocolor) { - chalk = new chalk.constructor({ enabled: false }); + if (options.color === false) { + chalk = initChalkWithNoColor(); } if (word.indexOf('%') >= 0) { @@ -171,3 +171,11 @@ function highlight(string, key, defaultColor) { chalk[defaultColor]('$1') + chalk.yellow('$2'), ); } + +function initChalkWithNoColor() { + try { + return new chalk.constructor({ enabled: false }); + } catch (e) { + return new chalk.Instance({ level: 0 }); + } +}