Commit initial

This commit is contained in:
bvaudour 2020-03-13 15:03:36 +01:00
commit df4f2c07c1
67 changed files with 1781 additions and 0 deletions

@ -0,0 +1 @@
Subproject commit 4933947f086421494cfb444b2d90ce0a51faa493

@ -0,0 +1 @@
Subproject commit 5a361ca5ce20a57e1f80a9ee893c2423e63e7ee1

@ -0,0 +1 @@
Subproject commit 97a5aa575fa60be55e61800d885e6108ccca04ff

@ -0,0 +1 @@
Subproject commit 21e048ee6dca73c27d61068e03a113c97cf0a278

@ -0,0 +1 @@
Subproject commit 3ff9fe88bb40dff3591d7e40e3c7dfa06c584e60

@ -0,0 +1 @@
Subproject commit 1010ade24d1dee0a9b62506cfa86298158cac70f

55
lib/moi/aliases.elv Normal file
View file

@ -0,0 +1,55 @@
use github.com/zzamboni/elvish-modules/alias
#fn pacman [@_args]{
# if (and (== (count $_args) 0) (has-value [-S -Sy -Syu -Syyu -Su -Suu] $_args[0])) {
# mirror-check --fast
# }
# e:pacman $@_args
#}
alias:new cat bat -pp
alias:new midi e:fluidsynth -a pulseaudio /usr/share/soundfonts/FluidR3_GM.sf2
alias:new timidity e:timidity -a -K -1
alias:new git e:hub
#alias:new pacmanhisto cat /var/log/pacman.log | grep "ALPM" | grep
alias:new pf e:pkgfile -vri
alias:new trsen e:rlwrap trans -b -t en
alias:new trsfr e:rlwrap trans -b -t fr
alias:new youtube-dl e:youtube-dl --no-check-certificate
alias:new youtube_audio youtube-dl -x --audio-format best
#alias:new history edit:command-history
alias:new cp e:cp -iv
alias:new mv e:mv -iv
alias:new rm e:rm -Iv
@argls = -N --color=auto --group-directories-first --ignore=lost+found '--time-style=+"%Y.%m.%d %H:%M"' --indicator-style=classify
#alias:new br e:broot -dp
alias:new tree e:tree -puhC --dirsfirst --du -D
alias:new ls e:ls $@argls
alias:new la e:ls -a $@argls
alias:new ll e:ls -lh $@argls
alias:new lla e:ls -la $@argls
alias:new df e:df -h
alias:new du e:du -h
alias:new diff e:colordiff
alias:new grep e:grep --color=tty -d skip
alias:new vi e:vim
alias:new vv e:vim -R
alias:new vb e:vim ~/.bashrc
alias:new vf e:vim ~/.config/config.fish
alias:new vz e:vim ~/.zshrc
alias:new vc e:vim ~/.vimrc
alias:new vp e:vim PKGBUILD
fn export []{ alias:export }

8
lib/moi/completion.elv Normal file
View file

@ -0,0 +1,8 @@
use ./completion/arc
use ./completion/archiver
use ./completion/desarchiver
use ./completion/kcp
use ./completion/mpv
use ./completion/pacman
use ./completion/ssh
use ./completion/sudo

View file

@ -0,0 +1,48 @@
use moi/util/condition
use moi/util/file
commands = [
help
archive
unarchive
extract
ls
]
extensions = [ tar bz2 zip gz lz4 sz xz zst rar ]
fn -comp-commands { explode $commands }
fn -comp-archive-files [m]{
local:type = (condition:set (eq $m '') prefix deep-prefix)
file:match-extensions &type=$type $m $@extensions
}
fn -comp-inline-files [archive]{
try {
e:arc ls $archive | eawk [_ @argv]{ put $argv[-1] }
} except e {
nop
}
}
fn complete [@argv]{
local:c = (count $argv)
local:cmd = $argv[1]
if (== $c 2) {
-comp-commands
} elif (== $c 3) {
if (not (has-value [help archive] $cmd)) {
-comp-archive-files $argv[-1]
}
} else {
if (eq $cmd archive) {
edit:complete-filename $@argv
} elif (eq $cmd extract) {
local:archive = $argv[2]
-comp-inline-files $archive
}
}
}
edit:completion:arg-completer[arc] = $complete~

View file

