ایجاد Command Line با استفاده از JavaScript

زبان برنامه نویسی JavaScript در ابتدا به عنوان یک زبان اسکریپت در بخش front برنامه های تحت وب برای تعامل بیشتر با کاربران استفاده می شد، از سال 2012 با معرفی NodeJS و توسعه عملکردهای آن به تدریج تکامل یافته و اکنون از این زبان می توان در بخش های مختلف استفاده کرد: برنامه های سمت سرور، برنامه های desktop، اپ های موبایل و …

برای ایجاد CLI نیاز به نصب NodeJS و NPM دارید، در صورتی که بر روی سیستم شما نصب نشده است با مراجعه به آدرس زیر NodeJS را دانلود و نصب نمائید (npm به همراه NodeJS نصب خواهد شد):

https://nodejs.org/en/download/

با استفاده از cli (command line) می توانید یک سری عملیات های معمول را خودکار کرده یا ابزارهایی رو برای سریعتر شدن روند توسعه برنامه هایتان ایجاد کنید. نمونه ای از ابزارهای معروفی که دارای cli هستند در زیر لیست شده است:

  • git
  • gulp
  • grunt
  • sass
  • react-native
  • angular-cli
  • ,...

به عنوان مثال در git فرمان های متفاوتی وجود دارد که برخی از فرامین معمول مورد استفاده برای درک عملکرد command line در زیر به طور مختصر شرح داده ایم:

1- فرمان init

git init

این دستور عملیات های لازم برای استفاده از سورس کنترل در پروژه مد نظر شما را به صورت خودکار انجام می دهد حالا فرض کنید که اگر می خواستید همه این موارد را خودتان مرحله به مرحله انجام بدهید!!

از ایجاد پوشه .git گرفته تا سایر پارامترهای لازم که بتوان از git در پروژه استفاده کرد.

2- فرمان add

git add .

این فرمان فایل ها و تغییراتی را که در پروژه انجام داده اید برای commit به مخزن git اضافه می کند، حال فرض کنید اگر بخواهید این کار را خودتان انجام دهید، باید بر روی پوشه راست کلیک کنید که بسته به نوع تغییراتی که میخواین commit کنید ممکن هست بالاترین پوشه یا پوشه ای در داخل پوشه جاری باشد، باید مسیر را دنبال کنید تا به پوشه مورد نظر برسید و فایل مورد نظر را برای اجرای فرمان add جستجو کنید اما در command line می توانید با دانستن مسیر مورد نظر و در کمترین زمان ممکن فرمان افزودن به مخزن رو اجرا کنید

و …

تعریف پروژه

برای اینکه بهتر بتوانیم درک کنیم که چگونه می توانیم یک CLI ایجاد کنیم با تعریف یک پروژه قدم به قدم جلو رفته و مراحل را شرح می دهیم. برای مثال می خواهیم یک پروژه ایجاد کنیم که نام، نام خانوادگی، شماره همراه و سن کاربر را دریافت کرده و در خروجی نمایش دهد.

این برنامه داده ها را ذخیره نمی کند و فقط برای نمایش روال کار هست اما شما می توانید دیتا را در پایگاه داده و... ذخیره کنید.

سورس پروژه را می توانید در مسیر زیر دانلود کنید:

https://github.com/afshintalebi/cli-sample-person-info

مرحله اول: ایجاد پروژه و مقداردهی اولیه با npm

ابتدا یک پوشه با نام دلخواه ایجاد کنید، ما اسم پوشه را cli-sample-person-info در نظر گرفتیم. بعد از ایجاد پوشه در Terminal به مسیر این پوشه رفته و فرمان زیر رو اجرا می کنیم:

npm init

در ادامه یک سری اطلاعات پروژه از شما درخواست می شود که می توانید اطلاعات مورد نظرتان را وارد کنید یا اینکه اطلاعات پیش فرض را تایید کنید. برای مشاهده مراحل مقداردهی بر روی لینک زیر کلیک کنید تا فیلم مربوطه را مشاهده کنید:

