279 lines
12 KiB
Bash
Executable File
279 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
## =================================================================
|
|
## === INSTALL-DREYMAR-XMOD.sh for DreymaR's XKB modifications ===
|
|
## === by Øystein "DreymaR" Bech-Aase, 2016- ===
|
|
## =================================================================
|
|
#
|
|
HeadStr="DreymaR's Big Bag Of Tricks install script (by OeBeAa, 2016-)"
|
|
DescStr=\
|
|
"\e[1mShell script to apply DreymaR's changes to the X keyboard files:\e[0m\n"\
|
|
" - The Colemak [edition DreymaR] layout, using my own lv3-4 mappings,\n"\
|
|
" - Curl/Angle/Wide Ergonomic keyboard models for pc104/pc105 keyboards,\n"\
|
|
" - Extend mappings as a Misc option and CapsLock as a chooser (using lv5-8),\n"\
|
|
" - locale variants of Colemak[eD] with 'keep local' or 'unified' symbol keys,\n"\
|
|
" - phonetic variants of Colemak for other scripts such as Greek,\n"\
|
|
" - mirrored Colemak[eD] for one-handed typing (if I ever break an arm...),\n"\
|
|
" - and the Tarmak(1-4) transitional step-by-step Colemak learning layouts.\n"\
|
|
"\n"\
|
|
"- By default, this script creates a backup of the X11 files if none exist.\n"\
|
|
"- With '-o', overwrite the system X11 files (makes the mod GUI accessible).\n"\
|
|
"- With a ShortStr at the end, specify a model/layout to activate immediately.\n"\
|
|
" - ShortStr format: '[4|5][n|a|c][w|f] loc [ks|us]'; 'loc'(ale) is 2-letter.\n"\
|
|
" - E.g., '5n fr us' is normal pc105 model, French Cmk[eD]-'UniSym'.\n"\
|
|
" - See setkb.sh help for more info on ShortStr syntax.\n"\
|
|
"- With '-?', list further instructions and default values.\n"\
|
|
"- See http://forum.colemak.com/viewtopic.php?id=1438 for more info\n"
|
|
#
|
|
FootStr="Happy xkb-hacking! ~ Øystein 'DreymaR' Bech-Aase"
|
|
#"- With '-i <dir>', specify a directory path/name to install in.\n"\
|
|
#"- With '-g', also install GTK 2.0/3.0 config for XF86 Cut/Copy/Paste.\n"\
|
|
|
|
## NOTE: The mod directory has the form $DModTag="x-mod_v<VER>[_<DATE>]"
|
|
## - Unless you change this tag, it should be in the same dir as this script
|
|
## - It has subdirectories like 'xkb' that are to be installed (one, some or all)
|
|
## NOTE: This is now the preferred way instead of patching the system files:
|
|
## - Backup system xkb to dbak-xkb_<DATE> (and the same for any other subdirs)
|
|
## - Copy X11/xkb to ${InstDir}/dxkb, then modify files in dxkb
|
|
## - Set up setkb.sh to run from the modified dxkb [WARNING: This may not work now!]
|
|
## - Or, (-o) overwrite the system files instead
|
|
## NOTE: The x-mod dir now holds x-mod*/xkb; eventually there may be a locale dir too.
|
|
|
|
|
|
##-------------- init ------------------------------------------
|
|
|
|
MyDATE=`date +"%Y-%m-%d_%H-%M"`
|
|
MyNAME=`basename $0`
|
|
MyPATH=`dirname $0`
|
|
## @@@ The default X11 dir under Debian/Ubuntu/etc is /usr/share/X11 @@@
|
|
## @@@ The default X11 dir under some (older) distros is /usr/lib/X11 @@@
|
|
X11DIR='/usr/share/X11'; [ -d "${X11DIR}" ] || X11DIR='/usr/lib/X11'
|
|
#~ XVERSION='2-17-1ub1'
|
|
XVERSION=''
|
|
ModDATE=''
|
|
|
|
DModDir=`dirname $0` # (-d) Path to the script (and mod?) root directory
|
|
ToolDir="${DModDir}/dreymar-xtools" # The loc. of tool scripts (like setkb.sh)
|
|
DMod='xkb-data_xmod' # (--) Name of the directory with DreymaR's modded xkb-data files
|
|
DModTag="${DMod}${XVERSION:+'_v'}${XVERSION}${ModDATE:+'_'}${ModDATE}" # (-t) Mod dir "prefix"
|
|
DBakFix='dbak-' # (--) Backup dir prefix
|
|
DModFix='d' # (--) Modded dir prefix
|
|
InstDir="${X11DIR}" # (-i) Path to install subfolder(s) in
|
|
#~ InstDir="${HOME}/dreymar-xmod" # (-i) Path to install subfolder(s) in
|
|
WriteSys='no' # (-o) Overwrite the original xkb dir with the modded one
|
|
Restore='0' # (-r) Reverse: Restore from backup # instead of installing
|
|
DoBackup='ifnone' # (-n/b) Default backup behavior is "if no backups are found"
|
|
SubDirs='all' # (-m) Directory/-ies inside X11 to modify (e.g., 'xkb locale', 'all')
|
|
InstGTK='no' # (-g) Whether to install the GTK 2.0/3.0 config (if not present)
|
|
NoSudo='no' # (-s) Do not use sudo. Helpful for local dir installation.
|
|
SetXMap='no' # (-x) Whether to run the setkb script after installing
|
|
SetXStr='5caws us us' # (--) Shortcut string for setkb - 'kbd loc sym' (model layout eD-variant)
|
|
## NOTE: '# (-a)' means that the value can be set by option argument '-a <value>'
|
|
|
|
HelpStr="\e[1mUsage: bash ${MyNAME} [optional args] [<kbd> [<loc> <sym>]]\e[0m\n"\
|
|
" Run this from the directory containing the x-mod dir\n"\
|
|
"===========================================================\n"\
|
|
"[-#] Functionality - 'default' \n"\
|
|
"===========================================================\n"\
|
|
"[-i] <Install path> - ${InstDir}\n"\
|
|
"[-c] Change path to X11 - ${X11DIR}\n"\
|
|
"[-o] Override install path w/ X11 - ${WriteSys}\n"\
|
|
"[-b] Force backup | location - ${X11DIR}\n"\
|
|
"[-n] Force no backup | default - ${DoBackup}\n"\
|
|
"[-r] <#> Restore backup | 1 is oldest - ${Restore}\n"\
|
|
"[-d] <mod dir path> - ${DModDir}\n"\
|
|
"[-m] <X11 subdir(s) to mod> - ${SubDirs}\n"\
|
|
"[-t] <mod dir prefix tag> - ${DModTag}\n"\
|
|
"[-g] Install GTK 2.0/3.0 edit config? - ${InstGTK}\n"\
|
|
"[-x] Run the setkb script afterwards? - ${SetXMap}\n"\
|
|
"[-s] Install without using sudo? - ${NoSudo}\n"\
|
|
"[--] [Setxkb ShortStr <kbd loc sym>] - ${SetXStr}\n"
|
|
#~ "( - <val> : Default settings)\n"
|
|
|
|
##-------------- functions and line parser ---------------------
|
|
|
|
MyMsg() # Formatted output: last arg is printf 'style[;fgcolor[;bgcolor]]'
|
|
{
|
|
# Style: 0-Off, 1-Bold, 4-Underscore, 5-Blink, 7-Reverse, 8-Concealed
|
|
# Color: (3#/4# FG/BG): 0-Black, 1-Red, 2-Green, 3-Yellow, 4-Blue, 5-Magenta, 6-Cyan, 7-White
|
|
printf "\n\e[${3:-1;32;40}m@@@ $1 @@@\e[0m\n$2" # default: Bold green on black
|
|
}
|
|
|
|
PrintHelpAndExit()
|
|
{
|
|
MyMsg "${HeadStr}" "\n"
|
|
printf "${DescStr}\n"
|
|
printf "${HelpStr}"
|
|
MyMsg "${FootStr}" "\n"
|
|
exit $1
|
|
}
|
|
|
|
MyEcho()
|
|
{
|
|
printf "$1\n"
|
|
[ -z "$2" ] || printf "$1\n" >> "$2"
|
|
}
|
|
|
|
MyPoint()
|
|
{
|
|
MyEcho "\e[1;32m¤ \e[0m$@" # Bold green
|
|
}
|
|
|
|
MyWarning()
|
|
{
|
|
MyMsg "WARNING: ${@:-'Beware of nargles!'}" "\n" '1;36;44' # Bold cyan on blue
|
|
#~ exit 1
|
|
}
|
|
|
|
MyError()
|
|
{
|
|
MyMsg "$MyNAME - ERROR: ${@:-'Undefined error'}" "\n" '1;37;41' # Bold white on red
|
|
exit 1
|
|
}
|
|
|
|
#~ MyCD()
|
|
#~ {
|
|
#~ OldDir=`pwd`
|
|
#~ NewDir=${1:-`pwd`}
|
|
#~ cd ${NewDir} || MyError "Change to '${NewDir}' failed"
|
|
#~ MyPoint "Changed dir to '${NewDir}'"
|
|
#~ }
|
|
|
|
#~ if [ "$#" == 0 ]; then PrintHelpAndExit 2; fi # No args
|
|
while getopts "obngxsm:i:c:d:t:r:h?" cmdarg; do
|
|
case $cmdarg in
|
|
o) WriteSys='yes' ;;
|
|
b) DoBackup='yes' ;;
|
|
n) DoBackup='no' ;;
|
|
g) InstGTK='yes' ;;
|
|
x) SetXMap='yes' ;;
|
|
s) NoSudo='yes' ;;
|
|
m) SubDirs="$OPTARG" ;;
|
|
i) InstDir="$OPTARG" ;;
|
|
c) X11DIR="$OPTARG" ;;
|
|
d) DModDir="$OPTARG" ;;
|
|
t) DModTag="$OPTARG" ;;
|
|
r) Restore="$OPTARG" ;;
|
|
h) PrintHelpAndExit 0 ;;
|
|
\?) PrintHelpAndExit 0 ;;
|
|
:) PrintHelpAndExit 1 ;;
|
|
# s) SetXStr="$OPTARG"
|
|
# SetXMap='yes' ;;
|
|
esac
|
|
done
|
|
#~ pos_arg=${@:$OPTIND:1} # Get the remaining positional arg (old way)
|
|
shift $(( $OPTIND - 1 )) # Remove already processed args
|
|
[[ "$@" == "" ]] || SetXStr=$@ # Don't split the ShortString here!
|
|
|
|
##-------------- main ------------------------------------------
|
|
|
|
MyMsg "$HeadStr"
|
|
#~ MyPoint "Working from '`pwd`'"
|
|
|
|
## Check for a mod dir (the latest found) and if found, get its full name
|
|
DModDir=`find "${DModDir%/}/${DModTag}"* -maxdepth 0 -type d 2>/dev/null | tail -n 1`
|
|
[ -n "${DModDir}" ] || MyError "Mod root dir not found!"
|
|
MyPoint "Found mod root dir '${DModDir}'"
|
|
|
|
## Read the mod subdirs
|
|
if [ "${SubDirs}" == "all" ]; then
|
|
SubDirs=`find "${DModDir}/"* -maxdepth 0 -type d -exec basename '{}' \; 2>/dev/null`
|
|
SubDirs=`echo ${SubDirs}` # A trick to make a var space separated for the following echo cmd
|
|
[ -n "${SubDirs}" ] || MyError "No mod subdirs found!"
|
|
fi
|
|
MyPoint "Subdirectories to mod: '${SubDirs}'"
|
|
|
|
## For each subdir, backup if either DoBackup = 'yes' or DoBackup = 'ifnone' and no backup exists
|
|
BackIt=''
|
|
if [ ${DoBackup} == 'yes' ]; then
|
|
BackIt="${SubDirs}"
|
|
elif [ ${DoBackup} == 'ifnone' ] && [ ${Restore} == '0' ]; then
|
|
for That in ${SubDirs}; do
|
|
MyPoint "Looking for '${That}' backup in '${X11DIR}'..."
|
|
# Test for (at least one) backup dir; if none found then proceed without errors
|
|
# if [ -z `find "${X11DIR}/${DBakFix}${That}"* -maxdepth 0 -type d 2>/dev/null | head -n 1` ]; then
|
|
if [ -z `find "${X11DIR}/${DBakFix}${That}"* -maxdepth 0 -type d -print -quit 2>/dev/null` ]; then
|
|
[ -n "${BackIt}" ] && BackIt+=' ' # join with ' '; note that += is a bashism
|
|
BackIt+="${That}"
|
|
fi
|
|
done
|
|
fi
|
|
[ -z "${BackIt}" ] && MyPoint "Backing up: None" || MyPoint "Backing up: '${BackIt}'"
|
|
|
|
## Check for root privileges (if not root, sudo command); note that root is only needed in some cases!
|
|
DoSudo=''
|
|
if [ ${NoSudo} = 'yes' ]; then
|
|
MyPoint "Not using sudo."
|
|
else
|
|
if [ "$EUID" -ne 0 ]; then # not root, so test for and use sudo instead (but some distros don't have it!)
|
|
#[ command -v sudo >/dev/null 2>&1 ] || MyError "Root access needed - sudo won't run!"
|
|
( command -v sudo >/dev/null 2>&1 ) || MyWarning "Root/superuser access may be needed!"
|
|
DoSudo='sudo'
|
|
fi
|
|
fi
|
|
|
|
## Perform the actual backup(s)
|
|
## NOTE: cp -a makes an "archive" copy, preserving all attributes and links
|
|
for That in ${BackIt}; do
|
|
[ -d "${X11DIR}/${That}" ] || MyError "Unable to backup '${That}': Directory not found!"
|
|
${DoSudo} cp -a "${X11DIR}/${That}" "${X11DIR}/${DBakFix}${That}_${MyDATE}" || MyError "Copy error!"
|
|
done
|
|
|
|
## For each subfolder: Restore from backup #, overwrite X11 files or make new mod folder
|
|
for That in ${SubDirs}; do
|
|
if [ ${Restore} != '0' ]; then # Restore from specified backup
|
|
## Restore from backup. Pick a backup # by parameter, 1 being oldest; use 999 or such for the last one
|
|
BackIt=`find "${X11DIR}/${DBakFix}${That}"* -maxdepth 0 -type d 2>/dev/null | head -n ${Restore} | tail -n 1`
|
|
[ -d "${BackIt}" ] || MyError "Unable to locate restore dir '$(basename "${BackIt}")'"
|
|
MyPoint "Restoring from backup '$(basename "${BackIt}")'"
|
|
${DoSudo} cp -a "${BackIt}/"* "${X11DIR}/${That}" 2>/dev/null \
|
|
&& MyPoint "Restore done" || MyError "Restore copy error!"
|
|
XKBDir="${X11DIR}/xkb" # Setxkbmap will default to the X11 dir, but this makes it unambigous
|
|
elif [ ${WriteSys} == 'yes' ] || [ ${InstDir} == ${X11DIR} ] && [ -d "${DModDir}/${That}" ]; then # Overwrite OS files
|
|
MyPoint "Replacing files in '${X11DIR}/${That}' with mod"
|
|
${DoSudo} cp -a "${DModDir}/${That}/"* "${X11DIR}/${That}" 2>/dev/null \
|
|
&& MyPoint "System install done" || MyError "System files copy error!"
|
|
XKBDir="${X11DIR}/xkb"
|
|
else ## Make new mod folder (will not show up in keyboard settings GUI; use setxkbmap instead)
|
|
DoSudo=''
|
|
mkdir -p "${InstDir}" 2>/dev/null && [ -w "${InstDir}" ] || DoSudo='sudo' # check whether sudo is needed
|
|
MyDir="${InstDir%/}/${DModFix}${That}"
|
|
#~ MyDir="$(dirname "${MyDir}")/${DModFix}$(basename "${MyDir}")" # Insert prefix in path/name
|
|
MyPoint "Installing mod files in '${MyDir}'"
|
|
MyWarning "It seems that setxkbmap w/ local dir isn't working now?!"
|
|
${DoSudo} mkdir -p "${MyDir}" || MyError "Can't make '${MyDir}'!"
|
|
${DoSudo} cp -a "${X11DIR}/${That}/"* "${MyDir}" 2>/dev/null || MyError "Local files copy error!"
|
|
${DoSudo} cp -a "${DModDir}/${That}/"* "${MyDir}" 2>/dev/null \
|
|
&& MyPoint "Local install done" || MyError "Local files copy error!"
|
|
XKBDir="${InstDir%/}/${DModFix}xkb" # Prepare for setxkbmap
|
|
cp -a setkb.sh ${InstDir} # Copy over the setkb.sh script to the new dir
|
|
fi
|
|
done
|
|
|
|
## If selected, call the DreymaR GTK bindings install script
|
|
## The DreymaR gtk edit install script sets GTK Cut/Copy/Paste key config (if not already present)
|
|
if [ ${InstGTK} == 'yes' ]; then
|
|
"${ToolDir}/gtk_edit_install.sh" || MyError "gtk_edit_install.sh failed!"
|
|
fi
|
|
|
|
#~ ## Call the DreymaR setxkbmap script unless 'q' is pressed, to activate the new (default) layout
|
|
#~ That='' #; [ ${InstGTK} == 'yes' ] && That=" and GTK edit config"
|
|
#~ MyMsg "Press any key to set the new xkb map${That}, or 'q' to quit"
|
|
#~ read -p '$>' -n 1 keypress
|
|
#~ if [ "${keypress}" == 'q' ]; then
|
|
|
|
## If selected, call the DreymaR setxkbmap script to activate the new (default) layout
|
|
if [ "${SetXMap}" != 'yes' ]; then
|
|
MyMsg "XKBmap activation skipped" "" '1;33;40'
|
|
else
|
|
bash ./setkb.sh -d "${XKBDir}" ${SetXStr} || MyError "setkb.sh failed!"
|
|
fi
|
|
|
|
MyMsg "${MyNAME} finished!" "\n"
|
|
exit 0
|
|
|
|
##-------------- misc ------------------------------------------
|
|
|
|
#~ MyWarning "'${MyNAME}' debug - exiting!"; exit 0
|
|
#~ echo "$1 $2 $3 $4 $5"; exit 0 # debug
|