@ -0,0 +1,29 @@
options = [
z
l
x
b
g
h
]
description = [
&z='zst compression (default)'
&l='lz4 compression'
&x='xz compression'
&b='bz2 compression'
&g='gzip compression'
&h='display help'
]
fn -options {
each [o]{
put [&short=$o &desc=$description[$o]]
} $options
}
fn complete [@argv]{
edit:complete-getopt $argv [(-options)] [ $edit:complete-filename~ ...]
}
edit:completion:arg-completer[archiver] = $complete~

View file

@ -0,0 +1,12 @@
use moi/util/condition
use moi/util/file
extensions = [ tar bz2 zip gz lz4 sz xz zst rar ]
fn complete [@argv]{
local:m = $argv[-1]
local:type = (condition:set (eq $m '') prefix deep-prefix)
file:match-extensions &type=$type $m $@extensions
}
edit:completion:arg-completer[desarchiver] = $complete~

View file

@ -0,0 +1,41 @@
fn -remotes-packages { kcp -lN }
options = [
-h
-v
-i
-di
-u
-l
-lN
-lS
-lI
-lO
-lx
-lxS
-lxI
-lxO
-lf
-s
-g
-V
]
np = [
-i
-di
-s
-g
-V
]
fn complete [@argv]{
local:c = (count $argv)
if (== $c 2) {
explode $options
} elif (and (== $c 3) (has-value $np $argv[-2])) {
-remotes-packages
}
}
edit:completion:arg-completer[kcp] = $complete~

View file

@ -0,0 +1,59 @@
use moi/util/condition
use moi/util/file
extensions = [
aac
ape
avi
divx
flac
flv
m3u
m4a
m4v
mp3
mp4
mpeg
mpg
mkv
mng
mov
qt
oga
ogg
ogm
ogv
opus
ra
rv
ts
vob
wav
webm
wmv
wma
wmx
]
fn -files [m]{
local:type = (condition:set (eq $m '') prefix deep-prefix)
file:match-extensions &type=$type $m $@extensions
}
fn complete [@argv]{
c = (count $argv)
if (== $c 2) {
put --speed
-files $argv[-1]
} elif (== $c 3) {
if (eq $argv[-2] --speed) {
put 0.8 0.9 1.0 1.1 1.2
} else {
-files $argv[-1]
}
} else {
-files $argv[-1]
}
}
edit:completion:arg-completer[mpv] = $complete~

View file

@ -0,0 +1,104 @@
use moi/util/condition
use moi/util/file
use moi/util/list
fn -local-packages { pacman -Q | eawk [_ p @_]{ put $p } }
fn -repo-packages {
local:packages = [(pacman -Ss | list:ploop &step=2 [_ v]{
put $v
} | eawk [_ p @_]{
put $p
})]
local:spackages = [&]
peach [p]{
splits '/' $p
} $packages | peach [e]{
spackages[$e] = $nil
}
keys $spackages
explode $packages
}
fn -downloaded-packages [m]{
local:type = (condition:set (eq $m '') prefix deep-prefix)
file:match-extensions &type=$type $m tar.zst tar.xz tar.gz tar.bz2
}
fn -local-file [m]{ edit:complete-filename $m }
options = [
-h
-V
-Q
-Qs
-Ql
-Qi
-Qm
-Qdt
-Qo
-R
-Rsn
-S
-Ss
-Si
-Sii
-Syu
-Syyu
-U
-D
]
asdeps = [
-S
-U
-D
]
lpack = [
-Q
-Qs
-Ql
-Qi
-D
-R
-Rsn
]
rpack = [
-S
-Ss
-Si
-Sii
]
dpack = [
-U
]
fpack = [
-Qo
]
fn complete [@argv]{
local:c = (count $argv)
if (< $c 3) {
explode $options
} else {
local:cmd = $argv[1]
if (and (== $c 3) (has-value $asdeps $cmd)) {
put --asdeps --asexplicit
}
if (has-value $lpack $cmd) {
-local-packages
} elif (has-value $rpack $cmd) {
-repo-packages
} elif (has-value $dpack $cmd) {
-downloaded-packages $argv[-1]
} elif (has-value $fpack $cmd) {
-local-file $argv[-1]
}
}
}
edit:completion:arg-completer[pacman] = $complete~

251
lib/moi/completion/ssh.elv Normal file
View file

