diff --git a/.eslintrc.js b/.eslintrc.js index 5ef0410..366a723 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,37 +1,37 @@ module.exports = { - "env": { - "browser": false, - "es6": true, - "mocha": true, - "node": true - }, - "extends": [ - "google", - "eslint:recommended" - ], - "rules": { - "block-spacing": [2, "always"], - "brace-style": [2, "1tbs", { "allowSingleLine": true }], - "camelcase": [2, {properties: "never"}], - "comma-dangle": 0, - "curly": 0, - "key-spacing": [2, {align: "value"}], - "max-len": [1, 120], - "no-control-regex": 0, - "no-console": 1, - "no-empty": [2, { "allowEmptyCatch": true }], - "no-eval": 1, // we use it on purpose - "no-loop-func": 1, - "no-multi-spaces": 0, - "no-proto": 1, - "no-unused-expressions": 1, - "no-unused-vars": 1, - "no-var": 0, - "no-warning-comments": 0, - "prefer-rest-params": 0, - "prefer-spread": 0, - "quote-props": 1, - "quotes": [2, "single", {avoidEscape: true}], - "require-jsdoc": 0, - } + 'env': { + 'browser': false, + 'es6': true, + 'mocha': true, + 'node': true + }, + 'extends': [ + 'google', + 'eslint:recommended' + ], + 'rules': { + 'block-spacing': [2, 'always'], + 'brace-style': [2, '1tbs', {'allowSingleLine': true}], + 'camelcase': [2, {properties: 'never'}], + 'comma-dangle': 0, + 'curly': 0, + 'key-spacing': [2, {align: 'value'}], + 'max-len': [1, 120], + 'no-control-regex': 0, + 'no-console': 1, + 'no-empty': [2, {'allowEmptyCatch': true}], + 'no-eval': 1, // we use it on purpose + 'no-loop-func': 1, + 'no-multi-spaces': 0, + 'no-proto': 1, + 'no-unused-expressions': 1, + 'no-unused-vars': 1, + 'no-var': 0, + 'no-warning-comments': 0, + 'prefer-rest-params': 0, + 'prefer-spread': 0, + 'quote-props': 1, + 'quotes': [2, 'single', {avoidEscape: true}], + 'require-jsdoc': 0, + } }; diff --git a/lib/api.js b/lib/api.js deleted file mode 100644 index 22a3417..0000000 --- a/lib/api.js +++ /dev/null @@ -1,107 +0,0 @@ -'use strict'; -var _ = require('underscore'); - -var chalk = require('./chalk'); -var cache = require('./cache'); -var config = require('./config'); -var h = require('./helper'); -var file = require('./file'); -var icon = require('./icon'); -var log = require('./log'); -var Plugin = require('./plugin'); - -// We are expecting a tier configuration like: -// global config < local config < cli params -// Color is a tricky one so we manually handle it here. -function initColor() { - chalk.enabled = config.color.enable && chalk.enabled; - chalk.init(); - chalk.setTheme(config.color.theme); -} - -function initIcon() { - icon.init(); - icon.setTheme(config.icon.theme); -} - -function initLogLevel() { - log.init(); - - let level = 'INFO'; - if (process.argv.indexOf('-v') >= 0) level = 'DEBUG'; - if (process.argv.indexOf('-vv') >= 0) level = 'TRACE'; - - // print HTTP details in TRACE - if (level === 'TRACE') { - const request = require('request'); - request.debug = true; - - console.error = _.wrap(console.error, function(func) { - let args = Array.from(arguments); - args.shift(); - - // FIXME: hack HTTP request log, hope no one else use it... - if (args.length > 0 && args[0].indexOf('REQUEST ') === 0) { - args = args.map((x) => h.printSafeHTTP(x)); - log.trace.apply(log, args); - } else { - log.info.apply(log, args); - } - }); - } - - log.setLevel(level); -} - -function initDir() { - file.init(); - file.mkdir(file.homeDir()) -} - -function initPlugins(cb) { - if (Plugin.init()) { - Plugin.save(); - return cb(); - } else { - Plugin.installMissing(function(e) { - if (e) return cb(e); - Plugin.init(); - return cb(); - }); - } -} - -var cli = {}; - -function runCommand() { - var yargs = require('yargs'); - h.width = yargs.terminalWidth(); - yargs.commandDir('commands') - .completion() - .help('h') - .alias('h', 'help') - .version(false) - .epilog('Seek more help at https://skygragon.github.io/leetcode-cli/commands') - .wrap(Math.min(h.width, 120)) - .argv; -} - -cli.run = function() { - process.stdout.on('error', function(e) { - if (e.code === 'EPIPE') process.exit(); - }); - - config.init(); - - initColor(); - initIcon(); - initLogLevel(); - initDir(); - initPlugins(function(e) { - if (e) return log.fatal(e); - cache.init(); - runCommand(); - }); -}; - -module.exports = cli; diff --git a/lib/cli.js b/lib/cli.js index 1965cea..fb84dbe 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -55,7 +55,7 @@ function initLogLevel() { function initDir() { file.init(); - file.mkdir(file.homeDir()) + file.mkdir(file.homeDir()); } function initPlugins(cb) { @@ -77,13 +77,13 @@ function runCommand() { var yargs = require('yargs'); h.width = yargs.terminalWidth(); yargs.commandDir('commands') - .completion() - .help('h') - .alias('h', 'help') - .version(false) - .epilog('Seek more help at https://skygragon.github.io/leetcode-cli/commands') - .wrap(Math.min(h.width, 120)) - .argv; + .completion() + .help('h') + .alias('h', 'help') + .version(false) + .epilog('Seek more help at https://skygragon.github.io/leetcode-cli/commands') + .wrap(Math.min(h.width, 120)) + .argv; } cli.run = function() { @@ -96,7 +96,7 @@ cli.run = function() { initColor(); initIcon(); initLogLevel(); - initDir() + initDir(); initPlugins(function(e) { if (e) return log.fatal(e); cache.init(); diff --git a/lib/commands/list.js b/lib/commands/list.js index b38cddd..50dc25d 100644 --- a/lib/commands/list.js +++ b/lib/commands/list.js @@ -14,32 +14,34 @@ const cmd = { desc: 'List questions', builder: function(yargs) { return yargs - .option('q', core.filters.query) - .option('s', { - alias: 'stat', - type: 'boolean', - default: false, - describe: 'Show statistics of listed questions' - }) - .option('t', core.filters.tag) - .option('x', { - alias: 'extra', - type: 'boolean', - default: false, - describe: 'Show extra details: category, companies, tags.' - }) - .positional('keyword', { - type: 'string', - default: '', - describe: 'Filter questions by keyword' - }) - .example(chalk.yellow('leetcode list'), 'List all questions') - .example(chalk.yellow('leetcode list -x'), 'Show extra info of questions, e.g. tags') - .example('', '') - .example(chalk.yellow('leetcode list array'), 'List questions that has "array" in name') - .example(chalk.yellow('leetcode list -q eD'), 'List questions that with easy level and not done') - .example(chalk.yellow('leetcode list -t google'), 'List questions from Google company (require plugin)') - .example(chalk.yellow('leetcode list -t stack'), 'List questions realted to stack (require plugin)'); + .option('q', core.filters.query) + .option('s', { + alias: 'stat', + type: 'boolean', + default: false, + describe: 'Show statistics of listed questions' + }) + .option('t', core.filters.tag) + .option('x', { + alias: 'extra', + type: 'boolean', + default: false, + describe: 'Show extra details: category, companies, tags.' + }) + .option('c', core.filters.category) + .positional('keyword', { + type: 'string', + default: '', + describe: 'Filter questions by keyword' + }) + .example(chalk.yellow('leetcode list'), 'List all questions') + .example(chalk.yellow('leetcode list -x'), 'Show extra info of questions, e.g. tags') + .example('', '') + .example(chalk.yellow('leetcode list array'), 'List questions that has "array" in name') + .example(chalk.yellow('leetcode list -q eD'), 'List questions that with easy level and not done') + .example(chalk.yellow('leetcode list -t google'), 'List questions from Google company (require plugin)') + .example(chalk.yellow('leetcode list -t stack'), 'List questions realted to stack (require plugin)') + .example(chalk.yellow('leetcode list -c lcof'), 'List questions from category (require plugin)'); } }; @@ -53,14 +55,14 @@ cmd.handler = function(argv) { if (word.endsWith(word.substr(-1).repeat(6))) { log.warn('Hmmm...you might need a new keyboard?'); } - problems = problems.filter(x => x.name.toLowerCase().includes(word)); + problems = problems.filter((x) => x.name.toLowerCase().includes(word)); } const stat = {}; - for (let x of ['locked', 'starred', 'ac', 'notac', 'None', 'Easy', 'Medium', 'Hard']) stat[x] = 0; + for (const x of ['locked', 'starred', 'ac', 'notac', 'None', 'Easy', 'Medium', 'Hard']) stat[x] = 0; - problems = _.sortBy(problems, x => x.id); - for (let problem of problems) { + problems = _.sortBy(problems, (x) => x.id); + for (const problem of problems) { stat[problem.level] = (stat[problem.level] || 0) + 1; stat[problem.state] = (stat[problem.state] || 0) + 1; if (problem.locked) ++stat.locked; @@ -82,7 +84,7 @@ cmd.handler = function(argv) { let buf = []; let len = 0; - for (let x of badges) { + for (const x of badges) { if (len + x.length + 3 >= 60) { log.printf('%12s%s', ' ', chalk.gray(buf.join(' | '))); buf = []; diff --git a/lib/core.js b/lib/core.js index 10dfd17..138efee 100644 --- a/lib/core.js +++ b/lib/core.js @@ -33,17 +33,23 @@ core.filters = { type: 'array', default: [], describe: 'Filter questions by tag' + }, + category: { + alias: 'category', + type: 'string', + default: '', + describe: 'Filter questions by category' } }; function hasTag(o, tag) { - return Array.isArray(o) && o.some(x => x.indexOf(tag.toLowerCase()) >= 0); + return Array.isArray(o) && o.some((x) => x.indexOf(tag.toLowerCase()) >= 0); } const isLevel = (x, q) => x.level[0].toLowerCase() === q.toLowerCase(); -const isACed = x => x.state === 'ac'; -const isLocked = x => x.locked; -const isStarred = x => x.starred; +const isACed = (x) => x.state === 'ac'; +const isLocked = (x) => x.locked; +const isStarred = (x) => x.starred; const QUERY_HANDLERS = { e: isLevel, @@ -63,14 +69,19 @@ const QUERY_HANDLERS = { core.filterProblems = function(opts, cb) { this.getProblems(function(e, problems) { if (e) return cb(e); - - for (let q of (opts.query || '').split('')) { + for (const q of (opts.query || '').split('')) { const f = QUERY_HANDLERS[q]; if (!f) continue; - problems = problems.filter(x => f(x, q)); + problems = problems.filter((x) => f(x, q)); + } + + if (opts.category) { + problems = problems.filter((x) => { + return x.category === opts.category; + }); } - for (let t of (opts.tag || [])) { + for (const t of (opts.tag || [])) { problems = problems.filter(function(x) { return x.category === t || hasTag(x.companies, t) || diff --git a/package-lock.json b/package-lock.json index 2b22fb1..0e44c41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -865,7 +865,6 @@ "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.2", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -1283,8 +1282,7 @@ "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "optionator": "^0.8.1" }, "bin": { "escodegen": "bin/escodegen.js", @@ -2729,9 +2727,6 @@ "resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz?cache=0&sync_timestamp=1604161912962&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - }, "optionalDependencies": { "graceful-fs": "^4.1.6" } diff --git a/package.json b/package.json index 1dcb688..8324211 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@baoxi/vsc-leetcode-cli", - "version": "2.7.1", + "version": "2.8.1", "description": "A cli tool to enjoy leetcode!", "engines": { "node": ">=12" @@ -60,7 +60,7 @@ "prompt": "1.1.0", "request": "2.88.2", "supports-color": "8.1.1", - "underscore": "1.12.0", + "underscore": "1.12", "wordwrap": "1.0.0", "yargs": "16.2.0" },