Skip to content

Instantly share code, notes, and snippets.

@robotlolita
Last active December 11, 2015 13:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robotlolita/4609128 to your computer and use it in GitHub Desktop.
Save robotlolita/4609128 to your computer and use it in GitHub Desktop.
Clee --- A functional compile-to-JS language for writing CLI programs

Clee

A functional compile-to-JS language for writing beautiful command-line interfaces.

Features

  • Functional (closures, first-class functions, purity)
  • Compile-to-JS, run-on-Node
  • Your code as the interface
  • Types and Type Inference (maybe?)
  • Seamless bash integration
  • Out-of-the-box promised asynchronous code
  • Destructuring
  • Prefix notation
  • NO operators
  • Infix anything
  • String interpolation

Inspirations

  • Haskell / Shake
  • Python
  • Bash
  • Markdown
  • Lisp / Dylan

Examples

Cat

#!/usr/bin/clee
@program cat version 1.0a
: cat --- Concatenate `files`, or `standard input`, to `standard output`

  Read a series of `files` (and/or the `standard input`), in order,
  concatenates them and write the result to the `standard output`.
  
  If no `files` are given, or if the standard input flag (`-`) is given,
  we read from the `standard input`.
  
  
  # Examples
  
  Output `f`'s contents, then `standard input`, then `g`'s contents:
  
      cat f - g
      
  Copy standard input to standard output:

      cat
      

@options
  (n) number    - Number all output lines.
  (e) show-ends - Display `$` at the end of each line.
  (a) show-all  = et
  (t) show-tabs - Display TAB characters as `^I`


: Reads files or standard input, returns a list of text.
read-files files... ->
  | empty? files => [io.read standard-input]
  | otherwise    => map io.read, files
  
  where io = require 'io'


: Higher-order for processing text.
process f, text -> (lines . map f . unlines) text


: Number all output lines.
number = process (line, n) -> "{:n}. {:line}"


: Display `$` at the end of each line.
show-ends = process (line, n) -> "{:line} $"


: Display tab characters as `^I`
show-tabs text -> replace /\t/, '^I', text


main options, files... ->
  contents = read-files options, file
  print processing (reduce + contents)

  where number'    = if options.number    then number    else id
      , show-ends' = if options.show-ends then show-ends else id
      , show-tabs' = if options.show-tabs then show-tabs else id
      , processing = number' . show-ends' . show-tabs'

Naval Fate

See decopt

#!/usr/bin/clee
@program naval-fate version 1.0a
: naval-fate --- Simple example of interfaces


@options
  speed    - speed in knots.
  moored   - Moored (anchored) mine.
  drifting - Drifting mine.


@module ship
  @simple-command new name... ->
    print "Created a new ship {:name}."
    
  @command move {speed:10}, name, x, y ->
    print "Moved ship to {:x}, {:y}{:s}"
    
    where s = | speed     => " at a speed of {:speed}kn."
              | otherwise => "."
    
  @simple-command shoot x, y ->
    print "Shot at {:x}, {:y}"



@module mine  
  @command set {moored | drifting}, x, y ->
    print "Set {:kind} mine at {:x}, {:y}."
    
    where kind = | moored    => 'moored'
                 | drifting  => 'drifting'
                 | otherwise => ''
  
  @command remove {moored | drifting}, x, y ->
    print "Removed {:kind} mine from {:x}, {:y}."
    
    where kind = | moored    => 'moored'
                 | drifting  => 'drifting'
                 | otherwise => ''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment