#!/bin/sh #description: control keyboard layouts #usage: shift-keyboard-layout #change keyboard layout to the next configured one default_layouts="latam,us,ru" #see /usr/share/X11/xkb/rules/base.lst progname="$(expr "${0}" : '.*/\([^/]*\)')" _str2lower() { [ -z "${1}" ] && return 1 printf "%s\\n" "${@}" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' } _notify() { [ -z "${1}" ] && return 1 if [ X"${TERM}" = X"linux" ] || [ -z "${TERM}" ]; then kill -9 $(pgrep notify-osd) >/dev/null 2>&1 if ! DISPLAY=:0 notify-send -t 1000 "${1}" "${2}"; then if command -v "gxmessage" 2>/dev/null; then font="Monaco 9" gxmessage "${font:+-fn "$font"}" "${1} ${2}" "ok" else font="fixed" xmessage "${font:+-fn "$font"}" "${1} ${2}" "ok" fi fi else if [ -z "${2}" ]; then printf "%s\\n" "${1}" else printf "%s: %s" "${1}" "${2}"; printf "\\n" fi fi } _return_valid_layouts() { [ -z "${1}" ] && { printf "%s" "${default_layouts}"; return; } || _return_valid_layouts__arg="${1}" _return_valid_layouts__reference=$(awk '/! layout/,/! variant/ {if ($0 !~ "^$" && $1 !~ "!") print $1}' /usr/share/X11/xkb/rules/base.lst 2>&1) _return_valid_layouts__arg="$(_str2lower "${_return_valid_layouts__arg}")" _return_valid_layouts__arg="$(printf "%s" "${_return_valid_layouts__arg}" | sed 's: :,:g')" _return_valid_layouts__cp="${_return_valid_layouts__arg}" while [ "${_return_valid_layouts__arg}" ]; do _return_valid_layouts__option="${_return_valid_layouts__arg%%,*}" if [ -z "$(printf "%s" "${_return_valid_layouts__reference}" | grep "${_return_valid_layouts__option}")" ]; then printf "%s" "${default_layouts}"; return; fi [ X"${_return_valid_layouts__arg}" = X"${_return_valid_layouts__option}" ] \ && _return_valid_layouts__arg="" \ || _return_valid_layouts__arg="${_return_valid_layouts__arg#*,}" done printf "%s" "${_return_valid_layouts__cp}"; return; } if [ ! -t 0 ]; then #there is input comming from pipe or file, add to the end of $@ set -- "${@}" $(cat) fi for arg; do #parse options case "${arg}" in --) shift; break ;; -h|--help) { printf "Usage: %b\\n" "${progname}\\nChange keyboard layout (see minos-config)." exit; } ;; -*) printf "%s\\n" "${progname}: unrecognized option '${arg}'" >&2 printf "Usage: %b\\n" "${progname}\\nChange keyboard layout (see minos-config)." >&2 exit 1 ;; esac done if ! command -v "setxkbmap" >/dev/null; then _notify "Error" "install setxkbmap to run this program" fi current_layout="$(setxkbmap -query | awk '/layout/ {print $2}')" layouts="$(minos-config keyboard-layouts 2>/dev/null)" [ -z "${layouts}" ] && layouts="${default_layouts}" || layouts="$(_return_valid_layouts "${layouts}")" d_layouts="${layouts}" c_layouts="${layouts}" c="0";d="0" while [ "${d_layouts}" ]; do option="${d_layouts%%,*}" d="$((${d} + 1))" [ X"${d_layouts}" = X"${option}" ] && d_layouts="" || d_layouts="${d_layouts#*,}" done while [ "${c_layouts}" ]; do #in what position is the current_layout with respect to the array? option="${c_layouts%%,*}" c="$((${c} + 1))" [ X"${current_layout}" = X"${option}" ] && break [ X"${c_layouts}" = X"${option}" ] && c_layouts="" || c_layouts="${c_layouts#*,}" done [ -z "${c_layouts}" ] && exit 1 #invalid layout format e="$((${c} + 1))" [ "${d}" -eq "${c}" ] && e="1" #return to first element if we're in the last item c="0"; while [ "${layouts}" ]; do #set next keyboard layout option="${layouts%%,*}" c="$((${c} + 1))" if [ "${c}" -eq "${e}" ]; then setxkbmap "${option}" _notify "Keyboard layout: $(printf "%s\\n" "${option}" | \ tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" fi [ X"${layouts}" = X"${option}" ] && layouts="" || layouts="${layouts#*,}" done