@ -0,0 +1,251 @@
use re
use str
use moi/util/condition
use moi/util/file
use moi/util/ip
use moi/util/list
use moi/util/map
use moi/util/option
options-ssh = [ 1 2 4 6 A D f g I i L l m o v a b C c e F k N n p q R s T t X x ]
options-scp = [ 3 4 6 B C p q r v c F i l o P S ]
fn -init-hosts {
local:result = [&]
cat /etc/hosts | peach $str:trim-space~ | peach [l]{
local:l = $l
if (and (not-eq $l '') (not-eq $l[0] '#')) {
put $l
}
} | eawk [_ ip @domains]{
if (ip:is-ip $ip) {
put [$ip $domains]
}
} | peach [e]{
local:ip local:domains = $@e
if (ip:is-ipv6 $ip) {
ip = (ip:short6 $ip)
}
each [d]{
if (eq $d[0] '#') {
break
}
put [$ip $d]
} $domains
} | each [e]{
local:ip local:d = $@e
local:ipd = (map:value-of $result $ip &default=[&])
ipd[$d] = $nil
result[$ip] = $ipd
}
put $result
}
fn -init-known-hosts {
local:khosts = [&22=[&]]
cat ~/.ssh/known_hosts | peach [l]{
put [(splits ' ' $l)]
} | peach [e]{
local:domains @local:id = $@e
id = (joins ' ' $id)
splits ',' $domains | peach [d]{
local:d = $d
local:port = 22
if (eq $d[0] '[') {
local:i = (str:index $d ']')
port = $d[(+ $i 2):]
d = $d[1:$i]
}
put [$id $d $port]
}
} | each [e]{
local:id local:d local:port = $@e
local:pdomains = (map:value-of $khosts $port &default=[&])
local:idomains = (map:value-of $pdomains $id &default=[&])
idomains[$d] = $nil
pdomains[$id] = $idomains
khosts[$port] = $pdomains
}
local:result = [&22=[&]]
keys $khosts | each [port]{
local:pdomains = (map:value-of $result $port &default=[&])
keys $khosts[$port] | peach [id]{
local:id = $id
local:domains = [(keys $khosts[$port][$id])]
if (list:contains-not $ip:is-ip~ $domains) {
list:filter-not $ip:is-ip~ $domains | peach [d]{ pdomains[$d] = $nil }
} else {
peach [d]{ pdomains[$d] = $nil } $domains
}
}
result[$port] = $pdomains
}
put $result
}
fn -init-history {
local:history = [&]
edit:command-history | peach [e]{
put $e[cmd]
} | peach [h]{
if (re:match '^(ssh|scp)\ .+' $h) {
history[$h] = $nil
}
}
local:result = [&22=[&]]
keys $history | peach [h]{
local:h = $h
put [(re:split '[ \t]+' $h)]
} | peach [e]{
local:cmd @local:argv = $@e
local:port local:name local:domain = 22 '' ''
local:c = (- (count $argv) 1)
list:loop [i arg]{
if (and (< $i $c) (or (and (eq $cmd ssh) (eq $arg -p)) (eq $arg -P))) {
port = $argv[(+ $i 1)]
} else {
local:nd = [(splits '@' $arg)]
if (== (count $nd) 2) {
name = $nd[0]
domain @_ = (splits ':' $nd[1])
break
}
}
} $argv
if (and (not-eq $name '') (not-eq $domain '')) {
put [$port $name $domain]
}
} | each [e]{
local:port local:name local:domain = $@e
local:pnames = (map:value-of $result $port &default=[&])
local:domains = (map:value-of $pnames $name &default=[&])
domains[$domain] = $nil
pnames[$name] = $domains
result[$port] = $pnames
}
put $result
}
combinaisons = [&]
fn init {
local:hosts local:known-hosts local:history = [] [] []
peach [f]{ $f } [
{ hosts = (-init-hosts) }
{ known-hosts = (-init-known-hosts) }
{ history = (-init-history) }
]
combinaisons = $history
keys $known-hosts | peach [port]{
local:port = $port
local:pdomains = $known-hosts[$port]
keys $pdomains | peach [domain]{
local:domain = $domain
if (and (ip:is-ip $domain) (has-key $hosts $domain)) {
del pdomains[$domain]
keys $hosts[$domain] | peach [d]{
local:d = $d
pdomains[$d] = $nil
}
}
}
if (> (keys $pdomains | count) 0) {
if (has-key $history $port) {
local:phist = $history[$port]
local:dhist = (keys $phist | peach [name]{ keys $phist[$name] } | map:to-set)
local:dknown = [&]
keys $pdomains | peach [domain]{
local:domain = $domain
if (not (has-key $dhist $domain)) {
dknown[$domain] = $nil
}
}
if (> (keys $dknown | count) 0) {
combinaisons[$port] = (assoc $phist '' $dknown)
} else {
combinaisons[$port] = [&''=$dknown]
}
} else {
combinaisons[$port] = [&''=$pdomains]
}
}
}
}
fn -known-ports { keys $combinaisons }
fn -known-names [&port=22]{
keys (map:value-of $combinaisons $port &default=[&]) | list:filter [n]{ not-eq $n '' }
}
fn -known-hosts [&port=22 &name=$false]{
local:phosts = (map:value-of $combinaisons $port &default=[&])
if $name {
keys (map:value-of $phosts $name &default=[&])
} else {
keys (keys $phosts | peach [name]{
local:name = $name
keys $phosts[$name]
} | map:to-set)
}
}
fn -port [&cmd=ssh @argv]{
o = (condition:set (eq $cmd 'ssh') '-p' '-P')
margs = (option:map $argv)
map:value-of $margs $o &default=[]
}
fn -complete-options [list @args]{ each [o]{ put -$o } $list }
fn -complete-args [cmd @argv]{
local:port = (-port $cmd $@argv)
if (list:empty $port) {
port = 22
} else {
port = $port[-1]
}
local:larg = $argv[-1]
local:name @local:host = (splits '@' $larg)
if (list:empty $host) {
-known-names &port=$port | each [n]{ put $n'@' }
if (eq $cmd 'scp') {
file:match-files $larg
}
} else {
host @_ = (splits ':' $host[0])
local:check = [h]{ has-prefix $h $host }
local:khosts = [(-known-hosts &port=$port &name=$name)]
if (not (list:contains $check $khosts)) {
khosts = [(-known-hosts &port=$port)]
if (not (list:contains $check $khosts)) {
khosts = [(-known-hosts)]
}
}
each [h]{ put $name'@'$h } $khosts
explode $khosts
}
}
fn complete [@argv]{
if (keys $combinaisons | list:empty) {
init
}
local:cmd = $argv[0]
local:is-ssh = (eq $cmd ssh)
local:po = (condition:set $is-ssh -p -P)
if (<= (count $argv) 2) {
-complete-options (condition:set $is-ssh $options-ssh $options-scp)
-complete-args $@argv
} elif (eq $argv[-2] $po) {
-known-ports
} else {
-complete-args $@argv
}
}
edit:completion:arg-completer[scp] = $complete~
edit:completion:arg-completer[ssh] = $complete~
init&

