2024-02-06 22:39:08 +00:00
#!/bin/flesh
2023-03-20 16:22:51 -07:00
2024-02-06 22:39:08 +00:00
;; Fl e sh : Flexible Shell
;; Co p yright ( C ) 2021 Ava Affine
2023-03-17 13:06:27 -07:00
; ;
;; Th i s program is free software : you can redistribute it and / or modify
;; it under the terms of the GNU General Public License as published by
;; th e Free Software Foundation , either version 3 of the License , or
;; (a t your option ) any later version .
; ;
;; Th i s program is distributed in the hope that it will be useful ,
;; bu t WITHOUT ANY WARRANTY ; without even the implied warranty of
;; ME R CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
;; GN U General Public License for more details .
; ;
;; Yo u should have received a copy of the GNU General Public License
;; al o ng with this program . If not , see < http : / / www . gnu . org / licenses / > .
2023-03-17 13:24:31 -07:00
2023-03-17 13:06:27 -07:00
;; US E RLIB
2023-03-20 16:22:51 -07:00
;; Th i s file contains useful features that are not shipped in the STL
2023-06-20 01:25:19 +00:00
;; TO D O
;; di r - path
;; ab s - path
;; re l - path
;; un i que ( make set )
;; se t add
;; se t del
;; su p erset
;; co m mon - set
;; ma k e - map
;; in s - mapping
;; de l - mapping
;; ge t - mapping
;; ma p ped ?
2023-03-17 13:06:27 -07:00
2023-03-20 16:22:51 -07:00
;; th i s would be way faster as code in stl
;; bu t stl already suffers scope creep
2023-03-17 13:06:27 -07:00
(def p repend
2024-07-10 13:22:28 -07:00
"take s a list and appends an element to the back of it .
retu r ns prepended list "
2023-03-17 13:06:27 -07:00
(el e m list )
2023-03-20 16:22:51 -07:00
(re v erse ( cons ( reverse list ) elem ) ) )
2023-03-17 13:06:27 -07:00
(def s et
2024-07-10 13:22:28 -07:00
"sets an existing variable without touching its docstring .
2023-03-20 16:22:51 -07:00
2023-05-16 10:58:06 -07:00
WARN I NG :
2023-03-20 16:22:51 -07:00
If y ou find yourself struggling to debug a complex error in state acce ss,
or y ou are having issues re - running commands in the shell consider the
fol l owing advice :
2023-05-16 10:58:06 -07:00
It i s very much an anti pattern to mutate global variable that contain state.
2023-03-20 16:22:51 -07:00
ref a ctor your program : put iterators , counters , procedurally generated code,
and all other mutable state into a let loop .
2024-02-06 22:39:08 +00:00
A c o zy script in flesh is one where each root level form ( or eval at r epl)
2023-03-20 16:22:51 -07:00
is s elf contained , and does not permanently modify any other one .
2024-07-10 13:22:28 -07:00
See the userlib tests for an easy to follow example of this . "
2023-03-20 16:22:51 -07:00
2023-03-17 13:06:27 -07:00
(va r val )
(le t ( ( doc ( get - doc var ) ) )
2023-03-20 16:22:51 -07:00
( d ef ( eval var ) doc val ) ) )
2023-03-20 17:16:44 -07:00
(def m ap
2024-07-10 13:22:28 -07:00
"Take s two arguments : a function and a list .
2023-03-20 16:22:51 -07:00
for e a ch element in the list , the function is applied and the
2024-07-10 13:22:28 -07:00
resul t is added to a new list . Returns the new list . "
2023-03-20 16:22:51 -07:00
(func list )
(let ( ( list - iter ( pop list ) )
( result ( ) ) )
(wh i le ( gt ? ( len list - iter ) 1 )
2024-07-10 13:22:28 -07:00
( l et ( ( current ( car list - iter ) )
( remaining ( cdr list - iter ) )
2023-03-20 16:22:51 -07:00
( current - res ( func current ) ) )
2024-07-10 13:22:28 -07:00
( set ( q result ) ( cons result current - res ) )
2023-03-20 16:22:51 -07:00
( set ( q list - iter ) ( pop remaining ) ) ) )
res u lt ) )
2023-03-20 21:07:16 -07:00
(def r educe
2024-07-10 13:22:28 -07:00
"Take s two arguments : a function and a list .
2023-03-20 21:07:16 -07:00
The f u nction is expected to take two arguments :
* the current list item
* the previous result
Initi a lly the function will take element1 and element2 , outputting resul t1.
Then t he function will take result1 and element3 , outputting result2 .
2024-07-10 13:22:28 -07:00
this w ill continue iuntil the list is exhausted . "
2023-03-20 21:07:16 -07:00
(func list )
(let ( ( list - iter ( pop list ) )
2024-07-10 13:22:28 -07:00
( result ( car list - iter ) ) )
2023-03-20 21:07:16 -07:00
(se t ( q list - iter ) ( pop ( cdr list - iter ) ) )
(if ( lt ? ( len list ) 2 )
( echo " list too short !")
( while ( gt ? ( len list - iter ) 1 )
2024-07-10 13:22:28 -07:00
( let ( ( current ( car list - iter ) )
2023-03-20 21:07:16 -07:00
( remaining ( cdr list - iter ) ) )
2024-07-10 13:22:28 -07:00
( set ( q result ) ( func result current ) )
2023-03-20 21:07:16 -07:00
( set ( q list - iter ) ( pop remaining ) ) ) ) )
res u lt ) )
2023-03-20 22:03:10 -07:00
2023-06-13 00:18:11 +02:00
(def c ond
2024-07-10 13:22:28 -07:00
"Take s one argument : a list of pairs consisting of a form containing a b ool and a form to execute
The f u nction iterates over the list checking if the first element of eac h form evaluates to true, if so it will execute the second form of the pair, returning its result, and stop the loop."
2023-06-13 00:18:11 +02:00
(list )
2024-07-10 13:22:28 -07:00
(let ( ( iter list ) )
(wh i le ( gt ? ( len iter ) 0 )
( l et ( ( current ( car iter ) )
( remaining ( pop iter ) ) )
( if ( eval ( car current ) )
( let ( ( res ( eval ( cdr current ) ) ) )
( set ( q iter ) ( ) )
res )
( set ( q iter ) ( cdr remaining ) ) ) ) ) ) )
2023-06-13 00:18:11 +02:00
2023-03-20 22:03:10 -07:00
(def c ontains ?
2024-07-10 13:22:28 -07:00
"Take s two arguments : a list and an element .
Retur n s true if the list contains the element . "
2023-03-20 22:03:10 -07:00
(list elem )
2024-07-10 13:22:28 -07:00
(let ( ( found false )
2023-03-20 22:03:10 -07:00
( list - iter ( pop list ) ) )
(wh i le ( and ( gt ? ( len list - iter ) 1 )
( not found ) )
2024-07-10 13:22:28 -07:00
( l et ( ( current ( car list - iter ) )
2023-03-20 22:03:10 -07:00
( remaining ( cdr list - iter ) ) )
( if ( eq ? current elem )
2024-07-10 13:22:28 -07:00
( set ( q found ) true )
2023-03-20 22:03:10 -07:00
( set ( q list - iter ) ( pop remaining ) ) ) ) )
fou n d ) )
2023-03-23 12:07:28 -07:00
(def g et - paths
2024-07-10 13:22:28 -07:00
"retu r ns each individual directory in PATH "
() (s p lit PATH ":" ) )
2023-03-23 12:07:28 -07:00
(def a dd - path
2024-07-10 13:22:28 -07:00
"Take s one argument .
adds a directory to PATH "
2023-03-23 12:07:28 -07:00
(path ) ( set ( q PATH )
2024-07-10 13:22:28 -07:00
( concat PATH ":" path ) ) )
2023-04-17 22:11:49 -07:00
(def d isplay - paths
2024-07-10 13:22:28 -07:00
"prin t s out each element of $ PATH one by one "
2023-04-17 22:11:49 -07:00
( )
(le t ( ( path - iter ( pop ( get - paths ) ) ) )
( w hile ( gt ? ( len path - iter ) 1 )
( let ( ( pat ( car path - iter ) )
( rem ( cdr path - iter ) ) )
( echo pat )
( set ( q path - iter ) ( pop rem ) ) ) ) ) )
2024-06-01 08:55:53 -07:00
(def j oin
2024-07-10 13:22:28 -07:00
"conc a tenates list elements into a string , while
inter s persing a provided delimiter in between elements "
2024-06-01 08:55:53 -07:00
(li s t delim )
(re d uce ( lambda ( res elem )
( if ( eq ? ( strlen res ) 0 )
2024-07-10 13:22:28 -07:00
( string elem )
2024-06-01 08:55:53 -07:00
( concat res delim elem ) ) )
l i st ) )
2024-06-11 17:07:49 -07:00
(def e xtend
2024-07-10 13:22:28 -07:00
"adds all elements in set2 to set1 "
2024-06-11 17:07:49 -07:00
(se t 1 set2 )
(re d uce ( lambda ( res elem ) ( cons res elem ) )
( prepend set1 set2 ) ) )