configuration form the arch linux stored

This commit is contained in:
filipriec
2025-09-22 08:27:51 +02:00
commit 3e6d1a0d61
166 changed files with 807076 additions and 0 deletions

313
rofi/scripts/bluetooth.sh Executable file
View File

@@ -0,0 +1,313 @@
#!/usr/bin/env bash
# __ _ _ _ _ _ _
# _ __ ___ / _(_) | |__ | |_ _ ___| |_ ___ ___ | |_| |__
# | '__/ _ \| |_| |_____| '_ \| | | | |/ _ \ __/ _ \ / _ \| __| '_ \
# | | | (_) | _| |_____| |_) | | |_| | __/ || (_) | (_) | |_| | | |
# |_| \___/|_| |_| |_.__/|_|\__,_|\___|\__\___/ \___/ \__|_| |_|
#
# Author: Nick Clyde (clydedroid)
#
# A script that generates a rofi menu that uses bluetoothctl to
# connect to bluetooth devices and display status info.
#
# Inspired by networkmanager-dmenu (https://github.com/firecat53/networkmanager-dmenu)
# Thanks to x70b1 (https://github.com/polybar/polybar-scripts/tree/master/polybar-scripts/system-bluetooth-bluetoothctl)
#
# Depends on:
# Arch repositories: rofi, bluez-utils (contains bluetoothctl)
# Constants
divider="---------"
goback="Back"
# Checks if bluetooth controller is powered on
power_on() {
if bluetoothctl show | grep -q "Powered: yes"; then
return 0
else
return 1
fi
}
# Toggles power state
toggle_power() {
if power_on; then
bluetoothctl power off
show_menu
else
if rfkill list bluetooth | grep -q 'blocked: yes'; then
rfkill unblock bluetooth && sleep 3
fi
bluetoothctl power on
show_menu
fi
}
# Checks if controller is scanning for new devices
scan_on() {
if bluetoothctl show | grep -q "Discovering: yes"; then
echo "Scan: on"
return 0
else
echo "Scan: off"
return 1
fi
}
# Toggles scanning state
toggle_scan() {
if scan_on; then
kill $(pgrep -f "bluetoothctl scan on")
bluetoothctl scan off
show_menu
else
bluetoothctl scan on &
echo "Scanning..."
sleep 5
show_menu
fi
}
# Checks if controller is able to pair to devices
pairable_on() {
if bluetoothctl show | grep -q "Pairable: yes"; then
echo "Pairable: on"
return 0
else
echo "Pairable: off"
return 1
fi
}
# Toggles pairable state
toggle_pairable() {
if pairable_on; then
bluetoothctl pairable off
show_menu
else
bluetoothctl pairable on
show_menu
fi
}
# Checks if controller is discoverable by other devices
discoverable_on() {
if bluetoothctl show | grep -q "Discoverable: yes"; then
echo "Discoverable: on"
return 0
else
echo "Discoverable: off"
return 1
fi
}
# Toggles discoverable state
toggle_discoverable() {
if discoverable_on; then
bluetoothctl discoverable off
show_menu
else
bluetoothctl discoverable on
show_menu
fi
}
# Checks if a device is connected
device_connected() {
device_info=$(bluetoothctl info "$1")
if echo "$device_info" | grep -q "Connected: yes"; then
return 0
else
return 1
fi
}
# Toggles device connection
toggle_connection() {
if device_connected $1; then
bluetoothctl disconnect $1
device_menu "$device"
else
bluetoothctl connect $1
device_menu "$device"
fi
}
# Checks if a device is paired
device_paired() {
device_info=$(bluetoothctl info "$1")
if echo "$device_info" | grep -q "Paired: yes"; then
echo "Paired: yes"
return 0
else
echo "Paired: no"
return 1
fi
}
# Toggles device paired state
toggle_paired() {
if device_paired $1; then
bluetoothctl remove $1
device_menu "$device"
else
bluetoothctl pair $1
device_menu "$device"
fi
}
# Checks if a device is trusted
device_trusted() {
device_info=$(bluetoothctl info "$1")
if echo "$device_info" | grep -q "Trusted: yes"; then
echo "Trusted: yes"
return 0
else
echo "Trusted: no"
return 1
fi
}
# Toggles device connection
toggle_trust() {
if device_trusted $1; then
bluetoothctl untrust $1
device_menu "$device"
else
bluetoothctl trust $1
device_menu "$device"
fi
}
# Prints a short string with the current bluetooth status
# Useful for status bars like polybar, etc.
print_status() {
if power_on; then
printf ''
mapfile -t paired_devices < <(bluetoothctl paired-devices | grep Device | cut -d ' ' -f 2)
counter=0
for device in "${paired_devices[@]}"; do
if device_connected $device; then
device_alias=$(bluetoothctl info $device | grep "Alias" | cut -d ' ' -f 2-)
if [[ $device_alias != "Bluetooth Mouse M336/M337/M535" ]]; then
if [ $counter -gt 0 ]; then
printf ", %s" "$device_alias"
else
printf " %s" "$device_alias"
fi
fi
((counter++))
fi
done
printf "\n"
else
echo ""
fi
}
# A submenu for a specific device that allows connecting, pairing, and trusting
device_menu() {
device=$1
# Get device name and mac address
device_name=$(echo $device | cut -d ' ' -f 3-)
mac=$(echo $device | cut -d ' ' -f 2)
# Build options
if device_connected $mac; then
connected="Connected: yes"
else
connected="Connected: no"
fi
paired=$(device_paired $mac)
trusted=$(device_trusted $mac)
options="$connected\n$paired\n$trusted\n$divider\n$goback\nExit"
# Open rofi menu, read chosen option
chosen="$(echo -e "$options" | $rofi_command "$device_name")"
# Match chosen option to command
case $chosen in
"" | $divider)
echo "No option chosen."
;;
$connected)
toggle_connection $mac
;;
$paired)
toggle_paired $mac
;;
$trusted)
toggle_trust $mac
;;
$goback)
show_menu
;;
esac
}
# Opens a rofi menu with current bluetooth status and options to connect
show_menu() {
# Get menu options
if power_on; then
power="Power: on"
# Human-readable names of devices, one per line
# If scan is off, will only list paired devices
devices=$(bluetoothctl devices | grep Device | cut -d ' ' -f 3-)
# Get controller flags
scan=$(scan_on)
pairable=$(pairable_on)
discoverable=$(discoverable_on)
# Options passed to rofi
options="$devices\n$divider\n$power\n$scan\n$pairable\n$discoverable\nExit"
else
power="Power: off"
options="$power\nExit"
fi
# Open rofi menu, read chosen option
chosen="$(echo -e "$options" | $rofi_command "")"
# Match chosen option to command
case $chosen in
"" | $divider)
echo "No option chosen."
;;
$power)
toggle_power
;;
$scan)
toggle_scan
;;
$discoverable)
toggle_discoverable
;;
$pairable)
toggle_pairable
;;
*)
device=$(bluetoothctl devices | grep "$chosen")
# Open a submenu if a device is selected
if [[ $device ]]; then device_menu "$device"; fi
;;
esac
}
# Rofi command to pipe into, can add any options here
rofi_command="rofi -dmenu -no-fixed-num-lines -yoffset -100 -i -p"
case "$1" in
--status)
print_status
;;
*)
show_menu
;;
esac

View File

@@ -0,0 +1,8 @@
#!/bin/sh
# cat $(dirname $0)/bookmarks.txt | rofi -dmenu -i -p "" | cut -d\- -f2- | xclip -selection clipboard
ADDRESS=$(cat $(dirname $0)/bookmarks.txt | rofi -dmenu -i -p "" | cut -d\- -f2-)
if [ -n "$ADDRESS" ]; then
brave -e $ADDRESS
i3-msg workspace number 2
fi

View File

@@ -0,0 +1,18 @@
br - https://search.brave.com
pm - https://mail.proton.me
gt - https://translate.google.com
gs - https://scholar.google.co.jp/?hl=en
yt - https://www.youtube.com
gm - https://www.google.com/maps
ch - https://chat.openai.com
wi - https://www.wikipedia.org
git - https://github.com
aur - https://aur.archlinux.org
gr - https://app.grammarly.com
fb - https://www.facebook.com
sp - https://open.spotify.com
angry - https://www.angryreviewer.com
deepl - https://www.deepl.com/write
typing - https://www.keybr.com
overleaf - https://www.overleaf.com/project
lang - https://www.languagetool.org