View file

@ -0,0 +1,10 @@
fn complete [@argv]{
if (and (> (count $argv) 2) (has-key $edit:completion:arg-completer $argv[1])) {
$edit:completion:arg-completer[$argv[1]] (explode $argv[1:])
} else {
edit:complete-sudo $@argv
}
}
edit:completion:arg-completer[sudo] = $edit:complete-sudo~
#edit:completion:arg-completer[sudo] = $-complete~

7
lib/moi/util.elv Normal file
View file

@ -0,0 +1,7 @@
use moi/util/condition
use moi/util/file
use moi/util/ip
use moi/util/list
use moi/util/map
use moi/util/number
use moi/util/option

View file

@ -0,0 +1,20 @@
fn set [c t f]{
if $c {
put $t
} else {
put $f
}
}
fn mset [c t f]{
explode (set $c $t $f)
}
fn call [c t f @argv]{
local:v = (set $c $t $f)
if (is (kind-of $v) fn) {
$v $@argv
} else {
put $v
}
}

63
lib/moi/util/file.elv Normal file
View file

@ -0,0 +1,63 @@
search-type = [
&exact= [m]{ e:ls $m 2>/dev/null }
&match= [m]{ put *$m* }
&prefix= [m]{ put $m* }
&suffix= [m]{ put *$m }
&deep-match= [m]{ put **$m** }
&deep-prefix= [m]{ put $m** }
&deep-suffix= [m]{ put **$m }
]
fn -less [f1 f2]{
use str
local:fl1 local:fl2 = (str:to-lower $f1) (str:to-lower $f2)
local:c = (str:compare $fl1 $fl2)
if (== $c 0) {
c = (str:compare $f1 $f2)
}
put (< $c 0)
}
fn -get-results [sort result]{
if $sort {
use ./list
keys $result | list:sort $-less~
} else {
keys $result
}
}
fn -search [&sort=$false &type=exact @motive]{
use ./list
local:f = $search-type[$type]
local:result = [&]
if (list:empty $motive) {
use ./map
result = (put * | map:to-set)
} else {
peach [m]{
local:m = $m
try {
$f $m | peach [e]{
local:e = $e
result[$e] = $nil
}
} except e { }
} $motive
}
-get-results $sort $result
}
fn match-files [&sort=$false &type=prefix @motive]{ -search &sort=$sort &type=$type $@motive }
fn match-extensions [&sort=$false &type=deep-prefix motive @extensions]{
use ./list
result = [&]
-search &type=$type $motive | peach [f]{
local:f = $f
if (list:contains [e]{ has-suffix $f .$e } $extensions) {
result[$f] = $nil
}
}
-get-results $sort $result
}

