OSDN Git Service

[fix] : Fixed command check
[alterlinux/dmc.git] / dmc
diff --git a/dmc b/dmc
index 32b5513..6e5872c 100755 (executable)
--- a/dmc
+++ b/dmc
@@ -2,11 +2,15 @@
 #
 # Yamada Hayao
 # Twitter: @Hayao0819
+# GitHub : @Hayao0819
 # Email  : hayao@fascode.net
 #
 # (c) 2019-2021 Fascode Network.
 #
-# dmc
+# dmc - display manager config tool
+#
+# Tool to change display manager settings
+# It supports various display managers.
 #
 # LICENSE: THE SUSHI-WARE LICENSE
 # https://github.com/MakeNowJust/sushi-ware
 # https://qiita.com/laikuaut/items/4bc07eabce56ee30812d
 # https://qiita.com/t_nakayama0714/items/80b4c94de43643f4be51
 
+SCRIPT_PATH="$( cd -P "$( dirname "$(readlink -f "${0}")" )" && pwd )"
+
 script_usage(){
     echo "usage: dmc [options] [command]"
     echo
-    echo "A simple tool for switching LightDM Greeters"
+    echo "Tool to change display manager settings"
+    echo
+    echo " Example:"
+    echo "    dmc lightdm greeter-list"
+    echo "    dmc gdm root-login true"
+    echo
+    echo " General command:"
+    echo "    dm [display manager]              Set display manager"
+    echo "    [mode] [command]                  You can specify the mode as a command"
+    echo "    gtk-list                          Show a list of GTK theme"
+    echo "    help                              Show this help document"
     echo
     echo " LightDM command:"
     echo "    autologin [username] [session]    Set up automatic login (with blank username to disable)"
@@ -35,32 +51,79 @@ script_usage(){
     echo " GDM command:"
     echo "    autologin [username] [session]    Set up automatic login (with blank username to disable)"
     echo "    cursor                            Run cursor selection wizard"
-    #echo "    cursor-change [cursor]            Specify the cursor theme"
+    echo "    cursor-change [cursor]            Specify the cursor theme"
     echo "    cursor-list                       Show a list of cursor theme"
+    echo "    edit                              Edit config file"
     echo "    sound [true or false]             Toggle the sound when an event occurs"
     echo "    logo [image]                      Specify the logo of the login screen"
     echo "    tap [true or false]               Toggle whether to recognize the tap as a click"
     echo "    accessibility [true or false]     Toggle whether to show accessibility menu"
     echo "    root-login [true or false]        Toggle whether to enable root login"
+    echo "    remove                            Removes all settings"
     echo
-    echo " Webkit2 command:"
+    echo " GTKG command: (lightdm-gtk-greeter)"
+    echo "    gtk                               Run gtk theme selection wizard"
+    echo "    gtk-change [theme]                Specify gtk theme"
+    echo "    icon                              Run icon theme selection wizard"
+    echo "    icon-change [icon]                Specify the icon theme"
+    echo
+    echo " Webkit2 command: (lightdm-webkit2-greeter)"
     echo "    theme                             Run theme selection wizard"
     echo "    theme-change [theme]              Specify the theme"
+    echo "    remove                            Removes all settings"
+    echo "    debug [true or false]             Toggle debug mode"
     echo
-    echo " Qtquick command:"
+    echo " Qtquick command: (lightdm-qtquick-greeter)"
     echo "    back                              Specify the background image"
+    echo "    remove                            Removes all settings"
+    echo
+    echo " Slick command: (lightdm-slick-greeter)"
+    echo "    back [image]                      Specify the background image"
+    echo "    grid [true or false]              Toggle whether to show grid"
+    echo "    icon                              Run icon theme selection wizard"
+    echo "    icon-change [icon]                Specify the icon theme"
+    echo "    gtk                               Run gtk theme selection wizard"
+    echo "    gtk-change [theme]                Specify gtk theme"
+    echo
+    echo " SDDM command:"
+    echo "    autologin [username] [session]    Set up automatic login (with blank username to disable)"
+    echo "    cursor                            Run cursor selection wizard"
+    echo "    cursor-change [cursor]            Specify the cursor theme"
+    echo "    numlock [true or false]           Toggle whether to enable Numlock force"
+    echo "    tty [int number]                  The lowest virtual terminal number that will be used"
+    echo "    theme                             Run theme selection wizard"
+    echo "    theme-change [theme]              Specify the theme"
+    echo
+    echo " LXDM command:"
+    echo "    autologin [username] [session]    Set up automatic login (with blank username to disable)"
+    echo "    back [image]                      Specify the background image"
+    echo "    session                           Run default session selection wizard"
+    echo "    session-change [session]          Specify the default session"
+    echo "    remove-last                       Remove last selected setting"
+    echo "    edit-script                       Edit the script"
+    echo "    gtk                               Run gtk theme selection wizard"
+    echo "    gtk-change [theme]                Specify gtk theme"
     echo
     echo " General option:"
-    echo "    -m | --mode                       Specifiy the target you want to set"
-    echo "    -e | --editer                     Specifiy the editor to use for editing"
+    echo "    -G | --lightdm-greeter            Automatically get the current greeter and set as mode (Only LightDM)"
+    echo "    -m | --mode [mode name]           Specifiy the target you want to set"
+    echo "    -e | --editer [editor path]       Specifiy the editor to use for editing"
     echo "    -h | --help                       This help message and exit"
     echo "    --non-interactive                 Run in non-interactive mode"
+    echo "    --no-check-target                 No check the target for the selected mode"
     echo "    --noroot                          No check root permission"
     echo "    --write-all-files                 Allows rewriting of all configuration files"
+    echo "    --remove                          Remove the file instead of renaming it with the remove command"
     echo
     echo " Supported modes:"
-    echo "    Display managers: lightdm, gdm"
-    echo "    LightDM greeters: webkit2, qtquick"
+    echo "    Display managers: lightdm, gdm, sddm, lxdm"
+    echo "    LightDM greeters: webkit2, qtquick, slick, gtkg"
+    echo
+    echo " Default mode: ${MODE}"
+    echo
+    echo " This tool is incomplete and still under development."
+    echo " If you find a bug, please report it on GitHub."
+    echo " https://github.com/FascodeNet/dmc"
     echo
 }
 
@@ -86,13 +149,9 @@ check_root(){
 
 # 数値チェック
 check_int(){
-    set +e
-    #if (( "$(expr "${1}" + 1 >/dev/null 2>&1; printf "${?}")" < 2 )); then
     if printf "%s" "${1}" | grep -E "^[0-9]+$" 1>/dev/null 2>&1; then
-        set -e
         return 0
     else
-        set -e
         return 1
     fi
 }
@@ -105,26 +164,35 @@ check_bool(){
     fi
 }
 
-# crudini ラッパー
-wrapper(){
-    local _command="${1}"
-    shift 1
-    if which "${_command}" >/dev/null 2>&1; then
-        $(which "${_command}") "${@}"
-    else
-        msg_error "${_command} was not found"
-        exit 1
-    fi
+# インストールされていないコマンドを確認
+check_tools(){
+    local _command
+    for _command in "${@}"; do
+        if ! which "${_command}" >/dev/null 2>&1; then
+            msg_error "${_command} was not found"
+            exit 1
+        fi
+    done
 }
 
-crudini(){
-    wrapper crudini "${@}"
-}
 
-jq(){
-    wrapper jq "${@}"
+# 指定されたコマンドが現在のモードで実行可能かどうかを判定する
+check_command_dm(){
+    if ! printf "%s\n" "${@}" | grep -xE "${MODE}" >/dev/null 2>&1; then
+        msg_error "This command (${COMMAND}) is not available in the current mode (${MODE})."
+        exit 1
+    fi
 }
 
+# 現在のモードのメインバイナリが存在しているかどうか確認する
+check_main_binary(){
+    if [[ -z "${MAIN_BINARY["${MODE}"]+SET}" ]]; then
+        msg_warn "The main binary for the selected mode is not set."
+    elif [[ ! -f "${MAIN_BINARY["${MODE}"]}" ]]; then
+        msg_error "The target for the selected mode is not installed."
+        exit 1
+    fi
+}
 
 # カーソルテーマの一覧を取得
 get_cursor_theme(){
@@ -135,20 +203,350 @@ get_cursor_theme(){
     local _dir _cursor_theme_dir_list _find_cursor_dir_list=("/usr/share/icons" "${HOME}/.local/share/icons" "${HOME}/.icons")
     for _dir in "${_find_cursor_dir_list[@]}"; do
         if [[ -d "${_dir}" ]]; then
-            _cursor_theme_dir_list=($(find "${_dir}" -type d -name "cursors" | xargs -i dirname {} | sort))
+            while read -r line; do
+                _cursor_theme_dir_list+=("${line}")
+            done < <(find "${_dir}" -type d -name "cursors" -print0 | xargs -0 -I{} dirname {} | sort)
         fi
     done
+    unset _dir _find_cursor_dir_list
     
-    local _cursor_theme _cursor_theme_name _temp
+    local _cursor_theme _cursor_theme_name _name
     for _cursor_theme in "${_cursor_theme_dir_list[@]}"; do
-        _temp+=("$(grep -E "^Name=" "${_cursor_theme}/cursor.theme" 2> /dev/null | sed "s|^Name=||g")")
-        if [[ -z "${_temp}" ]]; then
-            _cursor_theme_name+=("$(basename "${_cursor_theme}")")
+        _name="$(grep -E "^Name=" "${_cursor_theme}/cursor.theme" 2> /dev/null | sed "s|^Name=||g")"
+        if [[ -z "${_name}" ]]; then
+            _name="$(basename "${_cursor_theme}")"
+        fi
+        _cursor_theme_name+=("${_name}")
+    done
+    printf "%s\n" "${_cursor_theme_name[@]}"
+}
+
+# GTKテーマの一覧を取得
+get_gtk_theme(){
+    echo "Loading GTK themes..." >&2
+    local _dir _find_theme_dir_list=("/usr/share/themes" "${HOME}/.local/share/themes" "${HOME}/.themes")
+    for _dir in "${_find_theme_dir_list[@]}"; do
+        if [[ -d "${_dir}" ]]; then
+            while read -r line; do
+                _gtk_theme_dir_list+=("${line}")
+            done < <(find "${_dir}" -type d -name "gtk-*" -print0 | xargs -0 -I{} dirname {} | tr " " "\n" | sort | uniq)
+        fi
+    done
+
+    local _theme_name
+    for _dir in "${_gtk_theme_dir_list[@]}"; do
+        _theme_name="$(crudini --get "${_dir}/index.theme" 'Desktop Entry' "Name" 2> /dev/null ;:)"
+        if [[ -z "${_theme_name}" ]]; then
+            continue
+        else
+            _gtk_theme_name_list+=("${_theme_name}")
+        fi
+    done
+    
+    printf "%s\n" "${_gtk_theme_name_list[@]}" | sort | uniq
+}
+
+get_icon_theme(){
+    echo "Loading icons..." >&2
+    local _dir _find_theme_dir_list=("/usr/share/icons" "${HOME}/.local/share/icons" "${HOME}/.icons")
+    for _dir in "${_find_theme_dir_list[@]}"; do
+        if [[ -d "${_dir}" ]]; then
+            while read -r line; do
+                _icon_theme_dir_list+=("${line}")
+            done < <(find "${_dir}" -type f -name "index.theme" -print0 | xargs -0 -I{} dirname {} | tr " " "\n" | sort | uniq)
+        fi
+    done
+
+    local _theme_name
+    for _dir in "${_icon_theme_dir_list[@]}"; do
+        _theme_name="$(crudini --get "${_dir}/index.theme" 'Icon Theme' "Name" 2> /dev/null ;:)"
+        if [[ -z "${_theme_name}" ]]; then
+            continue
+        else
+            _gtk_theme_name_list+=("${_theme_name}")
+        fi
+    done
+    
+    printf "%s\n" "${_gtk_theme_name_list[@]}" | sort | uniq
+}
+
+get_session(){
+    find "/usr/share/xsessions" "/usr/share/wayland-sessions" -type f -print0 -name "*.desktop" | xargs -0 -I{} bash -c 'basename {} | sed "s|.desktop||g"'
+}
+
+
+# 質問を行う関数
+# Returns only the selected result to standard output
+# ask_question -d <デフォルト値> -p <質問文> <選択肢1> <選択肢2> ...
+ask_question(){
+    local arg OPTARG OPTIND _default="" _choice_list _count _choice _question
+    while getopts "d:p:" arg; do
+        case "${arg}" in
+            d) _default="${OPTARG}" ;;
+            p) _question="${OPTARG}" ;;
+            *) exit 1 ;;
+        esac
+    done
+    shift "$((OPTIND - 1))"
+    _choice_list=("${@}")
+    _digit="${##}"
+
+    # 選択肢に関するエラー
+    if (( ${#_choice_list[@]} < 0 )); then
+        msg_error "An exception error has occurred."
+        exit 1
+    fi
+
+    # 選択肢が1つしか無いならばそのまま値を返す
+    if (( ${#_choice_list[@]} <= 1 )); then
+        echo "${_choice_list[*]}"
+        return 0
+    fi
+
+    if [[ -v _question ]] && [[ ! "${_question}" = "" ]]; then
+        echo -e "${_question}" >&2
+    fi
+
+    for (( _count=1; _count<=${#_choice_list[@]}; _count++)); do
+        _choice="${_choice_list[$(( _count - 1 ))]}"
+        if [[ ! "${_default}" = "" ]] && [[ "${_choice}" = "${_default}" ]]; then
+            printf " * %${_digit}d: ${_choice}\n" "${_count}" >&2
+        else
+            printf "   %${_digit}d: ${_choice}\n" "${_count}" >&2
+        fi
+        unset _choice
+    done
+    echo -n "(1 ~ ${#_choice_list[@]}) > " >&2
+    read -r _input
+
+    # 回答を解析
+    if check_int "${_input}"; then
+        # 数字が入力された
+        if (( 1 <= _input)) && (( _input <= ${#_choice_list[@]} )); then
+            _choice="${_choice_list[$(( _input - 1 ))]}"
+        else
+            return 1
+        fi
+    else
+        # 文字が入力された
+        if printf "%s\n" "${_choice_list[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
+            _choice="${_input}"
+        else
+            return 1
+        fi
+    fi
+    echo "${_choice}"
+    return 0
+}
+
+# デスクトップセッションを聞く
+ask_session(){
+    local _session
+    if (( $(get_session | wc -l) <= 1 )); then
+        _session="$(get_session)"
+    elif [[ "${NON_INTERACTIVE}" = true ]]; then
+        # 非対話モード
+        # ~/.dmrcの値を設定します
+        _session="$(grep -E '^Session=' "${HOME}/.dmrc" 2> /dev/null | cut -d '=' -f 2)"
+        if [[ -z "${autologin_session}" ]]; then
+            msg_error "Failed to set the session."
+            msg_error "Not specified and ~/.dmrc does not exist either."
+            exit 1
+        fi
+    else
+        readarray -t _session_list < <(get_session)
+        if ! _session="$(ask_question -p "Select the desktop session to autologin" "${_session_list[@]}")"; then
+            msg_error "Please enter the correct session name."
+            exit 1
+        fi
+    fi
+    echo "${_session}"
+}
+
+# GTKテーマを聞く
+ask_gtk_theme(){
+    local gtk_themes _theme
+    readarray -t gtk_themes < <(get_gtk_theme)
+
+    # 質問する
+    if ! _theme="$(ask_question -p "Please select the theme to use" "${gtk_themes[@]}")"; then
+        msg_error "Please select the correct theme"
+        exit 1
+    fi
+    echo "${_theme}"
+}
+
+# セッションが利用可能かどうか確認する
+# check_session <session>
+check_session(){
+    for _file in "/usr/share/wayland-sessions/${1}.desktop" "/usr/share/xsessions/${1}.desktop"; do
+        if [[ -f "${_file}" ]]; then
+            return 0
+        fi
+    done
+    # 存在しないセッションが指定された場合
+    msg_error "This is a session (${1}) that does not exist."
+    return 1
+}
+
+# セッションのフルパスを返す
+get_session_path(){
+    check_session "${1}"
+    for _file in "/usr/share/wayland-sessions/${1}.desktop" "/usr/share/xsessions/${1}.desktop"; do
+        if [[ -f "${_file}" ]]; then
+            echo "${_file}"
+            return 0
+        fi
+    done
+}
+
+# セッションのバイナリを取得する
+# get_session <session name>
+get_session_exec(){
+    check_session "${1}"
+    local session_exec="$(crudini --get "$(get_session_path "${1}")" "Desktop Entry" "Exec")"
+    if [[ ! -f "${session_exec}" ]]; then
+        session_exec="$(type -p "${session_exec}")"
+    fi
+    echo -n "${session_exec}"
+    return 0
+}
+
+# ユーザーをグループに追加する
+# add_user_to_group <user> <group>
+add_user_to_group(){
+    if ! getent passwd "${1}" 1> /dev/null 2>&1; then
+        echo "${1} is a non-existent user."
+        exit 1
+    fi
+
+    if ! getent group "${2}" 1> /dev/null 2>&1; then
+        LANG=C groupadd -r "${2}"
+    fi
+    LANG=C gpasswd -a "${1}" "${2}"
+}
+
+# MIMEファイルタイプを返す
+# get_filetype <file>
+get_filetype(){
+    file -inb "${1}" | cut -d ";" -f 1
+}
+
+# MIMEファイルタイプを判別する
+# 
+# check_filetype <ファイルタイプ> <ファイルパス>
+check_filetype(){
+    local _type="${1}" _path="${2}"
+
+    # ファイルタイプに/が含まれているかどうか
+    if echo "${_type}" | grep -E "^.+/.+$" >/dev/null 2<&1; then
+        # 含まれていたらファイルタイプを完全一致で判定する\
+        if [[ "${_type}" = "$(get_filetype "${_path}")" ]]; then
+            return 0
+        fi
+    else
+        # 含まれていなかったらファイルタイプをメインタイプのみで判定する
+        if [[ "${_type}" = "$(get_filetype "${_path}" | cut -d "/" -f 1 )" ]]; then
+            return 0
+        fi
+    fi
+    # 正常終了しなかったので異常終了
+    return 1
+}
+
+# systemdのunitが存在しているか確認
+check_systemd_unit(){
+    if [[ ! -v 1 ]]; then
+        return 1
+    elif systemctl cat "${1}" 1> /dev/null 2>&1; then
+        return 0
+    fi
+    return 1
+}
+
+# removeコマンドの共通処理
+# 引数に削除したいファイルへのパス
+common_remove_command(){
+    local _file _yes_or_no
+    for _file in "${@}"; do
+        if [[ -f "${_file}" ]]; then
+            if [[ "${NON_INTERACTIVE}" = true ]]; then
+                _yes_or_no="y"
+            else
+                echo -e "Remove ${_file} ? It is irreversible"
+                echo -ne "(y or n) > "
+                read -r -n 1 _yes_or_no
+                echo
+            fi
+            if [[ "${_yes_or_no}" = "y" ]]; then
+                if [[ "${REMOVE_FILES}" = true ]]; then
+                    echo "Removed ${_file}"
+                    rm -rf "${_file}"
+                else
+                    echo "Moved ${_file} ${_file}.disabled"
+                    mv "${_file}" "${_file}.disabled"
+                fi
+            fi
+        else
+            continue
         fi
     done
-    echo "${_cursor_theme_name[@]}"
 }
 
+#== すべてのモード用コマンド ==#
+command_general_dm(){
+    if [[ -z "${1}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify display manager"
+        exit 1
+    fi
+
+    # 現在のディスプレイマネージャを無効化
+    if [[ -n "${CURRENT_DM+SET}" ]]; then
+        systemctl disable "${CURRENT_DM}.service"
+    fi
+
+    # 指定されたディスプレイマネージャを有効化
+    if check_systemd_unit "${1}"; then
+        systemctl enable "${1}.service"
+    else
+        msg_error "Wrong display manager name"
+    fi
+}
+
+# モードをコマンドとして扱い自身を再実行する
+# command_mode <mode> <command> <args>
+command_mode(){
+    if [[ -z "${2+SET}" ]] || [[ "${2}" = "" ]]; then
+        msg_error "Please specify command"
+        exit 1
+    fi
+
+    local _mode="${1}" _command="${2}"
+    local _dmc_args=("-e" "${USE_EDITOR}" "-m" "${_mode}")
+    shift 2
+
+    # 基本的な変数を設定
+    local _command_args=("${@}")
+
+    # オプション設定
+    if [[ "${NON_INTERACTIVE}" = true ]]; then
+        _dmc_args+=("--non-interactive")
+    fi
+    if [[ "${NOROOT}" = true ]]; then
+        _dmc_args+=("--noroot")
+    fi
+    if [[ "${NO_CHECK_TARGET}" = true ]]; then
+        _dmc_args+=("--no-check-target")
+    fi
+    if [[ "${WRITE_ALL_FILES}" = true ]]; then
+        _dmc_args+=("--write-all-files")
+    fi
+
+    bash "${SCRIPT_PATH}/$(basename "${0}")" "${_dmc_args[@]}" "${_command}" "${_command_args[@]}"
+}
+
+
+
 #== LightDM用の汎用関数 ==#
 # キーが設定されている設定ファイル
 lightdm_get_source_file(){
@@ -165,7 +563,7 @@ lightdm_get_source_file(){
 
 # 設定ファイルの値を変更する
 lightdm_set_config(){
-    local key="${1}" value="${2}" file=${3-${LIGHTDM_CONFIG}}
+    local key="${1}" value="${2}" file=${3-${MODE_CONFIG["lightdm"]}}
     if [[ "${WRITE_ALL_FILES}" = true ]] && [[ -n "$(lightdm_get_source_file "${1}")" ]]; then
         crudini --set "$(lightdm_get_source_file "${1}")" 'Seat:*' "${key}" "${value}"
     else
@@ -181,19 +579,19 @@ lightdm_set_config(){
 # 設定ファイルのキーを削除する
 lightdm_remove_key(){
     local key="${1}" _config
-    if grep -E "^ ?${key}.+" "${LIGHTDM_CONFIG}" 1>/dev/null 2>&1; then
-        sed -i -r "s|^ ?${key} ?=.+||g" "${LIGHTDM_CONFIG}"
-        sed -i '/^$/d' "${LIGHTDM_CONFIG}"
+    if grep -E "^ ?${key}.+" "${MODE_CONFIG["lightdm"]}" 1>/dev/null 2>&1; then
+        sed -i -r "s|^ ?${key} ?=.+||g" "${MODE_CONFIG["lightdm"]}"
+        sed -i '/^$/d' "${MODE_CONFIG["lightdm"]}"
     fi
 }
 
 # 設定ファイルを作成
 lightdm_init_configs(){
     check_root
-    if [[ ! -f "${LIGHTDM_CONFIG}" ]]; then
-        mkdir -p "$(dirname "${LIGHTDM_CONFIG}")"
-        touch "${LIGHTDM_CONFIG}"
-        echo "[Seat:*]" > "${LIGHTDM_CONFIG}"
+    if [[ ! -f "${MODE_CONFIG["lightdm"]}" ]]; then
+        mkdir -p "$(dirname "${MODE_CONFIG["lightdm"]}")"
+        touch "${MODE_CONFIG["lightdm"]}"
+        echo "[Seat:*]" > "${MODE_CONFIG["lightdm"]}"
     fi
 }
 
@@ -209,18 +607,23 @@ lightdm_get_value(){
     fi
 }
 
+lightdm_greeter_list(){
+    local greeter_list
+    readarray -t greeter_list < <( (find "${LIGHTDM_GREETERS_DIR}" -print0 -type f | xargs -0 -I{} basename {} | grep -E ".desktop$" | sed "s|.desktop$||g" | grep -xv "xgreeters") 2> /dev/null )
+    printf "%s\n" "${greeter_list[@]}" | sort | uniq
+}
+
 #== LightDM用コマンド ==#
 # greeter-changeコマンド
 command_lightdm_greeter_change() {
     # 引数チェック
     if [[ -z "${1}" ]] || [[ "${1}" = "" ]]; then
         msg_error "Please specify Greeter."
-        script_usage
         exit 1
     fi
 
     # 指定されたGreeterが正しいか確認
-    if ! printf "%s\n" "${LIGHTDM_GREETERS[@]}" | grep -x "${1}" > /dev/null 2>&2; then
+    if ! lightdm_greeter_list | grep -x "${1}" > /dev/null 2>&2; then
         msg_error "The greeter (${1}) doesn't exist."
         exit 1
     else
@@ -232,17 +635,14 @@ command_lightdm_greeter_change() {
 command_lightdm_greeter_create(){
     if [[ -z "${1}" ]] || [[ "${1}" = "" ]]; then
         msg_error "Please specify Greeter."
-        script_usage
         exit 1
     fi
     if [[ ! -f "${1}" ]]; then
         msg_error "${1} does not exist."
-        script_usage
         exit 1
     fi
     if [[ ! -x "${1}" ]]; then
         msg_error "hoge is not an executable file."
-        script_usage
         exit 1
     fi
 
@@ -266,7 +666,7 @@ EOF
 command_lightdm_greeter_list() {
     echo "Available Lightdm greeter list:"
     local _greeter
-    for _greeter in "${LIGHTDM_GREETERS[@]}"; do
+    for _greeter in $(lightdm_greeter_list); do
         if [[ "${_greeter}" = "${LIGHTDM_CURRENT_GREETER}" ]]; then
             echo " * ${_greeter}"
         else
@@ -276,74 +676,37 @@ command_lightdm_greeter_list() {
 }
 
 # greeterコマンド
-run_greeter_wizard(){
+command_lightdm_greeter_wizard(){
     # グリーターの数を確認
-    if (( ${#LIGHTDM_GREETERS[@]} < 1 )); then
+    if (( $(lightdm_greeter_list | wc -l) < 1 )); then
         msg_error "LightDM Greeter was not found."
         exit 1
     fi
 
     # 質問する
-    local _c _greeter
-    echo "Please select the greeter to use."
-    for (( _c=1; _c<=${#LIGHTDM_GREETERS[@]}; _c++)); do
-        _greeter="${LIGHTDM_GREETERS[$(( _c - 1 ))]}"
-        if [[ "${_greeter}" = "${LIGHTDM_CURRENT_GREETER}" ]]; then
-            echo " * ${_c}: ${_greeter}"
-        else
-            echo "   ${_c}: ${_greeter}"
-        fi
-        unset _greeter
-    done
-    echo -n "(1 ~ ${#LIGHTDM_GREETERS[@]}) > "
-    read -r _input
-
-    local _recall
-    _recall(){
-        echo "Please enter the correct value."
-        run_greeter_wizard
+    local _greeter
+    # shellcheck disable=SC2046
+    if ! _greeter="$(ask_question -p "Please select the greeter to use." -d "${LIGHTDM_CURRENT_GREETER}" $(lightdm_greeter_list))"; then
+        command_lightdm_greeter_wizard
         exit 0
-    }
-
-    # 回答を解析
-    if check_int "${_input}"; then
-        # 数字が入力された
-        if (( 1 <= _input)) && (( _input <= ${#LIGHTDM_GREETERS[@]} )); then
-            _greeter="${LIGHTDM_GREETERS[$(( _input - 1 ))]}"
-        else
-            _recall
-        fi
-    else
-        # 文字が入力された
-        if printf "%s\n" "${LIGHTDM_GREETERS[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
-            _greeter="${_input}"
-        else
-            _recall
-        fi
     fi
 
     # 結果に応じて処理を実行
     if [[ -n "${_greeter}" ]]; then
         command_lightdm_greeter_change "${_greeter}"
     else
-        run_greeter_wizard
+        command_lightdm_greeter_wizard
         exit 0
     fi
-    echo "Changed greeter to ${_greeter}"
+
+    if [[ ! "${LIGHTDM_CURRENT_GREETER}" = "${_greeter}" ]]; then
+        echo "Changed greeter to ${_greeter}"
+    fi
 }
 
 # removeコマンド
 command_lightdm_remove(){
-    if [[ ! -f "${LIGHTDM_CONFIG}" ]]; then
-        return 0
-    else
-        local _yes_or_no
-        echo -ne "Are you sure you want to delete all settings?\nThis change is irreversible.\n (y or n) > "
-        read -r -n 1 _yes_or_no
-        if [[ "${_yes_or_no}" = "y" ]]; then
-            mv "${LIGHTDM_CONFIG}" "${LIGHTDM_CONFIG}.disabled"
-        fi
-    fi
+    common_remove_command "${MODE_CONFIG["lightdm"]}"
 }
 
 # greeter-edit
@@ -353,7 +716,7 @@ command_lightdm_greeter_edit(){
         exit 1
     fi
     local _greeter="${1:-${LIGHTDM_CURRENT_GREETER}}"
-    if [[ -z "${GREETER_CONFIG["${_greeter}"]+SET}" ]]; then
+    if [[ -z "${MODE_CONFIG[${GREETER_MODE["${_greeter}"]}]+SET}" ]]; then
         msg_error "This Greeter is not currently supported."
         msg_error "Please report the problem here."
         msg_error "https://github.com/FascodeNet/lightdm-config/issues"
@@ -365,7 +728,7 @@ command_lightdm_greeter_edit(){
             read -r
         fi
         set -u
-        bash -c "${USE_EDITOR} ${GREETER_CONFIG["${_greeter}"]}"
+        bash -c "${USE_EDITOR} ${MODE_CONFIG[${GREETER_MODE["${_greeter}"]}]}"
         exit
     fi
 }
@@ -376,7 +739,9 @@ command_lightdm_edit(){
         msg_error "You cannot use this command in non-interactive mode."
         exit 1
     fi
-    for _config in "${LIGHTDM_LOADED_CONFIG[@]}"; do
+    local loaded_config_list
+    readarray -t loaded_config_list < <(printf "%s\n" "$(lightdm --show-config 2>&1 | grep -x -A "$(lightdm --show-config 2>&1 | wc -l)" "Sources:" | grep -v "Sources" | sed 's|^[A-Z]  ||g')"  | tr -d " ")
+    for _config in "${loaded_config_list[@]}"; do
         echo -ne "Edit ${_config} ? (y or n)> "
         read -r -n 1 _yes_or_no
         echo
@@ -394,7 +759,7 @@ command_lightdm_auto_login(){
         if [[ -n "${autologin_user}" ]]; then
             # autologinを無効化
             for _autologin in "autologin-guest" "autologin-user" "autologin-user-timeout" "autologin-in-background" "autologin-session"; do
-                remove_key "${_autologin}"
+                lightdm_remove_key "${_autologin}"
             done
             echo "Canceled automatic login of ${autologin_user}"
         fi
@@ -404,54 +769,16 @@ command_lightdm_auto_login(){
             autologin_session="${2}"
         fi
 
-        # ユーザーチェック
-        if ! getent passwd "${autologin_user}" 1> /dev/null 2>&1; then
-            echo "${autologin_user} is a non-existent user."
-            exit 1
-        fi
-
-        # セッションを設定
+        # セッションを設定 (WayLandのセッションは現在サポートされていません)
         if [[ -z "${autologin_session+SET}" ]]; then
-            if (( $(ls "/usr/share/xsessions" 2> /dev/null | wc -l) <= 1 )); then
-                autologin_session="$(ls "/usr/share/xsessions" | sed 's|.desktop$||g')"
-            elif [[ "${NON_INTERACTIVE}" = true ]]; then
-                # 非対話モード
-                # ~/.dmrcの値を設定します
-                autologin_session="$(grep -E '^Session=' "${HOME}/.dmrc" 2> /dev/null | cut -d '=' -f 2)"
-                if [[ -z "${autologin_session}" ]]; then
-                    msg_error "Failed to set the session."
-                    msg_error "Not specified and ~/.dmrc does not exist either."
-                    exit 1
-                fi
-            else
-                echo "Select the desktop session to autologin"
-                local session
-                for session in "/usr/share/xsessions/"*; do
-                    echo "   ${session}"
-                done
-                echo -n "(session name) > "
-                read -r session
-                if [[ -f "/usr/share/xsessions/${session}.desktop" ]]; then
-                    autologin_session="${session}"
-                else
-                    msg_error "Please enter the correct session name."
-                    exit 1
-                fi
-            fi
+            autologin_session="$(ask_session)"
         else
             # 既に値が設定済み
-            if [[ ! -f "/usr/share/xsessions/${autologin_session}.desktop" ]]; then
-                # 存在しないセッションが指定された場合
-                msg_error "This is a session (${autologin_session}) that does not exist."
-                exit 1
-            fi
+            check_session "${autologin_session}"
         fi
 
         # autologin グループを設定
-        if ! getent group "autologin" 1> /dev/null 2>&1; then
-            LANG=C groupadd -r "autologin"
-        fi
-        LANG=C gpasswd -a "${autologin_user}" "autologin"
+        add_user_to_group "${autologin_user}" "autologin"
 
         # 設定を書き込み
         lightdm_set_config "autologin-guest" "false"
@@ -480,7 +807,7 @@ gdm_init_configs(){
     fi
 
     local _file
-    for _file in "${DISPLAY_MANAGER_CONFIG["gdm-dconf"]}" "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}"; do
+    for _file in "${MODE_CONFIG["gdm-dconf"]}" "${MODE_CONFIG["gdm-custom"]}"; do
         if [[ ! -f "${_file}" ]]; then
             mkdir -p "$(dirname "${_file}")"
             touch "${_file}"
@@ -491,29 +818,29 @@ gdm_init_configs(){
 # gdm_dconf_set_config <dconf path> <key> <value>
 gdm_dconf_set_config(){
     if check_int "${3}" || check_bool "${3}"; then
-        crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-dconf"]}" "${1}" "${2}" "${3}"
+        crudini --set "${MODE_CONFIG["gdm-dconf"]}" "${1}" "${2}" "${3}"
     else
-        crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-dconf"]}" "${1}" "${2}" "\"${3}\""
+        crudini --set "${MODE_CONFIG["gdm-dconf"]}" "${1}" "${2}" "\"${3}\""
     fi
     gdm_update
 }
 
 # gdm_dconf_get_value <dconf path> <key>
 gdm_dconf_get_value(){
-    dconf dump / | crudini --get - "${1}" "${2}"
+    find "/etc/dconf/db/gdm.d/" -type f -print0 | xargs -0 -I{} cat {} | crudini --get - "${1}" "${2}" | sed "s|^[\"\']||g" | sed "s|[\"\']$||g"
 }
 
 # gdm_custom_get_value <section> <key>
 gdm_custom_get_value(){
-    crudini --get "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}" "${1}" "${2}"
+    crudini --get "${MODE_CONFIG["gdm-custom"]}" "${1}" "${2}"
 }
 
 # gdm_custom_set_config <section> <key> <value>
 gdm_custom_set_config(){
     if check_int "${3}" || check_bool "${3}"; then
-        crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}" "${1}" "${2}" "${3}"
+        crudini --set "${MODE_CONFIG["gdm-custom"]}" "${1}" "${2}" "${3}"
     else
-        crudini --set "${DISPLAY_MANAGER_CONFIG["gdm-custom"]}" "${1}" "${2}" "\"${3}\""
+        crudini --set "${MODE_CONFIG["gdm-custom"]}" "${1}" "${2}" "\"${3}\""
     fi
     gdm_update
 }
@@ -534,7 +861,7 @@ command_gdm_logo(){
         exit 1
     fi
 
-    local _backgrounf_file="/usr/share/backgrounds/gdm/background"
+    local _backgrounf_file="${BACKGROUND_DIR}/gdm/background"
     mkdir -p "$(dirname "${_backgrounf_file}")"
     cp "${1}" "${_backgrounf_file}"
     chmod 644 "${_backgrounf_file}"
@@ -543,43 +870,14 @@ command_gdm_logo(){
 }
 
 command_gdm_cursor_wizard(){
-    # 一覧を生成
-    local _c
-    unset _cursor_theme
-    echo "Please select the cursor theme to use."
-    for (( _c=1; _c<=${#CURSOR_THEMES[@]}; _c++)); do
-        _cursor_theme="${CURSOR_THEMES[$(( _c - 1 ))]}"
-        echo "   ${_c}: ${_cursor_theme}"
-        unset _cursor_theme
-    done
-
-    # 質問する
-    local _input
-    echo -n "(1 ~ ${#CURSOR_THEMES[@]}) > "
-    read -r _input
+    # カーソル一覧を取得
+    local cursor_themes _current_theme="$(gdm_dconf_get_value "org/gnome/desktop/interface" "cursor-theme")"
+    readarray -t cursor_themes < <(get_cursor_theme)
 
-    local _recall
-    _recall(){
-        echo "Please enter the correct value."
+    # 一覧を生成
+    if ! _cursor_theme="$(ask_question -d "${_current_theme}" -p "Please select the cursor theme to use." "${cursor_themes[@]}")"; then
         command_gdm_cursor_wizard
         exit 0
-    }
-
-    # 回答を解析
-    if check_int "${_input}"; then
-        # 数字が入力された
-        if (( 1 <= _input)) && (( _input <= ${#CURSOR_THEMES[@]} )); then
-            _cursor_theme="${CURSOR_THEMES[$(( _input - 1 ))]}"
-        else
-            _recall
-        fi
-    else
-        # 文字が入力された
-        if printf "%s\n" "${CURSOR_THEMES[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
-            _cursor_theme="${_input}"
-        else
-            _recall
-        fi
     fi
 
     if [[ -n "${_cursor_theme}" ]]; then
@@ -588,7 +886,10 @@ command_gdm_cursor_wizard(){
         command_gdm_cursor_wizard
         exit 0
     fi
-    echo "Changed cursor to ${_cursor_theme}"
+
+    if [[ ! "${_current_theme}" = "${_cursor_theme}" ]]; then
+        echo "Changed cursor to ${_cursor_theme}"
+    fi
 }
 
 command_gdm_cursor_change(){
@@ -596,7 +897,9 @@ command_gdm_cursor_change(){
         msg_error "Please specify the cursor theme"
         exit 1
     fi
-    if ! printf "%s\n" "${CURSOR_THEMES[@]}" | grep -x "${1}" 1>/dev/null 2>&1; then
+    local cursor_themes
+    readarray -t cursor_themes < <(get_cursor_theme)
+    if ! printf "%s\n" "${cursor_themes[@]}" | grep -x "${1}" 1>/dev/null 2>&1; then
         msg_error "The cursor theme (${1}) was not found"
         exit 1
     fi
@@ -604,25 +907,35 @@ command_gdm_cursor_change(){
 }
 
 command_gdm_sound(){
-    local _arg="$(echo "${1-""}" | tr A-Z a-z)"
+    local _arg="$(echo "${1-""}" | tr "[:upper:]" "[:lower:]")"
     if ! check_bool "${_arg}"; then
         msg_error "Please specify true or false"
-        script_usage
         exit 1
     fi
     gdm_dconf_set_config "org/gnome/desktop/sound" "event-sounds" "${_arg}"
 }
 
 command_gdm_tap(){
-    local _arg="$(echo "${1-""}" | tr A-Z a-z)"
+    local _arg="$(echo "${1-""}" | tr "[:upper:]" "[:lower:]")"
     if ! check_bool "${_arg}"; then
         msg_error "Please specify true or false"
-        script_usage
         exit 1
     fi
     gdm_dconf_set_config "org/gnome/desktop/peripherals/touchpad" "tap-to-click" "${_arg}"
 }
 
+command_gdm_edit(){
+    if [[ "${NON_INTERACTIVE}" = true ]]; then
+        msg_error "You cannot use this command in non-interactive mode."
+        exit 1
+    fi
+    bash -c "${USE_EDITOR} ${MODE_CONFIG["gdm-custom"]}"
+}
+
+command_gdm_remove(){
+    common_remove_command "${MODE_CONFIG["gdm-custom"]}"
+}
+
 # autologin
 command_gdm_auto_login(){
     if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
@@ -638,54 +951,16 @@ command_gdm_auto_login(){
             autologin_session="${2}"
         fi
 
-        # ユーザーチェック
-        if ! getent passwd "${autologin_user}" 1> /dev/null 2>&1; then
-            echo "${autologin_user} is a non-existent user."
-            exit 1
-        fi
-
         # セッションを設定 (WayLandのセッションは現在サポートされていません)
         if [[ -z "${autologin_session+SET}" ]]; then
-            if (( $(ls "/usr/share/xsessions" 2> /dev/null | wc -l) <= 1 )); then
-                autologin_session="$(ls "/usr/share/xsessions" | sed 's|.desktop$||g')"
-            elif [[ "${NON_INTERACTIVE}" = true ]]; then
-                # 非対話モード
-                # ~/.dmrcの値を設定します
-                autologin_session="$(grep -E '^Session=' "${HOME}/.dmrc" 2> /dev/null | cut -d '=' -f 2)"
-                if [[ -z "${autologin_session}" ]]; then
-                    msg_error "Failed to set the session."
-                    msg_error "Not specified and ~/.dmrc does not exist either."
-                    exit 1
-                fi
-            else
-                echo "Select the desktop session to autologin"
-                local session
-                for session in "/usr/share/xsessions/"*; do
-                    echo "   $(basename ${session} | sed "s|.desktop$||g")"
-                done
-                echo -n "(session name) > "
-                read -r session
-                if [[ -f "/usr/share/xsessions/${session}.desktop" ]]; then
-                    autologin_session="${session}"
-                else
-                    msg_error "Please enter the correct session name."
-                    exit 1
-                fi
-            fi
+            autologin_session="$(ask_session)"
         else
             # 既に値が設定済み
-            if [[ ! -f "/usr/share/xsessions/${autologin_session}.desktop" ]]; then
-                # 存在しないセッションが指定された場合
-                msg_error "This is a session (${autologin_session}) that does not exist."
-                exit 1
-            fi
+            check_session "${autologin_session}"
         fi
 
         # autologin グループを設定
-        if ! getent group "autologin" 1> /dev/null 2>&1; then
-            LANG=C groupadd -r "autologin"
-        fi
-        LANG=C gpasswd -a "${autologin_user}" "autologin"
+        add_user_to_group "${autologin_user}" "autologin"
 
         # 設定を書き込み
         gdm_custom_set_config "daemon" "AutomaticLoginEnable" "True"
@@ -702,10 +977,9 @@ command_gdm_auto_login(){
 
 # accessibility コマンド
 command_gdm_accessibility(){
-    local _arg="$(echo "${1-""}" | tr A-Z a-z)"
+    local _arg="$(echo "${1-""}" | tr "[:upper:]" "[:lower:]")"
     if ! check_bool "${_arg}"; then
         msg_error "Please specify true or false"
-        script_usage
         exit 1
     fi
     gdm_dconf_set_config "org/gnome/desktop/interface" "toolkit-accessibility" "${_arg}"
@@ -713,10 +987,9 @@ command_gdm_accessibility(){
 
 # root-login コマンド
 command_gdm_root_login(){
-    local _arg="$(echo "${1-""}" | tr A-Z a-z)"
+    local _arg="$(echo "${1-""}" | tr "[:upper:]" "[:lower:]")"
     if ! check_bool "${_arg}"; then
         msg_error "Please specify true or false"
-        script_usage
         exit 1
     fi
     gdm_custom_set_config "daemon" "AllowRoot" "${_arg}"
@@ -725,68 +998,33 @@ command_gdm_root_login(){
 #== Webkit2用の汎用関数 ==#
 webkit2_init_configs(){
     check_root
-    if [[ ! -f "${GREETER_CONFIG["lightdm-webkit2-greeter"]}" ]]; then
-        mkdir -p "$(dirname "${GREETER_CONFIG["lightdm-webkit2-greeter"]}")"
-        touch "${GREETER_CONFIG["lightdm-webkit2-greeter"]}"
+    if [[ ! -f "${MODE_CONFIG["webkit2"]}" ]]; then
+        mkdir -p "$(dirname "${MODE_CONFIG["webkit2"]}")"
+        touch "${MODE_CONFIG["webkit2"]}"
     fi
 }
 
 # webkit2_get_value <section> <key>
 webkit2_get_value(){
-    crudini --get "${GREETER_CONFIG["lightdm-webkit2-greeter"]}" "${1}" "${2}"
+    crudini --get "${MODE_CONFIG["webkit2"]}" "${1}" "${2}"
 }
 
 # webkit2_set_config <section> <key> <value>
 webkit2_set_config(){
-    crudini --set "${GREETER_CONFIG["lightdm-webkit2-greeter"]}" "${1}" "${2}" "${3}"
+    crudini --set "${MODE_CONFIG["webkit2"]}" "${1}" "${2}" "${3}"
 }
 
 #== webkit2用コマンド ==#
 command_webkit2_theme_wizard(){
-    local _theme_list=($(ls /usr/share/lightdm-webkit/themes))
-    local _current_theme=$(webkit2_get_value greeter webkit_theme | sed "s|\"||g")
-    local _theme _c
-    echo "Please select the theme to use."
-    for (( _c=1; _c<=${#_theme_list[@]}; _c++)); do
-        _theme="${_theme_list[$(( _c - 1 ))]}"
-        if [[ "${_theme}" = "${_current_theme}" ]]; then
-            echo " * ${_c}: ${_theme}"
-        else
-            echo "   ${_c}: ${_theme}"
-        fi
-        unset _theme
-    done
-
-    # 質問する
-    local _input
-    echo -n "(1 ~ ${#_theme_list[@]}) > "
-    read -r _input
+    local _theme_list
+    readarray -t _theme_list < <(ls /usr/share/lightdm-webkit/themes)
 
-    # shellcheck disable=SC2034
-    local _recall
-    _recall(){
-        echo "Please enter the correct value."
+    local _current_theme=$(webkit2_get_value greeter webkit_theme | sed "s|\"||g")
+    local _theme
+    if ! _theme="$(ask_question -d "${_current_theme}" -p "Please select the theme to use." "${_theme_list[@]}")"; then
         command_webkit2_theme_wizard
         exit 0
-    }
-
-    # 回答を解析
-    if check_int "${_input}"; then
-        # 数字が入力された
-        if (( 1 <= _input)) && (( _input <= ${#_theme_list[@]} )); then
-            _theme="${_theme_list[$(( _input - 1 ))]}"
-        else
-            _recall
-        fi
-    else
-        # 文字が入力された
-        if printf "%s\n" "${_theme_list[@]}" | grep -x "${_input}" 1>/dev/null 2>&1; then
-            _theme="${_input}"
-        else
-            _recall
-        fi
     fi
-
     if [[ -n "${_theme}" ]]; then
         command_webkit2_theme_change "${_theme}"
         echo "Changed the theme to ${_theme}"
@@ -810,13 +1048,26 @@ command_webkit2_theme_change(){
     webkit2_set_config "greeter" "webkit_theme" "${1}"
 }
 
+command_webkit2_remove(){
+    common_remove_command "${MODE_CONFIG["webkit2"]}"
+}
+
+command_webkit2_debug(){
+    local _arg="$(echo "${1-""}" | tr "[:upper:]" "[:lower:]")"
+    if ! check_bool "${_arg}"; then
+        msg_error "Please specify true or false"
+        exit 1
+    fi
+    webkit2_set_config "greeter" "debug_mode" "${_arg}"
+}
+
 #== Qtquick用の汎用関数 ==#
 qtquick_init_configs(){
     check_root
-    if [[ ! -f "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" ]] || [[ -z "$(cat "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")" ]]; then
-        mkdir -p "$(dirname "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")"
-        touch "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
-        #echo -e "{\n\n}\n" > "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
+    if [[ ! -f "${MODE_CONFIG["qtquick"]}" ]] || [[ -z "$(cat "${MODE_CONFIG["qtquick"]}")" ]]; then
+        mkdir -p "$(dirname "${MODE_CONFIG["qtquick"]}")"
+        touch "${MODE_CONFIG["qtquick"]}"
+        #echo -e "{\n\n}\n" > "${MODE_CONFIG["qtquick"]}"
         qtquick_set_config background_path "file:///hoge/fuga.png"
         qtquick_set_config theme "qrc:/Login.qml"
     fi
@@ -824,16 +1075,20 @@ qtquick_init_configs(){
 
 #qtquick_get_value <key>
 qtquick_get_value(){
-    jq ".${1}" < "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
+    jq ".${1}" < "${MODE_CONFIG["qtquick"]}"
 }
 
 # command_qtquick_back <key> <value>
 qtquick_set_config(){
-    local _tempfile="/tmp/$(basename "${GREETER_CONFIG["lightdm-qtquick-greeter"]}")-$(cat /dev/urandom | base64 | fold -w 10 | head -n 1)"
-    cp "${GREETER_CONFIG["lightdm-qtquick-greeter"]}" "${_tempfile}"
-    #cat "${_tempfile}" | jq -r ".${1}|=\"${2}\"" > "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
-    jq -r ".${1}|=\"${2}\"" < "${_tempfile}" > "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
-    chmod 644 "${GREETER_CONFIG["lightdm-qtquick-greeter"]}"
+    local _tempfile="/tmp/$(basename "${MODE_CONFIG["qtquick"]}")-$(base64 < "/dev/urandom" | fold -w 10 | head -n 1)"
+    cp "${MODE_CONFIG["qtquick"]}" "${_tempfile}"
+    #cat "${_tempfile}" | jq -r ".${1}|=\"${2}\"" > "${MODE_CONFIG["qtquick"]}"
+    jq -r ".${1}|=\"${2}\"" < "${_tempfile}" > "${MODE_CONFIG["qtquick"]}"
+    chmod 644 "${MODE_CONFIG["qtquick"]}"
+}
+
+qtquick_command_remove(){
+    common_remove_command "${MODE_CONFIG["qtquick"]}"
 }
 
 #== Qtquick用コマンド ==#
@@ -847,7 +1102,7 @@ command_qtquick_back(){
         exit 1
     fi
 
-    local _backgrounf_file="/usr/share/backgrounds/lightdm/qtquick-greeter"
+    local _backgrounf_file="${BACKGROUND_DIR}/lightdm/qtquick-greeter"
     mkdir -p "$(dirname "${_backgrounf_file}")"
     cp "${1}" "${_backgrounf_file}"
     chmod 644 "${_backgrounf_file}"
@@ -855,73 +1110,571 @@ command_qtquick_back(){
     qtquick_set_config "background_path" "file://${_backgrounf_file}"
 }
 
+#== slick用の汎用関数 ==#
+slick_get_value(){
+    crudini --get "${MODE_CONFIG["slick"]}" "Greeter" "${1}"
+}
+
+slick_set_config(){
+    crudini --set "${MODE_CONFIG["slick"]}" "Greeter" "${1}" "${2}"
+}
 
-# 変数を設定
-declare -A GREETER_CONFIG=(
-    ["lightdm-webkit2-greeter"]="/etc/lightdm/lightdm-webkit2-greeter.conf"
-    ["lightdm-slick-greeter"]="/etc/lightdm/slick-greeter.conf"
-    ["lightdm-gtk-greeter"]="/etc/lightdm/lightdm-gtk-greeter.conf"
-    ["io.elementary.greeter"]="/etc/lightdm/io.elementary.greeter.conf"
-    ["lightdm-mini-greeter"]="/etc/lightdm/lightdm-mini-greeter.conf"
-    ["lightdm-qtquick-greeter"]="/etc/lightdm/lightdm-qtquick-greeter.json"
-)
+slick_init_configs(){
+    check_root
+    if [[ ! -f "${MODE_CONFIG["slick"]}" ]]; then
+        mkdir -p "$(dirname "${MODE_CONFIG["slick"]}")"
+        touch "${MODE_CONFIG["slick"]}"
+        echo "[Greeter]" > "${MODE_CONFIG["slick"]}"
+    fi
+}
+
+#== Slick用コマンド ==#
+command_slick_grid(){
+    local _arg="$(echo "${1-""}" | tr "[:upper:]" "[:lower:]")"
+    if ! check_bool "${_arg}"; then
+        msg_error "Please specify true or false"
+        exit 1
+    fi
+    slick_set_config "draw-grid" "${_arg}"
+}
 
-declare -A DISPLAY_MANAGER_CONFIG=(
+command_slick_back(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the image of background"
+        exit 1
+    fi
+    if [[ ! -f "${1}" ]]; then
+        msg_error "${1} was not found."
+        exit 1
+    fi
+
+    local _backgrounf_file="${BACKGROUND_DIR}/lightdm/slick-greeter"
+    mkdir -p "$(dirname "${_backgrounf_file}")"
+    cp "${1}" "${_backgrounf_file}"
+    chmod 644 "${_backgrounf_file}"
+    
+    slick_set_config "background" "${_backgrounf_file}"
+}
+
+command_slick_gtk_wizard(){
+    local _theme="$(ask_gtk_theme)"
+
+    # 結果に応じて処理を実行
+    if [[ -n "${_theme}" ]]; then
+        command_slick_gtk_change "${_theme}"
+    else
+        exit 1
+    fi
+    echo "Changed theme to ${_theme}"
+}
+
+command_slick_gtk_change(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the theme"
+        exit 1
+    fi
+    if [[ ! -d "/usr/share/themes/${1}" ]]; then
+        msg_error "${1} was not found."
+        exit 1
+    fi
+    slick_set_config "theme-name" "${1}"
+}
+
+command_slick_icon_wizard(){
+    local icons
+    readarray -t icons < <(get_icon_theme)
+
+    local _icon
+    echo "Please select the icon theme to use."
+    if ! _icon="$(ask_question "${icons[@]}")"; then
+        command_slick_icon_wizard
+        exit 0
+    fi
+
+    if [[ -n "${_icon}" ]]; then
+        slick_set_config "icon-theme-name" "${_icon}"
+    else
+        command_slick_icon_wizard
+        exit 0
+    fi
+    echo "Changed icon theme to ${_icon}"
+}
+
+command_slick_icon_chenge(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the icon theme to use."
+        exit 1
+    fi
+    if ! printf "%s\n" "$(get_icon_theme)" | grep -x "${1}" 1> /dev/null 2>&1; then
+        msg_error "${1} was not found."
+        exit 1
+    fi
+    slick_set_config "icon-theme-name" "${1}"
+}
+
+command_slick_remove(){
+    common_remove_command "${MODE_CONFIG["slick"]}"
+}
+
+
+#== SDDM用の汎用関数 ==#
+# sddm_get_value <section> <key> <valye>
+sddm_get_value(){
+    crudini --set "${MODE_CONFIG["sddm"]}" "${1}" "${2}"
+}
+
+# sddm_set_config <section> <key> <value>
+sddm_set_config(){
+    crudini --set "${MODE_CONFIG["sddm"]}" "${1}" "${2}" "${3}"
+}
+
+# sddm_remove_key <section> <key>
+sddm_remove_key(){
+    crudini --del "${MODE_CONFIG["sddm"]}" "${1}" "${2}"
+}
+
+
+sddm_init_configs(){
+    check_root
+    if [[ ! -f "${MODE_CONFIG["sddm"]}" ]]; then
+        mkdir -p "$(dirname "${MODE_CONFIG["sddm"]}")"
+        sddm --example-config > "${MODE_CONFIG["sddm"]}"
+    fi
+}
+
+#== SDDM用コマンド ==#
+command_sddm_auto_login(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        # 既に自動ログインが設定されているかを確認
+        local autologin_user="$(sddm_get_value Autologin User)"
+        if [[ -n "${autologin_user}" ]]; then
+            sddm_remove_key "Autologin" "User"
+            echo "Canceled automatic login of ${autologin_user}"
+        fi
+    else
+        local autologin_user="${1}" autologin_session
+        if [[ -v 2 ]]; then
+            autologin_session="${2}"
+        fi
+
+        # セッションを設定 (WayLandのセッションは現在サポートされていません)
+        if [[ -z "${autologin_session+SET}" ]]; then
+            autologin_session="$(ask_session)"
+        else
+            # 既に値が設定済み
+            check_session "${autologin_session}"
+        fi
+
+        # autologin グループを設定
+        add_user_to_group "${autologin_user}" "autologin"
+
+        # 設定を書き込み
+        sddm_set_config "Autologin" "User" "${autologin_user}"
+        sddm_set_config "Autologin" "Session" "${autologin_session}"
+
+        echo "${autologin_user} will automatically log in with ${autologin_session}"
+    fi
+}
+
+command_sddm_cursor_wizard(){
+    # カーソル一覧を取得
+    local cursor_themes _current_theme="$(sddm_get_value "Theme" "CursorTheme")"
+    readarray -t cursor_themes < <(get_cursor_theme)
+
+    # 一覧を生成
+    if ! _cursor_theme="$(ask_question -d "${_current_theme}" -p "Please select the cursor theme to use." "${cursor_themes[@]}")"; then
+        command_sddm_cursor_wizard
+        exit 0
+    fi
+
+    if [[ -n "${_cursor_theme}" ]]; then
+        command_sddm_cursor_change "${_cursor_theme}"
+    else
+        command_sddm_cursor_change
+        exit 0
+    fi
+
+    if [[ ! "${_current_theme}" = "${_cursor_theme}" ]]; then
+        echo "Changed cursor to ${_cursor_theme}"
+    fi
+}
+
+command_sddm_cursor_change(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the cursor theme"
+        exit 1
+    fi
+    local cursor_themes
+    readarray -t cursor_themes < <(get_cursor_theme)
+    if ! printf "%s\n" "${cursor_themes[@]}" | grep -x "${1}" 1>/dev/null 2>&1; then
+        msg_error "The cursor theme (${1}) was not found"
+        exit 1
+    fi
+    sddm_set_config "Theme" "CursorTheme" "${1}"
+}
+
+command_sddm_numlock(){
+    local _arg="$(echo "${1-""}" | tr "[:upper:]" "[:lower:]")"
+    if ! check_bool "${_arg}"; then
+        msg_error "Please specify true or false"
+        exit 1
+    fi
+    local _value
+    if [[ "${_arg}" = true ]]; then
+        _value="on"
+    else
+        _value="none"
+    fi
+    sddm_set_config "General" "Numlock" "${_value}"
+}
+
+command_sddm_tty(){
+    if ! check_int "${1}" || (( "${1}" < 1 )); then
+        msg_error "Please enter an integer greater than 1"
+        exit 1
+    fi
+    sddm_set_config "X11" "MinimumVT" "${1}"
+}
+
+command_sddm_theme_wizard(){
+    local _theme_list
+    readarray -t _theme_list < <(find "/usr/share/sddm/themes/" -maxdepth 1 -mindepth 1 -type d -print0 | xargs -0 -I{} basename {})
+
+    local _theme _current_theme=$(sddm_get_value "Theme" "Current")
+    if ! _theme="$(ask_question -d "${_current_theme}" -p "Please select the theme to use." "${_theme_list[@]}")"; then
+        command_sddm_theme_wizard
+        exit 0
+    fi
+    if [[ -n "${_theme}" ]]; then
+        command_sddm_theme_change "${_theme}"
+        echo "Changed the theme to ${_theme}"
+    else
+        command_sddm_theme_wizard
+        exit 0
+    fi
+    
+}
+
+command_sddm_theme_change(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the theme name"
+        exit 1
+    fi
+    if [[ ! -d "/usr/share/sddm/themes/${1}" ]]; then
+        msg_error "The specified theme (${1}) does not exist"
+        exit 1
+    fi
+
+    sddm_set_config "Theme" "Current" "${1}"
+}
+
+#== LXDM用の汎用関数 ==#
+# sddm_get_value <section> <key> <valye>
+lxdm_get_value(){
+    crudini --set "${MODE_CONFIG["lxdm"]}" "${1}" "${2}"
+}
+
+# sddm_set_config <section> <key> <value>
+lxdm_set_config(){
+    crudini --set "${MODE_CONFIG["lxdm"]}" "${1}" "${2}" "${3}"
+}
+
+# sddm_remove_key <section> <key>
+lxdm_remove_key(){
+    crudini --del "${MODE_CONFIG["lxdm"]}" "${1}" "${2}"
+}
+
+
+lxdm_init_configs(){
+    check_root
+    if [[ ! -f "${MODE_CONFIG["lxdm"]}" ]]; then
+        mkdir -p "$(dirname "${MODE_CONFIG["lxdm"]}")"
+        touch "${MODE_CONFIG["lxdm"]}"
+    fi
+}
+
+#== LXDM用コマンド ==#
+command_lxdm_auto_login(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        # 既に自動ログインが設定されているかを確認
+        local autologin_user="$(lxdm_get_value "base" "autologin")"
+        if [[ -n "${autologin_user}" ]]; then
+            sddm_remove_key "base" "autologin"
+            echo "Canceled automatic login of ${autologin_user}"
+        fi
+    else
+        local autologin_user="${1}" autologin_session
+        if [[ -v 2 ]]; then
+            autologin_session="${2}"
+        fi
+
+        # セッションを設定 (WayLandのセッションは現在サポートされていません)
+        if [[ -z "${autologin_session+SET}" ]]; then
+            autologin_session="$(ask_session)"
+        else
+            # 既に値が設定済み
+            check_session "${autologin_session}"
+        fi
+
+        # autologin グループを設定
+        add_user_to_group "${autologin_user}" "autologin"
+
+        # 自動ログインするユーザーを書き込み
+        sddm_set_config "base" "autologin" "${autologin_user}"
+
+        # デフォルトセッションを設定
+        command_lxdm_session_change "${autologin_session}"
+
+        echo "${autologin_user} will automatically log in with ${autologin_session}"
+    fi
+}
+
+command_lxdm_session_wizard(){
+    command_lxdm_session_change "$(ask_session)"
+}
+
+command_lxdm_session_change(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the session name"
+        exit 1
+    fi
+    local session="${1}"
+    check_session "${session}"
+    local session_exec="$(get_session_exec "${session}")"
+    lxdm_set_config "base" "session" "${session_exec}"
+}
+
+command_lxdm_remove_last(){
+    rm -rf "/var/lib/lxdm/lxdm.conf"
+    echo "Removed last configs"
+}
+
+comamnd_lxdm_edit_script(){
+    local _filelist=(
+        "LoginReady : executed with root privileges when LXDM is ready to show the login window"
+        "PreLogin   : run as root before logging a user in"
+        "PostLogin  : run as the logged-in user right after they have logged in"
+        "PostLogout : run as the logged-in user right after they have logged out"
+        "PreReboot  : run as root before rebooting with LXDM"
+        "PreShutdown: run as root before poweroff with LXDM"
+    )
+    if ! file=$(ask_question -p "Select the script you want to edit" "${_filelist[@]}" | cut -d ":" -f 1 | tr -d " "); then
+        comamnd_lxdm_edit_script
+        exit 0
+    fi
+    bash -c "${USE_EDITOR} ${file}"
+}
+
+command_lxdm_back(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the image of background"
+        exit 1
+    fi
+    if [[ ! -f "${1}" ]]; then
+        msg_error "${1} was not found."
+        exit 1
+    fi
+
+    local _backgrounf_file="${BACKGROUND_DIR}/lxdm/background"
+    mkdir -p "$(dirname "${_backgrounf_file}")"
+    cp "${1}" "${_backgrounf_file}"
+    chmod 644 "${_backgrounf_file}"
+    
+    lxdm_set_config "display" "bg" "file://${_backgrounf_file}"
+}
+
+command_lxdm_gtk_wizard(){
+    local _theme="$(ask_gtk_theme)"
+
+    # 結果に応じて処理を実行
+    if [[ -n "${_theme}" ]]; then
+        command_lxdm_gtk_change "${_theme}"
+    else
+        exit 1
+    fi
+    echo "Changed theme to ${_theme}"
+}
+
+command_lxdm_gtk_change(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the theme"
+        exit 1
+    fi
+    if [[ ! -d "/usr/share/themes/${1}" ]]; then
+        msg_error "${1} was not found."
+        exit 1
+    fi
+    lxdm_set_config "display" "gtk_theme" "${1}"
+}
+
+#== GTk Greeter用の汎用関数 ==#
+# gtk_greeter_get_value <section> <key>
+gtk_greeter_get_value(){
+    crudini --set "${MODE_CONFIG["gtkg"]}" "${1}" "${2}"
+}
+
+# gtk_greeter_set_config <section> <key> <value>
+gtk_greeter_set_config(){
+    crudini --set "${MODE_CONFIG["gtkg"]}" "${1}" "${2}" "${3}"
+}
+
+# gtk_greeter_remove_key <section> <key>
+gtk_greeter_remove_key(){
+    crudini --del "${MODE_CONFIG["gtkg"]}" "${1}" "${2}"
+}
+
+gtk_greeter_init_configs(){
+    check_root
+    if [[ ! -f "${MODE_CONFIG["gtkg"]}" ]]; then
+        mkdir -p "$(dirname "${MODE_CONFIG["gtkg"]}")"
+        touch "${MODE_CONFIG["gtkg"]}"
+    fi
+}
+
+#== GTk Greeter用のコマンド==#
+command_gtk_greeter_gtk_wizard(){
+    local _theme="$(ask_gtk_theme)"
+
+    # 結果に応じて処理を実行
+    if [[ -n "${_theme}" ]]; then
+        gtk_greeter_set_config "greeter" "theme-name" "${_theme}"
+    else
+        exit 1
+    fi
+    echo "Changed theme to ${_theme}"
+}
+
+command_gtk_greeter_gtk_change(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the theme"
+        exit 1
+    fi
+    if ! printf "%s\n" "$(get_gtk_theme)" | grep -x "${1}" 1> /dev/null 2>&1; then
+        msg_error "${1} was not found."
+        exit 1
+    fi
+    gtk_greeter_set_config "greeter" "theme-name" "${1}"
+}
+
+command_gtk_greeter_icon_wizard(){
+    local icons
+    readarray -t icons < <(get_icon_theme)
+
+    local _icon
+    echo "Please select the icon theme to use."
+    if ! _icon="$(ask_question "${icons[@]}")"; then
+        command_gtk_greeter_icon_wizard
+        exit 0
+    fi
+
+    if [[ -n "${_icon}" ]]; then
+        gtk_greeter_set_config "greeter" "icon-theme-name" "${_icon}"
+    else
+        command_gtk_greeter_icon_wizard
+        exit 0
+    fi
+    echo "Changed icon theme to ${_icon}"
+}
+
+command_gtk_greeter_icon_chenge(){
+    if [[ -z "${1+SET}" ]] || [[ "${1}" = "" ]]; then
+        msg_error "Please specify the icon theme to use."
+        exit 1
+    fi
+    if ! printf "%s\n" "$(get_icon_theme)" | grep -x "${1}" 1> /dev/null 2>&1; then
+        msg_error "${1} was not found."
+        exit 1
+    fi
+    gtk_greeter_set_config "greeter" "icon-theme-name" "${_icon}"
+}
+
+
+#== 設定ファイルのパス ==#
+declare -A MODE_CONFIG=(
     ["lightdm"]="/etc/lightdm/lightdm.conf.d/00-dmc-lightdm.conf"
     ["gdm-dconf"]="/etc/dconf/db/gdm.d/00-dmc-gdm"
     ["gdm-custom"]="/etc/gdm/custom.conf"
+    ["sddm"]="/etc/sddm.conf.d/sddm.conf"
+    ["lxdm"]="/etc/lxdm/lxdm.conf"
+    ["webkit2"]="/etc/lightdm/lightdm-webkit2-greeter.conf"
+    ["slick"]="/etc/lightdm/slick-greeter.conf"
+    ["gtkg"]="/etc/lightdm/lightdm-gtk-greeter.conf"
+    ["elementary"]="/etc/lightdm/io.elementary.greeter.conf"
+    ["mini"]="/etc/lightdm/lightdm-mini-greeter.conf"
+    ["qtquick"]="/etc/lightdm/lightdm-qtquick-greeter.json"
 )
 
+declare -A MAIN_BINARY=(
+    ["lightdm"]="/usr/bin/lightdm"
+    ["gdm"]="/usr/bin/gdm"
+    ["sddm"]="/usr/bin/sddm"
+    ["webkit2"]="/usr/bin/lightdm-webkit2-greeter"
+    ["slick"]="/usr/bin/slick-greeter"
+    ["gtkg"]="/usr/bin/lightdm-gtk-greeter"
+    ["elementary"]="/usr/bin/io.elementary.greeter"
+    ["mini"]="/usr/bin/lightdm-mini-greeter"
+    ["qtquick"]="/usr/bin/lightdm-qtquick-greeter"
+    ["lxdm"]="/usr/bin/lxdm"
+)
 
-#== CONFIGS ==#
+declare -A GREETER_MODE=(
+    ["lightdm-webkit2-greeter"]="webkit2"
+    ["lightdm-slick-greeter"]="slick"
+    ["io.elementary.greeter"]="elementary"
+    ["lightdm-mini-greeter"]="mini"
+    ["lightdm-qtquick-greeter"]="qtquick"
+    ["lightdm-gtk-greeter"]="gtkg"
+)
 
-# LightDM - 設定ファイル
-LIGHTDM_CONFIG="${DISPLAY_MANAGER_CONFIG["lightdm"]}"
 
+#== CONFIGS ==#
 # LightDM - Greeterのディレクトリ
 LIGHTDM_GREETERS_DIR="$(lightdm_get_value "greeters-directory")"
 : "${LIGHTDM_GREETERS_DIR:="/usr/share/xgreeters"}"
 
-# LightDM - Greeter一覧
-LIGHTDM_GREETERS=( $( (ls "${LIGHTDM_GREETERS_DIR}" | sed "s|.desktop$||g") 2> /dev/null ))
-
 # LightDM - 現在設定されているGreeter
 LIGHTDM_CURRENT_GREETER="$(lightdm --show-config 2>&1 | grep "greeter-session" | cut -d "=" -f 2)"
 : "${LIGHTDM_CURRENT_GREETER:="lightdm-gtk-greeter"}"
 
-# LightDM - 読み込まれた設定ファイルの一覧
-while read -r line; do
-    LIGHTDM_LOADED_CONFIG+=("${line}")
-done < <(printf "%s\n" "$(lightdm --show-config 2>&1 | grep -x -A "$(lightdm --show-config 2>&1 | wc -l)" "Sources:" | grep -v "Sources" | sed 's|^[A-Z]  ||g')"  | tr -d " ")
+# Global - エディタ
+USE_EDITOR="${EDITOR:-vi}"
 
-# Global
-while read -r line; do CURSOR_THEMES+=("${line}"); done < <(get_cursor_theme)
+# Global - 背景画像をコピーするディレクトリ
+BACKGROUND_DIR="/usr/share/backgrounds"
 
-USE_EDITOR="${EDITOR:-vi}"
-DISPLAY_MANAGER="lightdm"
+# Global - 現在のディスプレイマネージャ名
+if [[ -f "/etc/systemd/system/display-manager.service" ]]; then
+    CURRENT_DM="$(basename "$(readlink "/etc/systemd/system/display-manager.service")" | sed "s|.service$||g")"
+else
+    CURRENT_DM=""
+fi
+
+# モード
+MODE="${CURRENT_DM}"
+: "${MODE:="lightdm"}"
 
 # dmc config
 NON_INTERACTIVE=false
 WRITE_ALL_FILES=false
 NOROOT=false
-
+NO_CHECK_TARGET=false
+REMOVE_FILES=false
 
 #== 引数解析 ==#
-ARGUMENT="${*}"
-OPTS="m:e:h"
-OPTL="mode:,editor:,help,non-interactive,noroot,write-all-files"
-# shellcheck disable=SC2086
-if ! OPT="$(getopt -o ${OPTS} -l ${OPTL} -- ${ARGUMENT})"; then
+ARGUMENT=("${@}")
+OPTS=("m:" "e:" "h" "G")
+OPTL=("mode:" "editor:" "help" "non-interactive" "noroot" "write-all-files" "no-check-target" "lightdm-greeter" "remove")
+if ! readarray -t OPT < <(getopt -o "$(printf "%s," "${OPTS[@]}")" -l "$(printf "%s," "${OPTL[@]}")" -- "${ARGUMENT[@]}"); then
     exit 1
 fi
 
-eval set -- "${OPT}"
+eval set -- "${OPT[@]}"
 unset OPT OPTS OPTL
 
 while true; do
     case "${1}" in
         -m | --mode)
-            DISPLAY_MANAGER="${2}"
+            MODE="${2}"
             shift 2
             ;;
         -e | --editor)
@@ -932,6 +1685,15 @@ while true; do
             script_usage
             exit 0
             ;;
+        -G | --lightdm-greeter)
+            if [[ -n "${LIGHTDM_CURRENT_GREETER+SET}" ]]; then
+                MODE="${GREETER_MODE["${LIGHTDM_CURRENT_GREETER}"]}"
+            else
+                msg_error "Failed to get the currently running Greeter."
+                exit 1
+            fi
+            shift 1
+            ;;
         --non-interactive)
             NON_INTERACTIVE=true
             shift 1
@@ -940,10 +1702,18 @@ while true; do
             NOROOT=true
             shift 1
             ;;
+        --no-check-target)
+            NO_CHECK_TARGET=true
+            shift 1
+            ;;
         --write-all-files)
             WRITE_ALL_FILES=true
             shift 1
             ;;
+        --remove)
+            REMOVE_FILES=true
+            shift 1
+            ;;
         --)
             shift 1
             break
@@ -951,121 +1721,318 @@ while true; do
     esac
 done
 
+# コマンドの引数を解析
 COMMAND="${1:-null}"
 if (( "${#}" >= 1 )); then
     shift 1
 fi
-COMMAND_ARGS="${*}"
-: "${COMMAND_ARGS-""}" # サブコマンドの引数が何も指定されなかった場合に空文字を代入
+COMMAND_ARGS=("${@}")
+: "${COMMAND_ARGS=""}" # サブコマンドの引数が何も指定されなかった場合に空文字を代入
 
 if [[ "${COMMAND}" = "null" ]]; then
     script_usage
     exit 1
 fi
 
-case "${DISPLAY_MANAGER}" in
-    "lightdm")
-        case "${COMMAND}" in
-            "autologin")
+# メインバイナリの確認を実行
+if [[ "${NO_CHECK_TARGET}" = false ]]; then
+    check_main_binary
+fi
+
+# 依存コマンドの確認
+ check_tools "jq" "crudini"
+
+# コマンドとモードに応じて関数を実行する
+case "${COMMAND}" in
+    "accessibility")
+        check_command_dm "gdm"
+        gdm_init_configs
+        command_gdm_accessibility "${COMMAND_ARGS[@]}"
+        ;;
+    "autologin")
+        check_command_dm "lightdm" "gdm" "sddm" "lxdm"
+        case "${MODE}" in
+            "lightdm")
                 lightdm_init_configs
-                command_lightdm_auto_login "${COMMAND_ARGS}"
+                command_lightdm_auto_login "${COMMAND_ARGS[@]}"
                 ;;
-            "greeter")
-                lightdm_init_configs
-                run_greeter_wizard
+            "gdm")
+                gdm_init_configs
+                command_gdm_auto_login "${COMMAND_ARGS[@]}"
                 ;;
-            "greeter-change")
-                lightdm_init_configs
-                command_lightdm_greeter_change "${COMMAND_ARGS}"
+            "sddm")
+                sddm_init_configs
+                command_sddm_auto_login "${COMMAND_ARGS[@]}"
                 ;;
-            "greeter-create")
-                lightdm_init_configs
-                command_lightdm_greeter_create "${COMMAND_ARGS}"
+            "lxdm")
+                lxdm_init_configs
+                command_lxdm_auto_login "${COMMAND_ARGS[@]}"
                 ;;
-            "greeter-list")
-                command_lightdm_greeter_list
+        esac
+        ;;
+    "back")
+        check_command_dm "qtquick" "slick" "lxdm"
+        case "${MODE}" in
+            "qtquick")
+                qtquick_init_configs
+                command_qtquick_back "${COMMAND_ARGS[@]}"
                 ;;
-            "greeter-edit")
-                check_root
-                command_lightdm_greeter_edit "${COMMAND_ARGS}"
+            "slick")
+                slick_init_configs
+                command_slick_back "${COMMAND_ARGS[@]}"
                 ;;
-            "remove")
-                check_root
-                command_lightdm_remove
+            "back")
+                lxdm_init_configs
+                command_lxdm_back "${COMMAND_ARGS[@]}"
+                ;;
+        esac
+        ;;
+    "cursor")
+        check_command_dm "gdm" "sddm"
+        case "${MODE}" in
+            "gdm")
+                gdm_init_configs
+                command_gdm_cursor_wizard
                 ;;
-            "edit")
+            "sddm")
+                sddm_init_configs
+                command_sddm_cursor_wizard
+                ;;
+        esac
+        ;;
+    "cursor-change")
+        check_command_dm "gdm" "sddm"
+        case "${MODE}" in
+            "gdm")
+                gdm_init_configs
+                command_gdm_cursor_change "${COMMAND_ARGS[@]}"
+                ;;
+            "sddm")
+                sddm_init_configs
+                command_sddm_cursor_change "${COMMAND_ARGS[@]}"
+                ;;
+        esac
+        ;;
+    "debug")
+        check_comamnd_dm "webkit2"
+        command_webkit2_debug "${COMMAND_ARGS[@]}"
+        ;;
+    "dm")
+        command_general_dm "${COMMAND_ARGS[@]}"
+        ;;
+    "edit")
+        check_command_dm "lightdm" "gdm"
+        case "${MODE}" in
+            "lightdm")
                 check_root
                 command_lightdm_edit
                 ;;
-            "show-config")
-                command_lightdm_show_config
+            "gdm")
+                gdm_init_configs
+                command_gdm_edit
+                ;;
+        esac
+        ;;
+    "edit-script")
+        check_command_dm "lxdm"
+        lxdm_init_configs
+        comamnd_lxdm_edit_script
+        ;;
+    "gtk")
+        check_command_dm "slick" "lxdm" "gtkg"
+        case "${MODE}" in
+            "slick")
+                slick_init_configs
+                command_slick_gtk_wizard
+                ;;
+            "lxdm")
+                lxdm_init_configs
+                command_lxdm_gtk_wizard
                 ;;
-            *)
-                msg_error "Undefined commnad(${COMMAND})"
+            "gtkg")
+                gtk_greeter_init_configs
+                command_gtk_greeter_gtk_wizard
                 ;;
         esac
         ;;
-    "gdm")
-        case "${COMMAND}" in
-            "autologin")
-                gdm_init_configs
-                command_gdm_auto_login "${COMMAND_ARGS}"
+    "greeter")
+        check_command_dm "lightdm"
+        lightdm_init_configs
+        command_lightdm_greeter_wizard
+        ;;
+    "greeter-change")
+        check_command_dm "lightdm"
+        lightdm_init_configs
+        command_lightdm_greeter_change "${COMMAND_ARGS[@]}"
+        ;;
+    "greeter-create")
+        check_command_dm "lightdm"
+        lightdm_init_configs
+        command_lightdm_greeter_create "${COMMAND_ARGS[@]}"
+        ;;
+    "greeter-edit")
+        check_command_dm "lightdm"
+        check_root
+        command_lightdm_greeter_edit "${COMMAND_ARGS[@]}"
+        ;;
+    "greeter-list")
+        check_command_dm "lightdm"
+        command_lightdm_greeter_list
+        ;;
+
+    "grid")
+        check_command_dm "slick"
+        slick_init_configs
+        command_slick_grid "${COMMAND_ARGS[@]}"
+        ;;
+    "gtk-change")
+        check_command_dm "slick" "lxdm" "gtkg"
+        case "${MODE}" in
+            "slick")
+                slick_init_configs
+                command_slick_gtk_change "${COMMAND_ARGS[@]}"
                 ;;
-            "cursor")
-                gdm_init_configs
-                command_gdm_cursor_wizard
+            "lxdm")
+                command_lxdm_gtk_change "${COMMAND_ARGS[@]}"
                 ;;
-            "sound")
-                gdm_init_configs
-                command_gdm_sound "${COMMAND_ARGS}"
+            "gtkg")
+                command_gtk_greeter_gtk_change "${COMMAND_ARGS[@]}"
                 ;;
-            "logo")
-                gdm_init_configs
-                command_gdm_logo "${COMMAND_ARGS}"
+        esac
+        ;;
+    "icon")
+        check_command_dm "slick" "gtkg"
+        case "${MODE}" in
+            "slick")
+                slick_init_configs
+                command_slick_icon_wizard
                 ;;
-            "tap")
-                gdm_init_configs
-                command_gdm_tap "${COMMAND_ARGS}"
+            "gtkg")
+                gtk_greeter_init_configs
+                command_gtk_greeter_icon_wizard
                 ;;
-            "accessibility")
-                gdm_init_configs
-                command_gdm_accessibility "${COMMAND_ARGS}"
+        esac
+        ;;
+    "icon-change")
+        check_command_dm "slick" "gtkg"
+        case "${MODE}" in
+            "slick")
+                slick_init_configs
+                command_slick_icon_chenge "${COMMAND_ARGS[@]}"
                 ;;
-            "root-login")
+            "gtkg")
+                gtk_greeter_init_configs
+                command_gtk_greeter_icon_chenge "${COMMAND_ARGS[@]}"
+                ;;
+        esac
+        ;;
+    "logo")
+        check_command_dm "gdm" "slick"
+        case "${MODE}" in
+            "gdm")
                 gdm_init_configs
-                command_gdm_root_login "${COMMAND_ARGS}"
+                command_gdm_logo "${COMMAND_ARGS[@]}"
                 ;;
-            *)
-                msg_error "Undefined commnad(${COMMAND})"
+            "slick")
+                slick_init_configs
+                command_slick_logo "${COMMAND_ARGS[@]}"
                 ;;
         esac
         ;;
-    "webkit2")
-        case "${COMMAND}" in
-            "theme")
+    "numlock")
+        check_command_dm "sddm"
+        sddm_init_configs
+        command_sddm_numlock "${COMMAND_ARGS[@]}"
+        ;;
+    "other-monitor")
+        check_command_dm "slick"
+        slick_init_configs
+        command_slick_other_monitor "${COMMAND_ARGS[@]}"
+        ;;
+    "remove")
+        check_command_dm "lightdm" "gdm" "webkit2" "qtquick"
+        check_root
+        eval "command_${MODE}_remove"
+        ;;
+    "remove-last")
+        check_command_dm "lxdm"
+        lxdm_init_configs
+        command_lxdm_remove_last
+        ;;
+    "root-login")
+        check_command_dm "gdm"
+        gdm_init_configs
+        command_gdm_root_login "${COMMAND_ARGS[@]}"
+        ;;
+    "session")
+        check_command_dm "lxdm"
+        lxdm_init_configs
+        command_lxdm_session_wizard
+        ;;
+    "session-change")
+        check_command_dm "lxdm"
+        lxdm_init_configs
+        command_lxdm_session_change "${COMMAND_ARGS[@]}"
+        ;;
+    "show-config")
+        check_command_dm "lightdm"
+        command_lightdm_show_config
+        ;;
+
+    "sound")
+        check_command_dm "gdm"
+        gdm_init_configs
+        command_gdm_sound "${COMMAND_ARGS[@]}"
+        ;;
+    "tap")
+        check_command_dm "gdm"
+        gdm_init_configs
+        command_gdm_tap "${COMMAND_ARGS[@]}"
+        ;;
+    "theme")
+        check_command_dm "webkit2" "sddm"
+        case "${MODE}" in
+            "webkit2")
                 webkit2_init_configs
                 command_webkit2_theme_wizard
                 ;;