https://www.aparat.com/v/BIGZz

مرحله دوم: ایجاد فایل index

در پروژه یک فایل با نام index.js ایجاد می کنیم، می توانید از طریق ترمینال و یا از ide ها استفاده کنید. بعد از ایجاد فایل کد زیر را در فایل ذخیره کنید:

console.log(“Hello World”)

مرحله سوم: ایجاد CLI

اگر تجربه کار با NodeJS را داشته باشید با دستور زیر باید آشنا باشید:

node index,js

دستور node برای تفسیر فایل های js استفاده می شود. اگر فرمان بالا رو در مسیر پروژه اجرا کنید پیغام Hello World بر روی صفحه نمایش داده خواهد شد.

تبدیل فایل js به اسکریپت CLI :

برای اینکه برنامه همانند سایر اسکریپت های cli قابل اجرا باشد، باید از Shebang Line استفاده کنیم. با استفاده از Shebang فایل های js قابلیت اجرا در cli خواهند داشت. برای این منظور خط زیر را در ابتدای فایل js قرار می دهیم:

#!/usr/bin/env node

در این روش برای سیستم های مبتنی بر unix مشخص می کنیم که این فایل با چه فرمانی باید اجرا شود. این خط در ویندوز به هنگام اجرا نادیده گرفته شده و به عنوان توضیح (comment) در نظر گرفته می شود، اما باز هم باید در ابتدای فایل قرار گیرد چون هنگام استفاده از cli بر روی ویندوز npm این خط را می خواند.

فعال کردن ویژگی executable:

ویژگی executable برای فایل javascript که برای cli استفاده می شود در سیستمهای مبتنی بر unix باید فعال شود، در بیشتر فایل های جدید که ایجاد می شوند این ویژگی فعال نیست. برای این منظور فرمان زیر رو در ترمینال اجرا کنید:

chmod +x index.js

برای ادامه می خواهیم با استفاده از console پیغام Hello World را در خروجی نمایش دهیم اما با وارد کردن نام فایل و بدون تایپ فرمان node، برای این منظور #!/usr/bin/env node را در ابتدای فایل index.js اضافه می کنیم:

حال اگر index.js/. را در ترمینال اجرا کنید پیغام Hello World نمایش داده می شود:

کد بالا تنها در سیستم های unix اجرا میشود، برای اجرا در ویندوز باید از node.cmd استفاده کنید به صورت زیر:

node.cmd index.js

تا اینجا برنامه را همانند یک خط فرمان در سیستم های unix اجرا کردیم اما برای اجرا در ویندوز هنوز باید از node.cmd استفاده کنیم.

مرحله چهارم: تعریف یک نام مستعار برای اجرای اسکریپت cli

در npm می توانید برای اجرای اسکریپت مورد نظرتان یک نام مستعار (command name) تعریف کنید که با اجرای این نام عملیات مورد نظر شما انجام می شود. این تنظیمات را باید درون فایل package.json و در قسمت bin ذخیره کنید.

در تصویر بالا کادر رنگی بخشی است که نام مستعار برای اسکریپت cli را تعریف می کنیم، در مثال بالا print-hello نام فرمان و index.php/. نام فایل می باشد. در ادامه خواهیم دید که با اجرای فرمان print-hello پیغام Hello World در ترمینال نمایش داده خواهد شد.

نکته: در نامگذاری فرمان ها سعی کنید از انتخاب نام های متداول مانند ls, dir, mkdir, git, … اجتناب کنید. در صورتی که یکی از این نام ها رو انتخاب کنید اسکریپت شما اجرا نمی شود و ممکن هست با نتایج متفاوتی برخورد داشته باشید.

مرحله پنجم: لینک کردن فرمان

با لینک کردن فرمان می توانید به صورت عمومی در هر مسیری از فرمان مدنظر استفاده کرد.

اجرای فرمان npm link باعث میشود که به صورت local یک ارجاع (reference) به اسکریپت شما ایجاد شود. در این حالت شما در هر مسیری در ترمینال نام فرمان رو اجرا کنید سیستم اسکریپت شما رو تشخیص داده و عملیات تعریف شده را اجرا می کند. به عبارتی می توان گفت که npm link عملیات نصب پکیج های npm را شبیه سازی می کند.

حالا در مسیر جاری اسکریپت cli فرمان npm link رو اجرا کنید و سپس فرمان print-hello رو می توانید به صورت عمومی اجرا کنید.

مرحله ششم: حذف فرمان لینک شده

در صورتی که بخواهید بعد از تست ها و اتمام پروژه، برنامه را از حالت لینک شده خارج کنید کافیست فرمان زیر رو اجرا کنید:

npm unlink

مرحله هفتم: دریافت ورودی از کاربر در هنگام اجرای برنامه

می خواهیم برنامه را کمی کاملتر کنیم، به جای کلمه World نام و نام خانوادگی کاربر را دریافت کرده و در خروجی نمایش دهیم. برای گرفتن ورودی از کاربر دو روش وجود دارد:

  1. ارسال همه مقادیر ورودی به همراه فرمان توسط کاربر
  2. اجرای فرمان و دریافت اطلاعات از کاربر مرحله به مرحله

دریافت مقادیر ورودی به همراه فرمان:

در این روش کاربر مقادیر مورد نظر را همزمان با تایپ نام فرمان برای برنامه ارسال می کند، با خود API های NodeJS می توان این عمل را انجام داد اما کتابخانه هایی وجود دارد که این عمل را ساده تر می کند و تعداد خط های کدی که باید نوشته شود به مراتب کمتر می شود. کتابخانه های متفاوتی برای این منظور وجود دارد مانند commander ، yargs و…

در این پروژه ما از commander استفاده می کنیم. ابتدا با اجرای فرمان زیر commander را نصب کنید:

npm install commander --save

محتویات فایل index,js را به غیر از سطر اول که Shebang Line می باشد را حذف می کنیم و خط کد های زیر را وارد می کنیم:

var program = require('commander');
program  
.option('-f, --firstname', 'The user first name')
.option('-l, --lastname', 'The user last name')
.action(function () {
      console.log('Hello %s %s', program.firstname.toUpperCase(), program.lastname.toUpperCase());
 })
 .parse(process.argv);


سطر اول کتابخانه را در متغیر program ذخیره می کند. در ادامه از متدهای option، action و parse استفاده شده است.

  • متد option: این متد برای تعریف تنظیمات و آرگومان های فرمان استفاده می شود، همچنین می توانید راهنمای هر تنظیم را در این متد تعریف کنید. در مثال بالا دو آرگومان برای دریافت نام و نام خانوادگی تعریف کرده ایم که کاربر می تواند به صورت اختصاری یا به صورت کامل نام آرگومان به همراه مقادیر را وارد کرده و ارسال کند.
  • متد action: این متد یک تابع به عنوان پارامتر دریافت می کند که می توانید عملیات مورد نظر خود را در این تابع تعریف کنید، در مثال بالا نام و نام خانوادگی که همراه فرمان در پارامترها ارسال می شود را در خروجی چاپ می کنیم.
  • متد parse: این متد کل پارامترهای ارسالی را دریافت کرده و پردازش می کند تا در متدهای تعریف شده قابل استفاده باشد.

در تصویر زیر اجرای فرمان در حالت های مختلف و نتایج را مشاهده می کنید:

نکته: در تصویر بالا برنامه به npm لینک شده است به همین دلیل از نام فرمان استفاده شده است اگر شما برنامه را لینک نکرده اید باید نام فایل را به جای نام فرمان استفاده کنید. index.js/.
نکته: در تصویر بالا برنامه به npm لینک شده است به همین دلیل از نام فرمان استفاده شده است اگر شما برنامه را لینک نکرده اید باید نام فایل را به جای نام فرمان استفاده کنید. index.js/.


دریافت مقادیر از کاربر بعد از اجرای فرمان