132
lib/moi/util/ip.elv Normal file
View file

@ -0,0 +1,132 @@
fn is-ipv4 [arg]{
use re
if (not (re:match '^([0-9]{1,3}\.){3}[0-9]{1,3}$' $arg)) {
put $false
} else {
use ./list
not (splits '.' $arg | list:contains [p]{ > $p 255 })
}
}
fn is-ipv6 [arg]{
use re
local:p = '[0-9a-fA-F]{1,4}'
local:g1 local:g2 = '('$p':)' '(:'$p')'
local:cases = [
$g1'{7,7}'$p
$g1'{1,7}:'
$g1'{1,6}:'$p
$g1'{1,5}'$g2'{1,2}'
$g1'{1,4}'$g2'{1,3}'
$g1'{1,3}'$g2'{1,4}'
$g1'{1,2}'$g2'{1,5}'
$p':'$g2'{1,6}'
':'$g2'{1,7}'
'::'
]
local:r = '^('(joins '|' $cases)')$'
put (re:match $r $arg)
}
fn -long-part6 [p]{
use str
p = (str:to-lower $p)
c = (- 4 (count $p))
put (repeat $c '0' | joins '')$p
}
fn -middle-part6 [p]{
while (and (> (count $p) 1) (eq $p[0] 0)) {
p = $p[1:]
}
put $p
}
fn -find-max0 [parts]{
use ./list
use ./condition
local:idx local:s = -1 1
local:ci local:cs local:f = -1 0 $false
list:loop [i p]{
if (eq $p 0) {
condition:call $f { cs = (+ $cs 1) } { ci cs f = $i 1 $true }
} elif $f {
f = $false
if (> $cs $s) {
idx s = $ci $cs
}
}
} $parts
if (and $f (> $cs $s)) {
idx s = $ci $cs
}
put $idx $s
}
fn long6 [ip]{
if (not (is-ipv6 $ip)) {
fail 'Not an IPv6'
}
if (eq $ip '::') {
repeat 8 '0000' | joins ':'
return
}
use str
local:c = (- 7 (str:count $ip ':'))
if (> $c 0) {
local:i = (str:index $ip '::')
local:z = (repeat $c ':' | joins '')
ip = (joins '' [$ip[:$i] $z $ip[{$i}:]])
}
splits ':' $ip | each $-long-part6~ | joins ':'
}
fn middle6 [ip]{
splits ':' (long6 $ip) | each $-middle-part6~ | joins ':'
}
fn short6 [ip]{
local:parts = [(splits ':' (middle6 $ip))]
local:i local:s = (-find-max0 $parts)
if (>= $i 0) {
local:left local:right = $parts[:$i] $parts[(+ $i $s):]
if (== (count $left) 0) {
left = ['']
}
if (== (count $right) 0) {
right = ['']
}
parts = [$@left '' $@right]
}
joins ':' $parts
}
fn is-ip [arg]{ or (is-ipv4 $arg) (is-ipv6 $arg) }
fn -cmp [e1 e2]{
use ./list
use ./condition
local:c = 0
list:loop [i p1]{
local:p2 = $e2[$i]
c = (condition:set (< $p1 $p2) -1 (condition:set (> $p1 $p2) 1 0))
if (!= $c 0) {
break
}
} $e1
put $c
}
fn cmp4 [ip1 ip2]{
if (or (not (is-ipv4 $ip1)) (not (is-ipv4 $ip2))) {
fail 'Not an IPv4'
}
-cmp [(splits . $ip1)] [(splits . $ip2)]
}
fn cmp6 [ip1 ip2]{
if (or (not (is-ipv6 $ip1)) (not (is-ipv6 $ip2))) {
fail 'Not an IPv6'
}
-cmp [(splits : (middle6 $ip1))] [(splits : (middle6 $ip2))]
}