-            "theme-change")
-                webkit2_init_configs
-                command_webkit2_theme_change "${COMMAND_ARGS}"
-                ;;
-            *)
-                msg_error "Undefined commnad(${COMMAND})"
+            "sddm")
+                sddm_init_configs
+                command_sddm_theme_wizard
                 ;;
         esac
         ;;
-    "qtquick")
-        case "${COMMAND}" in
-            "back")
-                qtquick_init_configs
-                command_qtquick_back "${COMMAND_ARGS}"
+    "theme-change")
+        check_command_dm "webkit2" "sddm"
+        case "${MODE}" in
+            "webkit2")
+                webkit2_init_configs
+                command_webkit2_theme_change "${COMMAND_ARGS[@]}"
+                ;;
+            "sddm")
+                sddm_init_configs
+                command_sddm_theme_change
                 ;;
         esac
         ;;
+    "tty")
+        check_command_dm "sddm"
+        sddm_init_configs
+        command_sddm_tty "${COMMAND_ARGS[@]}"
+        ;;
+    "gtk-list")
+        get_gtk_theme
+        exit 0
+        ;;
+    "lightdm" | "gdm" | "sddm" | "lxdm" | "webkit2" | "qtquick" | "slick" | "gtkg")
+        command_mode "${COMMAND}" "${COMMAND_ARGS[@]}"
+        ;;
+    "help")
+        script_usage
+        exit 0
+        ;;
     *)
-        msg_error "A display manager that is not currently supported."
+        msg_error "This command cannot be used in any mode"
         exit 1
         ;;
 esac
-exit 0