Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

clino

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

clino

  • 0.1.3
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

Clino

Clino (originally Clinohumite) gem is a CLI builder library that provides a simple way to create a command line interface for your Ruby application.

It is inspired by the Thor and Typer libraries, and aims to provide a simple and easy to use interface for building command line interfaces.

Installation

Install this gem as a regular gem:

gem install clino

or add this line to your application's Gemfile:

gem 'clino'

Link: RubyGems

Usage

Interfaces

There are two interfaces available: Min and Cli.

Min

The Min interface is a minimalistic interface that provides a simple way to create a command line interface for your Ruby application.

It is inspired by the Typer pythonic approach

It tries to unleash all the power of Ruby's metaprogramming capabilities to provide a simple and easy to use interface for building command line interfaces.

Cli

The Cli interface is a more advanced interface that provides a more complex way to create a command line interface for your Ruby application.

It is inspired by the Thor library and provides a more complex and feature-rich interface for building command line interfaces.

Examples

Hello World

Let's write a simple script that takes a name as an argument and prints a greeting message.

# hello.rb

require "clino/interfaces/min"

Min.new(->(name) { "Hello, #{name}!" }).start

Writing lambda containing only business logic is enough, as the input and output handling is done by the Min interface.

Run the script with the following command:

ruby hello.rb World  # => Hello, World!

Get help with the following command:

ruby hello.rb --help

or

ruby hello.rb -h

It will print the following output:

Script: hello.rb

Arguments:

  <name> [string]

Usage: hello.rb [arguments] [options]
Randomizer Minimalistic Example

Let's write a simple script that generates a random number within a given range with some conditions and transformations.

# min_randomizer.rb

require "clino/interfaces/min"

def generate_rnd_uni(from, to, incl)
  range = incl ? from..to : from...to
  rand(range)
end

def generate_rnd_exp(from, to, _incl)
  mean = (from + to) / 2.0
  -mean * Math.log(rand) if mean.positive?
end

def generate_rnd(from, to, mult = 1.0, alg:, incl: false)
  from = load_input :integer, from
  to = load_input :integer, to
  mult = load_input :float, mult
  incl = load_input :bool, incl

  raise ArgumentError, "The lower bound (#{from}) must be less than the upper bound (#{to})" if from >= to
  raise ArgumentError, "Algorithm must be one of: [uni, exp]" unless %w[uni exp].include?(alg)

  send("generate_rnd_#{alg}", from, to, incl) * mult
end

Min.new(:generate_rnd).start

As we can see, for more complex (or just non-string) input, we can use the load_input method to load the input and validate it.

Anyway, it requires us to write additional logic for validation and error handling.

Run the script with the following command:

ruby min_randomizer.rb 1 10 --alg uni  # => some number from [1.0, 9.0]

Get help with the following command:

ruby min_randomizer.rb --help

or

ruby min_randomizer.rb -h

It will print the following output:

Script: min_randomizer.rb

Arguments:

  <from> [string]

  <to> [string]

  [<mult>] [string] [default: unknown]

Options:

  --alg [string] 

  [--incl] [string]  [default: unknown]

Usage: min_randomizer.rb [arguments] [options]

As we can see, ruby's metaprogramming capabilities allow us to create a simple CLI, however it doesn't provide a way to handle complex input.

Unfortunately, ruby doesn't allow inspecting the method's signature default values, so we can handle input only as strings, and we can only show placeholders for default values this way.

Randomizer Advanced Example

Let's write an advanced version of the randomizer that has CLI signature.

Our entry point is the run method, which is called with the parsed and validated input.

# randomizer.rb

require "securerandom"
require "clino/interfaces/cli"

class RandomGeneratorCLI < Cli
  # include Cli
  desc <<-TEXT
    Generate a random number between the given bounds
    using the specified algorithm and multiply it by the given multiplier
  TEXT
  opt :alg, aliases: ["-a"], type: :string, desc: "Algorithm to use (uni or exp)"
  opt :incl, aliases: ["-i"], type: :bool, default: false, desc: "Include upper bound"
  arg :from, type: :integer, desc: "Lower bound"
  arg :to, type: :integer, desc: "Upper bound"
  arg :mult, type: :float, default: 1, desc: "Multiplier"

  def run(from, to, mult, alg:, incl:)
    raise ArgumentError, "The lower bound (#{from}) must be less than the upper bound (#{to})" if from >= to
    raise ArgumentError, "Algorithm must be one of: [uni, exp]" unless %w[uni exp].include?(alg)

    send("generate_rnd_#{alg}", from, to, incl) * mult
  end

  private

  def generate_rnd_uni(from, to, incl)
    range = incl ? from..to : from...to
    rand(range)
  end

  def generate_rnd_exp(from, to, _incl)
    mean = (from + to) / 2.0
    -mean * Math.log(rand) if mean.positive?
  end
end

RandomGeneratorCLI.new.start

Run the script with the following command:

ruby randomizer.rb 1 2 --alg uni --i # => some number from [1.0, 2.0]

Get help with the following command:

ruby randomizer.rb --help

or

ruby randomizer.rb -h

It will print the following output:

Script: randomizer.rb

Description:
      Generate a random number between the given bounds
    using the specified algorithm and multiply it by the given multiplier


Arguments:
 # Lower bound
  <from> [integer]
 # Upper bound
  <to> [integer]
 # Multiplier
  [<mult>] [float] [default: 1.0]

Options:
 # Algorithm to use (uni or exp)
  --alg (-a) [string] 
 # Include upper bound
  [--incl] (-i) [bool]  [default: false]

Usage: randomizer.rb [arguments] [options]

As we can see, all the default values, helping notes, and types are written out, and the input validation is handled automatically.

Plugins

Input Types

It is possible to create custom input types for the Cli interface.

# weight_calculator.rb

require "clino/interfaces/cli"
require "clino/plugins/input_types"

def convert_positive_integer(value)
  raise ArgumentError, "Value must be a positive integer" unless value.to_i.positive?

  value.to_i
end

INPUT_TYPES_PLUGIN.register(:positive_integer, method(:convert_positive_integer))

class IdealWeight < Cli
  arg :height, type: :positive_integer

  def run(height)
    return height * 0.45 if height < 100

    (height - 100) * 0.9
  end
end

IdealWeight.new.start

Run the script with the following command:

ruby weight_calculator.rb 180  # => 72.0
ruby weight_calculator.rb -1 # => ArgumentError: Value must be a positive integer

The type will be automatically registered and the help message will be printed as follows:

Script: weight_calculator.rb

Arguments:

  <height> [positive_integer]

Usage: weight_calculator.rb [arguments] [options]

Improvements

  • Add more tests
  • Add better UI/UX in a sense of errors and help messages
  • Fix problem with arguments beginning with "--"
  • Add more input types (JSON?)
  • Add CI/CD
  • Add more examples
  • Create a proper documentation

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/snusmumr1000/Clino. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Clino project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

FAQs

Package last updated on 19 Feb 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc