# This file is included first and automatically in all Goalfiles
# (unless you use --no-prelude). It contains standard functions and
-# tactics.
+# predicates.
-# The only tactic that ‘make’ has.
-tactic *file (filename) = {
+# The only predicate that ‘make’ has.
+predicate is-file (filename) = @{
# Rebuild if the target file doesn't exist at all.
test -f %filename || exit 99
done
}
-# This is a simpler tactic than the above since it will
+# This is a simpler predicate than the above since it will
# rebuild if the file is missing, but not if it is older.
-tactic *exists (filename) = {
+predicate is-file-exists (filename) = @{
test -f %filename || exit 99
}
#----------------------------------------------------------------------
+# Basic functions.
+
+function error (msg) = @{
+ echo %msg >&2
+ exit 1
+}
+
+# Wrap list of strings in a call or predicate.
+pure function wrap (wrapper, xs) = @{
+ echo '['
+ for x in %xs; do
+ echo %wrapper "( "
+ quoted_string "$x"
+ echo " ),"
+ done
+ echo ']'
+}
+
+#----------------------------------------------------------------------
# Text functions.
+# Filter a list by regexp.
+pure function filter (pat, xs) returning strings = @{
+ for f in %xs; do echo "$f"; done | grep -E -- %pat
+}
+
+# Filter out a list by regexp.
+pure function filter-out (pat, xs) returning strings = @{
+ for f in %xs; do echo "$f"; done | grep -v -E -- %pat
+}
+
+# Head of a list.
+pure function head (xs) returning string = @{
+ for f in %xs; do
+ echo "$f"
+ exit 0
+ done
+}
+
+# Join two lists.
+pure function join (xs, ys) returning strings = @{
+ for f in %xs %ys; do echo "$f"; done
+}
+
+# Last element of a list.
+pure function last (xs) returning string = @{
+ for f in %xs; do
+ r="$f"
+ done
+ echo "$r"
+}
+
+# n'th element of a list.
+pure function nth (n, xs) returning string = @{
+ i=0
+ r=
+ for f in %xs; do
+ if [ $i -eq %n ]; then r="$f"; fi
+ ((++i))
+ done
+ echo "$r"
+}
+
# Sort + uniq a list.
-function sort (xs) returning strings = {
+pure function sort (xs) returning strings = @{
for f in %xs; do echo "$f"; done | sort -u
}
+# Split a string into a list.
+# https://superuser.com/a/1066541
+pure function split (s) returning strings = @{
+ s=%s
+ eval 'for f in '$s'; do echo "$f"; done'
+}
+
+# Substitute.
+pure function subst (from, to, text) returning string = @{
+ # We need to replace any / characters in ‘to’ with escaped ones.
+ to="$( echo -n %to | sed 's,/,\\/,g' )"
+ echo %text | sed -E s/%from/$to/g
+}
+
+# Tail of a list.
+pure function tail (xs) returning strings = @{
+ drop=1
+ for f in %xs; do
+ if [ -z "$drop" ]; then echo "$f"; fi
+ drop=
+ done
+}
+
#----------------------------------------------------------------------
# File functions.
+# Base name.
+pure function basename (name) returning string = @{
+ basename -- %name
+}
+
+# Directory name.
+pure function dirname (name) returning string = @{
+ dirname -- %name
+}
+
+# File extension.
+pure function extension (name) returning string = @{
+ name=%name
+ echo "${name##*.}"
+}
+
+# Read a file.
+function read (filename) returning string = @{
+ cat -- %filename
+}
+
+# Read a file as a list of lines.
+function readlines (filename) returning strings = @{
+ cat -- %filename
+}
+
+# Real path.
+function realpath (filename) returning string = @{
+ realpath -- %filename
+}
+
# Expand a wildcard into a list of filenames.
-function wildcard (wc) returning strings = {
+#
+# This function is probably not "pure" since it depends on the
+# current working directory and also files may be created in
+# the directory while goals is running which would affect the
+# result.
+function wildcard (wc) returning strings = @{
shopt -s nullglob
# Note that the substitution is quoted by goals, so to expand
# it we must assign it to a variable and then use it unquoted.