rename relish to flesh
This commit is contained in:
parent
415b1181fa
commit
9b447eb5b7
58 changed files with 252 additions and 245 deletions
148
snippets/userlib.f
Normal file
148
snippets/userlib.f
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#!/bin/flesh
|
||||
|
||||
;; Flesh: Flexible Shell
|
||||
;; Copyright (C) 2021 Ava Affine
|
||||
;;
|
||||
;; This program is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;; USERLIB
|
||||
;; This file contains useful features that are not shipped in the STL
|
||||
;; TODO
|
||||
;; dir-path
|
||||
;; abs-path
|
||||
;; rel-path
|
||||
;; unique (make set)
|
||||
;; set add
|
||||
;; set del
|
||||
;; superset
|
||||
;; common-set
|
||||
;; make-map
|
||||
;; ins-mapping
|
||||
;; del-mapping
|
||||
;; get-mapping
|
||||
;; mapped?
|
||||
|
||||
;; this would be way faster as code in stl
|
||||
;; but stl already suffers scope creep
|
||||
(def prepend
|
||||
'takes a list and appends an element to the back of it.
|
||||
returns prepended list'
|
||||
(elem list)
|
||||
(reverse (cons (reverse list) elem)))
|
||||
|
||||
(def set
|
||||
'sets an existing variable without touching its docstring.
|
||||
|
||||
WARNING:
|
||||
If you find yourself struggling to debug a complex error in state access,
|
||||
or you are having issues re-running commands in the shell consider the
|
||||
following advice:
|
||||
|
||||
It is very much an anti pattern to mutate global variable that contain state.
|
||||
refactor your program: put iterators, counters, procedurally generated code,
|
||||
and all other mutable state into a let loop.
|
||||
|
||||
A cozy script in flesh is one where each root level form (or eval at repl)
|
||||
is self contained, and does not permanently modify any other one.
|
||||
|
||||
See the userlib tests for an easy to follow example of this.'
|
||||
|
||||
(var val)
|
||||
(let ((doc (get-doc var)))
|
||||
(def (eval var) doc val)))
|
||||
|
||||
(def map
|
||||
'Takes two arguments: a function and a list.
|
||||
for each element in the list, the function is applied and the
|
||||
result is added to a new list. Returns the new list.'
|
||||
(func list)
|
||||
(let ((list-iter (pop list))
|
||||
(result ()))
|
||||
(while (gt? (len list-iter) 1)
|
||||
(let ((current (car list-iter))
|
||||
(remaining (cdr list-iter))
|
||||
(current-res (func current)))
|
||||
(set (q result) (cons result current-res))
|
||||
(set (q list-iter) (pop remaining))))
|
||||
result))
|
||||
|
||||
(def reduce
|
||||
'Takes two arguments: a function and a list.
|
||||
The function is expected to take two arguments:
|
||||
* the current list item
|
||||
* the previous result
|
||||
Initially the function will take element1 and element2, outputting result1.
|
||||
Then the function will take result1 and element3, outputting result2.
|
||||
this will continue iuntil the list is exhausted.'
|
||||
(func list)
|
||||
(let ((list-iter (pop list))
|
||||
(result (car list-iter)))
|
||||
(set (q list-iter) (pop (cdr list-iter)))
|
||||
(if (lt? (len list) 2)
|
||||
(echo "list too short!")
|
||||
(while (gt? (len list-iter) 1)
|
||||
(let ((current (car list-iter))
|
||||
(remaining (cdr list-iter)))
|
||||
(set (q result) (func result current))
|
||||
(set (q list-iter) (pop remaining)))))
|
||||
result))
|
||||
|
||||
(def cond
|
||||
'Takes one argument: a list of pairs consisting of a form returning a bool and a form to execute
|
||||
The function iterates over the list checking if the first form of a pair evaluates to true, in which
|
||||
case it will execute the second form of the pair, returning its result, and stop the loop.'
|
||||
(list)
|
||||
(let ((iter list))
|
||||
(while (gt? (len iter) 0)
|
||||
(let ((current (car iter))
|
||||
(remaining (pop iter)))
|
||||
(if (eval (car current))
|
||||
(car (pop ((set (q iter) ())
|
||||
(eval (cdr current)))))
|
||||
(set (q iter) (cdr remaining)))))))
|
||||
|
||||
(def contains?
|
||||
'Takes two arguments: a list and an element.
|
||||
Returns true if the list contains the element.'
|
||||
(list elem)
|
||||
(let ((found false)
|
||||
(list-iter (pop list)))
|
||||
(while (and (gt? (len list-iter) 1)
|
||||
(not found))
|
||||
(let ((current (car list-iter))
|
||||
(remaining (cdr list-iter)))
|
||||
(if (eq? current elem)
|
||||
(set (q found) true)
|
||||
(set (q list-iter) (pop remaining)))))
|
||||
found))
|
||||
|
||||
(def get-paths
|
||||
'returns each individual directory in PATH'
|
||||
() (split PATH ':'))
|
||||
|
||||
(def add-path
|
||||
'Takes one argument.
|
||||
adds a directory to PATH'
|
||||
(path) (set (q PATH)
|
||||
(concat PATH ':' path)))
|
||||
|
||||
(def display-paths
|
||||
'prints out each element of $PATH one by one'
|
||||
()
|
||||
(let ((path-iter (pop (get-paths))))
|
||||
(while (gt? (len path-iter) 1)
|
||||
(let ((pat (car path-iter))
|
||||
(rem (cdr path-iter)))
|
||||
(echo pat)
|
||||
(set (q path-iter) (pop rem))))))
|
||||
Loading…
Add table
Add a link
Reference in a new issue