-
Notifications
You must be signed in to change notification settings - Fork 107
feat(stdlib): add system utility functions (uname, wc, sort, uniq, mount, pgrep) #955
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
base: staging
Are you sure you want to change the base?
Conversation
…nctions Added new stdlib functions: env.ab: - uname_kernel_name() - returns kernel name (e.g., Linux, Darwin) - uname_nodename() - returns network hostname - uname_kernel_release() - returns kernel release version - uname_kernel_version() - returns kernel version - uname_machine() - returns machine architecture - uname_os() - returns OS name - uname_all() - returns all uname info - mount() - mounts a filesystem (requires root) - umount() - unmounts a filesystem (requires root) - umount_force() - force unmounts a filesystem - pgrep() - finds process IDs by name pattern - pgrep_exact() - finds process IDs by exact name - pkill() - kills processes by name pattern - pkill_exact() - kills processes by exact name - pkill_force() - forcefully kills processes (SIGKILL) text.ab: - lines_count() - counts lines in text - words_count() - counts words in text - chars_count() - counts characters in text - sort_lines() - sorts lines alphabetically - sort_lines_desc() - sorts lines in descending order - sort_lines_numeric() - sorts lines numerically - uniq_lines() - removes consecutive duplicate lines - uniq_all_lines() - removes all duplicate lines Closes amber-lang#951
|
pretty good, but usage examples should be updated (see #954) |
|
you could also make use of sudo modifier for functions that require root permsisions |
|
Cool! The commands that require sudo are mount/umount. I will review the code asap! |
- Changed echo to echo() in usage examples (v0.6.0+ syntax) - Added sudo modifier to mount/umount functions for privilege escalation
|
Thanks for the feedback! I've updated the PR:
|
|
code seems fine but i will also test it locally later |
Mte90
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some changes needed but tests works with no errors
src/std/env.ab
Outdated
| #[allow_absurd_cast] | ||
| pub fun pgrep(pattern: Text): [Int] { | ||
| let result = [Int] | ||
| trust $ while read -r pid; do {nameof result}+=("\$pid"); done < <(pgrep "{pattern}" 2>/dev/null) $ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This while needs to be in amber code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - rewrote it using split_lines() and parse_int() instead
| /// pkill("nginx")? | ||
| /// ``` | ||
| pub fun pkill(pattern: Text): Null? { | ||
| $ pkill "{pattern}" $? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return pkill output can be helpful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think it would be also useful to be able to use PIDs and signal to send (e.g. SIGTERM or SIGINT, etc). kill could be used as fallback, since it's a bash builtin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kept it as Null? for now since pkill doesn't output much useful info. Let me know if you'd prefer something different
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea - added a kill(pid, signal) function that defaults to TERM. Works with signal names or numbers
|
Hey, thanks for the feedback! I've made the changes:
Let me know if there's anything else! |
- Convert bash while loops to native Amber code in pgrep/pgrep_exact - Add kill() function with PID and signal support (SIGTERM, SIGKILL, etc.) - Use split_lines() and parse_int() for cleaner implementation
162952e to
b4bc86d
Compare
|
why always using |
|
This is already fixed in the latest commit - I removed the nameof/while loop and now it uses native Amber: You might be seeing a cached diff - try refreshing the page |
|
i would also consider using here-string instead of printf pipe where possible, but i could do that after the merge, since i'd have to rework files anyways |
- Simplified sort_lines, sort_lines_desc, sort_lines_numeric - Simplified uniq_lines, uniq_all_lines - Simplified lines_count, words_count - Keep printf for chars_count (here-string adds newline)
|
Applied the here-string suggestions - thanks for the cleaner approach!
Kept |
Tirito6626
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks way better now, time to run tests
Ph0enixKM
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job @rahuld109 ! Thank you for your contribution. This is a very well-written Amber code! Here are some minor suggestions regarding the library functions structure as a whole.
| /// | ||
| /// ### Usage | ||
| /// ```ab | ||
| /// mount("/dev/sda1", "/mnt/disk")? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to add usage example for mount with options?
| /// ### Usage | ||
| /// ```ab | ||
| /// let count = lines_count("one\ntwo\nthree") | ||
| /// echo(count) // 3 | ||
| /// ``` | ||
| #[allow_absurd_cast] | ||
| pub fun lines_count(text: Text): Int { | ||
| if text == "": return 0 | ||
| return trust $ wc -l <<< "{text}" | tr -d ' ' $ as Int | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that count_lines sounds better
| /// ### Usage | |
| /// ```ab | |
| /// let count = lines_count("one\ntwo\nthree") | |
| /// echo(count) // 3 | |
| /// ``` | |
| #[allow_absurd_cast] | |
| pub fun lines_count(text: Text): Int { | |
| if text == "": return 0 | |
| return trust $ wc -l <<< "{text}" | tr -d ' ' $ as Int | |
| } | |
| /// ### Usage | |
| /// ```ab | |
| /// let count = count_lines("one\ntwo\nthree") | |
| /// echo(count) // 3 | |
| /// ``` | |
| #[allow_absurd_cast] | |
| pub fun count_lines(text: Text): Int { | |
| if text == "": return 0 | |
| return trust $ wc -l <<< "{text}" | tr -d ' ' $ as Int | |
| } |
| /// ```ab | ||
| /// let count = words_count("hello world foo") | ||
| /// echo(count) // 3 | ||
| /// ``` | ||
| #[allow_absurd_cast] | ||
| pub fun words_count(text: Text): Int { | ||
| return trust $ wc -w <<< "{text}" | tr -d ' ' $ as Int | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that count_words sounds better
| /// ```ab | |
| /// let count = words_count("hello world foo") | |
| /// echo(count) // 3 | |
| /// ``` | |
| #[allow_absurd_cast] | |
| pub fun words_count(text: Text): Int { | |
| return trust $ wc -w <<< "{text}" | tr -d ' ' $ as Int | |
| } | |
| /// ```ab | |
| /// let count = count_words("hello world foo") | |
| /// echo(count) // 3 | |
| /// ``` | |
| #[allow_absurd_cast] | |
| pub fun count_words(text: Text): Int { | |
| return trust $ wc -w <<< "{text}" | tr -d ' ' $ as Int | |
| } |
| /// Counts the number of characters in the given text. | ||
| /// | ||
| /// ### Usage | ||
| /// ```ab | ||
| /// let count = chars_count("hello") | ||
| /// echo(count) // 5 | ||
| /// ``` | ||
| #[allow_absurd_cast] | ||
| pub fun chars_count(text: Text): Int { | ||
| return trust $ printf "%s" "{text}" | wc -m | tr -d ' ' $ as Int | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like count_chars sounds better
| /// Counts the number of characters in the given text. | |
| /// | |
| /// ### Usage | |
| /// ```ab | |
| /// let count = chars_count("hello") | |
| /// echo(count) // 5 | |
| /// ``` | |
| #[allow_absurd_cast] | |
| pub fun chars_count(text: Text): Int { | |
| return trust $ printf "%s" "{text}" | wc -m | tr -d ' ' $ as Int | |
| } | |
| /// Counts the number of characters in the given text. | |
| /// | |
| /// ### Usage | |
| /// ```ab | |
| /// let count = count_chars("hello") | |
| /// echo(count) // 5 | |
| /// ``` | |
| #[allow_absurd_cast] | |
| pub fun count_chars(text: Text): Int { | |
| return trust $ printf "%s" "{text}" | wc -m | tr -d ' ' $ as Int | |
| } |
| /// Sorts lines of text in ascending order. | ||
| /// | ||
| /// ### Usage | ||
| /// ```ab | ||
| /// let sorted = sort_lines("banana\napple\ncherry") | ||
| /// echo(sorted) // "apple\nbanana\ncherry" | ||
| /// ``` | ||
| pub fun sort_lines(text: Text): Text { | ||
| return trust $ sort <<< "{text}" $ | ||
| } | ||
|
|
||
| /// Sorts lines of text in descending order. | ||
| /// | ||
| /// ### Usage | ||
| /// ```ab | ||
| /// let sorted = sort_lines_desc("banana\napple\ncherry") | ||
| /// echo(sorted) // "cherry\nbanana\napple" | ||
| /// ``` | ||
| pub fun sort_lines_desc(text: Text): Text { | ||
| return trust $ sort -r <<< "{text}" $ | ||
| } | ||
|
|
||
| /// Sorts lines of text numerically. | ||
| /// | ||
| /// ### Usage | ||
| /// ```ab | ||
| /// let sorted = sort_lines_numeric("10\n2\n1") | ||
| /// echo(sorted) // "1\n2\n10" | ||
| /// ``` | ||
| pub fun sort_lines_numeric(text: Text): Text { | ||
| return trust $ sort -n <<< "{text}" $ | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's combine these functions into one function:
pub fun sort_lines(text: Text, desc: Bool = false, numeric: Bool = false)| /// Removes consecutive duplicate lines from text. | ||
| /// | ||
| /// ### Usage | ||
| /// ```ab | ||
| /// let result = uniq_lines("foo\nfoo\nbar\nbar\nbaz") | ||
| /// echo(result) // "foo\nbar\nbaz" | ||
| /// ``` | ||
| pub fun uniq_lines(text: Text): Text { | ||
| return trust $ uniq <<< "{text}" $ | ||
| } | ||
|
|
||
| /// Removes all duplicate lines from text (not just consecutive). | ||
| /// | ||
| /// ### Usage | ||
| /// ```ab | ||
| /// let result = uniq_all_lines("foo\nbar\nfoo\nbaz\nbar") | ||
| /// echo(result) // "foo\nbar\nbaz" | ||
| /// ``` | ||
| pub fun uniq_all_lines(text: Text): Text { | ||
| return trust $ awk '!seen[\$0]++' <<< "{text}" $ | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the following names make more sense to me:
uniq_lines_adj- this only removes adjacent duplicatesuniq_lines- this removes global duplicates
Hey! I noticed issue #951 had been open for a while and figured I'd take a crack at it. Added a bunch of stdlib functions that were requested:
What's included:
uname_*functions (kernel name, nodename, release, version, machine, os, all) - basically wrapping the uname commandlines_count,words_count,chars_count- text counting utilities using wcsort_lines,sort_lines_desc,sort_lines_numeric- sorting helpersuniq_lines,uniq_all_lines- deduplication (adjacent vs all duplicates)mount,umount,umount_force- filesystem mounting (withsudomodifier)pgrep,pgrep_exact,pkill,pkill_exact,pkill_force- process managementAdded tests for everything too. The pgrep tests are in the no_output directory since the results depend on what's running.
Closes #951
Partial fix for #954