71
rofi/scripts/books-search.sh Executable file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# Info:
# author: Miroslav Vidovic
# file: books-search.sh
# created: 13.08.2017.-08:06:54
# revision: ---
# version: 1.0
# -----------------------------------------------------------------------------
# Requirements:
# rofi
# Description:
# Use rofi to search my books.
# Usage:
# books-search.sh
# -----------------------------------------------------------------------------
# Script:
# Books directory
BOOKS_DIR=~/Library
mkdir -p ~/Library
# Save find result to F_ARRAY
readarray -t F_ARRAY <<< "$(find "$BOOKS_DIR" -type f -name '*.pdf')"
# Associative array for storing books
# key => book name
# value => absolute path to the file
# BOOKS['filename']='path'
declare -A BOOKS
# Add elements to BOOKS array
get_books() {
if [[ ! -z ${F_ARRAY[@]} ]]; then
for i in "${!F_ARRAY[@]}"
do
path=${F_ARRAY[$i]}
file=$(basename "${F_ARRAY[$i]}")
BOOKS+=(["$file"]="$path")
done
else
echo "$BOOKS_DIR is empty!"
echo "Please put some books in it."
echo "Only .pdf files are accepted."
exit
fi
}
# List for rofi
gen_list(){
for i in "${!BOOKS[@]}"
do
echo "$i"
done
}
main() {
get_books
book=$( (gen_list) | rofi -dmenu -i -matching normal -no-custom -location 0 -p " " )
if [ -n "$book" ]; then
echo "$book" | sed -e "s/^.... - //" -e "s/\ .*//" | xclip -selection clipboard
# xdg-open "${BOOKS[$book]}"
zathura "${BOOKS[$book]}"
fi
}
main
exit 0

View File

@@ -0,0 +1,13 @@
#!/bin/bash
# Get the currently focused workspace
workspace=$(i3-msg -t get_workspaces | jq '.[] | select(.focused==true).name' | tr -d '"')
# Run the provided command
$1 &
# Get the window ID of the most recently launched program
win_id=$(xdotool getactivewindow)
# Move the program to the initially focused workspace
i3-msg [id="$win_id"] move container to workspace $workspace

99
rofi/scripts/monitor-layout.sh Executable file
View File

