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

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	;;
		esac
		shift

		# 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
		swarm.update.geometry

		# 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"
			#return
			;;
		2)	# 2nd arg is right oriented
			$PRINTF "${posLEFT}$1"
			local posRIGHT="\33[$(( $numEND - $lenMiddle - ${lenEvalMiddle} - 1 + $fix_header_r ))G"
			$PRINTF "${posRIGHT}$2"
			#return
			;;
		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"
			;;
		esac

		$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/-}"
					shift
					;;
		*)			MODE="normal"
					;;
		esac
		# Get arg number if not forced yet
		[[ "normal" == "$MODE" ]] && [[ "-" != "$1" ]] && [[ "--" != "$1" ]] && MODE=${#@}
		# Get pipe?
		case "$1" in
		"--"|"-")
				case "$MODE" in
					"2")
						# Read pipe, expect 2 lines
						while read LEFT
						do
							read RIGHT
							printe "$LEFT" "" "$RIGHT"
						done
						return
						;;
					"1")
						# Read pipe, expect 1 lines
						while read LEFT
						do
							printe "$LEFT"
						done
						return
						;;
					*)
						# Read pipe, expect 3 lines (default)
						while read LEFT
						do
							read CENTER; read RIGHT
							printe "$LEFT" "$CENTER" "$RIGHT"
						done
						return
						;;
					esac
				;;
		esac
		#set +x
		case "$MODE" in
			"0")
				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")
				swarm.print.border -e
				swarm.print.text -e "$1" "$2" "$3"
				;;
		esac
		$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 :stuck_out_tongue:

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?

TODO:

  • 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? :wink: )
  • 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 :wink:

	swarm.eu.function.list() { # [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
					do
						# The IFS takes care of the GREP filenames
						# and this variable-regex takes care of the function definition
						echo "${two/()}"
					done
				}
				# Show data
				raw_output | sort -u
				unset -f raw_output
		fi
	}
	swarm.eu.function.show() { # 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
				"--text")
					MODE=text
					shift
					;;
				"--code")
					MODE=code
					shift
					;;
				*)
					MODE=text
					#return 1
					;;
			esac
			[[ -f "$1" ]] && \
				local curFILE="$1" && shift || \
				local curFILE=""
		#
		# Code
		#
			# Prepare command
			case "$MODE" in
				"text")
					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"
					;;
				"code")
					type "$1"
					;;
			esac
	}

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? :wink: