Journo: /ˈdʒɜːnəʊ/ noun (plural journos)
- An informal word for journalist.
Journo is a Janet library for building interactive, interview-style CLI interfaces.
- Nicely formatted interactive question and answer interface
- Several basic question types (
:text,:password,:select,:checkbox) - Windows and Linux compatible
- Ability to customize styles with a
:stylekeyword - Ability to validate user inputs by passing any predicate function via a
:validatekeyword - More question types
- Helper functions (at least, if not a fleshed-out API/DSL) for branching question paths based on previously-entered inputs
Using Journo is simple:
- First, define a Question (or list of questions).
- Then, pass a single question to
journo/askor list of questions tojourno/interview.- These functions will present nicely formatted prompts to the user and return a table containing their response(s).
With JPM:
$ jpm install https://github.com/CFiggers/journoIn your project.janet:
(declare-project
:name "your-project"
:dependencies ["https://github.com/CFiggers/journo"])Optionally, run jpm deps after adding the dependency to your project.janet (not needed if you already installed via the instructions above).
In your main file:
(import journo)
# This will ask a single question and store the response in `answer`.
(def answer (journo/ask
{:question "What's your name?"
:type text}))
# This will ask all three questions and store the responses in `answer`.
(def answers (journo/interview
[{:label :q1
:question "What's the password?"
:password}
{:label :q2
:question "Favorite flavor?"
:type :select
:choices ["Vanilla" "Chocolate" "Strawberry"]}
{:label :q3
:question "Select all that apply"
:type :checkbox
:choices ["I'm overworked" "I'm underpaid"]}]))To see a quick example in action, run the following command from the journo project root:
$ janet example/example.janetJourno's API is very simple—it exposes two primary macros, each of which is a thin wrapper around a single function (which you're welcome to call directly if you like):
(journo/ask question &named keywordize)
Pass a single question to this function to have it asked at the command line.
The question must be a dictionary (table or struct) and contain :label, :question, and :type. :type can be one of:
:textor "text" = Open input:passwordor "password" = Open input, replaced with*in terminal:selector "select" = Single choice (provide with:choices):checkbox= Multiple choice (provide with:choices)
Example:
(journo/ask {:label :q1 :question "Who?" :type :text})
Returns a single table containing :question and ':answer'.
(journo/interview questions &named keywordize)
Pass an indexed datastructure of questions to this function to have each one asked in order at the command line.
Questions must be a dictionary (table or struct) and contain :label, :question, and type. type can be one of:
:textor "text" = Open input:passwordor "password" = Open input, replaced with*in terminal:selector "select" = Single choice (provide with:choices):checkbox= Multiple choice (provide with:choices)
Example:
(journo/interview
[{:label :q1 :question "Who?" :type :text}
{:label :q2 :question "What?" :type :select
:choices ["Me" "Not me"]}])
Returns a table of user inputs as captured for each question.
(journo/interview* qs &named keywordize)
This is the function form of the journo/ask and journo/interview macros.
Pass either a question or an indexed datastructure of questions to this function to have each one asked in order at the command line.
Returns a table of user inputs captured for each question.
Comments, concerns, questions, issues, pull requests, code critiques, all are welcome.
The following libraries do this sort of thing way better and have been doing it for way longer:
- JavaScript
- Python
As far as I know, at time of writing there is nothing comparable to this library for Janet (happy to be corrected on that count though).
Enjoy!