@@ -0,0 +1,99 @@
#!/bin/bash
XRANDR=$(which xrandr)
MONITORS=( $( ${XRANDR} | awk '( $2 == "connected" ){ print $1 }' ) )
NUM_MONITORS=${#MONITORS[@]}
TITLES=()
COMMANDS=()
function gen_xrandr_only()
{
selected=$1
cmd="xrandr --output ${MONITORS[$selected]} --auto "
for entry in $(seq 0 $((${NUM_MONITORS}-1)))
do
if [ $selected != $entry ]
then
cmd="$cmd --output ${MONITORS[$entry]} --off"
fi
done
echo $cmd
}
declare -i index=0
TILES[$index]="Cancel"
COMMANDS[$index]="true"
index+=1
for entry in $(seq 0 $((${NUM_MONITORS}-1)))
do
TILES[$index]="Only ${MONITORS[$entry]}"
COMMANDS[$index]=$(gen_xrandr_only $entry)
index+=1
done
##
# Dual screen options
##
for entry_a in $(seq 0 $((${NUM_MONITORS}-1)))
do
for entry_b in $(seq 0 $((${NUM_MONITORS}-1)))
do
if [ $entry_a != $entry_b ]
then
TILES[$index]="Dual Screen ${MONITORS[$entry_a]} -> ${MONITORS[$entry_b]}"
COMMANDS[$index]="xrandr --output ${MONITORS[$entry_a]} --auto \
--output ${MONITORS[$entry_b]} --auto --left-of ${MONITORS[$entry_a]}"
index+=1
fi
done
done
##
# Clone monitors
##
for entry_a in $(seq 0 $((${NUM_MONITORS}-1)))
do
for entry_b in $(seq 0 $((${NUM_MONITORS}-1)))
do
if [ $entry_a != $entry_b ]
then
TILES[$index]="Clone Screen ${MONITORS[$entry_a]} -> ${MONITORS[$entry_b]}"
COMMANDS[$index]="xrandr --output ${MONITORS[$entry_a]} --auto \
--output ${MONITORS[$entry_b]} --auto --same-as ${MONITORS[$entry_a]}"
index+=1
fi
done
done
##
# Generate entries, where first is key.
##
function gen_entries()
{
for a in $(seq 0 $(( ${#TILES[@]} -1 )))
do
echo $a ${TILES[a]}
done
}
# Call menu
SEL=$( gen_entries | rofi -dmenu -p "Monitor Setup:" -a 0 -no-custom | awk '{print $1}' )
# Call xrandr
$( ${COMMANDS[$SEL]} )

857
rofi/scripts/networkmanager Normal file
View File

@@ -0,0 +1,857 @@
#!/usr/bin/env python3
# encoding:utf8
"""NetworkManager command line dmenu script.
To add new connections or enable/disable networking requires policykit
permissions setup per:
https://wiki.archlinux.org/index.php/NetworkManager#Set_up_PolicyKit_permissions
OR running the script as root
Add dmenu formatting options and default terminal if desired to
~/.config/networkmanager-dmenu/config.ini
"""
import pathlib
import struct
import configparser
import itertools
import locale
import os
from os.path import expanduser
import shlex
import sys
import uuid
from subprocess import Popen, PIPE
import gi
gi.require_version('NM', '1.0')
from gi.repository import GLib, NM # pylint: disable=wrong-import-position
ENV = os.environ.copy()
ENV['LC_ALL'] = 'C'
ENC = locale.getpreferredencoding()
CLIENT = NM.Client.new(None)
LOOP = GLib.MainLoop()
CONNS = CLIENT.get_connections()
CONF = configparser.ConfigParser()
CONF.read(expanduser("~/.config/networkmanager-dmenu/config.ini"))
def dmenu_cmd(num_lines, prompt="", active_lines=None): # pylint: disable=too-many-branches
"""Parse config.ini if it exists and add options to the dmenu command
Args: args - num_lines: number of lines to display
prompt: prompt to show
Returns: command invocation (as a list of strings) for
dmenu -l <num_lines> -p <prompt> -i ...
"""
dmenu_command = "dmenu"
if not CONF.sections():
res = [dmenu_command, "-i", "-l", str(num_lines), "-p", str(prompt)]
res.extend(sys.argv[1:])
return res
if CONF.has_section('dmenu'):
args = CONF.items('dmenu')
args_dict = dict(args)
dmenu_args = []
if "dmenu_command" in args_dict:
command = shlex.split(args_dict["dmenu_command"])
dmenu_command = command[0]
dmenu_args = command[1:]
del args_dict["dmenu_command"]
if "p" in args_dict and prompt == "":
prompt = args_dict["p"]
del args_dict["p"]
elif "p" in args_dict:
del args_dict["p"]
if "rofi" in dmenu_command:
lines = "-i -dmenu -lines"
# rofi doesn't support 0 length line, it requires at least -lines=1
# see https://github.com/DaveDavenport/rofi/issues/252
num_lines = num_lines or 1
else:
lines = "-i -l"
if "l" in args_dict:
# rofi doesn't support 0 length line, it requires at least -lines=1
# see https://github.com/DaveDavenport/rofi/issues/252
if "rofi" in dmenu_command:
args_dict['l'] = min(num_lines, int(args_dict['l'])) or 1
lines = "{} {}".format(lines, args_dict['l'])
del args_dict['l']
else:
lines = "{} {}".format(lines, num_lines)
if "pinentry" in args_dict:
del args_dict["pinentry"]
if "compact" in args_dict:
del args_dict["compact"]
if "wifi_chars" in args_dict:
del args_dict["wifi_chars"]
rofi_highlight = CONF.getboolean('dmenu', 'rofi_highlight', fallback=False)
if CONF.has_option('dmenu', 'rofi_highlight'):
del args_dict["rofi_highlight"]
if rofi_highlight is True and "rofi" in dmenu_command:
if active_lines:
dmenu_args.extend(["-a", ",".join([str(num)
for num in active_lines])])
if prompt == "Passphrase":
if CONF.has_section('dmenu_passphrase'):
args = CONF.items('dmenu_passphrase')
args_dict.update(args)
rofi_obscure = CONF.getboolean('dmenu_passphrase', 'rofi_obscure', fallback=True)
if CONF.has_option('dmenu_passphrase', 'rofi_obscure'):
del args_dict["rofi_obscure"]
if rofi_obscure is True and "rofi" in dmenu_command:
dmenu_args.extend(["-password"])
dmenu_password = CONF.getboolean('dmenu_passphrase', 'dmenu_password', fallback=False)
if CONF.has_option('dmenu_passphrase', 'dmenu_password'):
del args_dict["dmenu_password"]
if dmenu_password is True:
dmenu_args.extend(["-P"])
extras = (["-" + str(k), str(v)] for (k, v) in args_dict.items())
res = [dmenu_command, "-p", str(prompt)]
res.extend(dmenu_args)
res += list(itertools.chain.from_iterable(extras))
res[1:1] = lines.split()
res = list(filter(None, res)) # Remove empty list elements
res.extend(sys.argv[1:])
return res
def choose_adapter(client):
"""If there is more than one wifi adapter installed, ask which one to use
"""
devices = client.get_devices()
devices = [i for i in devices if i.get_device_type() == NM.DeviceType.WIFI]
if not devices: # pylint: disable=no-else-return
return None
elif len(devices) == 1:
return devices[0]
device_names = "\n".join([d.get_iface() for d in devices]).encode(ENC)
sel = Popen(dmenu_cmd(len(devices), "CHOOSE ADAPTER:"),
stdin=PIPE,
stdout=PIPE,
env=ENV).communicate(input=device_names)[0].decode(ENC)
if not sel.strip():
sys.exit()
devices = [i for i in devices if i.get_iface() == sel.strip()]
assert len(devices) == 1
return devices[0]
def is_modemmanager_installed():
"""Check if ModemManager is installed"""
with open(os.devnull) as devnull:
try:
Popen(["ModemManager"], stdout=devnull, stderr=devnull).communicate()
except OSError:
return False
return True
def bluetooth_get_enabled():
"""Check if bluetooth is enabled via rfkill.
Returns None if no bluetooth device was found.
"""
# See https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-rfkill
for path in pathlib.Path('/sys/class/rfkill/').glob('rfkill*'):
if (path / 'type').read_text().strip() == 'bluetooth':
return (path / 'soft').read_text().strip() == '0'
return None
def create_other_actions(client):
"""Return list of other actions that can be taken
"""
networking_enabled = client.networking_get_enabled()
networking_action = "Disable" if networking_enabled else "Enable"
wifi_enabled = client.wireless_get_enabled()
wifi_action = "Disable" if wifi_enabled else "Enable"
bluetooth_enabled = bluetooth_get_enabled()
bluetooth_action = "Disable" if bluetooth_enabled else "Enable"
actions = [Action("{} Wifi".format(wifi_action), toggle_wifi,
not wifi_enabled),
Action("{} Networking".format(networking_action),
toggle_networking, not networking_enabled)]
if bluetooth_enabled is not None:
actions.append(Action("{} Bluetooth".format(bluetooth_action),
toggle_bluetooth, not bluetooth_enabled))
actions += [Action("Launch Connection Manager", launch_connection_editor),
Action("Delete a Connection", delete_connection)]
if wifi_enabled:
actions.append(Action("Rescan Wifi Networks", rescan_wifi))
return actions
def rescan_wifi():
"""
Rescan Wifi Access Points
"""
for dev in CLIENT.get_devices():
if gi.repository.NM.DeviceWifi == type(dev):
try:
dev.request_scan_async(None, rescan_cb, None)
LOOP.run()
except gi.repository.GLib.Error as err:
# Too frequent rescan error
notify("Wifi rescan failed", urgency="critical")
if not err.code == 6: # pylint: disable=no-member
raise err
def rescan_cb(dev, res, data):
"""Callback for rescan_wifi. Just for notifications
"""
if dev.request_scan_finish(res) is True:
notify("Wifi scan complete")
else:
notify("Wifi scan failed", urgency="critical")
LOOP.quit()
def ssid_to_utf8(nm_ap):
""" Convert binary ssid to utf-8 """
ssid = nm_ap.get_ssid()
if not ssid:
return ""
ret = NM.utils_ssid_to_utf8(ssid.get_data())
return ret
def prompt_saved(saved_cons):
"""Prompt for a saved connection."""
actions = create_saved_actions(saved_cons)
sel = get_selection(actions)
sel()
def ap_security(nm_ap):
"""Parse the security flags to return a string with 'WPA2', etc. """
flags = nm_ap.get_flags()
wpa_flags = nm_ap.get_wpa_flags()
rsn_flags = nm_ap.get_rsn_flags()
sec_str = ""
if ((flags & getattr(NM, '80211ApFlags').PRIVACY) and
(wpa_flags == 0) and (rsn_flags == 0)):
sec_str += " WEP"
if wpa_flags != 0:
sec_str += " WPA1"
if rsn_flags != 0:
sec_str += " WPA2"
if ((wpa_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_802_1X) or
(rsn_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_802_1X)):
sec_str += " 802.1X"
# If there is no security use "--"
if sec_str == "":
sec_str = "--"
return sec_str.lstrip()
class Action(): # pylint: disable=too-few-public-methods
"""Helper class to execute functions from a string variable"""
def __init__(self,
name,
func,
args=None,
active=False):
self.name = name
self.func = func
self.is_active = active
if args is None:
self.args = None
elif isinstance(args, list):
self.args = args
else:
self.args = [args]
def __str__(self):
return self.name
def __call__(self):
if self.args is None:
self.func()
else:
self.func(*self.args)
def conn_matches_adapter(conn, adapter):
"""Return True if the connection is applicable for the given adapter.
There seem to be two ways for a connection specify what interface it belongs
to:
- By setting 'mac-address' in [wifi] to the adapter's MAC
- By setting 'interface-name` in [connection] to the adapter's name.
Depending on how the connection was added, it seems like either
'mac-address', 'interface-name' or neither of both is set.
"""
# [wifi] mac-address
setting_wireless = conn.get_setting_wireless()
mac = setting_wireless.get_mac_address()
if mac is not None:
return mac == adapter.get_permanent_hw_address()
# [connection] interface-name
setting_connection = conn.get_setting_connection()
interface = setting_connection.get_interface_name()
if interface is not None:
return interface == adapter.get_iface()
# Neither is set, let's assume this connection is for multiple/all adapters.
return True
def process_ap(nm_ap, is_active, adapter):
"""Activate/Deactivate a connection and get password if required"""
if is_active:
CLIENT.deactivate_connection_async(nm_ap, None, deactivate_cb, nm_ap)
else:
conns_cur = [i for i in CONNS if
i.get_setting_wireless() is not None and
conn_matches_adapter(i, adapter)]
con = nm_ap.filter_connections(conns_cur)
if len(con) > 1:
raise ValueError("There are multiple connections possible")
if len(con) == 1:
CLIENT.activate_connection_async(con[0], adapter, nm_ap.get_path(),
None, activate_cb, nm_ap)
else:
if ap_security(nm_ap) != "--":
password = get_passphrase()
else:
password = ""
set_new_connection(nm_ap, password, adapter)
LOOP.run()
def activate_cb(dev, res, data):
"""Notification if activate connection completed successfully
"""
try:
conn = dev.activate_connection_finish(res)
except GLib.Error:
conn = None
if conn is not None:
notify("Activated {}".format(conn.get_id()))
else:
notify("Problem activating {}".format(data.get_id()),
urgency="critical")
LOOP.quit()
def deactivate_cb(dev, res, data):
"""Notification if deactivate connection completed successfully
"""
if dev.deactivate_connection_finish(res) is True:
notify("Deactivated {}".format(data.get_id()))
else:
notify("Problem deactivating {}".format(data.get_id()),
urgency="critical")
LOOP.quit()
def process_vpngsm(con, activate):
"""Activate/deactive VPN or GSM connections"""
if activate:
CLIENT.activate_connection_async(con, None, None,
None, activate_cb, con)
else:
CLIENT.deactivate_connection_async(con, None, deactivate_cb, con)
LOOP.run()
def create_ap_actions(aps, active_ap, active_connection, adapter): # pylint: disable=too-many-locals
"""For each AP in a list, create the string and its attached function
(activate/deactivate)
"""
active_ap_bssid = active_ap.get_bssid() if active_ap is not None else ""
names = [ssid_to_utf8(ap) for ap in aps]
max_len_name = max([len(name) for name in names]) if names else 0
secs = [ap_security(ap) for ap in aps]
max_len_sec = max([len(sec) for sec in secs]) if secs else 0
ap_actions = []
for nm_ap, name, sec in zip(aps, names, secs):
bars = NM.utils_wifi_strength_bars(nm_ap.get_strength())
wifi_chars = CONF.get("dmenu", "wifi_chars", fallback=False)
if wifi_chars:
bars = "".join([wifi_chars[i] for i, j in enumerate(bars) if j == '*'])
is_active = nm_ap.get_bssid() == active_ap_bssid
compact = CONF.getboolean("dmenu", "compact", fallback=False)
if compact:
action_name = u"{} {} {}".format(name, sec, bars)
else:
action_name = u"{:<{}s} {:<{}s} {}".format(name, max_len_name, sec,
max_len_sec, bars)
if is_active:
ap_actions.append(Action(action_name, process_ap,
[active_connection, True, adapter],
active=True))
else:
ap_actions.append(Action(action_name, process_ap,
[nm_ap, False, adapter]))
return ap_actions
def create_vpn_actions(vpns, active):
"""Create the list of strings to display with associated function
(activate/deactivate) for VPN connections.
"""
active_vpns = [i for i in active if i.get_vpn()]
return _create_vpngsm_actions(vpns, active_vpns, "VPN")
def create_wireguard_actions(wgs, active):
"""Create the list of strings to display with associated function
(activate/deactivate) for Wireguard connections.
"""
active_wgs = [i for i in active if i.get_connection_type() == "wireguard"]
return _create_vpngsm_actions(wgs, active_wgs, "Wireguard")
def create_eth_actions(eths, active):
"""Create the list of strings to display with associated function
(activate/deactivate) for Ethernet connections.
"""
active_eths = [i for i in active if 'ethernet' in i.get_connection_type()]
return _create_vpngsm_actions(eths, active_eths, "Eth")
def create_gsm_actions(gsms, active):
"""Create the list of strings to display with associated function
(activate/deactivate) GSM connections."""
active_gsms = [i for i in active if
i.get_connection() is not None and
i.get_connection().is_type(NM.SETTING_GSM_SETTING_NAME)]
return _create_vpngsm_actions(gsms, active_gsms, "GSM")
def create_blue_actions(blues, active):
"""Create the list of strings to display with associated function
(activate/deactivate) Bluetooth connections."""
active_blues = [i for i in active if
i.get_connection() is not None and
i.get_connection().is_type(NM.SETTING_BLUETOOTH_SETTING_NAME)]
return _create_vpngsm_actions(blues, active_blues, "Bluetooth")
def create_saved_actions(saved):
"""Create the list of strings to display with associated function
(activate/deactivate) for VPN connections.
"""
return _create_vpngsm_actions(saved, [], "SAVED")
def _create_vpngsm_actions(cons, active_cons, label):
active_con_ids = [a.get_id() for a in active_cons]
actions = []
for con in cons:
is_active = con.get_id() in active_con_ids
action_name = u"{}:{}".format(con.get_id(), label)
if is_active:
active_connection = [a for a in active_cons
if a.get_id() == con.get_id()]
if len(active_connection) != 1:
raise ValueError(u"Multiple active connections match"
" the connection: {}".format(con.get_id()))
active_connection = active_connection[0]
actions.append(Action(action_name, process_vpngsm,
[active_connection, False], active=True))
else:
actions.append(Action(action_name, process_vpngsm,
[con, True]))
return actions
def create_wwan_actions(client):
"""Create WWWAN actions
"""
wwan_enabled = client.wwan_get_enabled()
wwan_action = "Disable" if wwan_enabled else "Enable"
return [Action("{} WWAN".format(wwan_action), toggle_wwan, not wwan_enabled)]
def combine_actions(eths, aps, vpns, wgs, gsms, blues, wwan, others, saved):
"""Combine all given actions into a list of actions.
Args: args - eths: list of Actions
aps: list of Actions
vpns: list of Actions
gsms: list of Actions
blues: list of Actions
wwan: list of Actions
others: list of Actions
"""
compact = CONF.getboolean("dmenu", "compact", fallback=False)
empty_action = [Action('', None)] if not compact else []
all_actions = []
all_actions += eths + empty_action if eths else []
all_actions += aps + empty_action if aps else []
all_actions += vpns + empty_action if vpns else []
all_actions += wgs + empty_action if wgs else []
all_actions += gsms + empty_action if (gsms and wwan) else []
all_actions += blues + empty_action if blues else []
all_actions += wwan + empty_action if wwan else []
all_actions += others + empty_action if others else []
all_actions += saved + empty_action if saved else []
return all_actions
def get_selection(all_actions):
"""Spawn dmenu for selection and execute the associated action."""
rofi_highlight = CONF.getboolean('dmenu', 'rofi_highlight', fallback=False)
inp = []
if rofi_highlight is True:
inp = [str(action) for action in all_actions]
else:
inp = [('== ' if action.is_active else ' ') + str(action)
for action in all_actions]
active_lines = [index for index, action in enumerate(all_actions)
if action.is_active]
inp_bytes = "\n".join(inp).encode(ENC)
command = dmenu_cmd(len(inp), active_lines=active_lines)
sel = Popen(command, stdin=PIPE, stdout=PIPE,
env=ENV).communicate(input=inp_bytes)[0].decode(ENC)
if not sel.rstrip():
sys.exit()
if rofi_highlight is False:
action = [i for i in all_actions
if ((str(i).strip() == str(sel.strip())
and not i.is_active) or
('== ' + str(i) == str(sel.rstrip('\n'))
and i.is_active))]
else:
action = [i for i in all_actions if str(i).strip() == sel.strip()]
assert len(action) == 1, \
u"Selection was ambiguous: '{}'".format(str(sel.strip()))
return action[0]
def toggle_networking(enable):
"""Enable/disable networking
Args: enable - boolean
"""
toggle = GLib.Variant.new_tuple(GLib.Variant.new_boolean(enable))
try:
CLIENT.dbus_call(NM.DBUS_PATH, NM.DBUS_INTERFACE, "Enable", toggle,
None, -1, None, None, None)
except AttributeError:
# Workaround for older versions of python-gobject
CLIENT.networking_set_enabled(enable)
notify("Networking {}".format("enabled" if enable is True else "disabled"))
def toggle_wifi(enable):
"""Enable/disable Wifi
Args: enable - boolean
"""
toggle = GLib.Variant.new_boolean(enable)
try:
CLIENT.dbus_set_property(NM.DBUS_PATH, NM.DBUS_INTERFACE, "WirelessEnabled", toggle,
-1, None, None, None)
except AttributeError:
# Workaround for older versions of python-gobject
CLIENT.wireless_set_enabled(enable)
notify("Wifi {}".format("enabled" if enable is True else "disabled"))
def toggle_wwan(enable):
"""Enable/disable WWAN
Args: enable - boolean
"""
toggle = GLib.Variant.new_boolean(enable)
try:
CLIENT.dbus_set_property(NM.DBUS_PATH, NM.DBUS_INTERFACE, "WwanEnabled", toggle,
-1, None, None, None)
except AttributeError:
# Workaround for older versions of python-gobject
CLIENT.wwan_set_enabled(enable)
notify("Wwan {}".format("enabled" if enable is True else "disabled"))
def toggle_bluetooth(enable):
"""Enable/disable Bluetooth
Args: enable - boolean
References:
https://github.com/blueman-project/blueman/blob/master/blueman/plugins/mechanism/RfKill.py
https://www.kernel.org/doc/html/latest/driver-api/rfkill.html
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/uapi/linux/rfkill.h?h=v5.8.9
"""
type_bluetooth = 2
op_change_all = 3
idx = 0
soft_state = 0 if enable else 1
hard_state = 0
data = struct.pack("IBBBB", idx, type_bluetooth, op_change_all,
soft_state, hard_state)
try:
with open('/dev/rfkill', 'r+b', buffering=0) as rff:
rff.write(data)
except PermissionError:
notify("Lacking permission to write to /dev/rfkill.",
"Maybe you need to add your user to the 'rfkill' group?",
urgency="critical")
else:
notify("Bluetooth {}".format("enabled" if enable else "disabled"))
def launch_connection_editor():
"""Launch nmtui or the gui nm-connection-editor
"""
terminal = CONF.get("editor", "terminal", fallback="xterm")
gui_if_available = CONF.getboolean("editor", "gui_if_available", fallback=True)
if gui_if_available is True:
try:
Popen(["gnome-control-center", "network"]).communicate()
except OSError:
try:
Popen(["nm-connection-editor"]).communicate()
except OSError:
Popen([terminal, "-e", "nmtui"]).communicate()
else:
Popen([terminal, "-e", "nmtui"]).communicate()
def get_passphrase():
"""Get a password
Returns: string
"""
pinentry = CONF.get("dmenu", "pinentry", fallback=None)
if pinentry:
pin = ""
out = Popen(pinentry,
stdout=PIPE,
stdin=PIPE).communicate(input=b'setdesc Get network password\ngetpin\n')[0]
if out:
res = out.decode(ENC).split("\n")[2]
if res.startswith("D "):
pin = res.split("D ")[1]
return pin
return Popen(dmenu_cmd(0, "Passphrase"),
stdin=PIPE, stdout=PIPE).communicate()[0].decode(ENC)
def delete_connection():
"""Display list of NM connections and delete the selected one
"""
conn_acts = [Action(i.get_id(), i.delete_async, args=[None, delete_cb, None]) for i in CONNS]
conn_names = "\n".join([str(i) for i in conn_acts]).encode(ENC)
sel = Popen(dmenu_cmd(len(conn_acts), "CHOOSE CONNECTION TO DELETE:"),
stdin=PIPE,
stdout=PIPE,
env=ENV).communicate(input=conn_names)[0].decode(ENC)
if not sel.strip():
sys.exit()
action = [i for i in conn_acts if str(i) == sel.rstrip("\n")]
assert len(action) == 1, u"Selection was ambiguous: {}".format(str(sel))
action[0]()
LOOP.run()
def delete_cb(dev, res, data):
"""Notification if delete completed successfully
"""
if dev.delete_finish(res) is True:
notify("Deleted {}".format(dev.get_id()))
else:
notify("Problem deleting {}".format(dev.get_id()), urgency="critical")
LOOP.quit()
def set_new_connection(nm_ap, nm_pw, adapter):
"""Setup a new NetworkManager connection
Args: ap - NM.AccessPoint
pw - string
"""
nm_pw = str(nm_pw).strip()
profile = create_wifi_profile(nm_ap, nm_pw, adapter)
CLIENT.add_and_activate_connection_async(profile, adapter, nm_ap.get_path(),
None, verify_conn, profile)
LOOP.run()
def create_wifi_profile(nm_ap, password, adapter):
# pylint: disable=C0301
# From https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python/gi/add_connection.py
# and https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python/dbus/add-wifi-psk-connection.py
# pylint: enable=C0301
"""Create the NM profile given the AP and passphrase"""
ap_sec = ap_security(nm_ap)
profile = NM.SimpleConnection.new()
s_con = NM.SettingConnection.new()
s_con.set_property(NM.SETTING_CONNECTION_ID, ssid_to_utf8(nm_ap))
s_con.set_property(NM.SETTING_CONNECTION_UUID, str(uuid.uuid4()))
s_con.set_property(NM.SETTING_CONNECTION_TYPE, "802-11-wireless")
profile.add_setting(s_con)
s_wifi = NM.SettingWireless.new()
s_wifi.set_property(NM.SETTING_WIRELESS_SSID, nm_ap.get_ssid())
s_wifi.set_property(NM.SETTING_WIRELESS_MODE, 'infrastructure')
s_wifi.set_property(NM.SETTING_WIRELESS_MAC_ADDRESS, adapter.get_permanent_hw_address())
profile.add_setting(s_wifi)
s_ip4 = NM.SettingIP4Config.new()
s_ip4.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto")
profile.add_setting(s_ip4)
s_ip6 = NM.SettingIP6Config.new()
s_ip6.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto")
profile.add_setting(s_ip6)
if ap_sec != "--":
s_wifi_sec = NM.SettingWirelessSecurity.new()
if "WPA" in ap_sec:
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT,
"wpa-psk")
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_AUTH_ALG,
"open")
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_PSK, password)
elif "WEP" in ap_sec:
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT,
"None")
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
NM.WepKeyType.PASSPHRASE)
s_wifi_sec.set_wep_key(0, password)
profile.add_setting(s_wifi_sec)
return profile
def verify_conn(client, result, data):
"""Callback function for add_and_activate_connection_async
Check if connection completes successfully. Delete the connection if there
is an error.
"""
try:
act_conn = client.add_and_activate_connection_finish(result)
conn = act_conn.get_connection()
if not all([conn.verify(),
conn.verify_secrets(),
data.verify(),
data.verify_secrets()]):
raise GLib.Error
notify("Added {}".format(conn.get_id()))
except GLib.Error: # pylint: disable=catching-non-exception
try:
notify("Connection to {} failed".format(conn.get_id()),
urgency="critical")
conn.delete_async(None, None, None)
except UnboundLocalError:
pass
finally:
LOOP.quit()
def create_ap_list(adapter, active_connections):
"""Generate list of access points. Remove duplicate APs , keeping strongest
ones and the active AP
Args: adapter
active_connections - list of all active connections
Returns: aps - list of access points
active_ap - active AP
active_ap_con - active Connection
adapter
"""
aps = []
ap_names = []
active_ap = adapter.get_active_access_point()
aps_all = sorted(adapter.get_access_points(),
key=lambda a: a.get_strength(), reverse=True)
conns_cur = [i for i in CONNS if
i.get_setting_wireless() is not None and
conn_matches_adapter(i, adapter)]
try:
ap_conns = active_ap.filter_connections(conns_cur)
active_ap_name = ssid_to_utf8(active_ap)
active_ap_con = [active_conn for active_conn in active_connections
if active_conn.get_connection() in ap_conns]
except AttributeError:
active_ap_name = None
active_ap_con = []
if len(active_ap_con) > 1:
raise ValueError("Multiple connection profiles match"
" the wireless AP")
active_ap_con = active_ap_con[0] if active_ap_con else None
for nm_ap in aps_all:
ap_name = ssid_to_utf8(nm_ap)
if nm_ap != active_ap and ap_name == active_ap_name:
# Skip adding AP if it's not active but same name as active AP
continue
if ap_name not in ap_names:
ap_names.append(ap_name)
aps.append(nm_ap)
return aps, active_ap, active_ap_con, adapter
def notify(message, details=None, urgency="low"):
"""Use notify-send if available for notifications
"""
args = ["-u", urgency, message]
if details is not None:
args.append(details)
try:
Popen(["notify-send"] + args,
stdout=PIPE, stderr=PIPE).communicate()
except FileNotFoundError:
pass
def run():
"""Main script entrypoint"""
active = CLIENT.get_active_connections()
adapter = choose_adapter(CLIENT)
if adapter:
ap_actions = create_ap_actions(*create_ap_list(adapter, active))
else:
ap_actions = []
vpns = [i for i in CONNS if i.is_type(NM.SETTING_VPN_SETTING_NAME)]
try:
wgs = [i for i in CONNS if i.is_type(NM.SETTING_WIREGUARD_SETTING_NAME)]
except AttributeError:
# Workaround for older versions of python-gobject with no wireguard support
wgs = []
eths = [i for i in CONNS if i.is_type(NM.SETTING_WIRED_SETTING_NAME)]
blues = [i for i in CONNS if i.is_type(NM.SETTING_BLUETOOTH_SETTING_NAME)]
vpn_actions = create_vpn_actions(vpns, active)
wg_actions = create_wireguard_actions(wgs, active)
eth_actions = create_eth_actions(eths, active)
blue_actions = create_blue_actions(blues, active)
other_actions = create_other_actions(CLIENT)
wwan_installed = is_modemmanager_installed()
if wwan_installed:
gsms = [i for i in CONNS if i.is_type(NM.SETTING_GSM_SETTING_NAME)]
gsm_actions = create_gsm_actions(gsms, active)
wwan_actions = create_wwan_actions(CLIENT)
else:
gsm_actions = []
wwan_actions = []
list_saved = CONF.getboolean('dmenu', 'list_saved', fallback=False)
saved_cons = [i for i in CONNS if i not in vpns + wgs + eths + blues]
if list_saved:
saved_actions = create_saved_actions(saved_cons)
else:
saved_actions = [Action("Saved connections", prompt_saved, [saved_cons])]
actions = combine_actions(eth_actions, ap_actions, vpn_actions, wg_actions,
gsm_actions, blue_actions, wwan_actions,
other_actions, saved_actions)
sel = get_selection(actions)
sel()
if __name__ == '__main__':
run()
# vim: set et ts=4 sw=4 :

