MikeBeller / spork

Various Janet utility modules.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Spork

Various Janet utility modules. Spork aims to be grab bag of useful Janet functionality that does not belong in the core library.

To use all features mentioned below in one program you can do (use spork) to import them. When you need only part of the functionality, please use import as seen in the example for the part.

Formatting

Provides a way to format Janet code strings and files.

Strings

(import spork/fmt)

(fmt/format "(def     a\n 3 )")  => @"(def a\n  3)\n"

Files

(import spork/fmt)

(fmt/format-file "main.janet")

Message Protocol

Provide a symmetric way to send and receive seqential messages over a networked stream. Useful for building more complicated application level protocols on top of TCP.

(import spork/msg)

(def stream (net/connect "http://example.com" "1234"))

(def send (msg/make-send stream))
(def recv (msg/make-recv stream))

(send "blob1")
(def blob-respose (recv))

Networked REPL

Launch a networked REPL server on one machine and connect to it from another machine or process.

Server

(import spork/netrepl)

(def some-def 10)

# Serve a repl into the current environment (some-def will be visible)
(netrepl/server "127.0.0.1" "9000" (fiber/getenv (fiber/current)))

Client

(import spork/netrepl)

# Starts a nice terminal repl.
(netrepl/client "127.0.0.1" "9000" "bob")

RPC Protocol

A simple remote procedure call tool for Janet.

Server

(import spork/rpc)

(def functions
  @{:print (fn [self x] (print "remote print: " x))
    :add (fn [self & xs] (sum xs))})

(rpc/server functions "127.0.0.1" "9001")

Client

(import spork/rpc)

(def c (rpc/client "127.0.0.1" "9001" "joe"))

# Will print on server
(:print c "Hello from client!")

(:add c 1 3 5 7 9) # -> 25

# Close the underlying connection
(:close c)

Path

Simple path manipulation module for Janet. Supports manipulation both windows and posix paths on any platform, and provides functions that work according to the current host platform.

All functions have three forms, under path, path/win, and path/posix. The prefix indicates which type of path the function manipulates.

(import spork/path)

# Examples for a non-windows system, use path/win/ for windows and
# path/posix/ for posix.

(path/ext "my/long/path.txt") # -> ".txt"
path/sep # -> "/" on posix, "\\" on windows
path/delim # -> ":" on posix, ";" on windows
(path/basename "some/path.txt") # -> "path.txt"
(path/dirname "some/path.txt") # -> "some/"
(path/parts "some/path/file.txt") # -> ["some" "path" "file.txt"]
(path/normalize "some/.././thing/file.txt") # -> "thing/file.txt"
(path/join "some/path" "../thing/file.txt") # -> "some/thing/file.txt"
(path/abspath? "/home/blah") # -> true
(path/abspath "file.txt") # -> "/home/me/cwd/file.txt"

argparse

A moderately opinionated argument parser for janet. Use this for writing CLI scripts that need to have UNIX style switches and options.

Sample

#!/usr/bin/env janet

(import spork/argparse :prefix "")

(def argparse-params
  ["A simple CLI tool. An example to show the capabilities of argparse."
   "debug" {:kind :flag
            :short "d"
            :help "Set debug mode."}
   "verbose" {:kind :multi
              :short "v"
              :help "Print debug information to stdout."}
   "key" {:kind :option
          :short "k"
          :help "An API key for getting stuff from a server."
          :required true}
   "expr" {:kind :accumulate
           :short "e"
           :help "Search for all patterns given."}
   "thing" {:kind :option
            :help "Some option?"
            :default "123"}])

(let [res (argparse ;argparse-params)]
  (unless res
    (os/exit 1))
  (pp res))

Usage

Call argparse/argparse to attempt to parse the command line args (available at (dyn :args)).

The first argument should be a description to be displayed as help text.

All subsequent options should be alternating keys and values where the keys are options to accept and the values are definitions of each option.

To accept positional arguments, include a definition for the special value :default. For instance, to gather all positional arguments into an array, include :default {:kind :accumulate} in your arguments to argparse.

Run (doc argparse/argparse) after importing for more information.

Temple

HTML templates for Janet.

Simplified version of Mendoza's template system that is cleaner and easier to use. Templates can be used recursively, and output is printed via print, so goes to (dyn :out).

Expands on the mendoza templates with the {- ... -} brackets, which do non-escaped substitution, so temple can be used for formats besides HTML. Also exposes the escape function inside templates for HTML escaping if you want to manually print to template output.

Example

foo.temple

{$ (def n 20) # Run at template compile time $}
<html>
  <body>
    {{ (string/repeat "<>" n) # HTML escaped }}
    <ul>
      {% (each x (range n) (print "<li>" x " " (args :a) "</li>")) # No auto-print %}
    </ul>
    {- (string/repeat "<span>1</span>" n) # Not HTML escaped -}
  </body>
</html>

main.janet

(import temple)
(temple/add-loader)

(import ./foo :as foo)
(foo/render :a "hello")

There is one more involved example in the (/janet-lang/spork/examples/temple/). You can runnit with janet examples/temple/example.janet.

Test

This module contains a simple test helper when you do not need a specialized library.

assert

Modified version of assert, with some nice error handling.

(test/assert false "How is this?")
# => ✘ How is this?
(test/assert true "OK")
# => ✔true

assert-not

Invert assert.

(test/assert-not false "OK")
# => ✔true

assert-error

Test passes if forms throw errors.

(test/assert-error "To err is natural" (error "Bad"))
# => ✔true

assert-no-error

Test passes if forms throw errors.

(test/assert-no-error "To not err is desired" (do "Good"))
# => ✔true

start-suite

Starts test suite, which counts all and passed tests.

end-suite

Ends test suite and print summary.

All together

Example of simple test suite.

(import spork/test)

(test/start-suite 0)

(test/assert true "is always true")
(test/assert-not false "is always false")
(test/assert-error "To err is natural" (error "Bad"))
(test/assert-no-error "To not err is desired" (do "Good"))

(test/end-suite)

# =>

Test suite 0 finished in 0.000 soconds
4 of 4 tests passed.

timeit

Time code execution using os/clock, and print the result. Returns the value of the timed expression.

repl> (misc/timeit (sum (seq [i :range [1 1000000]] (math/sqrt i))))
Elapsed time: 0.0718288 seconds
6.66666e+08

capture-stdout

Runs the form and captures stdout. Returns tuple with result and captured stdout in string.

(capture-stdout
  (do
    (print "Interesting output")
    true))
# => (true "Interesting output")

supress-stdout

Runs the form, but supresses its stdout.

(suppress-stdout (print "Hello world!"))
# => nil

Misc

Dedent

Remove indentation after concatenating the arguments.

(misc/dedent ``
      ho
        hoho
          hohoho
``))))) => "ho\n  hoho\n    hohoho"

set*

Allow parallel mutation of multiple mutable variables. (All right hand sides are computed before setting the left hand sides.)

# you can use it with vars
(var a 2)
(var b 3)
(misc/set* [a b] [b (+ a b)])
[a b] => [3 5]

# or you can use it with arrays, for example:
(def x @[2 3])
(misc/set* [[x 0] [x 1]] [(in x 1) (+ (in x 0) (in x 1))])
x => @[3 5]

Installation

[sudo] jpm install https://github.com/janet-lang/spork.git

About

Various Janet utility modules.

License:MIT License