Chapter10 Command Line Rosetta

If you find this content useful, consider buying this book:

  • Amazon
  • Purchase all books bundle
  • Purchase from pragmatic ai labs
  • Subscribe all content monthly
  • If you enjoyed this book considering buying a copy

    Chapter 10: Command-line Rosetta Stone #

    This chapter serves as a guidebook for users coming from another language. The source code can be found here. The same style, hello world command-line tool is written in many languages.

    R Hello World #

    This step is an example of a hello world command-line tool in R. The source code is here.

    #!/usr/bin/env Rscript
    #Hello World R command-line tool
    parser <- OptionParser()
    parser <- add_option(parser, c("-c", "--count"), type = "integer",
                         help = "Number of times to print phrase",
                         metavar = "number")
    parser <- add_option(parser, c("-p", "--phrase"),
                        help = "Phrase to print")
    args <- parse_args(parser)
    # Function to Generate Phrases
    phrasegen <- function(arguments){
        for (count in 1:arguments$count) {
            cat(paste(arguments$phrase, "\n"))
    #Run the program

    Depends on for R

    Usage #

    $  hello-world git:(master) $ ./hello-world.R --count 5 --phrase "hello world"
    hello world
    hello world
    hello world
    hello world
    hello world

    Bash Hello World #

    This step is a hello world Bash example. The source code is here.

    #output looks like this:
    #  $hello-world git:(master) $ ./ --count 5 --phrase "hello world"
    #hello world
    #hello world
    #hello world
    #hello world
    #hello world
    #Generate phrase "N" times
    phrase_generator() {
        for ((i=0; i<$1;i++)); do
            echo "$2"
    #Parse Options
    while [[ $# -gt 1 ]]
    case $key in
    #Run program
    phrase_generator "${COUNT}" "${PHRASE}"

    To lint use make lint. And now run it:

    $  hello-world git:(master) $ ./hello-world.rb --count 5 --phrase "hello world"
    hello world
    hello world
    hello world
    hello world
    hello world

    Environment #

    You may need to also do:

    $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshenv
    $ echo 'eval "$(rbenv init -)"' >> ~/.zshenv
    $ echo 'source $HOME/.zshenv' >> ~/.zshrc
    $ exec $SHELL

    Go Hello World #

    The go source code is here.

    package main
    import (
        "" // imports as package "cli"
    func main() {
        app := cli.NewApp()
        app.Flags = []cli.Flag{
                Name:  "phrase",
                Usage: "Print phrase",
                Name:  "count",
                Usage: "Count to print a phrase",
        app.Action = func(c *cli.Context) error {
            sum := 0
            for i := 0; i < c.Int("count"); i++ {
                sum -= i
            return nil

    Running program #

    Run make all

    Then run program:

    $  hello-world git:(master) $ hello-world --phrase "hello world" --count 5
    hello world
    hello world
    hello world
    hello world
    hello world

    Environment #

    Setting these variables:

    export GOPATH="${HOME}/.go"
    export GOROOT="$(brew --prefix golang)/libexec"
    export PATH="$PATH:${GOPATH}/bin:${GOROOT}/bin"
    export GOBIN=$GOPATH/bin

    Node Hello World #

    The source code for the node examples is here. This project has several components. First, there are the .js file.

    #!/usr/bin/env node
    "use strict";
    Hello World Commandline Tool
    node index.js --phrase "hello world" --count 10
    hello world hello world hello world
    const program = require('commander');
      .option('-p, --phrase [value]', 'phrase')
      .option('-c, --count <n>', 'Number of Times To Repeat Phrase', parseInt)
     * Multiplies string with additional space.
     * @param {string} phrase The phrase.
     * @param {number} count The number of times to repeat
     * @returns {string} The multiplied string
    function phraseGenerator (phrase, count) {
        return phrase.concat(" ").repeat(count);
    // Check to see both options are used
    if (typeof program.phrase === 'undefined' ||
        typeof program.count === 'undefined') {
        console.error('ERROR! --phrase and --count options required');;
    // Print Phrase To Standard Out

    Next there is a package.json file.

      "name": "nodecli",
      "version": "1.0.0",
      "description": "nodecli",
      "main": "index.js",
      "dependencies": {
        "commander": "^2.10.0"
      "devDependencies": {
        "eslint": "^4.1.1",
        "eslint-config-defaults": "^9.0.0"
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      "repository": {
        "type": "git",
        "url": "git+"
      "keywords": [
      "author": "Noah Gift",
      "license": "MIT",
      "bugs": {
        "url": ""
      "homepage": ""

    To run the example, you would do the following.

    Steps to run:

    npm install ./hello-world --phrase "hello world" --count 3

    The output should be:

    hello world hello world hello world

    Multi-paradigm Node.js #

    Getting Started #

    This application source code is here.

    To build this project, you need to:

    npm install

    To talk to the blockchain network, please run ./ Then ./query-cli.js. Further information and background of this forked version can be found here

    Features #

    • Color Output
    • JSON Formatting
    • Async Network Operations
    • Blockchain Integration

    Screenshots #

    • Screenshot No Options: Output
    • Screenshot One Option: Output

    The source is below. You can see how a more sophisticated node tool integrates with both blockchain, and colored output works.

    #!/usr/bin/env node
    "use strict";
    Hyperledger Query Commandline Tool
    __dirname = path.resolve();
    const Hfc = require('fabric-client'),
        path = require('path'),
        chalk = require('chalk'),
        prettyjson = require('prettyjson'),
        program = require('commander'),
        options = {
            walletPath: path.join(__dirname, './network/creds'),
            userId: 'PeerAdmin',
            channelId: 'mychannel',
            chaincodeId: 'fabcar',
            networkUrl: 'grpc://localhost:7051'
    let channel = {},
        transactionId = null,
        client = null,
        jsonResult = null;
        .option('-c, --car [value]', 'car to query')
     * Queries Blockchain
     * @param {string} chaincodeFunc The chaincode function to query
     * @param {string} car The individual car to query
     * @returns {string} nothing
    function queryHelper (chaincodeFunc = 'queryAllCars', car = '') {
        Promise.resolve().then(() => {
            console.log("Create a client and set the wallet location"));
            client = new Hfc();
            return Hfc.newDefaultKeyValueStore({path: options.walletPath});
        .then((wallet) => {
            console.log("Set wallet path, and associate user ",
                options.userId, " with application"));
            return client.getUserContext(options.userId, true);
        .then((user) => {
                "Check user is enrolled, and set a query URL in the network"
            if (typeof user === "undefined" || user.isEnrolled() === false) {
                console.error("User not defined, or not enrolled - error");
            channel = client.newChannel(options.channelId);
        .then(() => {
            console.log("Make query"));
            transactionId = client.newTransactionID();
            console.log("Assigning transaction_id: "),
            // The queryCar - requires 1 argument, ex: args: ['CAR4'],
            // The queryAllCars - requires no arguments , ex: args: [''],
            const request = {
                chaincodeId: options.chaincodeId,
                txId: transactionId,
                fcn: chaincodeFunc,
                args: [car]
            return channel.queryByChaincode(request);
        .then((queryResponses) => {
            console.log("returned from query"));
            if (typeof queryResponses.length === 'undefined') {
                console.log("No payloads were returned from query");
            } else {
                    chalk.bgBlue("Query result count = ", queryResponses.length));
            if (queryResponses[0] instanceof Error) {
                console.error("error from query = ", queryResponses[0]);
            jsonResult = JSON.parse(queryResponses[0].toString());
            console.log(prettyjson.render(jsonResult, {
                keysColor: 'yellow',
                dashColor: 'blue',
                stringColor: 'white'
        .catch((err) => {
            console.error("Caught Error", err);
    // Run The Command line Tool
    if (typeof === 'undefined') {
    } else {

    Python Hello World #

    Python 3.6.1

    Running #

    Steps to Run:

    Install packages:

    make install

    Activate Virtual Env:

    source ~/.hello-world-py-cli/bin/activate

    Run Tool:

    ./ --phrase "hello world" --count 3

    The output should be:

    hello world hello world hello world

    The `Makefile looks like:

          mkdir -p ~/.hello-world-py-cli &&\
          python3 -m venv ~/.hello-world-py-cli &&\
          pip install -r requirements.txt
        echo "Virtualenv source command" 
        #source ~/.hello-world-py-cli/bin/activate

    The requirements.txt file looks like:


    Finally, the python code is as follows.

    #!/usr/bin/env python
    import click
    def cli():
        """Hello World"""
    @click.option("--phrase", help="phrase to print")
    @click.option("--count", help="Number of times to repeat phrase", type=int)
    def hello(phrase, count):
        """Hello World Command-line tool"""
        while count:
            count -= 1
    if __name__ == '__main__':

    A full example of lint and run:

        (.hello-world-py-cli) $  hello-world git:(master) $ ./ hello\
            --phrase "hello world" --count 3
        hello world
        hello world
        hello world
        (.hello-world-py-cli) $  hello-world git:(master) $ make lint
        Your code has been rated at 10.00/10 (previous run: 7.50/10, +2.50)

    You can find the latest up to date examples in the Github Repo