169
rofi/scripts/nordvpn.sh Executable file
View File

@@ -0,0 +1,169 @@
#!/bin/sh
# __ _ _
# _ __ ___ / _(_) _ __ ___ _ __ __| |_ ___ __ _ __
# | '__/ _ \| |_| |_____| '_ \ / _ \| '__/ _` \ \ / / '_ \| '_ \
# | | | (_) | _| |_____| | | | (_) | | | (_| |\ V /| |_) | | | |
# |_| \___/|_| |_| |_| |_|\___/|_| \__,_| \_/ | .__/|_| |_|
# |_|
# exit when any command fails
set -e
echoexit() {
# Print to stderr and exit
printf "%s\n" "$@" 1>&2
exit 1
}
# Checking dependencies:
whereis nordvpn > /dev/null || echoexit "'nordvpn' not found."
menu() {
# Menu command, should read from stdin and write to stdout.
rofi -dmenu -i -p "Select" -no-custom
}
usage() {
printf "Dynamic menu interface for nordvpn.
Usage:
rofi-nordvpn [-h] [-s LABEL]
-h Display this help message.
-s Display current vpn status, useful for status bars.
"
}
init_menu() {
# Initial menu.
local choices
choices="connect\ndisconnect\nstatus\nsettings"
printf "%b" "$choices" | menu
}
connect() {
# nordvpn connect options.
local choices
choices="default\ncountries\ncities\np2p\nonion"
printf "%b" "$choices" | menu
}
countries() {
# Country selection.
local choices
choices="$(nordvpn countries | tr -d '\r,-' | tr -s "[:blank:]" "\n" | sed '/^\s*$/d' | sort)"
printf "%s" "$choices" | menu
}
cities() {
# City selection.
local choices
choices="$(nordvpn cities "$1" | tr -d '\r,-' | tr -s "[:blank:]" "\n" | sed '/^\s*$/d' | sort)"
printf "%s" "$choices" | menu
}
disconnect() {
# disconnect
nordvpn disconnect
}
status() {
# Echo the status.
local status
status="$(nordvpn status | tr -d '\r -')"
if [ -n "${status##*Connected*}" ]; then
printf "Off"
else
printf "%s" "$(printf "%s" "$status" | grep "City" | cut -d ":" -f 2)"
fi
}
vpn_status() {
# Show vpn status.
local choices
choices="$(nordvpn status | tr -d '\r-' | sed 's/^ *//')"
printf "%s" "$choices" | menu
}
settings() {
# Show vpn settings.
local choices
choices="$(nordvpn settings | tr -d '\r-' | sed 's/^ *//')"
printf "%s" "$choices" | menu
}
# Parse options to the `rofi-nordvpn` command
while getopts ":hs" opt; do
case ${opt} in
h )
usage
exit 0
;;
s )
status
exit 0
;;
\? )
printf "Invalid Option: -%s\n" "$OPTARG" 1>&2
usage
exit 1
;;
esac
done
case "$(init_menu)" in
"connect")
case $(connect) in
"default")
nordvpn connect
;;
"countries")
country="$(countries)"
[ -n "$country" ] && nordvpn connect "$country"
;;
"cities")
country="$(countries)"
[ -n "$country" ] && city="$(cities "$country")"
[ -n "$city" ] && nordvpn connect "$country" "$city"
;;
"p2p")
nordvpn connect p2p
;;
"onion")
nordvpn connect onion_over_vpn
;;
*)
;;
esac
;;
"disconnect")
disconnect
;;
"status")
vpn_status
;;
"settings")
settings
;;
*)
;;
esac
© 2021 GitHub, Inc.
Terms
Privacy
Security
Status
Docs
Contact GitHub
Pricing
API
Training
Blog
About

247
rofi/scripts/powermenu.sh Executable file
View File

@@ -0,0 +1,247 @@
#!/usr/bin/env bash
# This script defines just a mode for rofi instead of being a self-contained
# executable that launches rofi by itself. This makes it more flexible than
# running rofi inside this script as now the user can call rofi as one pleases.
# For instance:
#
# rofi -show powermenu -modi powermenu:./rofi-power-menu
#
# See README.md for more information.
set -e
set -u
# All supported choices
all=(shutdown reboot suspend logout)
# By default, show all (i.e., just copy the array)
show=("${all[@]}")
declare -A texts
# texts[lockscreen]="lock screen"
texts[switchuser]="switch user"
texts[logout]="log out"
texts[suspend]="suspend"
# texts[hibernate]="hibernate"
texts[reboot]="reboot"
texts[shutdown]="shut down"
declare -A icons
# icons[lockscreen]=""
icons[switchuser]=" "
icons[logout]=" "
icons[suspend]=" "
# icons[hibernate]=" "
icons[reboot]=" "
icons[shutdown]=" "
icons[cancel]=" "
declare -A actions
# actions[lockscreen]="loginctl lock-session ${XDG_SESSION_ID-}"
# actions[lockscreen]="i3lock -d -u -e -c 000000 -i ~/Pictures/lock.png"
#actions[switchuser]="???"
actions[logout]="loginctl terminate-session ${XDG_SESSION_ID-}"
actions[suspend]="systemctl suspend"
# actions[hibernate]="systemctl hibernate"
actions[reboot]="systemctl reboot"
actions[shutdown]="systemctl poweroff"
# By default, ask for confirmation for actions that are irreversible
confirmations=(reboot shutdown logout)
# By default, no dry run
dryrun=false
showsymbols=true
function check_valid {
option="$1"
shift 1
for entry in "${@}"
do
if [ -z "${actions[$entry]+x}" ]
then
echo "Invalid choice in $1: $entry" >&2
exit 1
fi
done
}
# Parse command-line options
parsed=$(getopt --options=h --longoptions=help,dry-run,confirm:,choices:,choose:,symbols,no-symbols --name "$0" -- "$@")
if [ $? -ne 0 ]; then
echo 'Terminating...' >&2
exit 1
fi
eval set -- "$parsed"
unset parsed
while true; do
case "$1" in
"-h"|"--help")
echo "rofi-power-menu - a power menu mode for Rofi"
echo
echo "Usage: rofi-power-menu [--choices CHOICES] [--confirm CHOICES]"
echo " [--choose CHOICE] [--dry-run] [--symbols|--no-symbols]"
echo
echo "Use with Rofi in script mode. For instance, to ask for shutdown or reboot:"
echo
echo " rofi -show menu -modi \"menu:rofi-power-menu --choices=shutdown/reboot\""
echo
echo "Available options:"
echo " --dry-run Don't perform the selected action but print it to stderr."
echo " --choices CHOICES Show only the selected choices in the given order. Use / "
echo " as the separator. Available choices are lockscreen, logout,"
echo " suspend, hibernate, reboot and shutdown. By default, all"
echo " available choices are shown."
echo " --confirm CHOICES Require confirmation for the gives choices only. Use / as"
echo " the separator. Available choices are lockscreen, logout,"
echo " suspend, hibernate, reboot and shutdown. By default, only"
echo " irreversible actions logout, reboot and shutdown require"
echo " confirmation."
echo " --choose CHOICE Preselect the given choice and only ask for a confirmation"
echo " (if confirmation is set to be requested). It is strongly"
echo " recommended to combine this option with --confirm=CHOICE"
echo " if the choice wouldn't require confirmation by default."
echo " Available choices are lockscreen, logout, suspend,"
echo " hibernate, reboot and shutdown."
echo " --[no-]symbols Show Unicode symbols or not. Requires a font with support"
echo " for the symbols. Use, for instance, fonts from the"
echo " Nerdfonts collection. By default, they are shown"
echo " -h,--help Show this help text."
exit 0
;;
"--dry-run")
dryrun=true
shift 1
;;
"--confirm")
IFS='/' read -ra confirmations <<< "$2"
check_valid "$1" "${confirmations[@]}"
shift 2
;;
"--choices")
IFS='/' read -ra show <<< "$2"
check_valid "$1" "${show[@]}"
shift 2
;;
"--choose")
# Check that the choice is valid
check_valid "$1" "$2"
selectionID="$2"
shift 2
;;
"--symbols")
showsymbols=true
shift 1
;;
"--no-symbols")
showsymbols=false
shift 1
;;
"--")
shift
break
;;
*)
echo "Internal error" >&2
exit 1
;;
esac
done
# Define the messages after parsing the CLI options so that it is possible to
# configure them in the future.
function write_message {
icon="<span font_size=\"medium\">$1</span>"
text="<span font_size=\"medium\">$2</span>"
if [ "$showsymbols" = "true" ]
then
echo -n "\u200e$icon \u2068$text\u2069"
else
echo -n "$text"
fi
}
function print_selection {
echo -e "$1" | $(read -r -d '' entry; echo "echo $entry")
}
declare -A messages
declare -A confirmationMessages
for entry in "${all[@]}"
do
messages[$entry]=$(write_message "${icons[$entry]}" "${texts[$entry]^}")
done
for entry in "${all[@]}"
do
confirmationMessages[$entry]=$(write_message "${icons[$entry]}" "Yes")
done
confirmationMessages[cancel]=$(write_message "${icons[cancel]}" "No")
if [ $# -gt 0 ]
then
# If arguments given, use those as the selection
selection="${@}"
else
# Otherwise, use the CLI passed choice if given
if [ -n "${selectionID+x}" ]
then
selection="${messages[$selectionID]}"
fi
fi
# Don't allow custom entries
echo -e "\0no-custom\x1ftrue"
# Use markup
echo -e "\0markup-rows\x1ftrue"
if [ -z "${selection+x}" ]
then
echo -e "\0prompt\x1f⏻"
for entry in "${show[@]}"
do
echo -e "${messages[$entry]}\0icon\x1f${icons[$entry]}"
done
else
for entry in "${show[@]}"
do
if [ "$selection" = "$(print_selection "${messages[$entry]}")" ]
then
# Check if the selected entry is listed in confirmation requirements
for confirmation in "${confirmations[@]}"
do
if [ "$entry" = "$confirmation" ]
then
# Ask for confirmation
echo -e "\0prompt\x1fAre you sure?"
echo -e "${confirmationMessages[$entry]}\0icon\x1f${icons[$entry]}"
echo -e "${confirmationMessages[cancel]}\0icon\x1f${icons[cancel]}"
exit 0
fi
done
# If not, then no confirmation is required, so mark confirmed
selection=$(print_selection "${confirmationMessages[$entry]}")
fi
if [ "$selection" = "$(print_selection "${confirmationMessages[$entry]}")" ]
then
if [ $dryrun = true ]
then
# Tell what would have been done
echo "Selected: $entry" >&2
else
# Perform the action
${actions[$entry]}
fi
exit 0
fi
if [ "$selection" = "$(print_selection "${confirmationMessages[cancel]}")" ]
then
# Do nothing
exit 0
fi
done
# The selection didn't match anything, so raise an error
echo "Invalid selection: $selection" >&2
exit 1
fi

184
rofi/scripts/rofi-screenshot.sh Executable file
View File

@@ -0,0 +1,184 @@
#!/usr/bin/env bash
## rofi-screenshot
## Author: ceuk @ github
## Licence: WTFPL
## Usage:
## show the menu with rofi-screenshot
## stop recording with rofi-screenshot -s
# Screenshot directory
screenshot_directory="$HOME/Pictures/Screenshots"
# set ffmpeg defaults
ffmpeg() {
command ffmpeg -hide_banner -loglevel error -nostdin "$@"
}
video_to_gif() {
ffmpeg -i "$1" -vf palettegen -f image2 -c:v png - |
ffmpeg -i "$1" -i - -filter_complex paletteuse "$2"
}
countdown() {
notify-send "Screenshot" "Recording in 3 seconds" -t 1000
sleep 1
notify-send "Screenshot" "Recording in 2 seconds" -t 1000
sleep 1
notify-send "Screenshot" "Recording in 1 seconds" -t 1000
sleep 1
}
crtc() {
notify-send "Screenshot" "Select a region to capture"
ffcast -q $(slop -n -f '-g %g ') png /tmp/screenshot_clip.png
xclip -selection clipboard -t image/png /tmp/screenshot_clip.png
rm /tmp/screenshot_clip.png
notify-send "Screenshot" "Region copied to Clipboard"
}
crtf() {
notify-send "Screenshot" "Select a region to capture"
dt=$(date '+%d-%m-%Y %H:%M:%S')
ffcast -q $(slop -n -f '-g %g ') png "$screenshot_directory/$dt.png"
notify-send "Screenshot" "Region saved to $screenshot_directory"
}
cstc() {
ffcast -q png /tmp/screenshot_clip.png
xclip -selection clipboard -t image/png /tmp/screenshot_clip.png
rm /tmp/screenshot_clip.png
notify-send "Screenshot" "Screenshot copied to Clipboard"
}
cstf() {
dt=$(date '+%d-%m-%Y %H:%M:%S')
ffcast -q png "$screenshot_directory/$dt.png"
notify-send "Screenshot" "Screenshot saved to $screenshot_directory"
}
rgrtf() {
notify-send "Screenshot" "Select a region to record"
dt=$(date '+%d-%m-%Y %H:%M:%S')
ffcast -q $(slop -n -f '-g %g ' && countdown) rec /tmp/screenshot_gif.mp4
notify-send "Screenshot" "Converting to gif... (this can take a while)"
video_to_gif /tmp/screenshot_gif.mp4 "$screenshot_directory/$dt.gif"
rm /tmp/screenshot_gif.mp4
notify-send "Screenshot" "Recording saved to $screenshot_directory"
}
rgstf() {
countdown
dt=$(date '+%d-%m-%Y %H:%M:%S')
ffcast -q rec /tmp/screenshot_gif.mp4
notify-send "Screenshot" "Converting to gif... (this can take a while)"
video_to_gif /tmp/screenshot_gif.mp4 "$screenshot_directory/$dt.gif"
rm /tmp/screenshot_gif.mp4
notify-send "Screenshot" "Recording saved to $screenshot_directory"
}
rvrtf() {
notify-send "Screenshot" "Select a region to record"
dt=$(date '+%d-%m-%Y %H:%M:%S')
ffcast -q $(slop -n -f '-g %g ' && countdown) rec "$screenshot_directory/$dt.mp4"
notify-send "Screenshot" "Recording saved to $screenshot_directory"
}
rvstf() {
countdown
dt=$(date '+%d-%m-%Y %H:%M:%S')
ffcast -q rec "$screenshot_directory/$dt.mp4"
notify-send "Screenshot" "Recording saved to $screenshot_directory"
}
get_options() {
echo " Capture Region  Clip"
echo " Capture Region  File"
echo " Capture Screen  Clip"
echo " Capture Screen  File"
echo " Record Region  File (GIF)"
echo " Record Screen  File (GIF)"
echo " Record Region  File (MP4)"
echo " Record Screen  File (MP4)"
}
check_deps() {
if ! hash $1 2>/dev/null; then
echo "Error: This script requires $1"
exit 1
fi
}
main() {
# check dependencies
check_deps slop
check_deps ffcast
check_deps ffmpeg
check_deps xclip
check_deps rofi
if [[ $1 == '--help' ]] || [[ $1 = '-h' ]]
then
echo ### rofi-screenshot
echo USAGE: rofi-screenshot [OPTION]
echo \(no option\)
echo " show the screenshot menu"
echo -s, --stop
echo " stop recording"
echo -h, --help
echo " this screen"
exit 1
fi
if [[ $1 = '--stop' ]] || [[ $1 = '-s' ]]
then
pkill -fxn '(/\S+)*ffmpeg\s.*\sx11grab\s.*'
exit 1
fi
# Get choice from rofi
choice=$( (get_options) | rofi -dmenu -i -fuzzy -p "Screenshot" )
# If user has not picked anything, exit
if [[ -z "${choice// }" ]]; then
exit 1
fi
# run the selected command
case $choice in
' Capture Region  Clip')
crtc
;;
' Capture Region  File')
crtf
;;
' Capture Screen  Clip')
cstc
;;
' Capture Screen  File')
cstf
;;
' Record Region  File (GIF)')
rgrtf
;;
' Record Screen  File (GIF)')
rgstf
;;
' Record Region  File (MP4)')
rvrtf
;;
' Record Screen  File (MP4)')
rvstf
;;
esac
# done
set -e
}
main $1 &
exit 0
!/bin/bash

