Packages

An experimental, general purpose LFE REPL

Current section

Files

Jump to
xrepl src xrepl.lfe
Raw

src/xrepl.lfe

(defmodule xrepl
(behaviour gen_server)
;; gen_server implementation
(export
(start_link 0)
(stop 0))
;; callback implementation
(export
(init 1)
(handle_call 3)
(handle_cast 2)
(handle_info 2)
(terminate 2)
(code_change 3))
;; API
(export
(start 0)
(pid 0)
(echo 1))
;; Utility
(export
(version 0) (versions 0)))
;;; ----------------
;;; config functions
;;; ----------------
(defun SERVER () (MODULE))
(defun initial-state () '#())
(defun genserver-opts () '())
(defun unknown-command () #(error "Unknown command."))
;;; -------------------------
;;; gen_server implementation
;;; -------------------------
(defun start_link ()
(gen_server:start_link `#(local ,(SERVER))
(MODULE)
(initial-state)
(genserver-opts)))
(defun stop ()
(gen_server:call (SERVER) 'stop))
;;; -----------------------
;;; callback implementation
;;; -----------------------
(defun init (state)
`#(ok ,state))
(defun handle_cast (_msg state)
`#(noreply ,state))
(defun handle_call
(('stop _from state)
`#(stop shutdown ok ,state))
((`#(echo ,msg) _from state)
`#(reply ,msg ,state))
((message _from state)
`#(reply ,(unknown-command) ,state)))
(defun handle_info
((`#(EXIT ,_from normal) state)
`#(noreply ,state))
((`#(EXIT ,pid ,reason) state)
(io:format "Process ~p exited! (Reason: ~p)~n" `(,pid ,reason))
`#(noreply ,state))
((_msg state)
`#(noreply ,state)))
(defun terminate (_reason _state)
'ok)
(defun code_change (_old-version state _extra)
`#(ok ,state))
;;; --------------
;;; xrepl API
;;; --------------
(defun default-opts ()
`#m(banner? true))
(defun start()
(start #m()))
(defun start (opts)
(application:ensure_all_started 'xrepl)
(let* ((opts (maps:merge (default-opts) opts))
(banner? (mref opts 'banner?)))
(if banner? (write (banner)))
(lfe_xrepl:start)))
(defun pid ()
(erlang:whereis (SERVER)))
(defun echo (msg)
(gen_server:call (SERVER) `#(echo ,msg)))
;;; Public utility functions
(defun version () (xrepl-vsn:get))
(defun versions () (xrepl-vsn:all))
;;; Private functions
(defun banner ()
(let* ((file (filename:join (list (code:priv_dir 'xrepl)
"banners"
"v1.txt")))
(`#(ok ,bytes) (file:read_file file)))
(bbmustache:render bytes `#m("xrepl-version" ,(xrepl-vsn:get)
"lfe-version" ,(xrepl-vsn:get 'lfe)
"erlang-version" ,(erlang:system_info 'otp_release)
"red" "\e[31m"
"pnk" "\e[1;31m"
"ylw" "\e[1;33m"
"gld" "\e[33m"
"cyn" "\e[36m"
"blu" "\e[1;34m"
"dbl" "\e[34m"
"grn" "\e[32m"
"bgn" "\e[1;32m"
"gry" "\e[37m"
"wht" "\e[1;37m"
"end" "\e[0m"))))
(defun write (string)
(io:put_chars (erlang:whereis 'user) string))