前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >10分钟开发一个npm全局依赖包(下)

10分钟开发一个npm全局依赖包(下)

作者头像
kai666666
发布2020-10-17 09:49:36
6300
发布2020-10-17 09:49:36
举报
文章被收录于专栏:橙光笔记橙光笔记

在上一篇中我们用了10分钟实现了一个完整的古诗词命令行工具,本章中我们主要简绍2个命令行工具开发中常用的库,整个代码大概用时20分钟。


修改命令行颜色

第一个简绍的库就是‘colors-cli’,他支持修改打印出来的文字的样式。 首先安装一下这个依赖npm install colors-cli,新建一个文件test-color.js,测试一下它的代码:

var color = require('colors-cli/safe')
console.log(color.red.bold('Error!'));
console.log(color.yellow.magenta_b('Warning'));
console.log(color.blue.underline('Notice'));

引入color库的时候可以使用var color = require('colors-cli/safe'),也可以使用var color = require('colors-cli'),推荐使用前者,因为前者可以支持链式调用,使用起来更方便。上面运行结果如下:

修改颜色
修改颜色

他是怎么实现的呢?其实是把文字用特殊符号包了一层,命令行对这种特殊符号会处理成样式,就比如color.red.bold('Error!')其实最后会返回一个字符串'[1mError!',所以上面三行log代码和下面的结果是一样的,你可以直接用node运行一下:

console.log('Error!');
console.log('Warning');
console.log('Notice');

处理用户输入

在使用命令行的时候往往需要根据用户的参数给出友好的提示,yargs就是处理这种情况的一个优质的库。 有关yargs的具体使用可以直接看官方的文档,这里就不展开说了。现在我们做一个需求,就是根据用户传入的值,来改变诗词、作者、来源的颜色。代码大致是这样的:

#!/usr/bin/env node
const axios = require('axios');
const color = require('colors-cli/safe');
let argv = require('yargs')
  .option('ps', {
    alias: 'poem-style',
    demand: false,
    default: 'blue_bt',
    describe: '诗词样式,如--ps=blue_bt',
    type: 'string'
  }).option('as', {
    alias: 'author-style',
    demand: false,
    default: 'green_bt',
    describe: '作者样式,如--as=green_bt',
    type: 'string'
  }).option('os', {
    alias: 'origin-style',
    demand: false,
    default: 'cyan',
    describe: '来源颜色,如--os=cyan',
    type: 'string'
  }).option('h', {
    alias: 'help',
    demand: false,
    boolean: true,
    describe: '帮助',
  }).option('v', {
    alias: 'version',
    demand: false,
    boolean: true,
    describe: '版本号',
  })
  .argv;

function getColorMethod(commandStr = ''){
  let command = commandStr.replace(/\,/g,'.').split(".");
  let colorMethod = color
  for (let i = 0; i < command.length; i++) {
    colorMethod = colorMethod[command[i]];
  }
  return colorMethod;
}

axios.get('https://api.gushi.ci/all.json')
  .then(function (response) {
    let data = response.data || {};
    let signature = data.author + '《' + data.origin + '》';
    let prefix =  '———— ';
    let paddingSpacing = '';
    let spacingLength = data.content.length * 2 - signature.length * 2 - prefix.length;
    if (spacingLength > 0) {
      if (data.origin.indexOf('·') !== -1) {
        spacingLength++;
      }
      paddingSpacing = new Array(spacingLength).fill(' ').join('');
    }
    signature = getColorMethod(argv.as)(data.author) + '《' + getColorMethod(argv.os)(data.origin) + '》';
    signature = (paddingSpacing + prefix) + signature
    console.log();
    console.log(getColorMethod(argv.ps)(data.content));
    console.log(signature);
    console.log();
  });

运行结果如下:

支持修改颜色
支持修改颜色

代码还是在可以控制的行数范围内,上述代码中4~34行,是yargs的处理,也是通用的一种写法,这里面有2个属性比较特殊一个是help另一个是version,从下面的结果我们可以看到,当输入这两个的时候都会阻止代码的执行,并直接返回相应的信息,如运行node index -h会返回帮助信息、node index -v会返回版本信息。在代码中我们可以使用argv.psargv.asargv.os等(其实就是option函数的第一个值)来获取参数的值。getColorMethod运行使用英文的点或者逗号来拆分以添加多个样式。

代码优化

上述代码中getColorMethod方法其实可以抽取出去,另外color库并不是支持输入任何参数,比如你输入node index --as=123就会报错,因为123并不是color所支持的样式,所以我们有必要对颜色相关的操作抽取成一个文件,另外检测一下color库是否支持这个颜色,不支持的话给出有好地提示,现在新建color-util.js文件。代码如下:

const color = require('colors-cli/safe')

const COLOR_TITLE = ['样式','前景色','背景色','前景色(明亮)','背景色(明亮)'];
const COLOR_STYLE = ['bold', 'faint', 'italic', 'underline', 'blink', 'overline', 'inverse', 'conceal', 'strike'];
const COLOR_FOREGROUND = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'];
const COLOR_BACKGROUND = ['black_b', 'red_b', 'green_b', 'yellow_b', 'blue_b', 'magenta_b', 'cyan_b', 'white_b'];
const COLOR_FOREGROUND_BRIGHT = ['black_bt', 'red_bt', 'green_bt', 'yellow_bt', 'blue_bt', 'magenta_bt', 'cyan_bt', 'white_bt'];
const COLOR_BACKGROUND_BRIGHT = ['black_bbt', 'red_bbt', 'green_bbt', 'yellow_bbt', 'blue_bbt', 'magenta_bbt', 'cyan_bbt', 'white_bbt'];
const STYLE = [ COLOR_STYLE, COLOR_FOREGROUND, COLOR_BACKGROUND, COLOR_FOREGROUND_BRIGHT, COLOR_BACKGROUND_BRIGHT];

