From 19e1d458a39622e5e8dbdc01471e1e0b35fc8633 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 28 Jun 2026 14:02:56 -0400 Subject: [PATCH] Added -d and -D flags to generate a default I38 setup. -D also creates the .xinitrc and .xprofiles. This is basically a silent mode with no prompts and uses the items it finds with other sane defaults, e.g. alt+escape for RP mode and control+escape for personal mode. --- I38.md | 4 ++ README.md | 4 ++ i38.sh | 138 ++++++++++++++++++++++++++++++++++++----- scripts/filemanager.sh | 74 ++++++++++++++++++++++ 4 files changed, 204 insertions(+), 16 deletions(-) create mode 100755 scripts/filemanager.sh diff --git a/I38.md b/I38.md index b471904..15da8a0 100644 --- a/I38.md +++ b/I38.md @@ -421,6 +421,10 @@ To update I38 on this system: Running `./i38.sh` regenerates your I38 configuration and refreshes the installed scripts. Your personal shortcuts in `~/.config/i3/customizations` are preserved. +To generate the default configuration without prompts, use `./i38.sh -d`. To also generate `~/.xinitrc` and `~/.xprofile` without prompts, use `./i38.sh -D`. + +Default configuration mode uses I38Lock when it is installed and supported by the screen-reader setup. In that case I38 locks on startup and autolocks after 5 minutes when `xprintidle` is available. + If you only need to copy the latest scripts and do not want to regenerate the full i3 configuration, you can use `./i38.sh -u` instead. ## Getting Help diff --git a/README.md b/README.md index 3cef8e0..e940281 100644 --- a/README.md +++ b/README.md @@ -111,11 +111,15 @@ You can apply the same configuration to GTK2 apps. Create or edit ~/.gtkrc-2.0 ## Usage: - With no arguments, create the i3 configuration. +- -d: Generate the default I38 configuration without prompting. +- -D: Generate the default I38 configuration plus ~/.xinitrc and ~/.xprofile without prompting. - -h: Help screen. - -u: Copy over the latest version of scripts. - -x: Generate ~/.xinitrc and ~/.xprofile. - -X: Generate ~/.xprofile only. +Default configuration mode uses I38Lock when it is installed and supported by the screen-reader setup. In that case I38 locks on startup and autolocks after 5 minutes when `xprintidle` is available. + ## Dependency Helpers Distro-specific dependency helpers live in `extra/`. On Arch Linux, run: diff --git a/i38.sh b/i38.sh index ca7331c..f327e55 100755 --- a/i38.sh +++ b/i38.sh @@ -16,6 +16,8 @@ i3msg="i3-msg" configFile="${PWD}/I38_preferences.conf" i38VersionFile="${i3Path}/i38-version" i38CheckoutPath="${PWD}" +defaultConfig=0 +defaultGenerateX=0 # Dialog accessibility export DIALOGOPTS='--no-lines --visit-items' @@ -184,10 +186,82 @@ rangebox() { yesno() { # Returns: Yes 0 or No 1 # Args: Question to user. + if [[ $defaultConfig -eq 1 ]]; then + return 0 + fi dialog --clear --title "I38" --yesno "$*" -1 -1 --stdout return $? } +first_available_program() { + local program + + for program in "$@"; do + if command -v "${program#-}" &> /dev/null; then + printf '%s\n' "${program#-}" + return 0 + fi + done + + return 1 +} + +first_available_path() { + local program + + if program="$(first_available_program "$@")"; then + command -v "$program" + fi +} + +set_default_configuration() { + escapeKey="Mod1+Escape" + mod="Mod1" + kbd=() + volumeJump=5 + i3FontSize=12 + screenReader="$(first_available_path cthulhu orca || true)" + screenReader="${screenReader:-none}" + emailClient="$(first_available_path betterbird evolution thunderbird || true)" + webBrowser="$(first_available_path brave chromium epiphany firefox google-chrome-stable google-chrome-unstable microsoft-edge-stable microsoft-edge-beta microsoft-edge-dev midori seamonkey vivaldi || true)" + textEditor="$(first_available_path emacs geany gedit kate kwrite l3afpad leafpad libreoffice mousepad pluma || true)" + fileBrowser="$(first_available_path caja nemo nautilus pcmanfm pcmanfm-qt thunar || true)" + ircClient="$(first_available_path albikirc Albikirc access-irc || true)" + terminalEmulator="$(first_available_path mate-terminal lxterminal gnome-terminal terminator xfce4-terminal tilix ptyxis kgx sakura roxterm termit guake tilda qterminal konsole || true)" + if [[ -z "$terminalEmulator" ]] && command -v xterm &> /dev/null && command -v fenrir &> /dev/null; then + terminalEmulator="$(command -v xterm)" + fi + udiskie=1 + if command -v udiskie &> /dev/null; then + udiskie=0 + fi + dex=1 + if command -v dex &> /dev/null; then + dex=0 + fi + batteryAlert=1 + if command -v acpi &> /dev/null; then + batteryAlert=0 + fi + brlapi=1 + if [[ "$screenReader" != "none" ]] && [[ -n "$screenReader" ]]; then + brlapi=0 + fi + sounds=0 + screenlockMethod="none" + screenlockPinHash="" + screenlockAutolockSeconds=0 + screenlockOnStartup=1 + if i38lock_is_supported; then + screenlockMethod="i38lock" + screenlockAutolockSeconds=300 + screenlockOnStartup=0 + fi + personalModeEnabled=0 + personalModeKey="Control+Escape" + waytrayUseI38Config=0 +} + # Personal mode helpers normalize_ratpoison_key() { local key="$1" @@ -414,7 +488,7 @@ load_config() { source "$configFile" # Convert kbd string back to array if present - if [[ -n "$kbd" ]]; then + if [[ -n "${kbd[*]:-}" ]]; then IFS=' ' read -ra kbd <<< "$kbd" fi @@ -424,6 +498,10 @@ load_config() { } save_config() { + if [[ $defaultConfig -eq 1 ]]; then + return 0 + fi + if yesno "Save this configuration for future runs?"; then cat > "$configFile" << EOF # I38 Configuration Preferences @@ -576,7 +654,6 @@ if new_content: new_content += block xprofile_path.write_text(new_content, encoding="utf-8") PY -exit 0 } apply_screenlock_pin() { @@ -722,6 +799,8 @@ write_i38_version() { # Array of command line arguments declare -A command=( [h]="This help screen." + [d]="Generate the default I38 configuration without prompting." + [D]="Generate the default I38 configuration plus ~/.xinitrc and ~/.xprofile without prompting." [u]="Copy over the latest version of scripts." [x]="Generate ~/.xinitrc and ~/.xprofile." [X]="Generate ~/.xprofile only." @@ -733,16 +812,27 @@ args="${args//[[:space:]]/}" while getopts "${args}" i ; do case "$i" in h) help;; + d) defaultConfig=1;; + D) defaultConfig=1; defaultGenerateX=1;; u) update_scripts;; - x) write_xinitrc ;& - X) write_xprofile ;; + x) write_xinitrc; write_xprofile; exit 0;; + X) write_xprofile; exit 0;; esac done +if [[ $defaultConfig -eq 1 ]]; then + set_default_configuration +fi + +if [[ $defaultGenerateX -eq 1 ]]; then + write_xinitrc + write_xprofile +fi + # Load saved configuration if available configLoaded=0 configChanged=0 -if load_config; then +if [[ $defaultConfig -eq 0 ]] && load_config; then configLoaded=1 dialog --title "I38" --msgbox "Loaded saved preferences from $configFile\n\nMissing or invalid values will be prompted." 0 0 fi @@ -772,7 +862,7 @@ if [[ -z "$escapeKey" ]] || [[ -z "$mod" ]]; then done fi # Multiple keyboard layouts -if [[ ${#kbd[@]} -eq 0 ]]; then +if [[ $defaultConfig -eq 0 && ${#kbd[@]} -eq 0 ]]; then if yesno "Do you want to use multiple keyboard layouts?"; then unset kbd while : ; do @@ -792,7 +882,7 @@ if [[ -z "$i3FontSize" ]] || [[ ! "$i3FontSize" =~ ^[0-9]+$ ]]; then fi fi # Screen Reader -if [[ -z "$screenReader" ]] || { [[ "$screenReader" != "none" ]] && ! command -v "$screenReader" &> /dev/null; }; then +if [[ $defaultConfig -eq 0 ]] && { [[ -z "$screenReader" ]] || { [[ "$screenReader" != "none" ]] && ! command -v "$screenReader" &> /dev/null; }; }; then programList=() for i in cthulhu orca ; do if command -v "${i/#-/}" &> /dev/null ; then @@ -816,7 +906,7 @@ else export screenReader fi # Email client -if [[ -z "$emailClient" ]] || ! command -v "$emailClient" &> /dev/null; then +if [[ $defaultConfig -eq 0 ]] && { [[ -z "$emailClient" ]] || ! command -v "$emailClient" &> /dev/null; }; then programList=() for i in betterbird evolution thunderbird ; do if command -v "${i/#-/}" &> /dev/null ; then @@ -835,7 +925,7 @@ else export emailClient fi # Web browser -if [[ -z "$webBrowser" ]] || ! command -v "$webBrowser" &> /dev/null; then +if [[ $defaultConfig -eq 0 ]] && { [[ -z "$webBrowser" ]] || ! command -v "$webBrowser" &> /dev/null; }; then programList=() for i in brave chromium epiphany firefox google-chrome-stable google-chrome-unstable microsoft-edge-stable microsoft-edge-beta microsoft-edge-dev midori seamonkey vivaldi ; do if command -v "${i/#-/}" &> /dev/null ; then @@ -854,7 +944,7 @@ else export webBrowser fi # Text editor -if [[ -z "$textEditor" ]] || ! command -v "$textEditor" &> /dev/null; then +if [[ $defaultConfig -eq 0 ]] && { [[ -z "$textEditor" ]] || ! command -v "$textEditor" &> /dev/null; }; then programList=() for i in emacs geany gedit kate kwrite l3afpad leafpad libreoffice mousepad pluma ; do if command -v "${i/#-/}" &> /dev/null ; then @@ -873,7 +963,7 @@ else export textEditor fi # File browser -if [[ -z "$fileBrowser" ]] || ! command -v "$fileBrowser" &> /dev/null; then +if [[ $defaultConfig -eq 0 ]] && { [[ -z "$fileBrowser" ]] || ! command -v "$fileBrowser" &> /dev/null; }; then programList=() for i in caja nemo nautilus pcmanfm pcmanfm-qt thunar ; do if command -v "${i/#-/}" &> /dev/null ; then @@ -892,7 +982,7 @@ else export fileBrowser fi # IRC client -if [[ -z "$ircClient" ]] || ! command -v "$ircClient" &> /dev/null; then +if [[ $defaultConfig -eq 0 ]] && { [[ -z "$ircClient" ]] || ! command -v "$ircClient" &> /dev/null; }; then programList=() for i in albikirc Albikirc access-irc ; do if command -v "${i/#-/}" &> /dev/null ; then @@ -911,7 +1001,11 @@ else export ircClient fi # Terminal emulator -if [[ -z "$terminalEmulator" ]] || { [[ ! -x "$terminalEmulator" ]] && ! command -v "$terminalEmulator" &> /dev/null; }; then +if [[ $defaultConfig -eq 1 && -z "$terminalEmulator" ]]; then + echo "No supported terminal emulator was found. Please install mate-terminal, lxterminal, gnome-terminal, terminator, another supported accessible terminal, or install both xterm and fenrir." + exit 1 +fi +if [[ $defaultConfig -eq 0 ]] && { [[ -z "$terminalEmulator" ]] || { [[ ! -x "$terminalEmulator" ]] && ! command -v "$terminalEmulator" &> /dev/null; }; }; then configChanged=1 programList=() for i in mate-terminal lxterminal gnome-terminal terminator xfce4-terminal tilix ptyxis kgx sakura roxterm termit guake tilda qterminal konsole ; do @@ -986,7 +1080,7 @@ if [[ -z "$sounds" ]]; then sounds=1 fi fi -if [[ -z "$screenlockPinHash" ]]; then +if [[ $defaultConfig -eq 0 && -z "$screenlockPinHash" ]]; then screenlockPinFile="${i3Path}/.screenpin" if [[ -f "$screenlockPinFile" ]]; then read -r screenlockPinHash < "$screenlockPinFile" @@ -997,7 +1091,7 @@ if [[ -z "${screenlockMethod+x}" ]]; then screenlockNeedsSelection=1 fi if [[ -z "$screenlockMethod" || "$screenlockMethod" == "none" ]]; then - if [[ -n "$screenlockPinHash" ]]; then + if [[ $defaultConfig -eq 0 && -n "$screenlockPinHash" ]]; then screenlockMethod="pin" else screenlockMethod="none" @@ -1115,7 +1209,11 @@ write_i38_version write_desktop_shortcuts_template write_i38_xresources # Move scripts into place -copy_scripts | dialog --backtitle "I38" --progressbox "Moving scripts into place and writing config..." -1 -1 +if [[ $defaultConfig -eq 1 ]]; then + copy_scripts > /dev/null +else + copy_scripts | dialog --backtitle "I38" --progressbox "Moving scripts into place and writing config..." -1 -1 +fi apply_screenlock_pin update_personal_customizations @@ -1537,6 +1635,11 @@ fi if command -v waytray-daemon &> /dev/null ; then echo 'exec_always --no-startup-id bash -c "pgrep -x waytray-daemon > /dev/null || waytray-daemon"' fi +case "${fileBrowser##*/}" in + thunar|pcmanfm|pcmanfm-qt) + echo "exec_always --no-startup-id ${i3Path}/scripts/filemanager.sh ${fileBrowser}" + ;; +esac echo "exec_always --no-startup-id ${i3Path}/scripts/i38-clipboard.py --daemon" echo "exec_always --no-startup-id ${i3Path}/scripts/desktop.sh" echo "exec_always --no-startup-id ${i3Path}/scripts/i38-update-check.sh" @@ -1800,3 +1903,6 @@ PY # Create the firstrun file touch "${i3Path}/firstrun" +if [[ $defaultConfig -eq 1 ]]; then + echo "Default I38 configuration generated." +fi diff --git a/scripts/filemanager.sh b/scripts/filemanager.sh new file mode 100755 index 0000000..29b7d90 --- /dev/null +++ b/scripts/filemanager.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +# This file is part of I38. +# +# I38 is free software: you can redistribute it and/or modify it under the terms +# of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. + +set -u + +set_ini_key() { + local filePath="$1" + local sectionName="$2" + local keyName="$3" + local keyValue="$4" + local tempFile + + mkdir -p -- "$(dirname -- "$filePath")" || return 0 + touch -- "$filePath" || return 0 + tempFile="$(mktemp "${filePath}.tmp.XXXXXX")" || return 0 + + awk -v section="$sectionName" -v key="$keyName" -v value="$keyValue" ' + BEGIN { + inSection = 0 + sawSection = 0 + wroteKey = 0 + } + $0 ~ "^\\[" { + if (inSection && !wroteKey) { + print key "=" value + wroteKey = 1 + } + inSection = ($0 == "[" section "]") + if (inSection) { + sawSection = 1 + } + } + inSection && $0 ~ "^[[:space:]]*" key "[[:space:]]*=" { + if (!wroteKey) { + print key "=" value + wroteKey = 1 + } + next + } + { print } + END { + if (sawSection && inSection && !wroteKey) { + print key "=" value + } else if (!sawSection) { + print "" + print "[" section "]" + print key "=" value + } + } + ' "$filePath" > "$tempFile" && mv -- "$tempFile" "$filePath" + rm -f -- "$tempFile" +} + +fileManager="${1:-}" +fileManager="${fileManager##*/}" + +case "$fileManager" in + thunar) + command -v xfconf-query > /dev/null || exit 0 + xfconf-query -c thunar -p /last-view -s ThunarDetailsView > /dev/null 2>&1 || true + ;; + pcmanfm) + set_ini_key "${XDG_CONFIG_HOME:-${HOME}/.config}/pcmanfm/default/pcmanfm.conf" "ui" "view_mode" "list" + ;; + pcmanfm-qt) + set_ini_key "${XDG_CONFIG_HOME:-${HOME}/.config}/pcmanfm-qt/lxqt/settings.conf" "FolderView" "Mode" "list" + ;; +esac