Blog-Thread: Creating a Shell Wrapper and Runtime Modifier (SWARM)

Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Blog-Thread: Creating a Shell Wrapper and Runtime Modifier (SWARM)
# 8  
Old 03-18-2020
Thank you drl!
When I execute 'as is' it works - but it isnt quite what I was aiming for..
-> Or I fail to see how to adapt.

But I'm not getting the expected results when I modify your script to my situation:
unset my_test_a my_test_b
pl " Results, in function f1:"
 	while true; do
) &
echo $my_test_a
echo $my_test_b

[sea@manjaro-desktop SWARM]$ bash ~/drl 

 Results, not in function:

 Results, in function f1:

Now here's my 'case output' , also, note the new time, isnt that great?
Allthough, this is one of the 'better' runs.

Please note the 'echo runs'!

[sea@manjaro-desktop SWARM]$ time . ./runtime 
.............+++ echo runs
+++ set +x
# | SWARM 0.4-7                                                                           | 2020-03-19 / 02:02:55 | #
# |                                                    my title                                                   | #
# | left                                               middle                                               right | #
# |                                                                                                               | #
# |                                                   Piped input                                                 | #
# | Is this cool? (yn)                                                                                            | #
# | Is this cool? (yn)                                                                                            | #
# |                                                  Piped Output                                                 | #
# | this is                                            a piped                                          test code | #
# | this is                                          an argument                                        test code | #
# | this was                                         an argument                                        test code | #
# | left                                                                                                          | #

real	0m0.047s
user	0m0.043s
sys	0m0.009s
 ----------- TEST AREA -----------

real	0m0.075s
user	0m0.067s
sys	0m0.015s
[sea@manjaro-desktop SWARM]$ echo $my_test_var 

[sea@manjaro-desktop SWARM]$ +++ echo runs
+++ set +x

[sea@manjaro-desktop SWARM]$ echo $my_test_var 

[sea@manjaro-desktop SWARM]$

But the $my_test_var remains empty. (just like in the modified script)

