3
shopt -s extglob nullglob globstar
4
export TEXTDOMAIN=fcitx
6
__test_bash_unicode() {
7
local magic_str='${1}'$'\xe4'$'\xb8'$'\x80'
8
local magic_replace=${magic_str//\$\{/$'\n'$\{}
9
! [ "${magic_str}" = "${magic_replace}" ]
12
if type gettext &> /dev/null && __test_bash_unicode; then
22
#############################
24
#############################
26
add_and_check_file() {
30
inode="$(stat -L --printf='%i' "${file}" 2> /dev/null)" || return 0
31
local varname="___add_and_check_file_${prefix}_${inode}"
32
[ ! -z "${!varname}" ] && return 1
48
for ((i = 0;i < n;i++)); do
61
eval 'fs=("${p}/"'"${w}"')'
62
for f in "${fs[@]}"; do
73
local conf_option="$1"
74
local default_name="$2"
75
for path in "$(fcitx4-config "--${conf_option}" 2> /dev/null)" \
76
"/usr/share/fcitx/${default_name}" \
77
"/usr/local/share/fcitx/${default_name}"; do
78
[ ! -z "${path}" ] && [ -d "${path}" ] && {
86
get_from_config_file() {
90
value=$(sed -ne "s=^${key}\=\(.*\)=\1=gp" "$file" 2> /dev/null)
91
[ -z "$value" ] && return 1
97
#############################
99
#############################
113
((__istty)) || return
114
echo -ne '\e['"${1}"'m'
120
if [ ! -z "$1" ]; then
122
echo "${line//$'\e'[0m/$'\e'[${1}m}"
124
[ -z "${line}" ] || {
125
echo -n "${line//$'\e'[0m/$'\e'[${1}m}"
134
local __line=${1//\$\{/$'\n'$\{}
137
echo "${__line}" | while read __line; do
138
if [[ ${__line} =~ ^\$\{([_a-zA-Z0-9]+)\} ]]; then
139
__varname="${BASH_REMATCH[1]}"
140
echo -n "${__line/\$\{${__varname}\}/${!__varname}}"
151
while read __line; do
152
__replace_line "${__line}" "$@"
154
[ -z "${__line}" ] || {
155
echo -n "$(__replace_line "${__line}" "$@")"
160
echo "$1" | __replace_vars "${@:2}"
165
print_tty_ctrl '01;36'
166
echo -n '`'"$1"'`' | replace_reset '01;36'
173
print_tty_ctrl '01;33'
174
echo -n "[$text]($url)" | replace_reset '01;33'
179
print_eval "$(_ '${1} not found.')" "$(code_inline $1)"
182
# indent levels and list index counters
190
if ((level >= 0)); then
191
((__current_level = level))
192
for ((i = 0;i <= __current_level;i++)); do
193
((indexes[i] = __list_indexes[i]))
195
__list_indexes=("${indexes[@]}")
197
((__current_level = 0))
202
increase_cur_level() {
204
((level = __current_level + level))
205
set_cur_level "$level"
216
local prefix="$(repeat_str "${__current_level}" " ")"
221
((__need_blank_line)) && echo
222
[ -z "${code}" ] || print_tty_ctrl "${code}"
226
whole_prefix="${prefix}${p1}"
228
whole_prefix="${prefix}${p2}"
231
[ -z "${line}" ] && {
234
echo "${whole_prefix}${line}"
236
done | replace_reset "${code}"
240
[ -z "${code}" ] || print_tty_ctrl "0"
245
write_paragraph "$(print_eval "$@")"
249
write_paragraph "**${1}**" "${2}" "${3}" '01;31'
253
write_error "$(print_eval "$@")"
261
write_paragraph "${str}" '' '' '01;35'
264
increase_cur_level -1
268
write_quote_str "$("$@" 2>&1)"
274
local prefix='######'
275
prefix="${prefix::$level}"
276
((__need_blank_line)) && echo
277
print_tty_ctrl '01;34'
278
echo "${prefix} ${title}" | replace_reset '01;34'
287
increase_cur_level -1
289
((index = ++__list_indexes[__current_level - 1]))
290
((${#index} > 2)) && index="${index: -2}"
292
increase_cur_level -1
293
write_paragraph "${str}" "${index::4}" ' ' '01;32'
297
write_order_list_eval() {
298
write_order_list "$(print_eval "$@")"
303
# increase_cur_level -1
304
# write_paragraph "${str}" '* ' ' ' '01;32'
305
# increase_cur_level 1
309
#############################
310
# print tips and links
311
#############################
313
wiki_url="http://fcitx-im.org/wiki"
315
beginner_guide_link() {
316
print_link "$(_ "Beginner's Guide")" \
317
"${wiki_url}$(_ /Beginner%27s_Guide)"
324
fmt=$(_ 'Please set environment variable ${env_name} to "${value}" using the tool your distribution provides or add ${1} to your ${2}. See ${link}.')
327
"$(_ "Input Method Related Environment Variables: ")${env_name}" \
328
"${wiki_url}$(_ "/Input_method_related_environment_variables")#${env_name}")
329
write_error_eval "${fmt}" "$(code_inline "export ${env_name}=${value}")" \
330
"$(code_inline '~/.xprofile')"
336
"$(_ "Note for GNOME Later than 3.6")" \
337
"${wiki_url}$(_ "/Note_for_GNOME_Later_than_3.6")")
339
fmt=$(_ 'If you are using ${1}, you may want to uninstall ${2} or remove ${3} to be able to use any input method other than ${2}. See ${link} for more detail as well as alternative solutions.')
340
write_error_eval "${fmt}" "$(code_inline 'gnome>=3.6')" \
341
"$(code_inline 'ibus')" "$(code_inline 'ibus-daemon')"
346
fmt=$(_ 'To see some application specific problems you may have when using xim, check ${link1}. For other more general problems of using XIM including application freezing, see ${link2}.')
349
"$(_ "Hall of Shame for Linux IME Support")" \
350
"${wiki_url}$(_ "/Hall_of_Shame_for_Linux_IME_Support")")
354
"${wiki_url}$(_ "/XIM")")
355
write_error_eval "${fmt}"
359
#############################
361
#############################
366
local _ldpaths=($(ldconfig -p 2> /dev/null | grep '=>' | \
367
sed -e 's:.* => \(.*\)/[^/]*$:\1:g' | sort -u)
368
/lib /lib32 /lib64 /usr/lib /usr/lib32 /usr/lib64
369
/usr/local/lib /usr/local/lib32 /usr/local/lib64)
372
for path in "${_ldpaths[@]}"; do
373
[ -d "${path}" ] && add_and_check_file ldpath "${path}" && {
374
ldpaths=("${ldpaths[@]}" "${path}")
381
write_title 1 "$(_ "System Info.")"
382
write_order_list "$(code_inline 'uname -a'):"
383
if type uname &> /dev/null; then
384
write_quote_cmd uname -a
386
write_error "$(print_not_found 'uname')"
388
if type lsb_release &> /dev/null; then
389
write_order_list "$(code_inline 'lsb_release -a'):"
390
write_quote_cmd lsb_release -a
391
write_order_list "$(code_inline 'lsb_release -d'):"
392
write_quote_cmd lsb_release -d
394
write_order_list "$(code_inline lsb_release):"
395
write_paragraph "$(print_not_found 'lsb_release')"
397
write_order_list "$(code_inline /etc/lsb-release):"
398
if [ -f /etc/lsb-release ]; then
399
write_quote_cmd cat /etc/lsb-release
401
write_paragraph "$(print_not_found '/etc/lsb-release')"
403
write_order_list "$(code_inline /etc/os-release):"
404
if [ -f /etc/os-release ]; then
405
write_quote_cmd cat /etc/os-release
407
write_paragraph "$(print_not_found '/etc/os-release')"
412
write_title 1 "$(_ "Environment.")"
413
write_order_list "DISPLAY:"
414
write_quote_str "DISPLAY='${DISPLAY}'"
415
write_order_list "$(_ "Keyboard Layout:")"
417
write_order_list "$(code_inline setxkbmap)"
418
if type setxkbmap &> /dev/null; then
419
write_quote_cmd setxkbmap -print
421
write_paragraph "$(print_not_found 'setxkbmap')"
423
write_order_list "$(code_inline xprop)"
424
if type xprop &> /dev/null; then
425
write_quote_cmd xprop -root _XKB_RULES_NAMES
427
write_paragraph "$(print_not_found 'xprop')"
429
increase_cur_level -1
430
write_order_list "$(_ "Locale:")"
431
if type locale &> /dev/null; then
433
write_order_list "$(_ "Current locale:")"
434
write_quote_cmd locale
435
write_order_list "$(_ "All locale:")"
436
write_quote_cmd locale -a
437
increase_cur_level -1
439
write_paragraph "$(print_not_found 'locale')"
445
write_title 1 "$(_ "Fcitx State.")"
446
write_order_list "$(_ 'executable:')"
447
if ! fcitx_exe="$(which fcitx 2> /dev/null)"; then
448
write_error "$(_ "Cannot find fcitx executable!")"
450
write_error_eval "$(_ 'Please check ${1} for how to install fcitx.')" \
451
"$(beginner_guide_link)"
454
write_eval "$(_ 'Found fcitx at ${1}.')" "$(code_inline "${fcitx_exe}")"
456
write_order_list "$(_ 'version:')"
457
version=$(fcitx -v 2> /dev/null | \
458
sed -e 's/.*fcitx version: \([0-9.]*\).*/\1/g')
459
write_eval "$(_ 'Fcitx version: ${version}')"
460
write_order_list "$(_ 'process:')"
461
psoutput=$(ps -Ao pid,comm)
464
if [[ $line =~ ^([0-9]*)\ .*fcitx.* ]]; then
465
[ "${BASH_REMATCH[1]}" = "$$" ] && continue
466
process=("${process[@]}" "${line}")
471
if ! ((${#process[@]})); then
472
write_error "$(_ "Fcitx is not running.")"
474
write_error_eval "$(_ 'Please check the Configure link of your distribution in ${1} for how to setup fcitx autostart.')" "$(beginner_guide_link)"
477
local pcount="${#process[@]}"
478
if ((pcount > 1)); then
479
write_eval "$(_ 'Found ${1} fcitx processes:')" "${#process[@]}"
481
write_eval "$(_ 'Found ${1} fcitx process:')" "${#process[@]}"
483
write_quote_cmd print_array "${process[@]}"
484
write_order_list "$(code_inline 'fcitx-remote'):"
485
if type fcitx-remote &> /dev/null; then
486
if ! fcitx-remote &> /dev/null; then
487
write_error "$(_ "Cannot connect to fcitx correctly.")"
489
write_eval "$(_ '${1} works properly.')" \
490
"$(code_inline 'fcitx-remote')"
493
write_error "$(print_not_found "fcitx-remote")"
498
#############################
500
#############################
504
"$(_ 'Environment variable ${1} is set to "${2}" correctly.')" \
510
"$(_ 'Environment variable ${1} is "${2}" instead of "${3}". Please check if you have exported it incorrectly in any of your init files.')" \
517
write_order_list "$(code_inline '${XMODIFIERS}'):"
518
if [ -z "${XMODIFIERS}" ]; then
519
set_env_link XMODIFIERS '@im=fcitx'
521
elif [ "${XMODIFIERS}" = '@im=fcitx' ]; then
522
_env_correct 'XMODIFIERS' '@im=fcitx'
525
_env_incorrect 'XMODIFIERS' '@im=fcitx' "${XMODIFIERS}"
526
if [[ ${XMODIFIERS} =~ @im=([-_0-9a-zA-Z]+) ]]; then
527
xim_name="${BASH_REMATCH[1]}"
530
write_error_eval "$(_ 'Cannot interpret XMODIFIERS: ${1}.')" \
533
if [ "${xim_name}" = "ibus" ]; then
538
write_eval "$(_ 'Xim Server Name from Environment variable is ${1}.')" \
540
write_order_list "$(_ 'XIM_SERVERS on root window:')"
541
local atom_name=XIM_SERVERS
542
if ! type xprop &> /dev/null; then
543
write_error "$(print_not_found 'xprop')"
545
xprop=$(xprop -root -notype -f "${atom_name}" \
546
'32a' ' $0\n' "${atom_name}" 2> /dev/null)
547
if [[ ${xprop} =~ ^${atom_name}\ @server=(.*)$ ]]; then
548
xim_server_name="${BASH_REMATCH[1]}"
549
if [ "${xim_server_name}" = "${xim_name}" ]; then
550
write_paragraph "$(_ "Xim server name is the same with that set in the environment variable.")"
552
write_error_eval "$(_ 'Xim server name: "${1}" is different from that set in the environment variable: "${2}".')" \
553
"${xim_server_name}" "${xim_name}"
556
write_error "$(_ "Cannot find xim_server on root window.")"
561
_check_toolkit_env() {
564
write_order_list "$(code_inline '${'"${env_name}"'}'):"
565
if [ -z "${!env_name}" ]; then
566
set_env_link "${env_name}" 'fcitx'
567
elif [ "${!env_name}" = 'fcitx' ]; then
568
_env_correct "${env_name}" 'fcitx'
570
_env_incorrect "${env_name}" 'fcitx' "${!env_name}"
572
if [ "${!env_name}" = 'xim' ]; then
573
write_error_eval "$(_ 'You are using xim in ${1} programs.')" \
578
"$(_ 'You may have trouble using fcitx in ${1} programs.')" \
580
if [ "${!env_name}" = "ibus" ] && [ "${name}" = 'qt' ]; then
585
set_env_link "${env_name}" 'fcitx'
591
_check_toolkit_env QT_IM_MODULE qt
593
write_order_list "$(_ 'Qt IM module files:')"
595
for path in "${ldpaths[@]}"; do
596
# the {/*,} here is for lib/$ARCH/ when output of ldconfig
597
# failed to include it
598
for file in "${path}"{/*,}/qt{,4}/**/*fcitx*.so; do
599
if [[ ${file} =~ (im-fcitx|inputmethods) ]]; then
601
add_and_check_file qt "${file}" && {
602
write_eval "$(_ 'Found fcitx qt im module: ${1}.')" \
603
"$(code_inline "${file}")"
608
add_and_check_file qt "${file}" && {
610
"$(_ 'Found unknown fcitx qt module: ${1}.')" \
611
"$(code_inline "${file}")"
616
if [ -z "${qtimmodule_found}" ]; then
618
write_error "$(_ "Cannot find fcitx input method module for qt.")"
622
check_gtk_immodule() {
626
local _query_immodule=($(find_in_path "gtk-query-immodules-${version}*"))
629
write_order_list "gtk ${version}:"
630
[ ${#_query_immodule[@]} = 0 ] && {
632
"$(_ "Cannot find gtk-query-immodules for gtk ${1}")" \
637
for f in "${_query_immodule[@]}"; do
638
add_and_check_file "gtk_immodule_${version}" "${f}" && {
640
"$(_ 'Found gtk-query-immodules for gtk ${1} at ${2}.')" \
641
"${version}" "$(code_inline "${f}")"
642
if fcitx_gtk=$("$f" | grep fcitx); then
645
write_eval "$(_ 'Found fcitx im modules for gtk ${1}.')" \
647
write_quote_str "${fcitx_gtk}"
651
((module_found)) || {
653
"$(_ 'Cannot find fcitx im module for gtk ${1}.')" \
658
check_gtk_immodule_cache() {
663
write_order_list "gtk ${version}:"
664
for path in /etc "${ldpaths[@]}"; do
665
# the {/*,} here is for lib/$ARCH/ when output of ldconfig
666
# failed to include it
667
for file in "${path}"{/*,}/gtk{-${version}{.0,},}{/**,}/*immodules*; do
668
[ -f "${file}" ] || continue
669
add_and_check_file "gtk_immodule_cache_${version}" "${file}" || {
672
write_eval "$(_ 'Found immodules cache for gtk ${1} ${2}.')" \
673
"${version}" "$(code_inline "${file}")"
674
if fcitx_gtk=$(grep fcitx "${file}"); then
677
write_eval "$(_ 'Found fcitx in cache file ${1}:')" \
678
"$(code_inline "${file}")"
679
write_quote_str "${fcitx_gtk}"
685
"$(_ 'Cannot find fcitx im module for gtk ${1} in cache.')" \
692
_check_toolkit_env GTK_IM_MODULE gtk
693
write_order_list "$(_ 'Gtk IM module files:')"
697
increase_cur_level -1
698
write_order_list "$(_ 'Gtk IM module cache:')"
700
check_gtk_immodule_cache 2
701
check_gtk_immodule_cache 3
702
increase_cur_level -1
706
#############################
708
#############################
712
write_title 2 "$(_ "Fcitx Addons:")"
713
write_order_list "$(_ 'Addon Config Dir:')"
714
addon_conf_dir="$(get_config_dir addonconfigdir addon)" || {
715
write_error "$(_ "Cannot find fcitx addon config directory.")"
718
local enabled_addon=()
719
local disabled_addon=()
722
write_eval "$(_ 'Found fcitx addon config directory: ${1}.')" \
723
"$(code_inline "${addon_conf_dir}")"
724
write_order_list "$(_ 'Addon List:')"
725
for file in "${addon_conf_dir}"/*.conf; do
726
if ! name=$(get_from_config_file "${file}" Name); then
728
"$(_ 'Invalid addon config file ${1}.')" \
729
"$(code_inline "${file}")"
732
enable=$(get_from_config_file "${file}" Enabled)
733
if [ -f ~/.config/fcitx/addon/${name}.conf ]; then
734
_enable=$(get_from_config_file \
735
~/.config/fcitx/addon/${name}.conf Enabled)
736
[ -z "${_enable}" ] || enable="${_enable}"
738
if [ $(echo "${enable}" | sed -e 's/.*/\L&/g') = false ]; then
739
disabled_addon=("${disabled_addon[@]}" "${name}")
741
enabled_addon=("${enabled_addon[@]}" "${name}")
745
write_order_list_eval "$(_ 'Found ${1} enabled addons:')" \
746
"${#enabled_addon[@]}"
747
[ "${#enabled_addon[@]}" = 0 ] || {
748
write_quote_cmd print_array "${enabled_addon[@]}"
750
write_order_list_eval "$(_ 'Found ${1} disabled addons:')" \
751
"${#disabled_addon[@]}"
752
[ "${#disabled_addon[@]}" = 0 ] || {
753
write_quote_cmd print_array "${disabled_addon[@]}"
755
increase_cur_level -1
758
check_input_methods() {
759
write_title 2 "$(_ "Input Methods:")"
761
local imlist=($(get_from_config_file \
762
~/.config/fcitx/profile EnabledIMList)) || {
763
write_error "$(_ "Cannot read im list from fcitx profile.")"
771
for im in "${imlist[@]}"; do
772
[[ $im =~ ^([^:]+):(True|False)$ ]] || {
773
write_error_eval "$(_ 'Invalid item ${1} in im list.')" \
777
name="${BASH_REMATCH[1]}"
778
if [ "${BASH_REMATCH[2]}" = True ]; then
779
enabled_im=("${enabled_im[@]}" "${name}")
781
disabled_im=("${disabled_im[@]}" "${name}")
784
write_order_list_eval "$(_ 'Found ${1} enabled input methods:')" \
786
[ "${#enabled_im[@]}" = 0 ] || {
787
write_quote_cmd print_array "${enabled_im[@]}"
789
write_order_list "$(_ 'Default input methods:')"
790
case "${#enabled_im[@]}" in
792
write_error "$(_ "You don't have any input methods enabled.")"
795
write_error "$(_ "You only have one input method enabled, please add a keyboard input method as the first one and your main input method as the second one.")"
798
if [[ ${enabled_im[0]} =~ ^fcitx-keyboard- ]]; then
800
"$(_ 'You have a keyboard input method "${1}" correctly added as your default input method.')" \
804
"$(_ 'Your first (default) input method is ${1} instead of a keyboard input method. You may have trouble deactivate fcitx.')" \
812
#############################
814
#############################
817
write_order_list "$(code_inline 'date')."
818
if type date &> /dev/null; then
821
write_error "$(print_not_found 'date')"
823
write_order_list "$(code_inline '~/.config/fcitx/log/')."
824
[ -d ~/.config/fcitx/log/ ] || {
825
write_paragraph "$(print_not_found '~/.config/fcitx/log/')"
828
write_quote_cmd ls -AlF ~/.config/fcitx/log/
829
write_order_list "$(code_inline '~/.config/fcitx/log/crash.log')."
830
if [ -f ~/.config/fcitx/log/crash.log ]; then
831
write_quote_cmd cat ~/.config/fcitx/log/crash.log
833
write_paragraph "$(print_not_found '~/.config/fcitx/log/crash.log')"
838
#############################
840
#############################
845
[ -z "$1" ] || exec > "$1"
848
#############################
850
#############################
855
#############################
857
#############################
863
((_check_frontend)) && {
864
write_title 1 "$(_ "Frontends setup.")"
870
((_check_modules)) && {
871
write_title 1 "$(_ "Configuration.")"
877
write_title 1 "$(_ "Log.")"