309
lib/moi/util/list.elv Normal file
View file

@ -0,0 +1,309 @@
use ./condition
fn -i [&reverse=false i c]{
if (and (== $c 0) (or (== $i 0) ($i -1))) {
put 0
return
}
if (< $i 0) {
i = (+ $c $i)
}
if (or (and (>= $i 0) (< $i $c)) (and (== $i -1) $reverse) (and (== $i $c) (not $reverse))) {
put $i
} else {
fail 'Index out of range'
}
}
fn -indexes [&from=$false &step=1 l]{
if (== $step 0) {
fail 'Step must be ≠ 0'
}
local:c local:r = (count $l) (< $step 0)
if (not $from) {
if $r {
range &step=$step[1:] $c | each [i]{ - $c $i 1 }
} else {
range &step=$step $c
}
} else {
from = (-i &reverse=$r $from $c)
if $r {
c = (+ $from 1)
range &step=$step[1:] $c | each [i]{ - $c $i 1 }
} else {
range &step=$step $from $c
}
}
}
fn -loop [&from=$false &step=1 &end=$false cb l]{
if (not $end) {
-indexes &from=$from &step=$step $l | each [i]{
put [$i $l[$i]]
} | each [e]{
$cb $@e
}
} else {
-indexes &from=$from &step=$step $l | each [i]{
put [$i $l[$i]]
} | each [e]{
local:i local:v = $@e
if ($end $i $v) {
break
}
$cb $i $v
}
}
}
fn -ploop [&from=$false &step=1 cb l]{
-indexes &from=$from &step=$step $l | peach [i]{
put [$i $l[$i]]
} | peach [e]{
$cb $@e
}
}
fn -reverse [l]{
-indexes &step=-1 $l | each [i]{ put $l[$i] }
}
fn -reach [cb l]{
-reverse $l | each [v]{ $cb $v }
}
fn -empty [l]{ eq (count $l) 0 }
fn -filter [cb l]{
each [v]{
if ($cb $v) {
put $v
}
} $l
}
fn -first [&from=$false &reverse=$false cb l]{
local:f = [v]{
if ($cb $v) {
put $v
break
}
}
if $reverse {
if $from {
local:end = (-i $from (count $l))
-reach $f $l[:(+ $end 1)]
} else {
-reach $f $l
}
} else {
if $from {
from = (-i $from (count $l))
drop $from $l | each $f
} else {
each $f $l
}
}
}
fn -filter-index [cb l]{
-loop [i v]{
if ($cb $v) {
put $i
}
} $l
}
fn -first-index [&from=$false &reverse=$false cb l]{
local:idx = -1
-loop &from=$from &step=(condition:set $reverse -1 1) [i v]{
if ($cb $v) {
idx = $i
break
}
} $l
put $idx
}
fn -search [cb l]{
-loop [i v]{
if ($cb $i $v) {
put $v
}
} $l
}
fn -search-first [&from=$false &reverse=$false cb l]{
-loop &from=$from &step=(condition:set $reverse -1 1) [i v]{
if ($cb $i $v) {
put $v
break
}
} $l
}
fn -search-index [cb l]{
-loop [i v]{
if ($cb $i $v) {
put $i
}
} $l
}
fn -search-first-index [&from=$false &reverse=$false cb l]{
local:idx = -1
-loop &from=$from &step=(condition:set $reverse -1 1) [i v]{
if ($cb $i $v) {
idx = $i
break
}
}
put $idx
}
fn -contains [cb l]{
local:e = $false
each [v]{
if ($cb $v) {
e = $true
break
}
} $l
put $e
}
fn -exists [cb l]{
local:e = $false
-loop [i v]{
if ($cb $i $v) {
e = $true
break
}
} $l
put $e
}
fn -remove-duplicate [l]{
local:done = [&]
each [v]{
put [&v=$v &e=(has-key $done $v)]
done[$v] = $nil
} $l | each [v]{
assoc $v k (not $v[e])
} | each [v]{
if $v[k] {
put $v[v]
}
}
}
fn -premove-duplicate [l]{
local:done= [&]
peach [v]{
local:v = $v
done[$v] = $nil
}
keys $done
}
fn -swap [i j l]{
local:c = (count $l)
i j = (-i $i $c) (-i $j $c)
if (or (eq $i $c) (eq $j $c)) {
fail 'Index out of range'
}
if (eq $i $j) {
explode $l
} else {
i j = (condition:mset (< $i $j) [$i $j] [$j $i])
take $i $l
put $l[j]
explode $l[(+ $i 1):$j]
put $l[$i]
drop (+ $j 1) $l
}
}
fn -p [@argv]{
local:c = (count $argv)
if (eq $c 0) {
put [(all)]
} elif (eq $c 1) {
put $argv[0]
} else {
fail '0 or 1 argument needed'
}
}
fn to-list [@argv]{
try {
-p $@argv
} except e {
put $argv
}
}
fn indexes [&from=$false &step=1 @argv]{ -indexes &from=$from &step=1 (-p $@argv) }
fn loop [&from=$false &step=1 &end=$false cb @argv]{ -loop &from=$from &step=$step &end=$end $cb (-p $@argv) }
fn rloop [&end=$false cb @argv]{ loop &step=-1 &end=$end $cb $@argv }
fn ploop [&from=$false &step=1 cb @argv]{ -ploop &from=$from &step=$step $cb (-p $@argv) }
fn reverse [@argv]{ -reverse (-p $@argv) }
fn reach [cb @argv]{ -reach $cb (-p $@argv) }
fn empty [@argv]{ -empty (-p $@argv) }
fn not-empty [@argv]{ not (empty $@argv) }
fn filter [cb @argv]{ -filter $cb (-p $@argv) }
fn filter-not [cb @argv]{ filter [v]{ not ($cb $v) } $@argv }
fn first [&from=$false &reverse=$false cb @argv]{ -first &from=$from &reverse=$reverse $cb (-p $@argv) }
fn filter-index [cb @argv]{ -filter-index $cb (-p $@argv) }
fn filter-index-not [cb @argv]{ filter-index [v]{ not ($cb $v) } $@argv }
fn first-index [&from=$false &reverse=$false cb @argv]{ -first-index &from=$from &reverse=$reverse $cb (-p $@argv) }
fn search [cb @argv]{ -search $cb (-p $@argv) }
fn search-not [cb @argv]{ search [i v]{ not ($cb $i $v) } $@argv }
fn search-first [&from=$false &reverse=$false cb @argv]{ -search-first &from=$from &reverse=$reverse $cb (-p $@argv) }
fn search-index [cb @argv]{ -search-index $cb (-p $@argv) }
fn search-index-not [cb @argv]{ search-index [i v]{ not ($cb $i $v) } $@argv }
fn search-first-index [&from=$false &reverse=$false cb @argv]{ -search-first-index &from=$from &reverse=$reverse $cb (-p $@argv) }
fn contains [cb @argv]{ -contains $cb (-p $@argv) }
fn contains-not [cb @argv]{ contains [v]{ not ($cb $v) } $@argv }
fn exists [cb @argv]{ -exists $cb (-p $@argv) }
fn exists-not [cb @argv]{ exists [i v]{ $cb $i $v } $@argv }
fn reduce [v cb @argv]{
each [e]{ v = ($cb $v $e) } (to-list $@argv)
put $v
}
fn remove-duplicate [@argv]{ -remove-duplicate (-p $@argv) }
fn premove-duplicate [@argv]{ -premove-duplicate (-p $@argv) }
fn swap [i j @argv]{ -swap $i $j (-p $@argv) }
fn -s1 [cb l e]{
c = (count $l)
i = (first-index [v]{ $cb $e $v } $l)
if (eq $i 0) {
put $e
explode $l
} elif (< $i 0) {
explode $l
put $e
} else {
explode $l[:$i]
put $e
explode $l[{$i}:]
}
}
fn -sort [cb l]{
c = (count $l)
if (> $c 1) {
l2 = $l[:1]
each [e]{ l2 = [ (-s1 $cb $l2 $e) ] } $l[1:]
l = $l2
}
explode $l
}
fn sort [cb @argv]{ -sort $cb (-p $@argv) }

