53 Commits
v1.7 ... v2.1

Author SHA1 Message Date
278ee7a581 Updated the comment at the top of the i3 configuration file. 2023-11-19 16:38:10 -05:00
1b031229a7 Removed lxpolkit because it was causing errors. 2023-10-30 16:55:07 -04:00
e86f2d01f6 Removed lxpolkit because it was causing errors. 2023-10-30 16:53:23 -04:00
07ed90d4fc Forgot to change the prompt to ask about the battery notifications. 2023-10-22 21:00:05 -04:00
65e8c0636a Ask if the battery alert script is wanted during setup if acpi is installed. 2023-10-22 20:54:31 -04:00
2e15449d9a Fixed a bug with restarting remind on i3 restart. Fixed a bug with battery_alert not being loaded. 2023-10-15 11:58:33 -04:00
8e9c2c8a7d Updated the README. 2023-10-13 11:13:17 -04:00
9b539d48ab Battery alert script added for laptops. Provides both speech and sound alerts. 2023-10-11 19:39:26 -04:00
aae01bff20 Make sure any remind process is terminated before restarting i3. This prevents multiples of notifications from happening from multiple instances of the server. 2023-10-04 13:39:35 -04:00
ef882604af Single time remind option added. 2023-10-04 13:21:35 -04:00
eb8fa44757 Hopefully fix it so that notifications aren't limited any more. 2023-10-02 22:31:19 -04:00
6063fac699 Updated keyboard layouts, Thanks Didier for the changes. 2023-10-02 17:04:17 -04:00
6f8b418e80 Fixed a typo in the cancel button for daily reminders. 2023-10-01 14:49:15 -04:00
239d110f58 Create ~/.reminders if remind is detected, this should hopefully prevent the daemon not running error that happens with new users. 2023-10-01 14:45:31 -04:00
b24c0fad91 Try to parse reminders for url, if found and xclip is installed, place the url in the clipboard and notify the reminder without the url. Much nicker for speech. 2023-10-01 02:17:38 -04:00
00a89467fd Set the expire time on notifications so hopefully max notifications exceeded error doesn't happen any more. 2023-09-28 18:00:49 -04:00
9c3cadd7dc Do not bind f to file browser in Ratpoison Mode if no file browser was found. 2023-09-28 09:45:10 -04:00
43bec02a2c Updated reminder dialog with better button icons. 2023-09-28 09:31:01 -04:00
a7746d962c Updated readme with GTK2 configuration as well. 2023-09-28 07:20:22 -06:00
0727ff31c3 Fixed README formatting. 2023-09-28 09:13:15 -04:00
482d8ebed2 Hopefully fixed formatting. 2023-09-28 07:02:54 -06:00
df4182b32f Added another small note about GTK sound themes. 2023-09-28 06:59:58 -06:00
ef030f9cd1 Updated readme, explains how to set gtk sound theme. 2023-09-28 06:58:08 -06:00
e484405684 Updated readme to include libcanberra as an optional dependency. 2023-09-28 06:30:25 -06:00
4d5abd5489 Added login sound option, uses canberra-gtk-play if installed, if not doesn't ask. 2023-09-28 06:27:39 -06:00
cff7288c9e Add daily reminder option added. A second option for viewing today's reminders added. It is view only, and does not contain the delete option like view all reminders has. 2023-09-27 01:35:06 -04:00
b1f413660f Fixed up formatting for hours, minutes, and day of month. Properly handle window close events using cancel or escape. Add monthly reminder option. 2023-09-26 21:49:35 -04:00
1a0ad68ad2 Merge branch 'master' of ssh://git.stormux.org/storm/I38 2023-09-26 06:56:27 -06:00
556b8cb7d8 Added a window close sound to the sound script. 2023-09-26 06:38:02 -06:00
563e0277aa View reminder wil now tell you if there are no reminders. 2023-09-26 08:33:15 -04:00
4e00211c02 Reminder notifications now play a sound before they happen, so should be harder to miss. 2023-09-26 08:26:55 -04:00
e61d0394c3 Add Custom reminder option. 2023-09-25 08:54:51 -04:00
af77a60355 Reminder dialog now handles pressing escape to close. 2023-09-24 14:21:27 -04:00
80cb28dc10 Simple reminder management gui added. For now, only simple recurring reminders can be added. I may try to add more options in the future. This was a bit complex, so watch for bugs and make sure your reminders actually work before depending on its reliability. 2023-09-24 13:40:22 -04:00
2968bbe325 Forgot to remove the background from the remind command. It's handled by the i3 config. 2023-09-22 00:50:52 -04:00
15bf470616 Started work on adding reminders. 2023-09-19 21:45:00 -04:00
19d201ecf4 Experimental multiple keyboard support added. 2023-08-31 01:31:51 -04:00
cb7bfb36e8 Add lxpolkit for policy kit authentication. 2023-08-30 16:08:24 -04:00
9c16367299 Email client bound to alt+e in ratpoison mode. 2023-08-29 16:57:06 -04:00
68620696fc Forgot to actually add some of my changes. 2023-08-29 16:23:51 -04:00
43067c0efe Fixed a couple of problems with screen brightness script. 2023-08-29 16:19:43 -04:00
4773bdae87 Screen brightness script added. 2023-08-29 16:14:11 -04:00
ea7450bb8b Fixed a bug when opening a terminal with RP + c. 2023-07-05 20:43:30 -04:00
50f7bd809a Work on Sway support for the window lister. Unfortunately, most of the window IDs that get returned are "None" so you can't actually select the window, but it does list them now. 2023-06-14 02:05:36 -04:00
1de8cde4cf Updated optional applications list in the README. 2023-06-10 13:21:29 -04:00
7ee783edeb Add ability to have removable storage auto mounted if udiskie is detected. 2023-06-07 00:15:13 -04:00
9c1ac5f7f3 Sound added for custom modes. Default mode sound should only play when switching back to the default mode now. This means we now have ratpoison mode sound, bypassmode sound, default sound for when no mode is being used other than default bindings, and custom, for when you add your on modes in the customizations file. 2023-06-01 15:47:10 -04:00
dca451c996 Workspace switching sound should now work correctly in Sway. 2023-06-01 15:20:52 -04:00
61cdfffc0d Window list should now work for sway. 2023-06-01 15:10:47 -04:00
5851aec8b3 Make the sway option use the sway version of sensible-terminal. 2023-06-01 14:48:52 -04:00
8b30abc8b6 Bypass mode added. In this mode, all keys except the toggle bypass mode key, mod+shift+backspace, will be passed to the application. As far as I know, the toggle key should not conflict with anything. 2023-04-25 19:09:20 -04:00
9efa0b110d this git push brought to you by my inability to type complete words. 2023-04-09 21:48:11 -04:00
c1278a81ee work around for Void Linux weirdness. 2023-04-09 21:22:38 -04:00
9 changed files with 754 additions and 16 deletions

