cli4clj Version 1.2.3 Released

cli4clj is a library for easing the implementation of simple interactive command line interfaces (CLIs) for Clojure applications. In this post, I briefly announce the release of cli4clj version 1.2.3.

The most important changes in version 1.2.3 are:

  • Add support for hiding commands in help and completion.
    Hidden commands are prefixed with “_”.
  • Hide the “enable-trace” command by changing it to “_enable-trace”.
  • Add a hidden “_sleep” command.

For hiding commands, the convention of prefixing hidden commands with “_” was introduced. This means that all commands that begin with an underscore, “_”, will neither be shown in the help nor in the command completion.

The rationale for hiding certain commands is to improve the usability by removing everything a “typical” user does not need. In this process, I also changed the “enable-trace” command to “_enable-trace” in order to hide it from the user.

The “_sleep” command was added as a stopgap solution for testing multi-threaded CLI applications. The current CLI test functionality works very well. However, there is a problem with multi-threaded applications.

Clearly, when a command triggers interaction with another thread that eventually prints a result, a corresponding unit test needs to wait until the processing finished and the result was printed. The CLI “UI thread” however, cannot know how long it has to wait. Thus, I added the “_sleep” command as a simple stopgap solution.

In the following, the code of the newly added unit tests for testing the “_sleep” command is shown for illustrating the problem and the current stopgap “solution”:

(deftest async-cmd-not-finished-test
  (let [cli-opts {:cmds {:async-foo {:fn (fn []
                                           (println "Starting...")
                                           (let [tmp-out *out*]
                                             (doto
                                               (Thread.
                                                 (fn []
                                                   (binding [*out* tmp-out]
                                                     (sleep 500)
                                                     (println "Finished."))))
                                               (.start)))
                                           "Started.")}}}
        test-cmd-input ["async-foo"]
        out-string (test-cli-stdout #(start-cli cli-opts) test-cmd-input)]
    (is (= (expected-string ["Starting..." "\"Started.\""]) out-string))))

(deftest async-cmd-sleep-finished-test
  (let [cli-opts {:cmds {:async-foo {:fn (fn []
                                           (println "Starting...")
                                           (let [tmp-out *out*]
                                             (doto
                                               (Thread.
                                                 (fn []
                                                   (binding [*out* tmp-out]
                                                     (sleep 500)
                                                     (println "Finished."))))
                                               (.start)))
                                           "Started.")}}}
        test-cmd-input ["async-foo" "_sleep 1000"]
        out-string (test-cli-stdout #(start-cli cli-opts) test-cmd-input)]
    (is (= (expected-string ["Starting..." "\"Started.\"" "Finished."]) out-string))))

Actually, using sleeps for this is not really an ideal solution. However, for now, this approach serves its purpose. In future, I may come up with something better that still allows me to keep cli4clj simple.

As usual, constructive criticism, feedback, and comments are always appreciated.

Advertisements
This entry was posted in cli4clj, Libs. and tagged , , . Bookmark the permalink.

One Response to cli4clj Version 1.2.3 Released

  1. Pingback: cli4clj 1.2.5 – Improved Testability of Multi-threaded Command Line Applications in Clojure | ruedigergad

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s