Now here's the code in question:
PHP Code:
# For easier code reusage, lets combine all math into a sub process
# Should help to speed things up a little more for the end user front ;)
# This seems useless... TODO remove or fix
if true
unset "${!len*}my_test_var
.geometry.update() { #
declare -g DATE_TIME=$($DATE +'%H:%M:%S')        # Time on the other hand is

declare -g  my_test_var="$(date +%T)"

# Set basic values
declare -g BORDER_LEFT="${SWARM_THEME_DATA[border-left]}"
declare -g BORDER_RIGHT="${SWARM_THEME_DATA[border-right]}"
declare -g clrFRONT="${SWARM_THEME_DATA[color-front]}"
declare -g clrBACK="${SWARM_THEME_DATA[color-back]}"
declare -g clrCL="\e[2K"

# Check if border-right was set:
[ -"$BORDER_RIGHT] && \
                declare -
i=${#BORDER_LEFT}-1;i>=0;i--)); do BORDER_RIGHT="$BORDER_RIGHT${BORDER_LEFT:$i:1}"; done

        # Get some numbers
declare -g lenLeft"${#BORDER_LEFT}"
declare -g lenRight="${#BORDER_RIGHT}"
declare -g lenClrFont=${#clrFRONT}
declare -g lenClrBack=${#clrBACK}
export identRight=$(( $lenRight + ${#clrCL}  ))
export numEND=$(( $COLUMNS ))

# If user wants extended logs, he shall have it
$isRO && $doLogExt && init.log "$SWARM_MSG_INIT_PID_GEOMETRY${PPID:-$PID}"
export -f swarm.geometry.update

# Sub shell
        while ${
PS:-\ps} ${PPID:-$PID} | ${GREP:-\grep} ${PPID:-$PID} >> /dev/zero
# Ok, lets keep it simple,
            #DATE_TODAY=$($DATE +'%Y.%m.%d')    # Cmon, day is not THAT important

echo runs >/dev/zero
# Using 15 secs for fallback mode
) & >> /dev/zero
Please acknowledge that on first try, I had the function definition inside the subshell.
Since that didnt work out the way I wanted, I moved it 'outside' - to no change.

To me, this still looks like we cannot 'save' a variable from a sub/background process, wether it would be from within a function or not.

Unless I would use a tempfile to write and read the data, but that is something I want to avoid.

Last edited by sea; 03-19-2020 at 06:07 AM..
# 9  
Old 03-19-2020
As I have a certain way... image... of how I want to use/show help and manpages, and how I want to handle code transparancy, I'm a bit.. focused.. on how the solution should look like.
My current expansion attempts didnt work quiet as I would have hoped.

However, to get something done, I've rearanged some and deleted some other files, as their code was now merged into functions for reusage and just a slightly more 'elegant' way how SWARM works internaly. (read: Fixed my own not-using-an-existing-variable issue)
This said, parts of status work now too.

But I still need to cross-check this with a TTY-only output, as they are (supposed to be) different - as in (translated if required) text only.

We're getting somewhere Smilie

Last edited by sea; 03-19-2020 at 05:51 AM..
# 10  
Old 03-19-2020
Just tried it on a TTY and... had to do some fixes... who would have thought that some shells return -bash as their $0 instead of just bash.
After that, it worked!

Though, figued I need to get rid of the underline for the title, as that becomes a 'cyan'ish background - which kinda makes it hard to read that blue text...
And sure as hell is not inteded, I mean, even adding the underline was just a little fun - and I wasnt sure wether I wanted to keep it or not.. this helps Smilie

Just thought I'd share the first image of the TTY test.
Blog-Thread: Creating a Shell Wrapper and Runtime Modifier (SWARM)-swarm-first-tty-side2jpg

But this 'experience' is always kind of a milestone - just to know that it -as it is- works in its basic form for/in both, X and TTY/environments.
Well, once I got rid of that cyan/underline that is... Smilie
# 11  
Old 03-20-2020
Uh finaly, I have it (printe) as I want it to behave.
A simple change - long intended, that when passing 2 strings, one is left, the other right (instead of center).

It doesnt come as easy as one might think...
	swarm.print.text() { # MODE [ LEFT CENTER RIGHT]
	# This simply puts the text
	# according to MODE
		local fix_title=0
		local fix_header_r=0
		case ${1/-} in
			t)	MODE=title
				fix_title=16	;;
			h)	MODE=header
				fix_header_r=4	;;
			*)	MODE=basic	;;

		# Check if it is too short, if so, print fallback mode and return
		[[ ${COLUMNS} -lt 25 ]] && \
				$PRINTF "%s\n" "${@}" && \
				return 1

		# Make sure values are udpated

		# Get the actual string
		local evalLeft=$($PRINTF "$1")
		local evalMiddle=$($PRINTF "$2")
		local evalRight=$($PRINTF "$3")

		# Retrieve their length
		local lenEvalLeft=${#evalLeft}
		local lenEvalMiddle=${#evalMiddle}
		local lenEvalRight=${#evalRight}

		# Output
		case ${#@} in
		0)	# Nothing to print
			$PRINTF "${posLEFT}"
		1)	# Just left oriented
			$PRINTF "${posLEFT}$1"
		2)	# 2nd arg is right oriented
			$PRINTF "${posLEFT}$1"
			local posRIGHT="\33[$(( $numEND - $lenMiddle - ${lenEvalMiddle} - 1 + $fix_header_r ))G"
			$PRINTF "${posRIGHT}$2"
		3)	# Default handling
			local posMIDDLE="\33[$(( $numHALF - $(( ${#2} / 2 ))  + $fix_title ))G"
			local posRIGHT="\33[$(( $numEND - $lenRight - ${lenEvalRight} - 1 + $fix_header_r ))G"
			$PRINTF "${posLEFT}$1"
			$PRINTF "${posMIDDLE}$2"
			$PRINTF "${posRIGHT}$3"

		$PRINTF "${posEND}"
	printe() { # STR1 STR2 STR3
	# Simply prints the strings as passed, it requires 3 strings to use the center
	# For piping, it expects 3 lines, each representing 1 variable
		#set -x
		local MODE="none"
		# Get args
		case "$1" in
		"-1"|"-2")	MODE="${1/-}"
		*)			MODE="normal"
		# Get arg number if not forced yet
		[[ "normal" == "$MODE" ]] && [[ "-" != "$1" ]] && [[ "--" != "$1" ]] && MODE=${#@}
		# Get pipe?
		case "$1" in
				case "$MODE" in
						# Read pipe, expect 2 lines
						while read LEFT
							read RIGHT
							printe "$LEFT" "" "$RIGHT"
						# Read pipe, expect 1 lines
						while read LEFT
							printe "$LEFT"
						# Read pipe, expect 3 lines (default)
						while read LEFT
							read CENTER; read RIGHT
							printe "$LEFT" "$CENTER" "$RIGHT"
		#set +x
		case "$MODE" in
				swarm.print.border -e
				swarm.print.text -e "" "" ""
				swarm.print.border -e
				swarm.print.text -e "$1" "" ""
				swarm.print.border -e
				swarm.print.text -e "$1" "" "$2"
				swarm.print.border -e
				swarm.print.text -e "$1" "$2" "$3"
		$PRINTF "$posEND\n"

Now comes the really fun part... passed string splitting...
And 'select'.

Also, if you wonder WHY (the heck) I upload so often pictures of SWARM, thats because 'just before' doing that picture, all of the 'UI' was terrible messed up.
So it's kind of: Hey it works (again), and as a reminder which build number I'd have to pick from the backups.
This said, here we go Smilie
Blog-Thread: Creating a Shell Wrapper and Runtime Modifier (SWARM)-community-st-swarmjpg

And I just thought, it might be 'easier' to 'make': select = pick (instead of choose) and ask = yesno, because for regular user input, I'd make a function called input.
What do you think?

  • Maybe even remove BOLD from title, looks a bit 'light' on TTY (hard to read : try different colors/theme first)
  • Find a non-tempfile using method printing different stages/index of an array (\ | / - \ | )
  • Fiddle my way around an 'intervall based' on UNIX seconds differences between calls from within a function without using tempfiles (alternative to the previous 'multi task' attempt)
  • select
  • edit/web/terminals
  • progress/bar
  • download
  • cfg.get & cfg.set
  • swarm configuration (general purpose *conf file handler, supports in-file-commented options for the handlers)
  • more themes (ideas or wishes, anyone? Smilie )
  • typewriter
  • swarm.bol.dir ?
  • swarm.str.distro ?
  • swarm.install (distro package manager wrapper ; install only)

And these are just whats on top of my mind.
Now, allthough I have most of this "done already" - it's for TUI which was based on individual files, rather than functions - and I'm using new syntax and methods which 'dont help' to reduce 'coding time' but should help with readability and reusability of the code.
If you compare printe, well incl swarm.print.border and swarm.print.text to it's origin tui-echo, it is ALOT more readable!

However, when it was 'all file based', it was simple, all user-commands were files, and had to have args like --help and --version, but with funcions?
Sure, I could do that.
Issue is, I want it translate-able.. by which I mean, people should be able to do that 'quickly' as part of a hobby or enhusiastic week.
Thus, I only want to focus on CORE (end-user) functions (that other script authors are supposed to be using - only - I know, wont happen).

Thanks to the syntax rules I had set within my project, I could already parse current files functions and list their description (First 2 commented lines after the function definition, which as well provides the ARGS syntax, where applicable Smilie
Code: { # [FILE]
	# Prints a list of properly declared functions
	# Please see: ./docs/{MANUAL,SYNTAX}.md)
		local tmp_list=""
		local tmp_oldpwd="${PWD:-$($PWD_EXEC)}"

		if [[ -n "$1" ]] && [[ -f "$1" ]]
		then	# There is a specific file passed to parse
				cd "$SWARM_DIR_LIBS"
				$GREP "() { #" "$1"| \
					$GREP -v GREP | \
					$AWK -v FS='() ' '{print $1}' | \
					$SED s,'()','',g
				cd "$tmp_oldpwd"
		else	# Just parse all files in SWARM_DIR_LIBS
				raw_output() {
						cd "$SWARM_DIR_LIBS"
						$GREP init.*"() {" * | $GREP -v GREP
						$GREP cfg.*"() {" * | $GREP -v GREP
						$GREP swarm.*"() {" * | $GREP -v GREP
						cd "$tmp_oldpwd"
					) | while IFS=": " read one two three
						# The IFS takes care of the GREP filenames
						# and this variable-regex takes care of the function definition
						echo "${two/()}"
				# Show data
				raw_output | sort -u
				unset -f raw_output
	} { # MODE [FILE] FUNCTIONNAME		## MODE= --text || --code
	# Prints either these 2 comment lines or the code
	# Please see: ./docs/{MANUAL,SYNTAX}.md)
		# Vars
			local tmp_oldpwd="${PWD:-$($PWD_EXEC)}"
			local GREP_OPTS=""
		# Check for args
			local MODE=none
			case "$1" in
					#return 1
			[[ -f "$1" ]] && \
				local curFILE="$1" && shift || \
				local curFILE=""
		# Code
			# Prepare command
			case "$MODE" in
					GREP_OPTS="-h -a2  ${1}"
					cd "$SWARM_DIR_LIBS"
					# This is just to reduce unrequired disk usage
					[[ -n "$curFILE" ]] && \
						$GREP $GREP_OPTS "$curFILE"|| \
						$GREP $GREP_OPTS *
					cd "$tmp_oldpwd"
					type "$1"

Though, the *show function still needs some tweaking on the --text handling.

It's funny, I know how cool it is when it's done, but still I'm kind of overhelmed by the annoyance of 'reinventing the wheel' (redo what's already done).
And that is despite the fact, that I get alot done, alot quicker than I had anticipated - with alot more tweaks than it used to have.

If I had done this like 20 or 25 years ago.. oh boy this would have been THE invention of the decade. (speaking of how 'swarm' (function, aka tui-browser) will behave when all is done and works properly)
Now it's just some enthusastic old reto fanboy hobby project.

Oh geez, guess I have one of my moments, as I was just preparing some post offline, lots of text to be structured before actual posting it.
Well, while I prepared that text - regarding (my hopes for) the community-project Script-Tools, I had figured how much work there's still to do.

If I could briefly describe what swarm does, I would.
And that part I could describe in short, doesnt nearly reflect its full potential!

Once I gotten that far, I'll need to do a good video (with actual editing and voice-overs) to show at least parts of it's full power.
Because just describing is WAY too abstract, even for me reading my own text - despite knowing what I'm refering to...
Yet it's all very simple and almost obvious - at least I tried to achieve this for me.

But I'm already thinking ahead of time.
Stay focused, here and now.

Oh boy, I cant wait until I have all basics covered.
Yeah that help thing....
Since no install, no need to adjust the manpages I'd say, dont you?
So just basic --help coverage for the intended 'user'/author functions usage, sounds about right'ish, right? Smilie
# 12  
Old 04-03-2020
Still writing and ironing out the default core display functions.
This includes reducing code that was written (at least) twice and could be 'combined' to a single function.

But mostly - as for optimizing code - I try to find a proper way around the the injection protection and 'bold' or colored strings that one might want to use/display.
At the very least so that the function title prints bold text.

The injection protection is not based on my skillset, however, I can read a case and some basic regex so I saw/knew that the console code for 'bold' causes an 'issue', which it did.

Next on my wish todolist is pick and cfg.set.
And I also need to finish bol2str in order to start with swarm.
I need to get the (basic, at least) swarm function done before the config editor - just so I can start scripting other things properly, and do 'external end-user' testing and so I can keep the code cleaner.
Also that will help to keep motivation up.

Current question...
However, for my current task at hand, the read wrappers, yesno, pick and input were, well - still are, based on the physicaly installed read I had to actualy parse the --help output of it to get its functionality to get them work poperly (for TUI).
Now for SWARM I'd like to reduce physical disk usage (files) to a minimum (for non-log actions; setting).

This and the recent Heureka that there's a builtin read, made me hope that the bash builtin read might have the same functions across all distros - as long the propper BASH version is installed, which would simplify the 'wrapping' process.... alot...

How to provide help?
Also the 'help' functionality of SWARM is slowly evolving in my head.
Main challenge here is that I want to distinct functions (for the help usage) between 'basics' and 'advanced', while keep most of it 'dynamic' to use - yet simple for translating.
Because I dont WANT to write actual help text for functions, because to get those, you would need to source SWARM and then call the function with --help, which seems 'too much' for me.

So I'd rather write/modify the (former) manpages and write a handler to work like:
./SWARM/runtime help [topic]

So you can 'stay' in your current project but still get the information you need.

That's for now, have a nice weekend and stay healthy everyone!
# 13  
Old 04-07-2020
My 'recent' speed increase commit, like 6 actual commits back, broke the actual creating of the user config file, which I didnt realize back then because I had forgotton to delete said file.
Next is the creating of the/a RAMDISK for RO systems, figured I dont need to copy SWARM over there, I just need to 'map' the semi-required files there.

With this said, I had lost track of the RO systems handling, allthough prepared....
Also I've copied to code to a laptop to work on that or a bit, which broke - for some weird reason - the application detection using which, allthough which is installed as well...
So, in a way, I'm back to square one again.

But that was to be expected after several years not using gnu+linux.
Gives me a chance to simplify and unify the 'init' procedure some more, hopefully Smilie
# 14  
Old 04-09-2020
Made some basic utilites for cross-plattform usage, as well as for unified and simplified usage.
Reused and wraped RudiC's echo_, thanks again Smilie

# Some tools
	swarm.util.isRoot() { #
	# Returns TRUE if user ID is 0
	# Returns FALSE otherwise
		if [[ ${UID:-${EUID:-0}} -eq 0 ]]
		then	$ECHO true
			return 0
		else	$ECHO false
			return 1
	swarm.util.isGUI() { #
	# Returns FALSE otherwise
		then	$ECHO true
			return 0
		else	$ECHO false
			return 1
	swarm.util.mkdir() { # /path/to/make
	# Creates full path structures
		${isRO:-false} && return 1
		# Remove any possible args from ARGS
		while [[ "-" == "${1:0:1}" ]] ; do shift ; done
		swarm.protect "$FUNCNAME" "${@}" && return 1
		# Vars
		local dir_done=""
		local dir_todo=$($PRINTF "${1:1}" | $SED s,"/","\n",g)
		# Start pipe
		$PRINTF '%s\n' "$dir_todo" | while read current
		do	# Prepare next dir
			# Create if not exist
			[[ -d "$dir_done" ]] || $MKDIR "$dir_done"
		return 0
	swarm.util.echo() { # [-e|-n|-en|-ne] STRING
	# Simple echo's, by RudiC @
		  ( IFS=" "; $PRINTF "%s\n" "$*" )
		# Portable echo -n
		echo_n() {
		  ( IFS=" "; $PRINTF "%s" "$*" )
		# Portable echo -e
		echo_e() {
		  ( IFS=" "; $PRINTF "%b\n" "$*" )
		# Portable echo -ne
		echo_ne() {
		  ( IFS=" "; $PRINTF "%b" "$*" )
		case "${1/-}" in
		"n")	shift ; echo_n "${@}"	;;
		"e")	shift ; echo_e "${@}"	;;
			shift ; echo_ne "${@}"	;;
		*)		echo_ "${@}"	;;
	swarm.util.isDir() { #  /path/to/dir
	# Returns true if passed string is a directory
		[[ -d "$1" ]] 
		return $?
# Short variable access to util functions
# and to keep file usage to a minimum

But currently I'm still busy in re-thinking/doing the init procedure....
Well, unifying (is that a word??) the procedure of using functions to do different checks, keep/put all variables to RAM while put some essential ones (usage speed increase / customize options) in the 'rc' file.

The specific part of preparing configuration files & folders that are optional - because it must run on a Read-Only system as well, is quite more challenging than making it just in a "must-be-installed" way.
Also, with my... crazy... idea of implementing an optional ramdisk support (as root, for configuration and tempfiles only) didnt make the init procedure any easier.
Further, I need to 'bypass' the (so far hardcoded) use of /root because not all systems have it, thus I have to place the configfile (swarmrc) in another place, like using '/etc' if root has no $HOME.
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Shell Script and Progress Bar or GUI Wrapper

Hi, I have shell script that I am running under Ubuntu as root. Is it possible to hide the command window and show the user some sort of progress /random progress bar / or other form of GUI interaction? On MAC, I have been using Platypus but on Ubuntu I am not sure what to do. (4 Replies)
Discussion started by: naveedanwar4u
4 Replies

2. Homework & Coursework Questions

Shell Script average runtime

Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted! 1. The problem statement, all variables and given/known data: Make a bash script that calculates average runtime for the first two scripts you made. The average should be... (17 Replies)
Discussion started by: navlelo
17 Replies

3. Shell Programming and Scripting

Wrapper Script in Perl Or shell

Hello, My requirement is based on Oracle where we run a perl script and it asked some questions.I want to write a wrapper which will answer all these questions. How is it possible. Thanks (16 Replies)
Discussion started by: cotton
16 Replies

4. Shell Programming and Scripting

Shell Runtime Statistics

Hi, I am trying to capture runtime stats of a shell script (c shell). Are there system variables to call? Or should I create a date variable at the start of the script and at the end of the script? I am trying to capture the time if the script stops or ends with error. Please help. ... (4 Replies)
Discussion started by: CKT_newbie88
4 Replies

5. Programming

creating multiple threads using single thread id

Hi all, Can I create multiple threads using single thread_id like pthread_t thread_id; pthread_create(&thread_id, NULL, &print_xs, NULL); pthread_create(&thread_id, NULL, &print_ys, NULL); pthread_create(&thread_id, NULL, &print_zs, NULL); pthread_join(thread_id, NULL); what... (2 Replies)
Discussion started by: zing_foru
2 Replies

6. Web Development

Creating a blog site on a local computer

Hello! I would like to create a blog website on a web domain of mine. The blog will be used for publishing economics-lated articles. I tried to use a few open source packages for blog creation (WorldPress, b2evolution, Movable type) which I wanted to test on a local computer before arranging... (5 Replies)
Discussion started by: degoor
5 Replies

7. Shell Programming and Scripting

Korn Shell Wrapper script

Hi Guys, I am trying write a wrapper script but I don't have any idea. I have 4 different korn shell scripts and all of them needs some parameters from command line (positional parameter). My script cant be interactive because its supposed to be automated. I am confused how can I write a wrapper... (6 Replies)
Discussion started by: pareshan
6 Replies

8. Shell Programming and Scripting

crontab is not creating runtime files which are in script..

this is the output i am getting here.. cp: cannot create /wls_domains/eoigw/eoigwsA/deliv/cron/MailingScript/eoigwsA_Health_Status_Report.html: Permission denied /wls_domains/eoigw/eoigwsA/deliv/cron/MailingScript/ /wls_domains/eoigw/eoigwsA/deliv/cron/MailingScript/ (6 Replies)
Discussion started by: surekha268
6 Replies

9. Shell Programming and Scripting

korn shell version at runtime?

How can I check what kornshell version I am using at runtime from within a kornshell script? (3 Replies)
Discussion started by: qanda
3 Replies
Login or Register to Ask a Question

Featured Tech Videos