From a7b2dce33d01be72eea61ec48f8824723bb20dc7 Mon Sep 17 00:00:00 2001 From: Fmstrat Date: Thu, 19 Nov 2020 22:05:52 -0500 Subject: [PATCH] Added auto-detection of applications --- install/ExtractPrograms.ps1 | 1 - install/inquirer.sh | 236 ++++++++++++++++++++++++++++-------- installer.sh | 143 +++++++++++++++++----- 3 files changed, 299 insertions(+), 81 deletions(-) diff --git a/install/ExtractPrograms.ps1 b/install/ExtractPrograms.ps1 index b8a765a..0111190 100644 --- a/install/ExtractPrograms.ps1 +++ b/install/ExtractPrograms.ps1 @@ -1,4 +1,3 @@ -# powershell.exe -ExecutionPolicy Bypass -File \\tsclient\home\Documents\Repos\winapps\install\ExtractPrograms.ps1 > \\tsclient\home\.local\share\winapps\include Function Get-Icon { <# diff --git a/install/inquirer.sh b/install/inquirer.sh index c14651a..e83f16e 100755 --- a/install/inquirer.sh +++ b/install/inquirer.sh @@ -33,6 +33,8 @@ set -e arrow="$(echo -e '\xe2\x9d\xaf')" checked="$(echo -e '\xe2\x97\x89')" unchecked="$(echo -e '\xe2\x97\xaf')" +down_arrow=$(echo -e '\u23f7') +up_arrow=$(echo -e '\u23f6') black="$(tput setaf 0)" red="$(tput setaf 1)" @@ -174,11 +176,26 @@ select_indices() { done } +print_checkbox_line_arrow() { + if [ "${_checkbox_selected[$1]}" = true ]; then + printf "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$1]} ${normal}" + else + printf "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$1]} ${normal}" + fi +} +print_checkbox_line() { + if [ "${_checkbox_selected[$1]}" = true ]; then + printf " ${green}${checked}${normal} ${_checkbox_list[$1]} ${normal}" + else + printf " ${normal}${unchecked} ${_checkbox_list[$1]} ${normal}" + fi +} - -on_checkbox_input_up() { - remove_checkbox_instructions +# https://www.gnu.org/software/termutils/manual/termutils-2.0/html_chapter/tput_1.html +# http://linuxcommand.org/lc3_adv_tput.php +on_checkbox_input_up2() { + #remove_checkbox_instructions tput cub "$(tput cols)" if [ "${_checkbox_selected[$_current_index]}" = true ]; then @@ -195,9 +212,9 @@ on_checkbox_input_up() { else _current_index=$((_current_index-1)) - tput cuu1 - tput cub "$(tput cols)" - tput el + tput cuu1 # Up one line + tput cub "$(tput cols)" # Back to beginning (does this work?) + tput el # Clear to end of line fi if [ "${_checkbox_selected[$_current_index]}" = true ]; then @@ -207,37 +224,146 @@ on_checkbox_input_up() { fi } +on_checkbox_input_up() { + #remove_checkbox_instructions + tput cub "$(tput cols)" + if (( ${_current_row} > 0 )) || (( ${#_checkbox_list[@]} <= 5 )); then + print_checkbox_line $_current_index + tput el + if [ $_current_index = 0 ]; then + _current_index=$((${#_checkbox_list[@]}-1)) + _current_row=4 + tput cud $((${#_checkbox_list[@]}-1)) + tput cub "$(tput cols)" + else + _current_index=$((_current_index-1)) + _current_row=$((_current_row-1)) + tput cuu1 + tput cub "$(tput cols)" + tput el + fi + print_checkbox_line_arrow $_current_index + else + if [ $_current_index = 0 ]; then + _current_index=$((${#_checkbox_list[@]}-1)) + _current_row=4 + tput cuu 1 + tput cub "$(tput cols)" + tput el + printf " ${cyan}${up_arrow}${normal}" + for I in 4 3 2 1; do + tput cud1 + tput cub "$(tput cols)" + tput el + print_checkbox_line $((_current_index-I)) + done + tput cud1 + tput cub "$(tput cols)" + tput el + print_checkbox_line_arrow $((_current_index)) + tput cud1 + tput cub "$(tput cols)" + tput el + printf " ${dim}${down_arrow}${normal}" + tput cuu 1 + else + _current_index=$((_current_index-1)) + tput cud 5 + tput cub "$(tput cols)" + tput el + printf " ${cyan}${down_arrow}${normal}" + for I in 4 3 2 1; do + tput cuu1 + tput cub "$(tput cols)" + tput el + print_checkbox_line $((_current_index+I)) + done + tput cuu1 + tput cub "$(tput cols)" + tput el + print_checkbox_line_arrow $((_current_index)) + if [ $_current_index = 0 ]; then + tput cuu1 + tput cub "$(tput cols)" + tput el + printf " ${dim}${up_arrow}${normal}" + tput cud1 + fi + fi + fi +} + on_checkbox_input_down() { - remove_checkbox_instructions + #remove_checkbox_instructions tput cub "$(tput cols)" - - if [ "${_checkbox_selected[$_current_index]}" = true ]; then - printf " ${green}${checked}${normal} ${_checkbox_list[$_current_index]} ${normal}" - else - printf " ${unchecked} ${_checkbox_list[$_current_index]} ${normal}" - fi - - tput el - - if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then - _current_index=0 - tput cuu $((${#_checkbox_list[@]}-1)) - tput cub "$(tput cols)" - else - _current_index=$((_current_index+1)) - tput cud1 - tput cub "$(tput cols)" + if (( ${_current_row} < 4 )) || (( ${#_checkbox_list[@]} <= 5 )); then + print_checkbox_line $_current_index tput el - fi - - if [ "${_checkbox_selected[$_current_index]}" = true ]; then - printf "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$_current_index]} ${normal}" + if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then + _current_index=0 + _current_row=0 + tput cuu $((${#_checkbox_list[@]}-1)) + tput cub "$(tput cols)" + else + _current_index=$((_current_index+1)) + _current_row=$((_current_row+1)) + tput cud1 + tput cub "$(tput cols)" + tput el + fi + print_checkbox_line_arrow $_current_index else - printf "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$_current_index]} ${normal}" + if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then + _current_index=0 + _current_row=0 + tput cuu 5 + tput cub "$(tput cols)" + tput el + printf " ${dim}${up_arrow}${normal}" + tput cud1 + tput cub "$(tput cols)" + tput el + print_checkbox_line_arrow $((_current_index)) + for I in 1 2 3 4; do + tput cud1 + tput cub "$(tput cols)" + tput el + print_checkbox_line $((_current_index+I)) + done + tput cud1 + tput cub "$(tput cols)" + tput el + printf " ${cyan}${down_arrow}${normal}" + tput cuu 5 + else + _current_index=$((_current_index+1)) + tput cuu 5 + tput cub "$(tput cols)" + tput el + printf " ${cyan}${up_arrow}${normal}" + for I in 4 3 2 1; do + tput cud1 + tput cub "$(tput cols)" + tput el + print_checkbox_line $((_current_index-I)) + done + tput cud1 + tput cub "$(tput cols)" + tput el + print_checkbox_line_arrow $((_current_index)) + if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then + tput cud1 + tput cub "$(tput cols)" + tput el + printf " ${dim}${down_arrow}${normal}" + tput cuu1 + fi + fi fi } on_checkbox_input_enter() { + remove_checkbox_instructions local OLD_IFS OLD_IFS=$IFS _checkbox_selected_indices=() @@ -254,11 +380,19 @@ on_checkbox_input_enter() { tput cud $((${#_checkbox_list[@]}-${_current_index})) tput cub "$(tput cols)" - for i in $(seq $((${#_checkbox_list[@]}+1))); do - tput el1 - tput el - tput cuu1 - done + if (( ${#_checkbox_list[@]} <= 5 )); then + for i in $(seq $((${#_checkbox_list[@]}+1))); do + tput el1 + tput el + tput cuu1 + done + else + for i in $(seq 8); do + tput el1 + tput el + tput cuu1 + done + fi tput cub "$(tput cols)" tput cuf $((${#prompt}+3)) @@ -274,7 +408,7 @@ on_checkbox_input_enter() { } on_checkbox_input_space() { - remove_checkbox_instructions + #remove_checkbox_instructions tput cub "$(tput cols)" tput el if [ "${_checkbox_selected[$_current_index]}" = true ]; then @@ -283,11 +417,7 @@ on_checkbox_input_space() { _checkbox_selected[$_current_index]=true fi - if [ "${_checkbox_selected[$_current_index]}" = true ]; then - printf "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$_current_index]} ${normal}" - else - printf "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$_current_index]} ${normal}" - fi + print_checkbox_line_arrow $_current_index } remove_checkbox_instructions() { @@ -316,6 +446,7 @@ _checkbox_input() { prompt=$1 eval _checkbox_list=( '"${'${2}'[@]}"' ) _current_index=0 + _current_row=0 _first_keystroke=true trap control_c SIGINT EXIT @@ -336,26 +467,31 @@ _checkbox_input() { done fi + if (( ${#_checkbox_list[@]} > 5 )); then + tput cub "$(tput cols)" + print " ${dim}${up_arrow}${normal}" + fi + for i in $(gen_index ${#_checkbox_list[@]}); do tput cub "$(tput cols)" if [ $i = 0 ]; then - if [ "${_checkbox_selected[$i]}" = true ]; then - print "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$i]} ${normal}" - else - print "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$i]} ${normal}" - fi + print_checkbox_line_arrow $i else - if [ "${_checkbox_selected[$i]}" = true ]; then - print " ${green}${checked}${normal} ${_checkbox_list[$i]} ${normal}" - else - print " ${unchecked} ${_checkbox_list[$i]} ${normal}" - fi + print_checkbox_line $i fi + print "" tput el + if (( $i > 3 )) && (( ${#_checkbox_list[@]} > 5 )); then + print " ${cyan}${down_arrow}${normal}" + break + fi done for j in $(gen_index ${#_checkbox_list[@]}); do tput cuu1 + if (( $j > 4 )); then + break + fi done on_keypress on_checkbox_input_up on_checkbox_input_down on_checkbox_input_space on_checkbox_input_enter on_default on_default on_checkbox_input_ascii diff --git a/installer.sh b/installer.sh index 77ff57f..1fb94d7 100755 --- a/installer.sh +++ b/installer.sh @@ -4,6 +4,8 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "${DIR}/install/inquirer.sh" +INSTALLED_EXES=() + function waUsage() { echo 'Usage: ./installer.sh --user # Install everything in ${HOME} @@ -27,10 +29,12 @@ function waFindInstalled() { rm -f ${HOME}/.local/share/winapps/installed.bat rm -f ${HOME}/.local/share/winapps/installed.tmp rm -f ${HOME}/.local/share/winapps/installed + cp "${DIR}/install/ExtractPrograms.ps1" ${HOME}/.local/share/winapps/ExtractPrograms.ps1 for F in $(ls "${DIR}/apps"); do . "${DIR}/apps/${F}/info" echo "IF EXIST \"${WIN_EXECUTABLE}\" ECHO ${F} >> \\\\tsclient\\home\\.local\\share\\winapps\\installed.tmp" >> ${HOME}/.local/share/winapps/installed.bat done; + echo "powershell.exe -ExecutionPolicy Bypass -File \\\\tsclient\\home\\.local\\share\\winapps\\ExtractPrograms.ps1 > \\\\tsclient\home\\.local\\share\\winapps\\detected" >> ${HOME}/.local/share/winapps/installed.bat echo "RENAME \\\\tsclient\\home\\.local\\share\\winapps\\installed.tmp installed" >> ${HOME}/.local/share/winapps/installed.bat xfreerdp /d:"${RDP_DOMAIN}" /u:"${RDP_USER}" /p:"${RDP_PASS}" /v:${RDP_IP} +auto-reconnect +home-drive -wallpaper /span /wm-class:"RDPInstaller" /app:"C:\Windows\System32\cmd.exe" /app-icon:"${DIR}/../icons/windows.svg" /app-cmd:"/C \\\\tsclient\\home\\.local\\share\\winapps\\installed.bat" 1> /dev/null 2>&1 & COUNT=0 @@ -55,15 +59,39 @@ function waFindInstalled() { echo " Finished." } +function waConfigureApp() { + . "${SYS_PATH}/apps/${1}/info" + echo -n " Configuring ${NAME}..." + ${SUDO} rm -f "${APP_PATH}/${1}.desktop" + echo "[Desktop Entry] +Name=${NAME} +Exec=${BIN_PATH}/winapps ${1} %F +Terminal=false +Type=Application +Icon=${SYS_PATH}/apps/${1}/icon.${2} +StartupWMClass=${FULL_NAME} +Comment=${FULL_NAME} +Categories=${CATEGORIES} +MimeType=${MIME_TYPES} +" |${SUDO} tee "${APP_PATH}/${1}.desktop" > /dev/null + ${SUDO} rm -f "${BIN_PATH}/${1}" + echo "#!/usr/bin/env bash +${BIN_PATH}/winapps ${1} $@ +" |${SUDO} tee "${BIN_PATH}/${1}" > /dev/null + ${SUDO} chmod a+x "${BIN_PATH}/${1}" + echo " Finished." +} + function waConfigureApps() { APPS=() for F in $(cat "${HOME}/.local/share/winapps/installed" |sed 's/\r/\n/g'); do . "${DIR}/apps/${F}/info" APPS+=("${FULL_NAME} (${F})") + INSTALLED_EXES+=("$(echo "${WIN_EXECUTABLE##*\\}" |tr '[:upper:]' '[:lower:]')") done IFS=$'\n' APPS=($(sort <<<"${APPS[*]}")) unset IFS - OPTIONS=("Set up all detected pre-configured applications" "Select which pre-configured applications to set up") + OPTIONS=("Set up all detected pre-configured applications" "Select which pre-configured applications to set up" "Do not set up any pre-configured applications") menuFromArr APP_INSTALL "How would you like to handle WinApps pre-configured applications?" "${OPTIONS[@]}" if [ "${APP_INSTALL}" = "Select which pre-configured applications to set up" ]; then checkbox_input "Which pre-configured apps would you like to set up?" APPS SELECTED_APPS @@ -73,40 +101,94 @@ function waConfigureApps() { APP="${APP%%)}" echo "${APP}" >> "${HOME}/.local/share/winapps/installed" done - fi + fi ${SUDO} cp "${DIR}/bin/winapps" "${BIN_PATH}/winapps" COUNT=0 - for F in $(cat "${HOME}/.local/share/winapps/installed" |sed 's/\r/\n/g'); do - COUNT=$((COUNT + 1)) - ${SUDO} cp -r "apps/${F}" "${SYS_PATH}/apps" - . "${DIR}/apps/${F}/info" - echo -n " Configuring ${NAME}..." - ${SUDO} rm -f "${APP_PATH}/${F}.desktop" - echo "[Desktop Entry] -Name=${NAME} -Exec=${BIN_PATH}/winapps ${F} %F -Terminal=false -Type=Application -Icon=${SYS_PATH}/apps/${F}/icon.svg -StartupWMClass=${FULL_NAME} -Comment=${FULL_NAME} -Categories=${CATEGORIES} -MimeType=${MIME_TYPES} -" |${SUDO} tee "${APP_PATH}/${F}.desktop" > /dev/null - ${SUDO} rm -f "${BIN_PATH}/${F}" - echo "#!/usr/bin/env bash -${BIN_PATH}/winapps ${F} $@ -" |${SUDO} tee "${BIN_PATH}/${F}" > /dev/null - ${SUDO} chmod a+x "${BIN_PATH}/${F}" - echo " Finished." - done + if [ "${APP_INSTALL}" != "Do not set up any pre-configured applications" ]; then + for F in $(cat "${HOME}/.local/share/winapps/installed" |sed 's/\r/\n/g'); do + COUNT=$((COUNT + 1)) + ${SUDO} cp -r "apps/${F}" "${SYS_PATH}/apps" + waConfigureApp "${F}" svg + done + fi rm -f "${HOME}/.local/share/winapps/installed" rm -f "${HOME}/.local/share/winapps/installed.bat" if (( $COUNT == 0 )); then - echo " No configured applications were found." + echo " No configured applications." fi } +function waConfigureDetectedApps() { + if [ -f "${HOME}/.local/share/winapps/detected" ]; then + sed -i 's/\r//g' "${HOME}/.local/share/winapps/detected" + . "${HOME}/.local/share/winapps/detected" + APPS=() + for I in "${!NAMES[@]}"; do + EXE=${EXES[$I]##*\\} + EXE_LOWER=$(echo "${EXE}" |tr '[:upper:]' '[:lower:]') + if ( dlm=$'\x1F' ; IFS="$dlm" ; [[ "$dlm${INSTALLED_EXES[*]}$dlm" != *"$dlm${EXE_LOWER}$dlm"* ]] ) ; then + APPS+=("${NAMES[$I]} (${EXE})") + fi + done + IFS=$'\n' APPS=($(sort <<<"${APPS[*]}")) + unset IFS + OPTIONS=("Set up all detected applications" "Select which applications to set up" "Do not set up any applications") + menuFromArr APP_INSTALL "How would you like to handle other detected applications?" "${OPTIONS[@]}" + if [ "${APP_INSTALL}" = "Select which applications to set up" ]; then + checkbox_input "Which other apps would you like to set up?" APPS SELECTED_APPS + echo "" > "${HOME}/.local/share/winapps/installed" + for F in "${SELECTED_APPS[@]}"; do + EXE="${F##*(}" + EXE="${EXE%%)}" + APP="${F% (*}" + echo "${EXE}|${APP}" >> "${HOME}/.local/share/winapps/installed" + done + elif [ "${APP_INSTALL}" = "Set up all detected applications" ]; then + for I in "${!EXES[@]}"; do + EXE=${EXES[$I]##*\\} + echo "${EXE}|${NAMES[$I]}" >> "${HOME}/.local/share/winapps/installed" + done + fi + COUNT=0 + if [ -f "${HOME}/.local/share/winapps/installed" ]; then + while read LINE; do + EXE="${LINE%|*}" + NAME="${LINE#*|}" + for I in "${!NAMES[@]}"; do + if [ "${NAME}" = "${NAMES[$I]}" ] && [[ "${EXES[$I]}" == *"\\${EXE}" ]]; then + EXE=$(echo "${EXE}" |tr '[:upper:]' '[:lower:]') + ${SUDO} mkdir -p "${SYS_PATH}/apps/${EXE}" + echo "# GNOME shortcut name +NAME=\"${NAME}\" + +# Used for descriptions and window class +FULL_NAME=\"${NAME}\" + +# The executable inside windows +WIN_EXECUTABLE=\"${EXES[$I]}\" + +# GNOME categories +CATEGORIES=\"WinApps\" + +# GNOME mimetypes +MIME_TYPES=\"\" +" > "${SYS_PATH}/apps/${EXE}/info" + echo "${ICONS[$I]}" | base64 -d > "${SYS_PATH}/apps/${EXE}/icon.ico" + waConfigureApp "${EXE}" ico + COUNT=$((COUNT + 1)) + fi + done + done < "${HOME}/.local/share/winapps/installed" + rm -f "${HOME}/.local/share/winapps/installed" + fi + rm -f "${HOME}/.local/share/winapps/installed.bat" + if (( $COUNT == 0 )); then + echo " No configured applications." + fi + fi +} + + function waConfigureWindows() { echo -n " Configuring Windows..." ${SUDO} rm -f "${APP_PATH}/windows.desktop" @@ -222,10 +304,11 @@ waInstall # Check for installed apps waFindInstalled -# Configure apps -waConfigureApps - # Install windows waConfigureWindows +# Configure apps +waConfigureApps +waConfigureDetectedApps + echo "Installation complete." \ No newline at end of file