Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stdlib): extract function #587

Merged
merged 19 commits into from
Nov 30, 2024
31 changes: 30 additions & 1 deletion src/std/fs.ab
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { join, replace_regex, split } from "std/text"
import { match_regex, join, replace_regex, split } from "std/text"

/// Checks if a directory exists.
pub fun dir_exist(path) {
Expand Down Expand Up @@ -108,3 +108,32 @@ pub fun glob_multiple(paths: [Text]): [Text]? {
pub fun glob(path: Text): [Text]? {
return glob_multiple([path])?
}

/// Extract the file detecting from the filename the extension
/// Supports: bz2, gz, xz, bz2, deb, rar, rpm, tar(gz/xz/bz), zip(war/jar), 7z
/// Note: Not all the commands supports the output folder path
pub fun extract(path: Text, target: Text): Null? {
if file_exist(path) {
if {
match_regex(path, "\.\(tar\.bz2\|tbz\|tbz2\)$"): $ tar xvjf "{path}" -C "{target}" $?
match_regex(path, "\.\(tar\.gz\|tgz\)$"): $ tar xzf "{path}" -C "{target}" $?
match_regex(path, "\.\(tar\.xz\|txz$\)$"): $ tar xJf "{path}" -C "{target}" $?
match_regex(path, "\.bz2$"): $ bunzip2 "{path}" $?
match_regex(path, "\.deb$"): $ dpkg-deb -xv "{path}" "{target}" $?
match_regex(path, "\.gz$"): $ gunzip "{path}" $?
match_regex(path, "\.rar$"): $ unrar x "{path}" "{target}" $?
match_regex(path, "\.rpm$"): $ rpm2cpio "{path}" | cpio -idm $?
match_regex(path, "\.tar$"): $ tar xf "{path}" -C "{target}" $?
match_regex(path, "\.xz$"): $ xz --decompress "{path}" $?
match_regex(path, "\.7z$"): $ 7z -y "{path}" -o "{target}" $?
match_regex(path, "\.\(zip\|war\|jar\)$"): $ unzip "{path}" -d "{target}" $?
else {
echo "Error: Unsupported file type"
fail 3
}
}
} else {
echo "Error: File not found"
fail 2
}
}
61 changes: 59 additions & 2 deletions src/std/text.ab
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fun replace_regex(source: Text, search: Text, replace: Text, extended: Bool
// contains "GNU sed".
$ re='\bCopyright\b.+\bFree Software Foundation\b'; [[ \$(sed --version 2>/dev/null) =~ \$re ]] $
let flag = status == 0 then "-r" else "-E"
return $ echo "{source}" | sed {flag} -e "s/{search}/{replace}/g" $
return $ echo "{source}" | sed "{flag}" -e "s/{search}/{replace}/g" $
hdwalters marked this conversation as resolved.
Show resolved Hide resolved
} else {
return $ echo "{source}" | sed -e "s/{search}/{replace}/g" $
}
Expand Down Expand Up @@ -91,7 +91,7 @@ pub fun chars(text: Text): [Text] {
return chars
}

/// Checks if some text contains a value/
/// Checks if some text contains a value.
pub fun contains(text: Text, phrase: Text): Bool {
let result = trust $ if [[ "{text}" == *"{phrase}"* ]]; then
echo 1
Expand All @@ -100,6 +100,63 @@ pub fun contains(text: Text, phrase: Text): Bool {
return result == "1"
}

/// Checks if an array value is in the text.
pub fun contains_any(text: Text, terms: [Text]): Bool {
for term in terms {
if contains(text, term) {
return true
}
}

return false
}

/// Checks if all the arrays values are in the string
pub fun contains_all(text: Text, terms: [Text]): Bool {
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
for term in terms {
if not contains(text, term) {
return false
}
}

return true
}

/// Match all occurences of a regex pattern.
///
/// Function uses `sed`
pub fun match_regex(source: Text, search: Text, extended: Bool = false): Bool {
trust {
search = replace(search, "/", "\/")
let output = ""
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
if extended {
// GNU sed versions 4.0 through 4.2 support extended regex syntax,
// but only via the "-r" option; use that if the version information
// contains "GNU sed".
$ re='\bCopyright\b.+\bFree Software Foundation\b'; [[ \$(sed --version 2>/dev/null) =~ \$re ]] $
let flag = status == 0 then "-r" else "-E"
output = $ echo "{source}" | sed "{flag}" -ne "/{search}/p" $
} else {
output = $ echo "{source}" | sed -ne "/{search}/p" $
}
if output != "" {
return true
}
}
return false
}

/// Checks if an array value (with regular expression) is in the text.
pub fun match_any_regex(text: Text, terms: [Text]): Bool {
for term in terms {
if match_regex(text, term, false) {
return true
}
}

return false
}

/// Reverses text using `rev`.
pub fun reverse(text: Text): Text {
return trust $ echo "{text}" | rev $
Expand Down
19 changes: 19 additions & 0 deletions src/tests/stdlib/contains_all.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { contains_all } from "std/text"
Mte90 marked this conversation as resolved.
Show resolved Hide resolved

// Output
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
// None: 0
// One: 0
// Right: 1
// Both: 1

fun test_multiple(label, text, terms) {
let result = contains_all(text, terms)
echo "{label}: {result}"
}

main {
test_multiple("None", "Hello World", ["Other", "Other"])
test_multiple("One", "Hello World", ["World", "Something"])
test_multiple("Right", "Hello World", ["World", "Hello"])
test_multiple("Both", "Hello World", ["Hello", "World"])
}
21 changes: 21 additions & 0 deletions src/tests/stdlib/contains_any.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { contains_any } from "std/text"
Mte90 marked this conversation as resolved.
Show resolved Hide resolved

// Output
// Empty: 0
// None: 0
// Left: 1
// Right: 1
// Both: 1

fun test_multiple(label, text, terms) {
let result = contains_any(text, terms)
echo "{label}: {result}"
}

main {
test_multiple("Empty", "Hello World", [Text])
test_multiple("None", "Hello World", ["Other", "Other"])
test_multiple("Left", "Hello World", ["Hello", "Other"])
test_multiple("Right", "Hello World", ["Other", "World"])
test_multiple("Both", "Hello World", ["Hello", "World"])
}
21 changes: 21 additions & 0 deletions src/tests/stdlib/extract.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * from "std/fs"
import { includes } from "std/array"

main {
let tmpdir = trust $ mktemp -d /tmp/amber-XXXX $
cd tmpdir
trust $ touch test.txt $
silent trust $tar -czf "filename.tar.gz" "{tmpdir}/test.txt"$
trust $ rm "test.txt" $
let package = tmpdir + "/" + "filename.tar.gz"

extract(package, tmpdir) failed {
echo "Error"
}

if dir_exist(tmpdir + "/" + tmpdir) {
echo "Succeeded"
}

trust $ rm -rf "{tmpdir}" $
}
21 changes: 21 additions & 0 deletions src/tests/stdlib/match_any_regex.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { match_any_regex } from "std/text"

// Output
// Empty: 0
// None: 0
// Right: 1
// Left: 1
// Both: 1

fun test_multiple(label, text, terms) {
let result = match_any_regex(text, terms)
echo "{label}: {result}"
}

main {
test_multiple("Empty", "Hello World", [Text])
test_multiple("None", "Hello World", ["Other", "Other$"])
test_multiple("Right", "Hello World", ["Other", "World$"])
test_multiple("Left", "Hello World", ["^Hello", "Other"])
test_multiple("Both", "Hello World", ["^Hello", "$World"])
}
7 changes: 7 additions & 0 deletions src/tests/stdlib/match_regex.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { match_regex } from "std/text"

main {
if match_regex("Hello World", "World$") {
echo "Succeeded"
}
}