می توانید مقادیر مورد نظر خود را بعد از اجرای فرمان مرحله به مرحله از کاربر دریافت کنید، برای این منظور از کتابخانه co-prompt استفاده می کنیم که بر مبنای کتابخانه co توسعه داده شده است. برای استفاده از این کتابخانه باید با ساختار ES6 آشنایی مقدماتی داشته باشید چون این کتابخانه از generator function استفاده می کند.

ابتدا کتابخانه ها را با اجرای دستور زیر نصب می کنیم:

npm install --save co co-prompt

محتویات فایل index,js را به غیر از سطر اول که Shebang Line می باشد را حذف می کنیم و خط کد های زیر را وارد می کنیم:

var co = require('co');
var prompt = require('co-prompt');
var program = require('commander');
program
  .option('-f, --firstname', 'The user first name')
  .option('-l, --lastname', 'The user last name')
  .option('-l, --cellphone', 'The user cellphone number')
  .option('-l, --age', 'The user age')
  .action(function () {
        co(function* () {
                var firstname = yield prompt('firstname: ');
                var lastname = yield prompt('lastname: ');
                var cellphone = yield prompt('cellphone number: ');
                var age = yield prompt('your age: ');
                console.log('------------');
                console.log('Hello %s %s', firstname.toUpperCase(), lastname.toUpperCase());
                console.log('CellPhone Number: ', cellphone);
                console.log('Your Age: ', age);
                console.log('Thanks for send your information.');
   });
   })
   .parse(process.argv);


در مثال بالا چهار پارامتر تعریف شده که نام، نام خانوادگی، شماره همراه و سن کاربر را دریافت می کند و مقادیر را در خروجی چاپ می کند. در متد action تابع co فراخوانی شده که یک generator function به عنوان پارامتر آن ارسال می شود در این تابع شما می توانید مقادیر را مرحله به مرحله از کاربر دریافت کنید و در خروجی چاپ کنید:

مرحله پایانی: رنگی کردن متون و پیام ها در خروجی

برای رنگی کردن پیام ها در خروجی از کتابخانه chalk استفاده می کنیم. ابتدا با اجرای فرمان زیر کتابخانه رو به پروژه اضافه می کنیم:

npm install --save chalk

با این کتابخانه می توانید متن ها و پس زمینه آنها را رنگی کنید. کار با آن بسیار ساده می باشد و با مطالعه راهنمای آن به راحتی می توانید نحوه استفاده از آن را فرا بگیرید.

var co = require('co');
var prompt = require('co-prompt');
var program = require('commander');
var chalk = require('chalk');
program
    .option('-f, --firstname', chalk.blue('User first name'))
    .option('-l, --lastname', chalk.blue('User last name'))
    .option('-l, --cellphone', chalk.blue('User cellphone number'))
    .option('-l, --age', chalk.blue('User age'))
    .action(function () {
        co(function* () {
            var firstname = yield prompt(chalk.blue('firstname: '));
            var lastname = yield prompt(chalk.red('lastname: '));
            var cellphone = yield prompt(chalk.green('cellphone number: '));
            var age = yield prompt(chalk.yellow('your age: '));
            console.log('------------');
            console.log('Hello %s %s', chalk.cyan(firstname.toUpperCase()), chalk.cyan(lastname.toUpperCase()));
            console.log('CellPhone Number: %s', chalk.cyan(cellphone));
            console.log('Your Age: %s', chalk.cyan(age));
            console.log('');
            console.log(chalk.bgWhite.black('Thanks for send your information.'));
        });
    })
    .parse(process.argv);



در این مقاله به طور مختصر شرح داده شد که چطوری می توانید از قدرت و سادگی cli برای توسعه سریعتر کارها استفاده کرد و یا برنامه هایی نوشت که عملیات مد نظر ما را بر روی سیستم انجام دهند، علاوه بر اون با کمی تنظیمات می توانیم محیط یکنواخت و ساده ترمینال را کمی تغییر دهیم تا کار با cli لذت بخش تر شود.

سورس پروژه را می توانید از مسیر زیر دانلود کنید:

https://github.com/afshintalebi/cli-sample-person-info

موفق باشید