Bashlib 1-6-0 is now live

2014-09-15

Updated 2018-06-28: Download is avaliable on GitHub at the moment, I'll eventually be switching away from GitHub, but will updated here when I do.

It's now here! 1.6.0 has been released into the wild. You can pick it up from the home page as normal.

Here's the finalised changelog (also included in the download):

1.5.3 -> 1.6.0
+Added class.sh module ('class.new', 'class.destroy' and contextual 'this' functions)
+Added array.sh function 'array.ifind'
+Added interface.sh function 'interface.horizontal_menu'
+Changed README to include new functions provided by class.sh module
+Changed 'array.list' to list array_name[set]=value
+Changed most functions in all modules to use less code
+Changed improved array.sh code generally across all functions
+Fixed array.sh not allowing spaces in array items
+Fixed several bugs in date.sh

This is a much more significant update than I had initially thought. Other than the new class prototype, arrays got a full go over and now work as you'd expect. Allowing spaces in elements was something I had taken for granted, but is again, one of the little quirks of bash. I also added the previously overlooked ifind function which is like a ${ARRAY[${i} =~ ^SEARCH$ regex rather than .+SEARCH.+. Useful if you know what you are looking for, but it could be upper case or lower case.

I've also worked on a much cleaner menu function (the "interface.horizontal_menu" function), which doesn't clear the screen, doesn't rely on any outside programs and feels really responsive (as there is no artificial wait times). It works in almost the exact same way as the vertical menus, except it uses escape codes to clear the line and reprint:

interface.horizontal_menu_select () {
	declare -a OPTIONS USERIN MENU
	declare -g RETURN
	for (( i=0; i < ${#@}; i++ )); do
		OPTIONS[${i}]="${@:$(( i + 1 )):1}"
	done
	for (( i=0; i < ${#OPTIONS[@]}; i++ )); do
		(( RETURN == i )) && MENU="${MENU}\e[0;30m\e[47m" || MENU="${MENU}\e[0m"
		MENU="${MENU}[${OPTIONS[${i}]}]"
		MENU="${MENU}\e[0m "
	done
	printf "\033[10000D%b\r\033[10000C" "${MENU}"
	read -r -s -n 1 USERIN
	case ${USERIN} in
		("D") (( RETURN > 0 )) && (( RETURN-- )) ;;
		("C") (( RETURN < ( ${#@} - 1 ) )) && (( RETURN++ )) ;;
		("") [[ ! ${RETURN} ]] && RETURN=0; return 0 ;;
	esac
	interface.horizontal_menu_select "${@}"
}

It doesn't include hard coded exit commands and only responded to left / right arrow keys (or capital D/C, because bash...), it will print the menu, then move the cursor as far right as possible (using "\033[10000D"). It will only move the line back when it redraws. Bear in mind though that it doesn't add a line break after you select an option, so you'll need to add that in yourself. As with the vertical menu, the return code starts with 0. So option 1 will return 0, option 2 will return 1 etc. A very basic example:

echo "First level:"
interface.horizontal_menu_select "continue" "exit"
echo
(( RETURN == 1 )) && exit
echo "Second level:"
interface.horizontal_menu_select "continue" "exit"
echo
(( RETURN == 1 )) && exit
echo "Third level:"
interface.horizontal_menu_select "continue" "exit"
echo
(( RETURN == 1 )) && exit
echo "All menus continued"

This simply gives the option to continue or exit and will progress down the line. Obviously, you can easily go backwards and forwards in menus using custom functions etc.

The date module also had a few minor bugs in it that would incorrectly calculate seconds between dates which have now been fixed.

One of the biggest code changes was the fact that I've gone through all the functions in bashlib and tried to rework them to make smaller code footprints, less reiteration and more streamlining. I can't say if this has significantly improved performance yet, but if nothing else, it's helped readability and makes more sense. Overall I've changed in the region of 1500 lines.