View File

@ -15,24 +15,57 @@ An uppercase I looks like a 1, 3 from i3, and 8 because the song [We Are 138](ht
## Requirements
- i3-wm: The i3 window manager.
- acpi: [optional] for battery status. It will still work even without this package, but uses it if it is installed.
- acpi: [optional] for battery status. It will still work even without this package, but uses it if it is installed. Required for the battery monitor with sound alerts.
- dex: [optional] Alternative method for auto starting applications.
- clipster: clipboard manager
- jq: for getting the current workspace
- libcanberra: [optional]To play the desktop login sound.
- libnotify: For sending notifications
- notification-daemon: To handle notifications
- ocrdesktop: For getting contents of the current window with OCR.
- pamixer: for the mute-unmute script
- playerctl: music controls
- python-i3ipc: for sounds etc.
- remind: [optional]For reminder notifications, Requires notify-daemon and notify-send for automatic reminders.
- sgtk-menu: for applications menu
- sox: for sounds.
- transfersh: [optional] for file sharing GUI
- udiskie: [optional] for automatically mounting removable storage
- xclip: Clipboard support
- xbacklight: [optional] for screen brightness adjustment
- xorg-setxkbmap: [optional] for multiple keyboard layouts
- yad: For screen reader accessible dialogs
I38 will try to detect your browser, file manager, and web browser and present you with a list of options to bind to their launch keys. It will also create bindings for pidgin and mumble if they are installed. To use the bindings, press your ratpoison mode key which is set when you run the i38.sh script. next, press the binding for the application you want, w for web browser, e for text editor, f for file manager, m for mumble, etc. To learn all the bindings, find and read the mode ratpoison section of ~/.config/i3/config.
I38 will try to detect your browser, file manager, and web browser and present you with a list of options to bind to their launch keys. It will also create bindings for pidgin and mumble if they are installed. To use the bindings, press your ratpoison mode key which is set when you run the i38.sh script. next, press the binding for the application you want; w for web browser, e for text editor, f for file manager, m for mumble, etc. To learn all the bindings, find and read the mode ratpoison section of ~/.config/i3/config.
The login sound uses the GTK sound theme. Configure this using GTK configuration files or gsettings. Replace "name" with the name of the theme you want to use.
Note that if you enable all sound events as shown below, you'll also hear GTK sounds when moving around menus, buttons, etc, if the sound theme has sounds for those events.
To configure the theme name with gsettings, do as follows.
gsettings set org.gnome.desktop.sound theme-name name
If you'd like all sound types enabled:
gsettings set org.gnome.desktop.sound input-feedback-sounds true
gsettings set org.gnome.desktop.sound event-sounds true
To configure with a config file, edit or create ~/.config/gtk-3.0/settings.ini
[Settings]
gtk-enable-event-sounds=1
gtk-enable-input-feedback-sounds=1
gtk-sound-theme-name=name
gtk-modules=canberra-gtk-module
You can apply the same configuration to GTK2 appss. Create or edit ~/.gtkrc-2.0
gtk-enable-event-sounds=1
gtk-enable-input-feedback-sounds=1
gtk-sound-theme-name=name
gtk-modules=canberra-gtk-module
## Usage:

203
i38.sh
View File

@ -6,6 +6,7 @@
i3Path="${XDG_CONFIG_HOME:-$HOME/.config}/i3"
i3msg="i3-msg"
sensibleTerminal="i3-sensible-terminal"
# Dialog accessibility
export DIALOGOPTS='--no-lines --visit-items'
@ -24,6 +25,110 @@ if [[ -n "${missing}" ]]; then
exit 1
fi
keyboard_menu() {
keyboardMenu=("us" "English (US)"
"af" "Dari"
"al" "Albanian"
"et" "Amharic"
"ara" "Arabic"
"ma" "Arabic (Morocco)"
"sy" "Arabic (Syria)"
"am" "Armenian"
"az" "Azerbaijani"
"ml" "Bambara"
"bd" "Bangla"
"by" "Belarusian"
"be" "Belgian"
"dz" "Berber (Algeria, Latin)"
"ba" "Bosnian"
"brai" "Braille"
"bg" "Bulgarian"
"mm" "Burmese"
"cn" "Chinese"
"hr" "Croatian"
"cz" "Czech"
"dk" "Danish"
"mv" "Dhivehi"
"nl" "Dutch"
"bt" "Dzongkha"
"au" "English (Australia)"
"gh" "English (Ghana)"
"ng" "English (Nigeria)"
"za" "English (South Africa)"
"gb" "English (UK)"
"epo" "Esperanto"
"ee" "Estonian"
"fo" "Faroese"
"ph" "Filipino"
"fi" "Finnish"
"fr" "French"
"ca" "French (Canada)"
"cd" "French (Democratic Republic of the Congo)"
"ge" "Georgian"
"de" "German"
"ch" "German (Switzerland)"
"gr" "Greek"
"il" "Hebrew"
"hu" "Hungarian"
"is" "Icelandic"
"in" "Indian"
"jv" "Indonesian (Javanese)"
"iq" "Iraqi"
"ie" "Irish"
"it" "Italian"
"jp" "Japanese"
"nec_vndr/jp" "Japanese (PC-98)"
"kz" "Kazakh"
"kh" "Khmer (Cambodia)"
"kr" "Korean"
"kg" "Kyrgyz"
"la" "Lao"
"lv" "Latvian"
"lt" "Lithuanian"
"mk" "Macedonian"
"mv" "Malay (Jawi, Arabic Keyboard)"
"mt" "Maltese"
"mao" "Maori"
"mn" "Mongolian"
"me" "Montenegrin"
"gn" "N'Ko (AZERTY)"
"np" "Nepali"
"no" "Norwegian"
"ir" "Persian"
"pl" "Polish"
"pt" "Portuguese"
"br" "Portuguese (Brazil)"
"ro" "Romanian"
"ru" "Russian"
"rs" "Serbian"
"lk" "Sinhala (phonetic)"
"sk" "Slovak"
"si" "Slovenian"
"es" "Spanish"
"latam" "Spanish (Latin American)"
"tz" "Swahili (Tanzania)"
"se" "Swedish"
"tw" "Taiwanese"
"tj" "Tajik"
"th" "Thai"
"tr" "Turkish"
"tm" "Turkmen"
"bw" "Tswana"
"ua" "Ukrainian"
"pk" "Urdu (Pakistan)"
"uz" "Uzbek (Afghanistan)"
"vn" "Vietnamese"
"sn" "Wolof"
)
dialog --title "I38" \
--backtitle "Use the arrow keys to find the option you want, and enter to select it. When you are finished selecting layouts, use right arrow to find \"Done\" and press enter." \
--clear \
--cancel-label "Done" \
--no-tags \
--menu "Select Keyboard Layout" 0 0 0 "${keyboardMenu[@]}" --stdout
return $?
}
menulist() {
# Args: List of items for menu.
# returns: selected tag
@ -37,7 +142,7 @@ menulist() {
--backtitle "Use the arrow keys to find the option you want, and enter to select it." \
--clear \
--no-tags \
--menu "$menuText" 0 0 0 ${menuList[@]} --stdout
--menu "$menuText" 0 0 0 "${menuList[@]}" --stdout
return $?
}
@ -147,6 +252,7 @@ while getopts "${args}" i ; do
s)
i3msg="swaymsg"
i3Path="${XDG_CONFIG_HOME:-$HOME/.config}/sway"
sensibleTerminal="sway --sensible-terminal"
;;
u) update_scripts;;
x) write_xinitrc ;&
@ -170,11 +276,35 @@ while [[ "$escapeKey" == "$mod" ]]; do
dialog --title "I38" --msgbox "Ratpoison and mod key cannot be the same key." -1 -1
fi
done
# Multiple keyboard layouts
if [[ $(yesno "Do you want to use multiple keyboard layouts?") -eq 0 ]]; then
unset kbd
while : ; do
kbd+=("$(keyboard_menu)") || break
done
fi
# Volume jump
volumeJump=$(rangebox "How much should pressing the volume keys change the volume?" 1 15 5)
# Email client
unset programList
for i in betterbird evolution thunderbird ; do
if command -v ${i/#-/} &> /dev/null ; then
if [ -n "$programList" ]; then
programList="$programList $i"
else
programList="$i"
fi
fi
done
if [ "$programList" != "${programList// /}" ]; then
emailClient="$(menulist "Email client:" $programList)"
else
emailClient="${programList/#-/}"
fi
emailClient="$(command -v $emailClient)"
# Web browser
unset programList
for i in brave chromium epiphany firefox google-chrome-stable midori seamonkey ; do
for i in brave chromium epiphany firefox google-chrome-stable microsoft-edge microsoft-edge-beta microsoft-edge-dev midori seamonkey ; do
if command -v ${i/#-/} &> /dev/null ; then
if [ -n "$programList" ]; then
programList="$programList $i"
@ -224,6 +354,11 @@ else
fileBrowser="${programList/#-/}"
fi
fileBrowser="$(command -v $fileBrowser)"
# Auto mount removable media
udiskie=1
if command -v udiskie &> /dev/null ; then
export udiskie=$(yesno "Would you like removable drives to automatically mount when plugged in?")
fi
# Auto start with dex
dex=1
if command -v dex &> /dev/null ; then
@ -232,10 +367,19 @@ fi
if [[ $dex -eq 0 ]]; then
dex -t "${XDG_CONFIG_HOME:-${HOME}/.config}/autostart" -c $(command -v orca)
fi
if command -v acpi &> /dev/null ; then
batteryAlert=1
batteryAlert=$(yesno "Do you want low battery notifications?")
fi
brlapi=1
brlapi=$(yesno "Do you want to use a braille display with Orca?")
sounds=1
sounds=$(yesno "Do you want window event sounds?")
# Play Login Sound
loginSound=1
if command -v canberra-gtk-play &> /dev/null ; then
export loginSound=$(yesno "Would you like to play the default desktop-login sound according to your GTK sound theme upon login?")
fi
if [[ -d "${i3Path}" ]]; then
yesno "This will replace your existing configuration at ${i3Path}. Do you want to continue?" || exit 0
@ -248,7 +392,7 @@ mkdir -p "${i3Path}"
cp -rv scripts/ "${i3Path}/" | dialog --backtitle "I38" --progressbox "Moving scripts into place and writing config..." -1 -1
cat << EOF > ${i3Path}/config
# Generated by I38 (${0##*/}) https://github.com/stormdragon2976/I38
# Generated by I38 (${0##*/}) https://git.stormux.org/storm/I38
# $(date '+%A, %B %d, %Y at %I:%M%p')
@ -302,7 +446,7 @@ bindsym XF86AudioStop exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2
bindsym XF86AudioNext exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2000 pad 0 .02" "| sox -np synth 0.03 sin 2000" norm 1.0 vol 0.4 & ${i3Path}/scripts/music_controler.sh next
# start a terminal
bindsym \$mod+Return exec i3-sensible-terminal
bindsym \$mod+Return exec $sensibleTerminal
# kill focused window
bindsym \$mod+F4 kill
@ -367,8 +511,22 @@ bindsym Control+Shift+F9 move container to workspace number \$ws9, exec spd-say
bindsym Control+Shift+F10 move container to workspace number \$ws10, exec spd-say -P important -Cw "moved to workspace 10"
# A mode that will pass all keys except $mod+shift+backspace to the current application.
# Use $mod+shift+backspace to exit the mode.
bindsym $mod+shift+BackSpace mode "bypass"
mode "bypass" {
# Exit bypass mode.
bindsym $mod+Shift+BackSpace mode "default"
}
EOF
# Multiple keyboard layouts if requested.
if [[ ${#kbd[@]} -gt 1 ]]; then
echo "bindsym Mod4+space exec ${i3Path}/scripts/keyboard.sh cycle ${kbd[@]}" >> ${i3Path}/config
fi
# Create ratpoison mode if requested.
if [[ -n "${escapeKey}" ]]; then
cat << EOF >> ${i3Path}/config
@ -377,11 +535,15 @@ mode "ratpoison" {
# I38 help bound to ?
bindsym Shift+slash exec ${i3Path}/scripts/i38-help.sh, mode "default"
# Terminal emulator bound to c
bindsym c exec i3-sensible-terminal, mode "default"
bindsym c exec $sensibleTerminal, mode "default"
# Text editor bound to e
bindsym e exec $textEditor, mode "default"
# File browser bound to f
bindsym f exec $fileBrowser, mode "default"
$(if [[ ${#fileBrowser} -gt 3 ]]; then
echo "# File browser bound to f"
echo "bindsym f exec $fileBrowser, mode \"default\""
fi)
# Email client bound to \$mod+e
bindsym \$mod+e exec $emailClient, mode "default"
# Web browser bound to w
bindsym w exec $webBrowser, mode "default"
# Kill window bound to k
@ -390,6 +552,10 @@ $(if command -v mumble &> /dev/null ; then
echo "# Mumble bound to m"
echo "bindsym m exec $(command -v mumble), mode \"default\""
fi)
$(if command -v remind &> /dev/null ; then
echo "# Reminders bound to r"
echo "bindsym r exec --no-startup-id ${i3Path}/scripts/reminder.sh, mode \"default\""
fi)
$(if command -v ocrdesktop &> /dev/null ; then
echo "# OCR desktop bound to print screen alternative \$mod+r"
echo "bindsym Print exec $(command -v ocrdesktop) -b, mode \"default\""
@ -399,6 +565,10 @@ $(if command -v pidgin &> /dev/null ; then
echo "# p bound to pidgin"
echo "bindsym p exec $(command -v pidgin), mode \"default\""
fi)
$(if command -v xrandr &> /dev/null ; then
echo "# alt+s bound to brightness control"
echo "bindsym \$mod+s exec --no-startup-id ${i3Path}/scripts/screen_controller.sh, mode \"default\""
fi)
$(if command -v transfersh &> /dev/null ; then
echo "# t bound to share file with transfer.sh"
echo 'bindsym t exec bash -c '"'"'fileName="$(yad --title "I38 Upload File" --file)" && url="$(transfersh "${fileName}" | tee >(yad --title "I38 - Uploading ${fileName##*/} ..." --progress --pulsate --auto-close))" && echo "${url#*saved at: }" | tee >(yad --title "I38 - Upload URL" --show-cursor --show-uri --button yad-close --sticky --text-info) >(xclip -selection clipboard)'"', mode \"default\""
@ -428,7 +598,7 @@ bindsym Shift+o exec $(command -v orca) --replace, mode "default"
# reload the configuration file
bindsym Control+semicolon exec bash -c '$i3msg -t run_command reload && spd-say -P important -Cw "I38 Configuration reloaded."', mode "default"
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym Control+Shift+semicolon exec bash -c '$i3msg -t run_command restart && spd-say -P important -Cw "I3 restarted."', mode "default"
bindsym Control+Shift+semicolon exec bash -c 'killall remind || true && $i3msg -t run_command restart && spd-say -P important -Cw "I3 restarted."', mode "default"
# Run dialog with exclamation
bindsym Shift+exclam exec ${i3Path}/scripts/run_dialog.sh, mode "default"
# exit i3 (logs you out of your X session)
@ -448,12 +618,29 @@ cat << EOF >> ${i3Path}/config
$(if [[ $sounds -eq 0 ]]; then
echo "exec_always --no-startup-id ${i3Path}/scripts/sound.py"
fi
if [[ $loginSound -eq 0 ]]; then
echo 'exec --no-startup-id canberra-gtk-play -i desktop-login'
fi
if [[ $brlapi -eq 0 ]]; then
echo 'exec --no-startup-id xbrlapi --quiet'
fi
if [[ $udiskie -eq 0 ]]; then
echo 'exec --no-startup-id udiskie'
fi
if [[ -x "/usr/lib/notification-daemon-1.0/notification-daemon" ]]; then
echo 'exec_always --no-startup-id /usr/lib/notification-daemon-1.0/notification-daemon -r'
fi
# Work around for weird Void Linux stuff.
if [[ -x "/usr/libexec/notification-daemon" ]]; then
echo 'exec_always --no-startup-id /usr/libexec/notification-daemon -r'
fi
if command -v remind &> /dev/null && command -v notify-send &> /dev/null ; then
echo "exec_always --no-startup-id $(command -v remind) -z '-k:${HOME}/.config/i3/scripts/reminder.sh %s &' ${HOME}/.reminders < /dev/null > /dev/null 2>&1"
touch ~/.reminders
fi
if [[ $batteryAlert -eq 0 ]]; then
echo "exec_always --no-startup-id ${i3Path}/scripts/battery_alert.sh"
fi
if [[ $dex -eq 0 ]]; then
echo '# Start XDG autostart .desktop files using dex. See also'
echo '# https://wiki.archlinux.org/index.php/XDG_Autostart'

View File

@ -1,8 +1,17 @@
#!/usr/bin/env bash
workSpace="$(i3-msg -t get_workspaces \
| jq '.[] | select(.focused==true).name' \
| cut -d"\"" -f2)"
path="$(readlink -f $0)"
path="${path%/*/*}"
path="${path##*/}"
if [[ "$path" == "i3" ]]; then
workSpace="$(i3-msg -t get_workspaces \
| jq '.[] | select(.focused==true).name' \
| cut -d"\"" -f2)"
else
workSpace="$(swaymsg -t get_workspaces \
| jq '.[] | select(.focused==true).name' \
| cut -d"\"" -f2)"
fi
left=9
right=0
msg="Workspace ${workSpace}"

25
scripts/battery_alert.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/sh
if ! command -v acpi &> /dev/null ; then
exit 0
fi
while : ; do
acpi -b | awk -F'[,:%]' '{print $2, $3}' | {
read -r status capacity
if [[ "$status" == "Discharging" ]] && [[ "$capacity" -le 15 ]] && [[ "$capacity" -gt 10 ]]; then
play -qV0 "|sox -n -p synth saw E2 fade 0 0.25 0.05" "|sox -n -p synth saw E2 fade 0 0.25 0.05" norm -7
spd-say -P important "Battery $capacity percent."
elif [[ "$status" == "Discharging" ]] && [[ "$capacity" -le 10 ]] && [[ "$capacity" -gt 5 ]]; then
play -qV0 "|sox -n -p synth saw E2 fade 0 0.25 0.05" "|sox -n -p synth saw E2 fade 0 0.25 0.05" norm -7
spd-say -P important "Battery $capacity percent."
elif [[ "$status" == "Discharging" ]] && [[ "$capacity" -lt 5 ]]; then
play -qV0 "|sox -np synth sq C#5 sq D#5 sq F#5 sq A5 sq C#6" remix - fade 0 5.5 5 pitch -400
spd-say -P important "Battery $capacity percent."
fi
}
sleep 5m
done
exit 0

48
scripts/keyboard.sh Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env bash
# This script is a modified version of i3-keyboard-layout.
# Originally Copyright (c) 2018 Sergio Gil.
# https://github.com/porras/i3-keyboard-layout
# This modified script, like the rest of I38, is released under the WTFPL license.
# The original work was released under the MIT license.
set -e
get_kbdlayout() {
layout=$(setxkbmap -query | grep -oP 'layout:\s*\K([\w,]+)')
variant=$(setxkbmap -query | grep -oP 'variant:\s*\K(\w+)')
echo "$layout" "$variant"
}
set_kbdlayout() {
eval "array=($1)"
setxkbmap "${array[@]}" &&
spd-say -P important -Cw "${array[@]}"
}
cycle() {
current_layout=$(get_kbdlayout | xargs)
layouts=("$@" "$1") # add the first one at the end so that it cycles
index=0
while [ "${layouts[$index]}" != "$current_layout" ] && [ $index -lt "${#layouts[@]}" ]; do index=$[index +1]; done
next_index=$[index +1]
next_layout=${layouts[$next_index]}
set_kbdlayout "$next_layout"
}
subcommand="$1"
shift || exit 1
case $subcommand in
"get")
echo -n $(get_kbdlayout)
;;
"cycle")
cycle "$@"
;;
esac
exit 0

376
scripts/reminder.sh Executable file
View File

@ -0,0 +1,376 @@
#!/usr/bin/env bash
error() {
yad --form --selectable-labels --title "I38 - Reminder Error" --field="${*}":lbl --button="Close!gtk-ok":0
}
message() {
yad --form --selectable-labels --title "I38 - Reminder" --field="${*}":lbl --button="Close!gtk-ok":0
}
add_reminder() {
info="$(yad --form --selectable-labels \
--title "I38 - New Reminder" \
--field="Comment for ~/.reminders file":lbl "" \
--field="Reminder Comment" "# Added by I38" \
--field="Enter date in yyyy-mm-dd format:":lbl "" \
--field="Date" "$(date '+%Y-%m-%d')" \
--field="Reminder text:":lbl "" \
--field="Reminder" "" \
--field="Select Hour:":num '1!1..12' \
--field="Select Minute:":num '0!0..59' \
--field="Select AM or PM":cb 'AM!PM' \
--button="Cancel!gtk-cancel:1" \
--button="Create Reminder!gtk-ok:0")"
if [[ $? -eq 1 || $? -eq 252 ]]; then
return
fi
while [[ $info =~ \|\| ]]; do
info="${info//||/|}"
done
info="${info#|#}"
# Get information for reminder into an array
IFS='|' read -a reminder <<< $info
# Fix time to be 2 digits.
[[ ${#reminder[3]} -eq 1 ]] && reminder[3]="0${reminder[3]}"
[[ ${#reminder[4]} -eq 1 ]] && reminder[4]="0${reminder[4]}"
# Check date format
if ! [[ "${reminder[1]}" =~ ^[2-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$ ]]; then
error "Invalid date format given, addition canceled."
return
fi
if [[ ${#reminder[2]} -lt 3 ]]; then
error "No reminder text given, addition canceled."
return
fi
# Add reminder
if [[ "${reminder[0]}" != "# " ]]; then
echo "# ${reminder[0]}" >> ~/.reminders
fi
echo "REM $(date -d "${reminder[1]}" '+%b %d %Y') AT ${reminder[3]}:${reminder[4]}${reminder[5]} +5 MSG ${reminder[2]} %2." >> ~/.reminders
if [[ -N ~/.reminders ]]; then
message "Reminder added."
else
error "Something went wrong. The reminder was not added."
fi
}
add_custom_reminder() {
info="$(yad --form --selectable-labels \
--title "I38 - New Custom Reminder" \
--field="Comment for ~/.reminders file":lbl "" \
--field="Reminder Comment" "" \
--field="Reminder entry. Remember for notifications, it must ccontain the +5 after the time and the %2. at the end of the MSG.":lbl "" \
--field="Reminder" "REM at +5 MSG %2.")"
if [[ $? -eq 1 || $? -eq 252 ]]; then
return
fi
while [[ $info =~ \|\| ]]; do
info="${info//||/|}"
done
info="${info#|#}"
# Get information for reminder into an array
IFS='|' read -a reminder <<< $info
if [[ "${reminder[0]}" != "# " ]]; then
echo "# ${reminder[0]}" >> ~/.reminders
fi
if [[ "${reminder[1]}" != "REM at +5 MSG %2." ]]; then
echo "${reminder[1]}" >> ~/.reminders
message "Custom reminder added."
else
error "No reminder text entered, No action taken."
fi
}
add_daily_reminder() {
info="$(yad --form --selectable-labels \
--title "I38 - New Daily Reminder" \
--field="Reminder Text" "" \
--field="Select Hour:":num '1!1..12' \
--field="Select Minute:":num '0!0..59' \
--field="Select AM or PM":cb 'AM!PM' \
--button="Cancel!gtk-cancel:1" \
--button="Create Reminder!gtk-ok:0")"
# Properly handle window close events.
if [[ $? -eq 1 || $? -eq 252 ]]; then
return
fi
# Get information for reminder into an array
IFS='|' read -a reminder <<< $info
# Fix time to be 2 digits.
[[ ${#reminder[1]} -eq 1 ]] && reminder[1]="0${reminder[1]}"
[[ ${#reminder[2]} -eq 1 ]] && reminder[2]="0${reminder[2]}"
# Make sure we have reminder text
if [[ ${#reminder[0]} -lt 3 ]]; then
error "No reminder text given, addition canceled."
return
fi
reminderEntry="REM AT ${reminder[1]}:${reminder[2]}${reminder[3]} +5 REPEAT daily MSG ${reminder[0]} %2."
echo "# Added by I38." >> ~/.reminders
echo "$reminderEntry" >> ~/.reminders
if [[ -N ~/.reminders ]]; then
message "Reminder added."
else
error "Something went wrong. The reminder was not added."
fi
}
add_monthly_reminder() {
info="$(yad --form --selectable-labels \
--title "I38 - New Monthly Reminder" \
--field="For dates over 28, some months may be skipped. If you want to be sure of the last day of the month, check the last day of month box.":lbl "" \
--field="Reminder Text" "" \
--field="Select Date:":num '1!1..31' \
--field="Select Hour:":num '1!1..12' \
--field="Select Minute:":num '0!0..59' \
--field="Select AM or PM":cb 'AM!PM' \
--field="Last day of month":chk "FALSE" \
--button="Cancel!gtk-cancel:1" \
--button="Create Reminder!gtk-ok:0")"
# Properly handle window close events.
if [[ $? -eq 1 || $? -eq 252 ]]; then
return
fi
# Get information for reminder into an array
IFS='|' read -a reminder <<< $info
# Fix time and date to be 2 digits.
[[ ${#reminder[2]} -eq 1 ]] && reminder[2]="0${reminder[2]}"
[[ ${#reminder[3]} -eq 1 ]] && reminder[3]="0${reminder[3]}"
[[ ${#reminder[4]} -eq 1 ]] && reminder[4]="0${reminder[4]}"
# Make sure we have reminder text
if [[ ${#reminder[1]} -lt 3 ]]; then
error "No reminder text given, addition canceled."
return
fi
if [[ "${reminder[6]}" == "FALSE" ]]; then
reminderEntry="REM ${reminder[2]} "
else
reminderEntry="REM 1 -1 "
fi
reminderEntry+="AT ${reminder[3]}:${reminder[4]}${reminder[5]} +5 REPEAT monthly MSG ${reminder[1]} %2."
echo "# Added by I38." >> ~/.reminders
echo "$reminderEntry" >> ~/.reminders
if [[ -N ~/.reminders ]]; then
message "Reminder added."
else
error "Something went wrong. The reminder was not added."
fi
}
add_weekly_reminder() {
info="$(yad --form --selectable-labels \
--title "I38 - New Weekly Reminder" \
--field="Reminder Text" "" \
--field="Select Days":lbl "" \
--field="Sunday":chk "FALSE" \
--field="Monday":chk "FALSE" \
--field="Tuesday":chk "FALSE" \
--field="Wednesday":chk "FALSE" \
--field="Thursday":chk "FALSE" \
--field="Friday":chk "FALSE" \
--field="Saturday":chk "FALSE" \
--field="Select Hour:":num '1!1..12' \
--field="Select Minute:":num '0!0..59' \
--field="Select AM or PM":cb 'AM!PM' \
--button="Cancel!gtk-cancel:1" \
--button="Create Reminder!gtk-ok:0")"
# Properly handle window close events.
if [[ $? -eq 1 || $? -eq 252 ]]; then
return
fi
# Get information for reminder into an array
IFS='|' read -a reminder <<< $info
# Fix time to be 2 digits.
[[ ${#reminder[9]} -eq 1 ]] && reminder[9]="0${reminder[9]}"
[[ ${#reminder[10]} -eq 1 ]] && reminder[10]="0${reminder[10]}"
# Change checked days into their name.
reminder[2]="${reminder[2]/TRUE/Sun}"
reminder[3]="${reminder[3]/TRUE/Mon}"
reminder[4]="${reminder[4]/TRUE/Tue}"
reminder[5]="${reminder[5]/TRUE/Wed}"
reminder[6]="${reminder[6]/TRUE/Thu}"
reminder[7]="${reminder[7]/TRUE/Fri}"
reminder[8]="${reminder[8]/TRUE/Sat}"
# Make sure we have reminder text
if [[ ${#reminder[0]} -lt 3 ]]; then
error "No reminder text given, addition canceled."
return
fi
reminderEntry="REM "
noDays=1
for ((i=2;i<=8;i++)) ; do
if [[ "${reminder[i]}" != "FALSE" ]]; then
reminderEntry+="${reminder[i]} "
noDays=0
fi
done
if [[ $noDays -eq 1 ]]; then
error "No days were selected for the reminder. Nothing changed."
return
fi
reminderEntry+="AT ${reminder[9]}:${reminder[10]}${reminder[11]} +5 REPEAT weekly MSG ${reminder[0]} %2."
echo "# Added by I38." >> ~/.reminders
echo "$reminderEntry" >> ~/.reminders
if [[ -N ~/.reminders ]]; then
message "Reminder added."
else
error "Something went wrong. The reminder was not added."
fi
}
view_reminders() {
if ! [[ -r ~/.reminders ]]; then
error "No reminders found."
return
fi
mapfile -t lines < ~/.reminders
# Create an empty array to store cleaned-up reminders
yadMenu=()
# Iterate through the reminder lines and clean them up
for i in "${lines[@]}"; do
# Remove the "REM" prefix and leading/trailing spaces
formattedLine="${i#*REM }"
# Remove MSG from the output.
formattedLine="${formattedLine/MSG /}"
# remove the usually %2. from the end of the line, but accept any digit in case someone changes it.
formattedLine="${formattedLine% %[[:digit:]].}"
# Add to the menu
yadMenu+=("$formattedLine")
done
# Display the reminders
reminder="$(yad --list --title "I38 - Reminders" --text "Current reminders:" \
--column "Reminder" "${yadMenu[@]}" \
--button="Close!gtk-ok:1" --button="Delete!gtk-delete:0" --response=1)"
if [[ $? -ne 0 ]]; then
return
fi
if [[ "${reminder:0:1}" == "#" ]]; then
error "Please select the actual reminder to be deleted, anything starting with # is only a comment. Nothing changed."
return
fi
# Remove the | from the end of reminder
reminder="${reminder%|}"
# Find the index to remove from lines.
for i in "${!yadMenu[@]}" ; do
if [[ "${yadMenu[i]}" == "${reminder}" ]]; then
# Delete selected reminder and possible preceeding comment.
commentIndex=$((i - 1))
if [[ "${lines[commentIndex]:0:1}" == "#" ]]; then
unset lines[$commentIndex]
fi
unset lines[$i]
message "Reminder deleted."
printf "%s\n" "${lines[@]}" > ~/.reminders
fi
done
}
view_today() {
if ! [[ -r ~/.reminders ]]; then
error "No reminders found."
return
fi
mapfile -t lines < <(rem | tr -s $'\n')
# Display the reminders
yad --list --title "I38 - Reminders" --text "Today's reminders:" \
--column "Reminder" "${lines[@]}" \
--button="Close!gtk-ok:0"
}
if ! command -v remind &> /dev/null ; then
error "Please install remind. For notifications, please make sure to have notification-daemon and notify-send as well. Run i38.sh to regenerate your i3 config after the needed components are installed."
exit 1
fi
if [[ $# -ne 0 ]]; then
sox -ndqV0 synth .1 tri 600 norm -9 pad .05 repeat
notification="$*"
if [[ "${notification}" =~ "http" ]]; then
url="${notification##*http}"
url="${url%%[[:space:]]*}"
url="http${url}"
notification="${notification/${url}[[:space:]]/}"
url="${url%[[:space:].?!]}"
fi
if command -v xclip &> /dev/null && [[ "${#url}" -gt 3 ]]; then
echo "${url}" | xclip -selection clipboard
notify-send --hint=int:transient:1 -t 500 -r 38 "${notification} The URL has been copied to the clipboard."
else
notify-send --hint=int:transient:1 -t 500 -r 38 "${*}"
fi
exit 0
fi
while : ; do
action=$(yad --title "I38 - Reminders" --form \
--button="_View Today's Reminders!gtk-info":3 \
--button="_View All Reminders!gtk-info":4 \
--button="_Add Reminder!gtk-edit":0 \
--button="_Add Daily Reminder!gtk-edit":2 \
--button="_Add Weekly Reminder!gtk-edit":5 \
--button="Add Monthly Reminder!gtk-edit":6 \
--button="Add Custom Reminder!gtk-edit":7 \
--button="Close!gtk-cancel":1 \
--separator="")
case $? in
0)
# Single reminder
add_reminder
;;
1|252)
# Handle "Close" button click and escape.
exit 0
;;
2)
# Handle "Add Daily Reminder" button click
add_daily_reminder
;;
3)
# View today's reminders
view_today
;;
4)
# View reminders
view_reminders
;;
5)
# Handle "Add Weekly Reminder" button click
add_weekly_reminder
;;
6)
# Handle "Add Monthly Reminder" button click
add_monthly_reminder
;;
7)
# Handle "Add Custom Reminder" button click
add_custom_reminder
;;
esac
done

24
scripts/screen_controller.sh Executable file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Not for multiple screens.
# Get the name of the screen.
screenName="$(xrandr --query | grep "connected" | cut -d ' ' -f1 | head -n 1)"
menuOptions=(
"1.0" "Maximum Brightness"
"0.75" "75 percent"
"0.5" "50 percent"
"0.25" "25 percent"
"0" "Screen Curtain"
)
brightness="$(yad --list --title "I38" --text "Set Screen Brightness" --columns 2 --hide-column 1 --column "" --column "Select" "${menuOptions[@]}")"
if [[ ${#brightness} -lt 1 ]]; then
exit 0
fi
xrandr --output ${screenName} --brightness ${brightness%%|*} &&
spd-say -P important -Cw "Screen set to ${brightness#*|}."
exit 0

View File

@ -12,12 +12,19 @@ i3 = i3ipc.Connection()
def on_new_window(self,i3):
system('play -n synth .25 sin 440:880 sin 480:920 remix - norm -3 pitch -500 &')
def on_close_window(self,i3):
system('play -n synth .25 sin 880:440 sin 920:480 remix - norm -3 pitch -500 &')
def on_mode(self,event):
mode= event.change
if mode == 'default':
if mode == 'ratpoison':
system('play -qV0 "|sox -np synth .07 sq 400" "|sox -np synth .5 sq 800" fade h 0 .5 .5 norm -20 &')
elif mode == 'bypass':
system('play -nqV0 synth .1 saw 700 saw 1200 delay 0 .04 remix - norm -6')
elif mode == 'default':
system('play -qV0 "|sox -np synth .07 sq 400" "|sox -np synth .5 sq 800" fade h 0 .5 .5 norm -20 reverse &')
else:
system('play -qV0 "|sox -np synth .07 sq 400" "|sox -np synth .5 sq 800" fade h 0 .5 .5 norm -20 &')
system('play -n synth 0.05 pluck F3 norm -8 : synth 0.05 pluck C4 norm -8 : synth 0.05 pluck F4 norm -8 : synth 0.05 pluck C5 norm -8')
def on_workspace_focus(self,i3):
#system('play -qnV0 synth pi fade 0 .25 .15 pad 0 1 reverb overdrive riaa norm -8 speed 1 &')
@ -38,6 +45,7 @@ def on_fullscreen(self,i3):
i3 = i3ipc.Connection()
i3.on('window::new', on_new_window)
i3.on('window::close', on_close_window)
i3.on(Event.MODE, on_mode)
i3.on('workspace::focus', on_workspace_focus)
i3.on('window::move', on_workspace_move)

View File

@ -1,5 +1,9 @@
#!/usr/bin/env bash
path="$(readlink -f $0)"
path="${path%/*/*}"
path="${path##*/}"
if [[ "$path" == "i3" ]]; then
mapfile -t windowList < <(python3 -c '
import i3ipc
@ -13,4 +17,28 @@ id="$(yad --title "I38" --list --separator "" --column "id" --column "Select Win
if [[ -z "${id}" ]]; then
exit 0
fi
i3-msg \[id="${id}"\] focus
i3-msg \[id="${id}"\] focus
else
mapfile -t windowList < <(python3 -c '
import i3ipc
i3 = i3ipc.Connection()
for con in i3.get_tree():
if con.window or con.type == "con":
if con.name:
print(con.window)
print(con.name)')
# Remove the first entry if it is "none"
if [[ "${windowList[0]}" == "none" ]]; then
unset "windowList[0]"
fi
id="$(yad --title "I38" --list --separator "" --column "id" --column "Select Window" --hide-column 1 --print-column 1 "${windowList[@]}")"
if [[ -z "${id}" ]]; then
exit 0
fi
swaymsg \[id="${id}"\] focus
fi