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

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
33 changes: 32 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 { contains_any_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,34 @@ 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): Bool? {
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
if file_exist(path) {
if {
contains_any_regex(path, ["/.tar.bz2$/g", "/.tbz$/g", "/.tbz2$/g"]): $ tar xvjf "{path}" -C "{target}" $?
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
contains_any_regex(path, ["/.tar.gz$/g", "/.tgz$/g"]): $ tar xzf "{path}" -C "{target}" $?
contains_any_regex(path, ["/.tar.xz$/g", "/.txz$/g"]): $ tar xJf "{path}" -C "{target}" $?
contains_any_regex(path, ["/.bz2$/g"]): $ bunzip2 "{path}" $?
contains_any_regex(path, ["/.deb$/g"]): $ dpkg-deb -xv "{path}" "{target}" $?
contains_any_regex(path, ["/.gz$/g"]): $ gunzip "{path}" $?
contains_any_regex(path, ["/.rar$/g"]): $ unrar x "{path}" "{target}" $?
contains_any_regex(path, ["/.rpm$/g"]): $ rpm2cpio "{path}" | cpio -idm $?
contains_any_regex(path, ["/.tar$/g"]): $ tar xf "{path}" -C "{target}" $?
contains_any_regex(path, ["/.xz$/g"]): $ xz --decompress "{path}" $?
contains_any_regex(path, ["/.7z$/g"]): $ 7z -y "{path}" -o "{target}" $?
contains_any_regex(path, ["/.zip$/g", "/.war$/g", "/.jar$/g"]): $ unzip "{path}" -d "{target}" $?
else {
echo "Error: Unsupported file type"
return false
}
}
} else {
echo "Error: File not found"
return false
}

return true
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
}
60 changes: 58 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,62 @@ 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
}

/// Search all occurences of a regex pattern in the content.
///
/// Function uses `sed`
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
pub fun contains_regex(source: Text, search: Text, extended: Bool = false): Bool {
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
trust {
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}" -e "{search}" $
} else {
output = $ echo "{source}" | sed -e "{search}" $
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to use sed -n (suppress automatic printing), and /.../p to print matching lines:

...
    output = $ echo "{source}" | sed "{flag}" -ne "/{search}/p" $
} else {
    output = $ echo "{source}" | sed -ne "/{search}/p" $
...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is working as it is now, if I change in that way doesn't work

}
if output == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to return true if sed output is not empty:

if output != "" {
    return true
}

Copy link
Contributor

@hdwalters hdwalters Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above for reasons why it's still recommended to use if output != "".

return true
}
}
return false
}

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

return false
}

/// Reverses text using `rev`.
pub fun reverse(text: Text): Text {
return trust $ echo "{text}" | rev $
Expand Down
15 changes: 15 additions & 0 deletions src/tests/stdlib/contains_all.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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
// Succeeded
// Succeeded

main {
if contains_all("Hello World", ["World", "Something"]) == false {
echo "Succeeded"
}

if contains_all("Hello World", ["World", "Hello"]) {
echo "Succeeded"
}
}
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/contains_any_regex.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { contains_any_regex } from "std/text"

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

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

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

main {
Mte90 marked this conversation as resolved.
Show resolved Hide resolved
if contains_regex("Hello World", "/World$/g") {
echo "Succeeded"
}
}
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}" $
}