163
rofi/scripts/rofitr.sh Executable file
View File

@@ -0,0 +1,163 @@
#!/usr/bin/env bash
# Copyright (C) 2019 Yusuf Aktepe <yusuf@yusufaktepe.com>
## Set defaults
SOURCE="ja" # source language code
TARGET="en" # translation language code
# ENGINE="google" # google, yandex or bing
# LOCALE="en" # translator language ($LANG var. by default)
# SPEAK_SOURCE="false" # speak the source (true/false)
# SPEAK_TRANSLATION="false" # speak the translation (true/false)
## Rofi general options
# leave these empty or comment out to use system defaults:
# FONT="mono 12"
WIDTH="50"
LOCATION="0"
# YOFFSET="-20"
# use alternative config and theme
# CONFIG="~/.config/rofi/translate-config.rasi"
# THEME="/usr/share/rofi/themes/lb.rasi"
## Rofi required options
HIST_LINES="5" # lines to show for history mode
RES_LINES="100" # limit output to screen height
PROMPT_TR=" "
PROMPT_HIST=" history"
PROMPT_DEL="﯊ delete"
CLR_RESULT="#ffffff" # text color for translation
CLR1="#5294e2"
CLR2="#1d2021"
HIST="${XDG_DATA_HOME:-~/.local/share}/rofi/rofitr_history"
mkdir -p "$(dirname "$HIST")"
help() {
cat <<EOF
# <u>Translate with defaults</u>
> <span background="$CLR1" foreground="$CLR2"><b><i>text</i></b></span>
# <u>Override default SOURCE and TARGET</u>
> <span background="$CLR1" foreground="$CLR2"><b>en:es <i>text</i></b></span>
# <u>Auto-detect SOURCE</u>
> <span background="$CLR1" foreground="$CLR2"><b>:en <i>text</i></b></span>
<s> </s>
<u>Actions:</u>
<span foreground="$CLR1"><b>!e</b></span> <i>word</i> => show examples for "word"
<span foreground="$CLR1"><b>!s</b></span> <i>text</i> => speak the "text"
<span foreground="$CLR1"><b>!!</b></span> => show last translation
<span foreground="$CLR1"><b>!!e</b></span> => show examples for last translation
<span foreground="$CLR1"><b>!!s</b></span> => speak last translation
<span foreground="$CLR1"><b>!</b></span> => select and translate from history
<span foreground="$CLR1"><b>!d</b></span> => select and remove from history
<span foreground="$CLR1"><b>!dd</b></span> => clear history (in delete mode)
<s> </s>
<u>Command line:</u>
$ rofitr :ru <i>text</i> <span foreground="$CLR1">=> </span>Translate into Russian
$ rofitr -s <span foreground="$CLR1">=> </span>Translate from primary selection
EOF
}
rofi_cmd() {
[ -n "$CONFIG" ] && params+=(-config "$CONFIG")
[ -n "$THEME" ] && params+=(-theme "$THEME")
[ -n "$WIDTH" ] && params+=(-width "$WIDTH")
[ -n "$LOCATION" ] && params+=(-location "$LOCATION")
[ -n "$YOFFSET" ] && params+=(-yoffset "$YOFFSET")
[ -n "$FONT" ] && params+=(-font "$FONT")
rofi -dmenu -i "${params[@]}" "$@"
}
crow_cmd() {
[ -n "$ENGINE" ] && crowparams+=(-e "$ENGINE")
[ -n "$LOCALE" ] && crowparams+=(-l "$LOCALE")
[ "$SPEAK_TRANSLATION" = "true" ] && crowparams+=(-p)
[ "$SPEAK_SOURCE" = "true" ] && crowparams+=(-u)
crow "${crowparams[@]}" "$@"
}
format() {
clean="s/^[\t]$//;/^$/d;s/\&/\&amp\;/g;s/</\&lt\;/g;s/>/\&gt\;/g;/ - translation options:$/d"
bold="s/^\(auxiliary verb\|abbreviation\|adjective\|adverb\|article\|conjunction\|contraction\|exclamation\|interjection\|noun\|particle\|prefix\|preposition\|pronoun\|suffix\|symbol\|verb\)$/<b>&<\/b>/"
trl="s/^\[ .*-\&gt\;.* \]$/<span foreground=\"$CLR1\"><i>&<\/i><\/span>/"
case "$1" in
ex) sed -e "$clean" -e "$bold" -ne '/- examples:/,$p' | head -n $RES_LINES ;;
sel) sed -e "$clean" -e '/ - examples:$/d' -e "$bold" -e "$trl" | sed -z 's/\n*(/ (/' | head -n $RES_LINES ;;
*) sed -e "$clean" -e '/- examples:$/Q' -e "$bold" -e "$trl" | sed -z 's/\n*(/ (/' | head -n $RES_LINES
esac
}
cklang() {
lslang=(
"af" "sq" "am" "ar" "hy" "az" "eu" "ba" "be" "bn" "bs" "bg" "ca" "yue" "ceb"
"zh-CN" "zh-TW" "co" "hr" "cs" "da" "nl" "en" "eo" "et" "fj" "fil" "fi" "fr"
"fy" "gl" "ka" "de" "el" "gu" "ht" "ha" "haw" "he" "mrj" "hi" "hmn" "hu" "is"
"ig" "id" "ga" "it" "ja" "jw" "kn" "kk" "km" "tlh" "tlh-Qaak" "ko" "ku" "ky" "lo"
"la" "lv" "apc" "lt" "lb" "mk" "mg" "ms" "ml" "mt" "mi" "mr" "mhr" "mn" "my" "ne"
"no" "ny" "pap" "ps" "fa" "pl" "pt" "pa" "otq" "ro" "ru" "sm" "gd" "sr-Cyrl"
"sr-Latin" "st" "sn" "sd" "si" "sk" "sl" "so" "es" "su" "sw" "sv" "tl" "ty" "tg"
"ta" "tt" "te" "th" "to" "tr" "udm" "uk" "ur" "uz" "vi" "cy" "xh" "yi" "yo" "yua"
)
printf '%s\n' "${lslang[@]}" | grep -x "$1"
}
esc() { sed 's|[][\\/.*^$]|\\&|g' <<< "$1" ;}
append_hist() {
sed -i "/^$(esc "$input")$/d" "$HIST"
printf '%s\n' "$input" >> "$HIST"
}
return_result() {
input="$(rofi_cmd -p "$PROMPT_TR" -l 0 -mesg "<span color='$CLR_RESULT'>$result</span>")"
}
[ -n "$*" ] && input="$*" || input="$(rofi_cmd -p "$PROMPT_TR" -l 0)"
while [ -n "$input" ]; do
case "$input" in
"?") input="$(rofi_cmd -p "Usage" -l 0 -mesg "<span color='$CLR_RESULT'>$(help)</span>")" ;;
!) input="$(tac "$HIST" | rofi_cmd -p "$PROMPT_HIST" -l "$HIST_LINES")"
[ "$input" = "!" ] && input="$(rofi_cmd -p "$PROMPT_TR" -l 0)" ;;
!!) input=$(tail -n1 "$HIST") ;;
!!e) input=$(printf "!e %s" "$(tail -n1 "$HIST")") ;;
!!s) input=$(printf "!s %s" "$(tail -n1 "$HIST")") ;;
!d) pattern="$(tac "$HIST" | rofi_cmd -p "$PROMPT_DEL" -l "$HIST_LINES")"
case "$pattern" in
!) input="$(rofi_cmd -p "$PROMPT_TR" -l 0)" ;;
!dd) printf '' > "$HIST" && exit 0 ;;
"") exit 0 ;;
*) sed -i "/^$(esc "$pattern")$/d" "$HIST"
esac ;;
??*:??*)
SOURCE=$(cklang "$(echo "$input" | awk -F':' '{print $1}')")
TARGET=$(cklang "$(echo "$input" | awk -F'[:| ]' '{print $2}')")
input=$(echo "$input" | cut -d' ' -f2-)
result=$(crow_cmd -s "${SOURCE:-en}" -t "${TARGET:-tr}" -- "$input" | format)
unset SOURCE TARGET
append_hist; return_result ;;
:??*)
TARGET=$(cklang "$(echo "$input" | awk -F'[:| ]' '{print $2}')")
input=$(echo "$input" | cut -d' ' -f2-)
result=$(crow_cmd -t "${TARGET:-tr}" -- "$input" | format)
unset TARGET
append_hist; return_result ;;
!e*)
input=$(echo "$input" | cut -d' ' -f2-)
result=$(crow_cmd -- "$input" | format ex)
append_hist; return_result ;;
!s*)
input=$(echo "$input" | cut -d' ' -f2-)
result=$(SPEAK_SOURCE="true" crow_cmd -- "$input" | format sel)
append_hist; return_result ;;
-s)
input=$(xclip -o | tr -d '\n'); [ -z "$input" ] && exit
result=$(crow_cmd -t "${TARGET:-tr}" -- "$input" | format)
append_hist; return_result ;;
*)
result=$(crow_cmd -s "${SOURCE:-en}" -t "${TARGET:-tr}" -- "$input" | format)
append_hist; return_result ;;
esac
done