function printSupportStyle(){
  console.log('所支持的样式有:\n');
  let message = '';

  for (let i = 0; i < COLOR_TITLE.length; i++) {
    message = STYLE[i].reduce(function (pre,next){
      return pre + color[next](next) + ' '
    }, COLOR_TITLE[i] + ": ");
    console.log(message);
  }
  // 换行
  console.log();
}

function checkStyle(styleName){
  return STYLE.join(',').split(',').indexOf(styleName) !== -1;
}

function getColorMethod(commandStr = ''){
  let command = commandStr.replace(/\,/g,'.').split(".");
  let colorMethod = color
  for (let i = 0; i < command.length; i++) {
    if (checkStyle(command[i])) {
      colorMethod = colorMethod[command[i]];
    } else {
      throw new Error('\n不支持的样式:' + command[i]);
    }
  }
  return colorMethod;
}

module.exports = {
  color,
  printSupportStyle,
  checkStyle,
  getColorMethod
}

请求接口的地方我们也可以封装成一个方法,这样可以减少耦合,另外也可以支持模块直接引入(直接使用require引入)。新建random-poem.js文件,代码如下:

const axios = require('axios');

module.exports = function (){
  return new Promise(function (resolve, reject) {
    axios.get('https://api.gushi.ci/all.json')
    .then(function (response) {
      resolve(response.data || {})
    }).catch(function (error){
      reject(error)
    });
  });
}

因为网络请求是异步的,所以需要使用回调或者Promise来处理,我们这里就使用Promise吧。此时还需要修改一下package.json文件,添加main字段,该字段是用来告诉直接模块引入的时候引入哪个文件。

{
  "name": "poem-cli",
  "version": "1.0.0",
  "description": "命令行随机打印一句诗词。",
  "main": "random-poem.js",
  "bin": {
    "poem-cli": "index.js"
  },
  "scripts": {
    "start": "node index"
  },
  "keywords": [
    "诗词",
    "命令行",
    "有趣"
  ],
  "author": "Orange",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.19.0",
    "colors-cli": "^1.0.26",
    "yargs": "^14.0.0"
  }
}

此时需要注意第5行代码。最后修改index.js文件,使用这些封装的方法:

#!/usr/bin/env node
const colorUtil = require('./color-util')
const randomPoem = require('./random-poem')
let argv = require('yargs')
    .option('s', {
      alias: 'style',
      demand: false,
      boolean: true,
      describe: '显示所支持的样式',
    }).option('ps', {
        alias: 'poem-style',
        demand: false,
        default: 'blue_bt',
        describe: '诗词样式,如--ps=blue_bt',
        type: 'string'
    }).option('as', {
        alias: 'author-style',
        demand: false,
        default: 'green_bt',
        describe: '作者样式,如--as=green_bt',
        type: 'string'
    }).option('os', {
      alias: 'origin-style',
      demand: false,
      default: 'cyan',
      describe: '来源颜色,如--os=cyan',
      type: 'string'
    }).option('h', {
      alias: 'help',
      demand: false,
      boolean: true,
      describe: '帮助',
    }).option('v', {
      alias: 'version',
      demand: false,
      boolean: true,
      describe: '版本号',
    })
    .argv;

// 显示所支持的样式
if (!!argv.s) {
  colorUtil.printSupportStyle();
} else {
  randomPoem().then(function (data){
    let signature = data.author + '《' + data.origin + '》';
    let prefix =  '———— ';
    let paddingSpacing = '';
    let spacingLength = data.content.length * 2 - signature.length * 2 - prefix.length;
    if (spacingLength > 0) {
      if (data.origin.indexOf('·') !== -1) {
        spacingLength++;
      }
      paddingSpacing = new Array(spacingLength).fill(' ').join('');
    }
    try {
      // 添加颜色
      signature = colorUtil.getColorMethod(argv.as)(data.author) + '《' + colorUtil.getColorMethod(argv.os)(data.origin) + '》';
      signature = (paddingSpacing + prefix) + signature
      console.log();
      console.log(colorUtil.getColorMethod(argv.ps)(data.content));
      console.log(signature);
      console.log();
    } catch (error) {
      // 错误处理
      console.log(colorUtil.color.red(error.message));
      colorUtil.printSupportStyle();
    }
  })
}

测试一下输入不支持的情况,你会发现提示的信息已经很友好了:

完整版
完整版

最后把多余的test-color.js文件删除了就可以提交了。

就这样我们把一个功能完善的古诗词命令行工具做完了,需要注意一点再次提交的时候,也就是运行npm publish前,需要修改一下package.json中的version字段,而且必须大于当前的版本号,建议使用npm version 1.0.1这样的命令去修改,因为该命令会顺带把package-lock.json文件中的版本号也改了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 修改命令行颜色
  • 处理用户输入
  • 代码优化
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档