JanetDocsSourcePlaygroundTutorialsI'm Feeling luckyCommunityGitHub sign in

Community documentation for Janet

Supported Modules

Welcome, I'm happy to see you here! Feel free to pick a function and add a happy example, the more the merrier!

Loading...

Recent Examples

# Expanding the example from https://janetdocs.org/core-api/stdin
# We use argparse to provide automatically add flags
# --help comes for free, try it!

(import spork/argparse)

(defn main [&]
  (let [opts (argparse/argparse "Sum numbers from files, stdin or data."
              "multiply" {:kind :option :short "m" :default "1" :map scan-number :help "Multiply the result"}
              "verbose"  {:kind :flag :help "Print the input first"}
              :default   {:kind :accumulate})

        _ (unless opts (os/exit 0)) # lest it crash on help etc.
        args (or (opts :default) []) # give empty? empty array of :default is nil
        data (cond (empty? args) (file/read stdin :all)
                   (os/stat (first args)) (slurp (first args))
                   (string/join args " "))
        total (* (opts "multiply") (sum (flatten (parse-all data))))]

    (if (opts "verbose") (print "Data: " data))
    (print total)))
argparse/argparseveqqqPlayground
# Linux pipes | send data through stdin
# To make linux programs accepting varied input forms:

(defn main [_ & args]
  # If no arguments, read from stdin
  (let [data (if (empty? args) (file/read stdin :all) (string/join args " "))]
    (print (sum (flatten (parse-all data))))))

# This accepts: 1 2 3 or "1" "2" "3" or "1 2 3" or "[1 2 3]" besides piping data in
# janet fib.janet 5 | janet sum.janet

# Allow file inputs also:

(defn main [_ & args]
  (let [data (cond (empty? args) (file/read stdin :all)
                   (os/stat (first args)) (slurp (first args))
                   (string/join args " "))]
    (print (sum (flatten (parse-all data))))))
stdinveqqqPlayground
(sandbox :fs) # disable access to the sandbox
(os/mkdir "lol")

# error: operation forbidden by sandbox
#   in os/mkdir [src/core/os.c] on line 2146
#   in thunk [repl] (tail call) on line 30, column 1
sandboxveqqqPlayground
(import spork/charts :as c)
(c/line-chart
  :width 400 :height 200
  :data {:timestamp [1 2 3 5 40 60]
         :temperature-1 [75.1 75.2 75.4 75.5 75.5 75.4]
         :temperature-2 [55.1 55.4 55.7 60.0 60.4 60.9]}
  :save-as "bla.png"
  :x-column :timestamp
  :y-column [:temperature-1 :temperature-2])

# then open bla.png to view
# bakpakin shared this example
spork/charts/line-chartveqqqPlayground
(import spork/charts :as c)
(import spork/gfx2d :as g)
(g/save "bla.png" (c/plot-line-graph
                   :canvas (g/blank 100 100)
                   :data {:timestamp [1 2 3 40 5 60]
                          :temperature-1 [75.1 75.2 75.4 75.5 75.5 75.4]
                          :temperature-2 [55.1 55.4 55.7 60.0 60.4 60.9]}
                   :x-column :timestamp
                   :y-column :temperature-1))

# then you can look at bla.png
spork/charts/plot-line-graphveqqqPlayground
(range 10000) # @[0 1 2 ... 9997 9998 9999]

# By default, pp truncates. You can change its behavior:
(setdyn :pretty-format "%j") # jdn format
(setdyn :pretty-format "%m") # full printing without truncation
# For a list of all print formats: https://janet-lang.org/capi/writing-c-functions.html#Panicking

(range 10000) # Prints all of them according to your dyn
ppveqqqPlayground
(def f (file/temp))
(file/write f "ok stuff")
(file/seek f :set 0)
(file/read f :all)

# N.b. file/temp's file is not accessible outside of the process
file/tempveqqqPlayground
# can execute query from a file like:
(db/query (slurp "db/sql/random.sql"))

# In context:
(defn show [request]
  (when-let [[name] (request :wildcard)
             name (uri/unescape name) # escaping is important for = and especially %
             name (string/replace "_q" "?" name)
             binding (first (db/query (slurp "db/sql/search.sql") [name]))]

    [:vstack {:spacing "m"}
     (binding-header binding)
     (examples/index (merge request {:binding binding}))]))

# From https://codeberg.org/veqq/janetdocs/src/commit/ac1dc9e3e82f17e8e9ac047297b00803b68034d0/routes/examples.janet#L217
joy/db/queryveqqqPlayground
# :as sets a /

(import /deeper/inside :prefix "" :export true)
# @{_ @{:value <cycle 0>} cat @{:private false}}
(import /deeper/inside :as "" :export true)
# @{/cat @{:private false} _ @{:value <cycle 0>} cat @{:private false}}

importveqqqPlayground
path/delim # => ":" on Unix and Linux, ";" on Windows
spork/path/delimclementiPlayground
  (->> (all-bindings)
       (keep (fn [sym]
               (when (string/has-prefix? "peg/" (string sym))
                 (string sym))))
       sort)

  # =>
  @["peg/compile"
    "peg/find"
    "peg/find-all"
    "peg/match"
    "peg/replace"
    "peg/replace-all"]

# from https://github.com/sogaiu/margaret/blob/master/tutorials/tutorial.janet
all-bindingsveqqqPlayground
# The optional array arg is used as the basis for the returned array

(os/dir "/tmp/dir_1" @["file_3" "file_4"]) # => @["file_3" "file_4" "file_1" "file_2"]
os/dirsnltdPlayground
# Some tips for working with bytes and unicode:
(string/bytes "что-нибудь")                         #> (209 135 209 130 208 190 45 208 189 208 184 ...
(print (string/from-bytes 208 176 208 177))         #> аб
(map string/from-bytes (string/bytes "что-нибудь")) #> @["\xD1" "\x87" "\xD1" "\x82" "\xD0" "\xBE" ...

# Print renders "\xD1" "\x87" as ч, as unicode characters may have multiple bytes
# So use apply:
(apply print (map string/from-bytes 
                  (string/bytes "что-нибудь")))     #> что-нибудь
string/bytesveqqqPlayground
# many terminals will truncate long data, use this if you need to see/copypaste it:
(defn full-print `Print a large DS without truncation` [ds] (print (string/format "%m" ds)))
ppveqqqPlayground
(defn bench `Feed bench a wrapped func and int, receive int for time in ns`
  [thunk times] 
  (def start (os/clock :cputime :tuple)) 
  (loop [_ :range [times]] 
    (thunk))
  (def end (os/clock :cputime :tuple)) 
  (/ (+ (* (- (end 0) (start 0)) 1e9) 
        (- (end 1) (start 1)))
     times))

# it turns out os/clock is pretty darn fast (comparatively)
(def iterations 2000000)
(bench |(os/clock :cputime :tuple) iterations) # 1283.30053 ns
(bench |(slurp "/proc/self/schedstat") iterations) # 7881.451760 ns
# these basically benchmark slurp
(bench |(do (def f (file/open "/proc/self/schedstat" :r))
            (def content (file/read f :all))
            (file/close f))
       iterations) # 4894.832760 ns
# even without opening and closing the file, reading in Janet's slower than os/clock
(def f (file/open "/proc/self/schedstat" :r)) 
(bench |(do (file/seek f :set 0)  
            (def content (file/read f :all))) iterations)  # 1802.511470 ns
(file/close f)

# Of course bench has some overhead, but it's amortized across iterations anyway
(bench (fn []) 10000000) # 42.030338 ns
os/clockveqqqPlayground