77
lib/moi/util/map.elv Normal file
View file

@ -0,0 +1,77 @@
fn empty [container]{ == (count $container) 0 }
fn values [container]{ keys $container | each [v]{ put $container[$v] } }
fn pvalues [container]{ keys $container | peach [v]{ put $container[$v] } }
fn value-of [container k &default=$nil]{
if (has-key $container $k) {
put $container[$k]
} else {
put $default
}
}
fn unzip [container]{
local:lkeys local:lvalues = [] []
keys $container | each [k]{
lkeys = [(explode $lkeys) $k]
lvalues = [(explode $lvalues) $container[$k]]
}
put $lkeys $lvalues
}
fn zip [lkeys lvalues]{
use ./condition
local:ck local:cv = (count $lkeys) (count $lvalues)
local:c = (condition:set (> $ck $cv) $cv $ck)
local:result = [&]
range $c | peach [i]{
put [&k=$lkeys[$i] &i=$i]
} | peach [e]{
assoc $e v $lvalues[$e[i]]
} | each [e]{
result[$e[k]] = $e[v]
}
put $result
}
fn to-map [@argv]{
use ./list
local:container = (list:to-list $@argv)
zip [(range (count $container))] $container
}
fn to-set [@argv]{
use ./list
local:m = [&]
each [k]{ m[$k] = $nil } (list:to-list $@argv)
put $m
}
fn mdissoc [container @argv]{
each [k]{
container = (dissoc $container $k)
} $argv
put $container
}
fn massoc [&replace=$true container @argv]{
each [e]{
local:k local:v = $@e
if (or $replace (not (has-key $container $k))) {
container[$k] = $v
}
} $argv
put $container
}
fn add [container key @values]{
use ./list
local:values = (list:to-list $values)
if (has-key $container $key) {
container[$key] = [(explode $container[$key]) $@values]
} else {
container[$key] = $values
}
put $container
}