12
rofi/scripts/scholar-search.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
query=$( (echo ) | rofi -dmenu -i -lines 0 -matching fuzzy -location 0 -p " " )
if [[ -n "$query" ]]; then
url=https://scholar.google.com/scholar?q=$query
xdg-open "$url"
else
exit
fi
exit 0

View File

@@ -0,0 +1,3 @@
#!/bin/sh
cat $(dirname $0)/symbol-list.txt | rofi -dmenu -i -p "Icon" | cut -f 1 | xclip -selection clipboard

View File

@@ -0,0 +1,62 @@
α alpha
β beta
γ gamma
δ delta
ε epsilon
ζ zeta
η eta
θ theta
ι iota
κ kappa
λ lambda
μ mu
ν nu
ξ xi
ο omicron
π pi
ρ rho
σ sigma
τ tau
υ upsilon
φ phi
χ chi
ψ psi
ω omega
Α Alpha
Β Beta
Γ Gamma
Δ Delta
Ε Epsilon
Ζ Zeta
Η Eta
Θ Theta
Ι Iota
Κ Kappa
Λ Lambda
Μ Mu
Ν Nu
Ξ Xi
Ο Omicron
Π Pi
Ρ Rho
Σ Sigma
Τ Tau
Υ Upsilon
Φ Phi
Χ Chi
Ψ Psi
Ω Omega
~
=
>
<
±
×
·
÷

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# rofi-virtualbox: manage virtualbox machines with rofi
# Originally by Oliver Kraitschy <okraits@arcor.de> (https://github.com/okraits/rofi-tools)
# With modifications by Alexander Pushkov <hey@ale.sh>
OPTIONS="Start machine\nStart headless\nSend ACPI shutdown signal\nClone machine\nDelete machine"
kb_start="Control-Return"
args=(
-dmenu
-kb-custom-1 "${kb_start}"
-kb-accept-custom ""
)
while true; do
# select machine to control
vm=$(vboxmanage list vms | awk -F '"' '{print $2}' | rofi "${args[@]}" 'Select machine:')
rofi_exit=$?
if [[ $rofi_exit -eq 1 ]]; then
exit
fi
case "${rofi_exit}" in
0) # default
# just pass through to the menu
;;
10) # -kb-custom-1
vboxmanage startvm "$vm"
exit
;;
esac
# select action to be executed
option=$(echo -e $OPTIONS | rofi "${args[@]}" 'Select action:')
rofi_exit=$?
if [[ $rofi_exit -eq 1 ]]; then
exit
fi
case "$option" in
"Start machine")
vboxmanage startvm "$vm"
exit
;;
"Start headless")
vboxmanage startvm "$vm" --type headless
;;
"Send ACPI shutdown signal")
vboxmanage controlvm "$vm" acpipowerbutton --type headless
;;
"Clone machine")
vboxmanage clonevm "$vm" --mode machine --register --options keepallmacs
;;
"Delete machine")
vboxmanage unregistervm "$vm" --delete
;;
*)
exit 1
;;
esac
done

14
rofi/scripts/web-search.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
query=$( (echo ) | rofi -dmenu -i -lines 0 -matching fuzzy -location 0 -p " " )
if [[ -n "$query" ]]; then
# https://scholar.google.com/scholar?hl=en&q=
# url=https://www.duckduckgo.com/?q=$query
url=https://search.brave.com/search?q=$query
xdg-open "$url"
else
exit
fi
exit 0