40
lib/moi/util/number.elv Normal file
View file

@ -0,0 +1,40 @@
fn sign [n]{
if (> $n 0) {
put 1
} elif (< $n 0) {
put -1
} else {
put 0
}
}
fn negative [n]{ < $n 0 }
fn positive [n]{ >= $n 0 }
fn ++ [n]{ to-string (+ $n 1) }
fn -- [n]{ to-string (+ $n 1) }
fn neg [n]{ to-string (* $n -1) }
fn abs [n]{
use ./condition
condition:call (negative $n) $neg~ $put~ $n
}
fn sum [@numbers]{
use ./list
to-string (list:reduce 0 $+~ $numbers)
}
fn -minmax [t numbers]{
if (== (count $numbers) 0) {
return
}
use ./list
use ./condition
f = [c v]{ condition:set ($t $v $c) $v $c }
list:reduce $numbers[0] $f $numbers[1:]
}
fn min [@numbers]{ -minmax $<~ $numbers }
fn max [@numbers]{ -minmax $>~ $numbers }

75
lib/moi/util/option.elv Normal file
View file

@ -0,0 +1,75 @@
use re
use str
use ./list
fn is-moptions [o]{ re:match '^\-\w{2,}$' $o }
fn is-soption [o]{ re:match '^\-\w$' $o }
fn is-loption [o]{ re:match '^\-\-\w+(=.*)?$' $o }
fn is-option [o]{ or (is-soption $o) (is-loption $o) (is-moptions $o) }
fn -splitm [o]{ each [e]{ put -$e } $o[1:] }
fn -splitl [o]{
if (str:contains $o '=') {
local:opt @local:value = (splits '=' $o)
put $opt
joins '=' $value
} else {
put $o
}
}
fn split [o]{
if (is-moptions $o) {
-splitm $o
} elif (is-loption $o) {
-splitl $o
} else {
put $o
}
}
fn -joins [opt]{
local:o = (each [o]{ put $o[1:] } $opt | joins '')
if (not-eq $o '') { put -$o }
}
fn join [@opt]{
local:opt = (list:-p $@opt)
local:cb = [o]{ or (is-soption $o) (is-moptions $o) }
local:idx = [(list:filter-index-not $cb $opt)]
local:i0 = 0
each [i]{
-joins $opt[{$i0}:$i]
put $opt[$i]
i0 = (+ $i 1)
} $idx
-joins $opt[{$i0}:]
}
fn expand [@argv]{ each $split~ (list:-p $@argv) }
fn map [@argv]{
use ./map
argv = [(expand $@argv)]
local:result = [&]
local:i local:c = 0 (count $argv)
while (< $i $c) {
local:o = $argv[$i]
if (is-option $o) {
local:k local:v = $o []
if (< $i (- $c 1)) {
local:e = $argv[(+ $i 1)]
if (not (is-option $e)) {
v = [$@v $e]
i = (+ $i 1)
}
}
result = (map:add $result $k $@v)
} else {
result = (map:add $result '' [$o])
}
i = (+ $i 1)
}
put $result
}