Initial Push.

This commit is contained in:
2025-08-15 17:44:24 -04:00
commit c9ff287462
62 changed files with 6649 additions and 0 deletions

View File

@@ -0,0 +1 @@
/home/th3r00t/Downloads/ShadowPCBeta.AppImage

67
home/.local/usr/bin/addpass Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
source $HOME/.config/rofi-pass/config
if [[ -n "$3" && "$2" == "--root" ]]; then
root="${2}"
elif [[ -n $root ]]; then
root=$root
elif [[ -n $PASSWORD_STORE_DIR ]]; then
root=$PASSWORD_STORE_DIR
else
root="$HOME/.password-store"
fi
if [[ $1 == "--help" || $1 == "-h" ]]; then
echo "add pass files for rofi-pass"
echo "(C) 2015 Rasmus Steinke <rasi at xssn dot at>"
echo ""
echo "--name \"foobar\" Mandatory first argument - filename of password file"
echo "--root \"foobar\" Optional second argument - Absolute path to password store"
echo ""
echo "+FIELD \"barbaz\" Every field name has to start with \"+\""
echo " Values should be quoted"
echo ""
echo "Example:"
echo "addpass --name \"my password file\" --root \"$HOME/passwords\" +user \"Richard\" +foo \"bar\" +autotype \"foo :tab user :tab pass\""
exit
else
echo "$1"
if [[ $1 != "--name" ]]; then
echo "Missing --name option. Try --help"
exit
elif [[ $1 == "--name" ]]; then
Name="$2"
fi
fi
echo "Using database \"$root\""
OIFS=$IFS;
IFS="+";
fields="$@";
fieldsArray=($fields);
read -p "Enter password for entry \"${Name}\" > " -s pass
cd "${root}"
group=$(echo -e "No Group\n---\n$(find -type d -not -iwholename '*.git*' -printf '%d\t%P\n' | sort -r -nk1 | cut -f2-)" | rofi -dmenu -p "Choose Group > ")
echo -e "\n\nStoring file ${Name} in group ${group}"
printEntry () {
echo -e "$pass\n---"
for ((i=1; i<${#fieldsArray[@]}; ++i)); do
field=$(echo "${fieldsArray[$i]}" | awk -F' ' '{print $1}')
option=$(echo "${fieldsArray[$i]}" | cut -d ' ' -f 2- | sed -e 's/[[:blank:]]\+$//')
echo "$field: $option" | grep -Ev 'name:|--root|root:|^:' #${fieldsArray[$i]}";
done
}
if [[ "$group" == "No Group" ]]; then
printEntry | PASSWORD_STORE_DIR="${root}" pass insert -m "${Name}"
elif [[ "$group" == "" ]]; then
exit
else
printEntry | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${Name}"
fi

View File

@@ -0,0 +1,7 @@
SLEEP_SEC=5
COUNT=0
while :; do
let COUNT=$COUNT+1
echo -e " HELLO $COUNT"
sleep $SLEEP_SEC
done

View File

@@ -0,0 +1 @@
/home/th3r00t/.local/build/Blightmud/target/release/blightmud

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env sh
mpv /mnt/audiobooks/Dune\ -\ Audiobook\ Collection\ 2015/03\ -\ Legends\ of\ Dune/01.\ The\ Butlerian\ Jihad.m4b

View File

@@ -0,0 +1,56 @@
#!/bin/bash
# Set directory path for Vimwiki files
WIKI_DIR="$HOME/org/wiki" # Replace with the path to your Vimwiki directory
# Get the list of existing note titles, replacing underscores with spaces for display
EXISTING_TITLES=$(find "$WIKI_DIR/notes" -type f -name "*.wiki" -exec basename {} .wiki \; | tr '_' ' ')
# Use fzf to let the user select an existing title or type a new one
TITLE=$( (echo "$EXISTING_TITLES" && echo "[New Note]") | fzf --prompt="Select or enter title: " --print-query)
# Check if the user chose an existing title or opted for a new note
if [[ "$TITLE" = "[New Note]" || -z "$TITLE" ]]; then
# Prompt for a new title if "New Note" was selected
TITLE=$(echo "" | fzf --prompt="Enter title for new entry: ")
fi
# Exit if no title was entered
if [[ -z "$TITLE" ]]; then
echo "No title entered. Exiting."
exit 1
fi
# Format the filename by replacing spaces with underscores and lowercasing
FILENAME_TIMESTAMP=$(date +"%Y%m%d%H%M")
FILENAME="${FILENAME_TIMESTAMP}-$(echo "$TITLE" | tr ' ' '_' | tr '[:upper:]' '[:lower:]').wiki"
NEW_FILE="$WIKI_DIR/notes/$FILENAME"
# Check if a file with this title already exists
EXISTING_FILE=$(find "$WIKI_DIR/notes" -type f -name "$(echo "$TITLE" | tr ' ' '_' | tr '[:upper:]' '[:lower:]').wiki")
if [[ -n "$EXISTING_FILE" ]]; then
# Open the existing file in Neovim if found
nvim "$EXISTING_FILE"
else
# Create a new file with the specified template if it does not exist
TIMESTAMP=$(date +"%Y-%m-%d %H:%M")
echo "= $TITLE =
*Created:* $TIMESTAMP
== Summary ==
== Tasks ==
== Notes ==
== Resources ==
* [[wiki link]] for additional content
* [[other wiki link|Desc]]
" > "$NEW_FILE"
# Add a link to the new file at the bottom of index.wiki
echo "- [[$FILENAME|$TITLE]]" >> "$WIKI_DIR/index.wiki"
# Open the new file in Neovim
nvim "$NEW_FILE"
fi

14
home/.local/usr/bin/chatgpt.js Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env node
import { ChatGPTAPIBrowser } from 'chatgpt'
async function example() {
const api = new ChatGPTAPIBrowser({
email: process.env.OPENAI_EMAIL,
password: process.env.OPENAI_PASSWORD
})
await api.initSession()
const result = await api.sendMessage("Hello World")
console.log(result.rseponse)
}

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Set the directory where your dotfiles are located
DOTFILES_DIR="${HOME}/.dotfiles"
# Use fzf to select a file
file=$(find "$DOTFILES_DIR" -type f -name "*.*" | \
fzf --delimiter / --with-nth=-1 --keep-right \
--prompt="Dotfiles 󰓾 " \
--tmux left,40 --reverse \
)
# Check if a directory was selected
if [[ -n "$file" ]]; then
projectname="${file##*/}"
escprojectname = $(printf '%q' "$projectname")
# Check if a tmux window with the project name already exists
if tmux list-windows -F "#{window_name}" | grep -q "^$escprojectname$"; then
tmux select-window -t "$projectname"
else
# Create a new tmux window with the project name and open nvim in the folder
tmux new-window -n "$projectname" "nvim '$file'"
fi
fi

2
home/.local/usr/bin/dropdown Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
urxvt -name dropdown -e tmux attach Dropdown &

View File

@@ -0,0 +1,898 @@
#!/bin/env python3
import sys
import os
import shutil
import argparse
import json
import urllib.request
import subprocess
import random
from pathlib import Path
from typing import Tuple
from typing import TypeAlias
CompletedProcess: TypeAlias = subprocess.CompletedProcess
class App:
""" Contains all settings and meta information for the application. """
name: str = 'emojicherrypick'
version: str = '0.2'
def __init__(self, args: argparse.Namespace) -> None:
""" Construct application attributes used as settings. """
self.list_version: bool = args.version
self.frozen: bool = bool(getattr(sys, 'frozen', False)
and hasattr(sys, '_MEIPASS'))
self.wipe_cache: bool = args.wipe_cache
self.offline: bool = args.offline
self.menu: str = args.menu
self.url: str = args.url
self.cache_dir: Path = fullpath(args.cache_dir)
self.db_source: Path = Path(self.cache_dir / 'emojis.json')
self.noemojis: bool = args.noemojis
self.db_filtered: Path | None = None
if not self.noemojis:
self.db_filtered = self.db_source.with_suffix('.cherry')
self.nofavorites: bool = args.nofavorites
self.db_favorites: Path | None = None
if not self.nofavorites:
self.db_favorites = fullpath(args.favorites)
self.recents_size: int = args.recents_size
self.norecents: bool = args.norecents
self.db_recents: Path | None = None
if not self.norecents:
self.db_recents = fullpath(args.recents)
self.font_family: str = args.font_family
self.font_size: int = args.font_size
self.list_size: int = args.list_size
self.selected_emoji: str | None = None
self.selected_desc: str | None = None
self.stdout: bool = args.stdout and not args.nostdout
self.clipboard: bool = args.clipboard and not args.noclipboard
self.notify: bool = args.notify and not args.nonotify
self.typing: bool = args.typing and not args.notyping
self.ignore_case: bool = args.ignore_case and not args.noignore_case
self.ignore_skin: bool = args.ignore_skin
self.matching_rofi: str = args.matching_rofi
self.pattern: str = args.pattern
self.prompt: str = args.prompt
self.list_programs: bool = args.list_programs
self.programs: dict[str, Path] = {
'Python': Path(sys.executable),
'rofi': App.which(args.rofi),
'dmenu': App.which(args.dmenu),
'pmenu': App.which(args.pmenu),
'fzf': App.which(args.fzf),
'xclip': App.which(args.xclip),
'xdotool': App.which(args.xdotool),
'notify-send': App.which(args.notifysend),
}
if self.wipe_cache:
self.wipe_cache_files()
if not self.offline or not self.noemojis:
self.download_db_source()
self.filter_db_source()
def load_emoji_list(self, aslist=False) -> str | list:
""" Read all emojis, recents and favorites into a single string. """
emoji_list: str = ''
filtered_list: str = ''
recents_list: str = ''
favorites_list: str = ''
if (not self.norecents
and self.db_recents
and self.db_recents.exists()):
recents_list = self.db_recents.read_text().strip('\n')
recents_top: list = recents_list.splitlines()
recents_top.reverse()
recents_top = list(dict.fromkeys(recents_top))
recents_top = recents_top[0:self.recents_size]
recents_list = '\n'.join(recents_top)
if (not self.nofavorites
and self.db_favorites
and self.db_favorites.exists()):
favorites_list = self.db_favorites.read_text().strip('\n')
if (not self.noemojis
and self.db_filtered
and self.db_filtered.exists()):
filtered_list = self.db_filtered.read_text().strip('\n')
if recents_list:
emoji_list += '\n' + recents_list
if favorites_list:
emoji_list += '\n' + favorites_list
if filtered_list:
emoji_list += '\n' + filtered_list
elist: list[str] = list(dict.fromkeys(emoji_list.splitlines()))
if aslist:
return elist
else:
emoji_list = '\n'.join(elist)
return emoji_list.lstrip('\n')
def wipe_cache_files(self) -> None:
""" Clean cache by deleting all known files in it. """
if self.db_source:
self.db_source.unlink(missing_ok=True)
if self.db_filtered:
self.db_filtered.unlink(missing_ok=True)
if self.db_recents:
self.db_recents.unlink(missing_ok=True)
return None
def download_db_source(self, force=False):
""" Download emojis.json database source from URL to cache. """
if force:
self.db_source.unlink(missing_ok=True)
if not self.db_source.exists():
self.cache_dir.mkdir(exist_ok=True)
self.db_filtered.unlink(missing_ok=True)
response = urllib.request.urlopen(self.url)
data = response.read()
text = data.decode('utf-8')
self.db_source.write_text(text)
def filter_db_source(self, force=False):
""" Convert, filter and sort cached database to a small text file. """
def sorted_by_order(elem):
""" Used to determined sort key by 'order' for sorted(). """
return elem['order']
if force:
self.db_filtered.unlink(missing_ok=True)
if self.db_filtered and not self.db_filtered.exists():
source = json.loads(self.db_source.read_text())
filtered: str = ''
emojis_face: str = ''
emojis_finger: str = ''
emojis_other: str = ''
for emoji in sorted(source['emojis'], key=sorted_by_order):
# Exclude emojis that have "skin" in their names, as they are
# mostly color variations of the main emoji.
not_ignored_by_skin = 'skin' not in emoji['name'] \
and 'skin_tone' not in emoji['shortname'] if self.ignore_skin \
else True
if (not_ignored_by_skin and emoji['name']):
# Format:
# ☺️ smiling face Smileys & Emotion (face-affection)
str_emoji: str = (emoji['emoji'].strip()
+ ' '
+ emoji['name'].strip()
+ ' ~ '
+ emoji['category'].strip())
# Create multiple lists with emojis, so later it can be put
# together for sorted groups.
if ('face' in emoji['name']
or 'face' in emoji['category']):
emojis_face += str_emoji + '\n'
elif 'finger' in emoji['category']:
emojis_finger += str_emoji + '\n'
else:
emojis_other += str_emoji + '\n'
filtered = emojis_face + emojis_finger + emojis_other
self.db_filtered.write_text(filtered.strip('\n'))
def update_selected_emoji(self, emoji: list | None) -> str | None:
""" Update last selected emoji and return by stripping newlines. """
if emoji is None:
self.selected_emoji = None
self.selected_desc = None
else:
try:
emoji = [emoji[0].strip('\n'), emoji[1].strip('\n')]
self.selected_emoji = emoji[0]
self.selected_desc = emoji[1]
self.append_recents()
except (ValueError, AttributeError, IndexError):
self.selected_emoji = None
self.selected_desc = None
return self.selected_emoji
def select_by_none(self):
""" Selects nothing and resets last selected emoji. """
return self.update_selected_emoji(None)
def select_by_random(self):
""" Selects an emoji by random chance. """
random_set: set = set(self.load_emoji_list(aslist=True))
random_set.discard('')
random_list: list = list(random_set)
random.shuffle(random_list)
emoji = random_list[0].split(' ', 1)
return self.update_selected_emoji(emoji)
def select_by_filter(self) -> str | None:
""" Select an emoji without a menu but first match on a filter. """
emoji_list: str | list = self.load_emoji_list(aslist=True)
if self.ignore_case:
emoji_list = list(filter(
lambda line: self.pattern.lower() in line.lower(),
emoji_list
))
else:
emoji_list = list(filter(
lambda line: self.pattern in line,
emoji_list
))
try:
emoji = emoji_list[0].split(' ', 1)
except (ValueError, AttributeError, IndexError):
emoji = None
return self.update_selected_emoji(emoji)
def select_by_dmenu(self):
""" Select an emoji with dmenu and get emoji and desc tuple. """
command: list[str] = []
command.append(self.programs['dmenu'].as_posix())
command.append('-p')
command.append(self.prompt)
command.append('-l')
command.append(str(self.list_size))
command.append('-fn')
command.append(f'"{self.font_family}-{str(self.font_size)}"')
emoji_list = self.load_emoji_list()
if self.ignore_case:
emoji_list = emoji_list.lower()
emoji = App.select_command_emoji(command, emoji_list)
return self.update_selected_emoji(emoji)
def select_by_rofi(self):
""" Select an emoji with rofi and get emoji and desc tuple. """
command: list[str] = []
command.append(self.programs['rofi'].as_posix())
command.append('-dmenu')
command.append('-steal-focus')
command.append('-p')
command.append(self.prompt)
command.append('-title')
command.append(self.name)
command.append('-l')
command.append(str(self.list_size))
command.append('-font')
command.append(f'"{self.font_family} {str(self.font_size)}"')
command.append('-no-custom')
command.append('-matching')
command.append(self.matching_rofi)
if self.ignore_case:
command.append('-i')
command.append('-nocase-sensitive')
emoji_list = self.load_emoji_list()
emoji = App.select_command_emoji(command, emoji_list)
return self.update_selected_emoji(emoji)
def select_by_pmenu(self):
""" Select an emoji with pmenu and get emoji and desc tuple. """
command: list[str] = []
command.append(self.programs['pmenu'].as_posix())
command.append('-p')
command.append(self.prompt)
emoji_list = self.load_emoji_list()
if self.ignore_case:
emoji_list = emoji_list.lower()
emoji = App.select_command_emoji(command, emoji_list)
return self.update_selected_emoji(emoji)
def select_by_fzf(self):
""" Select an emoji with fzf and get emoji and desc tuple. """
command: list[str] = []
command.append(self.programs['fzf'].as_posix())
command.append('--layout')
command.append('reverse')
command.append('--prompt')
command.append(self.prompt)
if self.pattern:
command.append('--filter')
command.append(self.pattern)
if self.ignore_case:
command.append('-i')
emoji_list = self.load_emoji_list()
emoji = App.select_command_emoji(command, emoji_list)
return self.update_selected_emoji(emoji)
@classmethod
def select_command_emoji(
cls,
command,
emoji_list) -> Tuple[str, str] | Tuple[None, None]:
""" Return selected emoji and desc from list using custom command. """
output_p: CompletedProcess | None = None
try:
output_p = subprocess.run(command,
input=emoji_list,
stdout=subprocess.PIPE,
text=True)
except FileNotFoundError:
raise subprocess.SubprocessError
if output_p and output_p.stdout:
try:
emoji, desc = output_p.stdout.split(' ', 1)
return emoji.strip(' \n'), desc.strip(' \n')
except ValueError:
return None, None
else:
return None, None
def send_emoji_to_stdout(self, newline=True) -> None:
""" Print out emoji to stdout. """
if newline:
print(self.selected_emoji)
else:
print(self.selected_emoji, end='')
def send_emoji_to_clipboard(self) -> subprocess.Popen | None:
""" Copy emoji to systems clipboard. """
command: list[str] = []
command.append(self.programs['xclip'].as_posix())
command.append('-rmlastnl')
command.append('-selection')
command.append('clipboard')
xclip_p: subprocess.Popen | None = None
xclip_p = subprocess.Popen(command,
stdin=subprocess.PIPE,
text=True)
if xclip_p:
try:
xclip_p.communicate(input=(self.selected_emoji), timeout=2)
if xclip_p.returncode:
raise subprocess.SubprocessError
except subprocess.TimeoutExpired:
xclip_p.kill()
xclip_p = None
raise subprocess.SubprocessError
else:
xclip_p = None
raise subprocess.SubprocessError
return xclip_p
def send_emoji_to_typing(self) -> CompletedProcess | None:
""" Output emoji to active window as if user typed it on keyboard. """
command: list[str] = []
command.append(self.programs['xdotool'].as_posix())
command.append('getwindowfocus')
command.append('windowfocus')
command.append('--sync')
command.append('type')
command.append('--clearmodifiers')
command.append('--delay')
command.append('25')
if self.selected_emoji:
command.append(self.selected_emoji)
xdotool_p: CompletedProcess | None = None
xdotool_p = subprocess.run(command,
stdin=subprocess.PIPE,
text=True,
check=True,
timeout=1)
return xdotool_p
def send_emoji_to_notify(self) -> CompletedProcess | None:
""" Send the emoji as a notification message. """
command: list[str] = []
command.append(self.programs['notify-send'].as_posix())
command.append('--urgency=low')
if self.selected_emoji:
command.append(self.selected_emoji)
notify_p: CompletedProcess | None = None
notify_p = subprocess.run(command,
stdin=subprocess.PIPE,
text=True,
check=True,
timeout=1)
return notify_p
def append_recents(self) -> bool:
""" Append the last selected emoji entry to the recents file. """
if (not self.norecents
and self.db_recents
and self.selected_emoji
and self.selected_desc):
line: str = ''
if self.db_recents.exists():
line = '\n'
self.trim_recents_file()
line += self.selected_emoji + ' ' + self.selected_desc
with open(self.db_recents, 'a') as file:
file.write(line)
return True
else:
return False
def trim_recents_file(self) -> bool:
""" Shortens and strips recents file if it gets big. """
max_byte_size: int = 4096
max_list_entries: int = 50
if (self.db_recents
and self.db_recents.stat().st_size > max_byte_size):
data: str = self.db_recents.read_text().strip('\n')
recents_list: list = data.splitlines()
recents_list.reverse()
recents_list = list(dict.fromkeys(recents_list))
recents_list = recents_list[0:max_list_entries]
recents_list.reverse()
data = '\n'.join(recents_list)
self.db_recents.unlink(missing_ok=True)
self.db_recents.write_text(data)
return True
else:
return False
def print_version(self):
""" Print version and frozen state of this program. """
if self.frozen:
frozen = ' (pyinstaller)'
else:
frozen = ''
print(f'{self.name} v{self.version}{frozen}')
def print_list_programs(self):
""" Print all program names and paths to stdout. """
for name, path in self.programs.items():
print(name + ':', path.as_posix())
@classmethod
def which(cls, command: str) -> Path:
""" Find command in $PATH or get fullpath. """
program: str | None = shutil.which(command)
path: Path
if program:
path = Path(program)
else:
path = fullpath(command)
if not path.is_file():
path = Path(command)
return path
def fullpath(file: str) -> Path:
""" Transform str to path, resolve env vars, tilde and make absolute. """
expandedfile: str = os.path.expandvars(file)
path: Path = Path(expandedfile).expanduser().resolve()
return path
def parse_arguments(args: list[str] | None = None) -> argparse.Namespace:
""" Programs CLI options. """
parser = argparse.ArgumentParser(
description=('🍒⛏️ Emoji Cherry Pick - Select an emoji and go wild.'),
epilog=('Copyright © 2022 Tuncay D. '
'<https://github.com/thingsiplay/emojicherrypick>'),
)
parser.add_argument(
'--version',
default=False,
action='store_true',
help='print version and exit'
)
parser.add_argument(
'--list-programs',
default=False,
action='store_true',
help='list available programs and exit'
)
p_enable_output = parser.add_argument_group('enable output')
p_enable_output.add_argument(
'-o', '--stdout',
default=False,
action='store_true',
help=('write selected emoji to stdout, unless option "--nostdout" '
'is in effect')
)
p_enable_output.add_argument(
'-t', '--typing',
default=False,
action='store_true',
help=('simulate typing out the emoji on the keyboard, unless option '
'"--notyping" is in effect, typing can be unreliable and not '
'all applications may accept or play nice with it')
)
p_enable_output.add_argument(
'-c', '--clipboard',
default=False,
action='store_true',
help=('copy selected emoji to system clipboard, unless option '
'"--noclipboard" is in effect')
)
p_enable_output.add_argument(
'-n', '--notify',
default=False,
action='store_true',
help=('send selected emoji as a notification message, unless option '
'"--nonotify" is in effect')
)
p_disable_output = parser.add_argument_group('disable output')
p_disable_output.add_argument(
'-O', '--nostdout',
default=False,
action='store_true',
help='disable interaction with stdout, regardless of other options'
)
p_disable_output.add_argument(
'-T', '--notyping',
default=False,
action='store_true',
help=('disable simulated typing to active window, regardless of '
'other options')
)
p_disable_output.add_argument(
'-C', '--noclipboard',
default=False,
action='store_true',
help=('disable interaction with clipboard, regardless of other '
'options')
)
p_disable_output.add_argument(
'-N', '--nonotify',
default=False,
action='store_true',
help=('do not send any notification messages, regardless of other '
'options')
)
p_programs = parser.add_argument_group('programs')
p_programs.add_argument(
'--rofi',
metavar='CMD',
default='rofi',
help=('name or path to "rofi" program when option "--menu" is set to '
'"rofi"')
)
p_programs.add_argument(
'--dmenu',
metavar='CMD',
default='dmenu',
help=('name or path to "dmenu" program when option "--menu" is set to '
'"dmenu"')
)
p_programs.add_argument(
'--pmenu',
metavar='CMD',
default='pmenu',
help=('name or path to "pmenu" program when option "--menu" is set to '
'"pmenu"')
)
p_programs.add_argument(
'--fzf',
metavar='CMD',
default='fzf',
help=('name or path to "fzf" program when option "--menu" is set to '
'"fzf"')
)
p_programs.add_argument(
'--xclip',
metavar='CMD',
default='xclip',
help=('name or path to "xclip" program to handle clipboard when '
'option "--clipboard" is active')
)
p_programs.add_argument(
'--xdotool',
metavar='CMD',
default='xdotool',
help=('name or path to "xdotool" program to handle typing when option '
'"--typing" is active')
)
p_programs.add_argument(
'--notifysend',
metavar='CMD',
default='notify-send',
help=('name or path to "notify-send" program to handle notifications '
'when option "--notify" is active')
)
p_menufilter = parser.add_argument_group('engines and filters')
default_menu: str = 'rofi'
p_menufilter.add_argument(
'-M', '--menu',
metavar='SYSTEM',
default=default_menu,
choices=['rofi', 'dmenu', 'pmenu', 'fzf', 'filter', 'random', 'none'],
help=('change menu engine to select emojis, available systems: '
'"rofi", "dmenu", "pmenu", "fzf", "filter", "random", "none", '
'system "none" disables selection, "filter" won\'t display a '
'menu but choose first entry in the list that matches the text '
'at option "--pattern", systems "fzf" and "pmenu" are terminal '
'programs, "random" won\'t display a menu but choose an entry '
f'by random chance, defaults to: "{default_menu}"')
)
p_menufilter.add_argument(
'-p', '--pattern',
metavar='filter',
default='',
help=('simple text filter, used when option "--menu" is set to '
'"filter" or "fzf", causes in both cases to non interactive '
'selection of first emoji that matches the pattern')
)
default_matching_rofi: str = 'normal'
p_menufilter.add_argument(
'-m', '--matching-rofi',
metavar='MODE',
default=default_matching_rofi,
choices=['normal', 'regex', 'glob', 'fuzzy', 'prefix'],
help=('set matching algorithm for search in rofi, available modes: '
'"normal", "regex", "glob", "fuzzy", "prefix", defaults to: '
f'"{default_matching_rofi}"')
)
p_menufilter.add_argument(
'-i', '--ignore-case',
default=False,
action='store_true',
help=('ignore case sensitivity when searching list of emojis, '
'unless option "--noignore-case" is in effect')
)
p_menufilter.add_argument(
'-I', '--noignore-case',
default=False,
action='store_true',
help='case sensitive search of emojis, regardless of other options'
)
p_cache = parser.add_argument_group('cache files')
default_url = ('https://gist.githubusercontent.com/thingsiplay/'
'1f500459bc117cf0b63e1f5c11e03963/raw/'
'd8e4b78cfe66862cf3809443c1dba017f37b61db/emojis.json')
p_cache.add_argument(
'-u', '--url',
metavar='URL',
default=(default_url),
help=('source web address to download file "emojis.json", defaults '
f'to: "{default_url}"')
)
p_cache.add_argument(
'-U', '--offline',
default=False,
action='store_true',
help='prohibit downloading files from network, mainly "emojis.json"'
)
default_cache: str = "~/.cache/emojicherrypick"
p_cache.add_argument(
'-d', '--cache-dir',
metavar='DIR',
default=default_cache,
help=('directory for downloads and other long-lived temporary files '
f'used for quick access, defaults to: "{default_cache}"')
)
p_cache.add_argument(
'-w', '--wipe-cache',
default=False,
action='store_true',
help=('delete temporary cache files, redownload and recreate them '
'unless option "--offline" is in effect')
)
p_cache.add_argument(
'-E', '--noemojis',
default=False,
action='store_true',
help=('disable loading from main emojis database created from '
'"emojis.json"')
)
default_recents: str = "~/.cache/emojicherrypick/recents.cherry"
p_cache.add_argument(
'-r', '--recents',
metavar='FILE',
default=default_recents,
help=('program keeps track of last used emojis and saves them to '
'a history file, the last entries will be displayed at the top '
'of each emoji listing in the menus, same format as '
'"--favorites" file, use option "--recents-size" to set number '
f'of entries to show blah, defaults to: "{default_recents}"')
)
p_cache.add_argument(
'-R', '--norecents',
default=False,
action='store_true',
help='disable recents file specified at option "--recents"'
)
default_recents_size: int = 2
p_cache.add_argument(
'-k', '--recents-size',
metavar='NUM',
default=default_recents_size,
type=int,
choices=range(0, 200),
help=('read number of recently used emojis and ignore rest of file, '
'can be used for displaying in the menu or at filters, '
f'defaults to: "{default_recents_size}"')
)
p_cache.add_argument(
'--ignore-skin',
default=True,
action=argparse.BooleanOptionalAction,
help='ignore emoji skin variations when creating the cache'
)
p_config = parser.add_argument_group('config files')
default_favorites: str = "~/.config/emojicherrypick/favorites.cherry"
p_config.add_argument(
'-f', '--favorites',
metavar='FILE',
default=default_favorites,
help=('user list of emojis to list at the beginning of each emoji '
'listing in the menus, 1 line per emoji set, each set starts '
'with an emoji or any text and goes until first space is found, '
'rest of the line are names, descripion and keywords, defaults '
f'to: "{default_favorites}"')
)
p_config.add_argument(
'-F', '--nofavorites',
default=False,
action='store_true',
help='disable favorites file specified at option "--favorites"'
)
p_menuinterface = parser.add_argument_group('menu interface')
default_prompt: str = '🍒'
p_menuinterface.add_argument(
'-@', '--prompt',
metavar='TEXT',
default=default_prompt,
help=('set custom prompt on user input menu left of entry field, '
f'defaults to: "{default_prompt}"')
)
default_font_family: str = 'Noto Color Emoji'
p_menuinterface.add_argument(
'-g', '--font-family',
metavar='NAME',
default=default_font_family,
help=('font name to use for dispaly with the menu, defaults to: '
f'"{default_font_family}"')
)
default_font_size: int = 16
p_menuinterface.add_argument(
'-s', '--font-size',
metavar='NUM',
default=default_font_size,
type=int,
choices=range(4, 256),
help=('font size of emojis and text to display in the menu, '
f'defaults to: "{default_font_size}"')
)
default_list_size: int = 15
p_menuinterface.add_argument(
'-l', '--list-size',
metavar='NUM',
default=default_list_size,
type=int,
choices=range(1, 200),
help=('number of rows to display in the menu, defaults to: '
f'"{default_list_size}"')
)
if args is None:
return parser.parse_args()
else:
return parser.parse_args(args)
def main(args: list[str] | None = None) -> int:
""" Run the application. """
app: App
if not args and not sys.argv[1:]:
args_default: list[str] = [os.getenv('EMOJICHERRYPICK_DEFAULT',
default='-con')]
app = App(parse_arguments(args_default))
else:
app = App(parse_arguments(args))
if app.list_version:
app.print_version()
return 0
elif app.list_programs:
app.print_list_programs()
return 0
try:
if app.menu == 'rofi':
app.select_by_rofi()
elif app.menu == 'dmenu':
app.select_by_dmenu()
elif app.menu == 'pmenu':
app.select_by_pmenu()
elif app.menu == 'fzf':
app.select_by_fzf()
elif app.menu == 'filter':
app.select_by_filter()
elif app.menu == 'random':
app.select_by_random()
elif app.menu == 'none':
app.select_by_none()
else:
raise RuntimeError('Unkown menu option.')
return -1
except subprocess.SubprocessError:
return 1
if app.selected_emoji:
try:
if app.stdout:
app.send_emoji_to_stdout()
if app.clipboard:
app.send_emoji_to_clipboard()
if app.typing:
app.send_emoji_to_typing()
if app.notify:
app.send_emoji_to_notify()
except subprocess.SubprocessError:
return 3
elif app.menu == 'none':
return 0
else:
return 2
return 0
if __name__ == '__main__':
sys.exit(main())

14
home/.local/usr/bin/foot-smart Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/sh
if footclient "$@" 2>/dev/null; then
exit 0
fi
exec foot --server &
sleep 0.2
exec footclient "$@" || {
echo "Failed to connect to foot server." >&2
exit 1
}

329
home/.local/usr/bin/fzf-git.sh Executable file
View File

@@ -0,0 +1,329 @@
# The MIT License (MIT)
#
# Copyright (c) 2024 Junegunn Choi
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# shellcheck disable=SC2039
[[ $0 = - ]] && return
__fzf_git_color() {
if [[ -n $NO_COLOR ]]; then
echo never
elif [[ $# -gt 0 ]] && [[ -n $FZF_GIT_PREVIEW_COLOR ]]; then
echo "$FZF_GIT_PREVIEW_COLOR"
else
echo "${FZF_GIT_COLOR:-always}"
fi
}
__fzf_git_cat() {
if [[ -n $FZF_GIT_CAT ]]; then
echo "$FZF_GIT_CAT"
return
fi
# Sometimes bat is installed as batcat
_fzf_git_bat_options="--style='${BAT_STYLE:-full}' --color=$(__fzf_git_color .) --pager=never"
if command -v batcat > /dev/null; then
echo "batcat $_fzf_git_bat_options"
elif command -v bat > /dev/null; then
echo "bat $_fzf_git_bat_options"
else
echo cat
fi
}
__fzf_git_pager() {
local pager
pager="${FZF_GIT_PAGER:-${GIT_PAGER:-$(git config --get core.pager 2>/dev/null)}}"
echo "${pager:-cat}"
}
if [[ $# -eq 1 ]]; then
branches() {
git branch "$@" --sort=-committerdate --sort=-HEAD --format=$'%(HEAD) %(color:yellow)%(refname:short) %(color:green)(%(committerdate:relative))\t%(color:blue)%(subject)%(color:reset)' --color=$(__fzf_git_color) | column -ts$'\t'
}
refs() {
git for-each-ref "$@" --sort=-creatordate --sort=-HEAD --color=$(__fzf_git_color) --format=$'%(if:equals=refs/remotes)%(refname:rstrip=-2)%(then)%(color:magenta)remote-branch%(else)%(if:equals=refs/heads)%(refname:rstrip=-2)%(then)%(color:brightgreen)branch%(else)%(if:equals=refs/tags)%(refname:rstrip=-2)%(then)%(color:brightcyan)tag%(else)%(if:equals=refs/stash)%(refname:rstrip=-2)%(then)%(color:brightred)stash%(else)%(color:white)%(refname:rstrip=-2)%(end)%(end)%(end)%(end)\t%(color:yellow)%(refname:short) %(color:green)(%(creatordate:relative))\t%(color:blue)%(subject)%(color:reset)' | column -ts$'\t'
}
hashes() {
git log --date=short --format="%C(green)%C(bold)%cd %C(auto)%h%d %s (%an)" --graph --color=$(__fzf_git_color) "$@"
}
case "$1" in
branches)
echo $'CTRL-O (open in browser) ALT-A (show all branches)\n'
branches
;;
all-branches)
echo $'CTRL-O (open in browser)\n'
branches -a
;;
hashes)
echo $'CTRL-O (open in browser) CTRL-D (diff)\nCTRL-S (toggle sort) ALT-A (show all hashes)\n'
hashes
;;
all-hashes)
echo $'CTRL-O (open in browser) CTRL-D (diff)\nCTRL-S (toggle sort)\n'
hashes --all
;;
refs)
echo $'CTRL-O (open in browser) ALT-E (examine in editor) ALT-A (show all refs)\n'
refs --exclude='refs/remotes'
;;
all-refs)
echo $'CTRL-O (open in browser) ALT-E (examine in editor)\n'
refs
;;
nobeep) ;;
*) exit 1 ;;
esac
elif [[ $# -gt 1 ]]; then
set -e
branch=$(git rev-parse --abbrev-ref HEAD 2> /dev/null)
if [[ $branch = HEAD ]]; then
branch=$(git describe --exact-match --tags 2> /dev/null || git rev-parse --short HEAD)
fi
# Only supports GitHub for now
case "$1" in
commit)
hash=$(grep -o "[a-f0-9]\{7,\}" <<< "$2")
path=/commit/$hash
;;
branch|remote-branch)
branch=$(sed 's/^[* ]*//' <<< "$2" | cut -d' ' -f1)
remote=$(git config branch."${branch}".remote || echo 'origin')
branch=${branch#$remote/}
path=/tree/$branch
;;
remote)
remote=$2
path=/tree/$branch
;;
file) path=/blob/$branch/$(git rev-parse --show-prefix)$2 ;;
tag) path=/releases/tag/$2 ;;
*) exit 1 ;;
esac
remote=${remote:-$(git config branch."${branch}".remote || echo 'origin')}
remote_url=$(git remote get-url "$remote" 2> /dev/null || echo "$remote")
if [[ $remote_url =~ ^git@ ]]; then
url=${remote_url%.git}
url=${url#git@}
url=https://${url/://}
elif [[ $remote_url =~ ^http ]]; then
url=${remote_url%.git}
fi
case "$(uname -s)" in
Darwin) open "$url$path" ;;
*) xdg-open "$url$path" ;;
esac
exit 0
fi
if [[ $- =~ i ]]; then
# -----------------------------------------------------------------------------
# Redefine this function to change the options
_fzf_git_fzf() {
fzf --height=50% --tmux 90%,70% \
--layout=reverse --multi --min-height=20 --border \
--border-label-pos=2 \
--color='header:italic:underline,label:blue' \
--preview-window='right,50%,border-left' \
--bind='ctrl-/:change-preview-window(down,50%,border-top|hidden|)' "$@"
}
_fzf_git_check() {
git rev-parse HEAD > /dev/null 2>&1 && return
[[ -n $TMUX ]] && tmux display-message "Not in a git repository"
return 1
}
__fzf_git=${BASH_SOURCE[0]:-${(%):-%x}}
__fzf_git=$(readlink -f "$__fzf_git" 2> /dev/null || /usr/bin/ruby --disable-gems -e 'puts File.expand_path(ARGV.first)' "$__fzf_git" 2> /dev/null)
_fzf_git_files() {
_fzf_git_check || return
local root query
root=$(git rev-parse --show-toplevel)
[[ $root != "$PWD" ]] && query='!../ '
(git -c color.status=$(__fzf_git_color) status --short --no-branch
git ls-files "$root" | grep -vxFf <(git status -s | grep '^[^?]' | cut -c4-; echo :) | sed 's/^/ /') |
_fzf_git_fzf -m --ansi --nth 2..,.. \
--border-label '📁 Files' \
--header $'CTRL-O (open in browser) ALT-E (open in editor)\n\n' \
--bind "ctrl-o:execute-silent:bash $__fzf_git file {-1}" \
--bind "alt-e:execute:${EDITOR:-vim} {-1} > /dev/tty" \
--query "$query" \
--preview "git diff --no-ext-diff --color=$(__fzf_git_color .) -- {-1} | $(__fzf_git_pager); $(__fzf_git_cat) {-1}" "$@" |
cut -c4- | sed 's/.* -> //'
}
_fzf_git_branches() {
_fzf_git_check || return
bash "$__fzf_git" branches |
_fzf_git_fzf --ansi \
--border-label '🌲 Branches' \
--header-lines 2 \
--tiebreak begin \
--preview-window down,border-top,40% \
--color hl:underline,hl+:underline \
--no-hscroll \
--bind 'ctrl-/:change-preview-window(down,70%|hidden|)' \
--bind "ctrl-o:execute-silent:bash $__fzf_git branch {}" \
--bind "alt-a:change-border-label(🌳 All branches)+reload:bash \"$__fzf_git\" all-branches" \
--preview "git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' \$(sed s/^..// <<< {} | cut -d' ' -f1) --" "$@" |
sed 's/^..//' | cut -d' ' -f1
}
_fzf_git_tags() {
_fzf_git_check || return
git tag --sort -version:refname |
_fzf_git_fzf --preview-window right,70% \
--border-label '📛 Tags' \
--header $'CTRL-O (open in browser)\n\n' \
--bind "ctrl-o:execute-silent:bash $__fzf_git tag {}" \
--preview "git show --color=$(__fzf_git_color .) {} | $(__fzf_git_pager)" "$@"
}
_fzf_git_hashes() {
_fzf_git_check || return
bash "$__fzf_git" hashes |
_fzf_git_fzf --ansi --no-sort --bind 'ctrl-s:toggle-sort' \
--border-label '🍡 Hashes' \
--header-lines 3 \
--bind "ctrl-o:execute-silent:bash $__fzf_git commit {}" \
--bind "ctrl-d:execute:grep -o '[a-f0-9]\{7,\}' <<< {} | head -n 1 | xargs git diff --color=$(__fzf_git_color) > /dev/tty" \
--bind "alt-a:change-border-label(🍇 All hashes)+reload:bash \"$__fzf_git\" all-hashes" \
--color hl:underline,hl+:underline \
--preview "grep -o '[a-f0-9]\{7,\}' <<< {} | head -n 1 | xargs git show --color=$(__fzf_git_color .) | $(__fzf_git_pager)" "$@" |
awk 'match($0, /[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]*/) { print substr($0, RSTART, RLENGTH) }'
}
_fzf_git_remotes() {
_fzf_git_check || return
git remote -v | awk '{print $1 "\t" $2}' | uniq |
_fzf_git_fzf --tac \
--border-label '📡 Remotes' \
--header $'CTRL-O (open in browser)\n\n' \
--bind "ctrl-o:execute-silent:bash $__fzf_git remote {1}" \
--preview-window right,70% \
--preview "git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' '{1}/$(git rev-parse --abbrev-ref HEAD)' --" "$@" |
cut -d$'\t' -f1
}
_fzf_git_stashes() {
_fzf_git_check || return
git stash list | _fzf_git_fzf \
--border-label '🥡 Stashes' \
--header $'CTRL-X (drop stash)\n\n' \
--bind 'ctrl-x:reload(git stash drop -q {1}; git stash list)' \
-d: --preview "git show --color=$(__fzf_git_color .) {1} | $(__fzf_git_pager)" "$@" |
cut -d: -f1
}
_fzf_git_lreflogs() {
_fzf_git_check || return
git reflog --color=$(__fzf_git_color) --format="%C(blue)%gD %C(yellow)%h%C(auto)%d %gs" | _fzf_git_fzf --ansi \
--border-label '📒 Reflogs' \
--preview "git show --color=$(__fzf_git_color .) {1} | $(__fzf_git_pager)" "$@" |
awk '{print $1}'
}
_fzf_git_each_ref() {
_fzf_git_check || return
bash "$__fzf_git" refs | _fzf_git_fzf --ansi \
--nth 2,2.. \
--tiebreak begin \
--border-label '☘️ Each ref' \
--header-lines 2 \
--preview-window down,border-top,40% \
--color hl:underline,hl+:underline \
--no-hscroll \
--bind 'ctrl-/:change-preview-window(down,70%|hidden|)' \
--bind "ctrl-o:execute-silent:bash $__fzf_git {1} {2}" \
--bind "alt-e:execute:${EDITOR:-vim} <(git show {2}) > /dev/tty" \
--bind "alt-a:change-border-label(🍀 Every ref)+reload:bash \"$__fzf_git\" all-refs" \
--preview "git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' {2} --" "$@" |
awk '{print $2}'
}
_fzf_git_worktrees() {
_fzf_git_check || return
git worktree list | _fzf_git_fzf \
--border-label '🌴 Worktrees' \
--header $'CTRL-X (remove worktree)\n\n' \
--bind 'ctrl-x:reload(git worktree remove {1} > /dev/null; git worktree list)' \
--preview "
git -c color.status=$(__fzf_git_color .) -C {1} status --short --branch
echo
git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' {2} --
" "$@" |
awk '{print $1}'
}
if [[ -n "${BASH_VERSION:-}" ]]; then
__fzf_git_init() {
bind -m emacs-standard '"\er": redraw-current-line'
bind -m emacs-standard '"\C-z": vi-editing-mode'
bind -m vi-command '"\C-z": emacs-editing-mode'
bind -m vi-insert '"\C-z": emacs-editing-mode'
local o c
for o in "$@"; do
c=${o:0:1}
bind -m emacs-standard '"\C-g\C-'$c'": " \C-u \C-a\C-k`_fzf_git_'$o'`\e\C-e\C-y\C-a\C-y\ey\C-h\C-e\er \C-h"'
bind -m vi-command '"\C-g\C-'$c'": "\C-z\C-g\C-'$c'\C-z"'
bind -m vi-insert '"\C-g\C-'$c'": "\C-z\C-g\C-'$c'\C-z"'
bind -m emacs-standard '"\C-g'$c'": " \C-u \C-a\C-k`_fzf_git_'$o'`\e\C-e\C-y\C-a\C-y\ey\C-h\C-e\er \C-h"'
bind -m vi-command '"\C-g'$c'": "\C-z\C-g'$c'\C-z"'
bind -m vi-insert '"\C-g'$c'": "\C-z\C-g'$c'\C-z"'
done
}
elif [[ -n "${ZSH_VERSION:-}" ]]; then
__fzf_git_join() {
local item
while read item; do
echo -n "${(q)item} "
done
}
__fzf_git_init() {
local m o
for o in "$@"; do
eval "fzf-git-$o-widget() { local result=\$(_fzf_git_$o | __fzf_git_join); zle reset-prompt; LBUFFER+=\$result }"
eval "zle -N fzf-git-$o-widget"
for m in emacs vicmd viins; do
eval "bindkey -M $m '^g^${o[1]}' fzf-git-$o-widget"
eval "bindkey -M $m '^g${o[1]}' fzf-git-$o-widget"
done
done
}
fi
__fzf_git_init files branches tags remotes hashes stashes lreflogs each_ref worktrees
# -----------------------------------------------------------------------------
fi

1
home/.local/usr/bin/getMusic Executable file
View File

@@ -0,0 +1 @@
#!/usr/env python

View File

@@ -0,0 +1,3 @@
#!/usr/bin/bash
layout=$( tmux display-message -p "#{window_layout}" )
echo $layout

16
home/.local/usr/bin/igrep Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Check if the first argument is a path and assign it to SEARCH_PATH
SEARCH_PATH="${1:-.}"
# Shift the arguments so any additional arguments are treated as the search pattern for `rg`
shift
# Execute `rg` in the specified path with the search pattern
rg --color=always --line-number --no-heading --smart-case --hidden "${*:-}" "$SEARCH_PATH" |
fzf --ansi \
--color "hl:-1:underline,hl+:-1:underline:reverse" \
--delimiter : \
--preview 'bat --color=always {1} --highlight-line {2}' \
--preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
--bind 'enter:become(nvim {1} +{2})'

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env sh
while true; do
inotifywait -e modify,create,delete -r ./src ./tests/
clear
echo "File change detected. Running tests..."
pytest -s
echo "Waiting for changes..."
done

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env sh
while true; do
inotifywait -e modify,create,delete -r ./src/
clear
echo "File change detected. Running build..."
cargo build
echo "Waiting for changes..."
done

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env sh
while true; do
inotifywait -e modify,create,delete -r ./build.zig ./build.zig.zon ./src/*
clear
echo "File change detected. Running tests..."
zig build run
echo "Waiting for changes..."
done

3
home/.local/usr/bin/nestX Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
Xephyr -br -ac -noreset -screen 1366x768 :1

10
home/.local/usr/bin/popuptmux Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
width=${2:-100%}
# width=${2:-80%}
height=${2:-30%}
if [ "$(tmux display-message -p -F "#{session_name}")" = "popup" ];then
tmux detach-client
else
tmux popup -d '#{pane_current_path}' -xC -y1 -w$width -h$height -E "tmux attach -t popup || tmux new -s popup"
# tmux popup -d '#{pane_current_path}' -xC -yC -w$width -h$height -E "tmux attach -t popup || tmux new -s popup"
fi

View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Set the directory where your projects are located
PROJECTS_DIR="${HOME}/Projects/"
# Use fzf to select a directory
folder=$(find "$PROJECTS_DIR" -type d -maxdepth 1 | \
fzf --delimiter / --with-nth=-1 --keep-right \
--prompt="Projects 󰓾 " \
--tmux left,40 --reverse \
)
# Check if a directory was selected
if [[ -n "$folder" ]]; then
projectname="${folder##*/}"
# Check if a tmux window with the project name already exists
if tmux list-windows -F "#{window_name}" | grep -q "^$projectname$"; then
tmux select-window -t "$projectname"
else
# Create a new tmux window with the project name and open nvim in the folder
# tmux new-window -n "$projectname" "cd '$folder' &&"
tmux new-window -n "$projectname" "cd '$folder' && nvim"
fi
fi

BIN
home/.local/usr/bin/pytui Executable file

Binary file not shown.

304
home/.local/usr/bin/qute-pass Executable file
View File

@@ -0,0 +1,304 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: Chris Braun (cryzed) <cryzed@googlemail.com>
#
# SPDX-License-Identifier: GPL-3.0-or-later
"""
Insert login information using pass and a dmenu-compatible application (e.g. dmenu, rofi -dmenu, ...). A short
demonstration can be seen here: https://i.imgur.com/KN3XuZP.gif.
"""
USAGE = """The domain of the site has to appear as a segment in the pass path,
for example: "github.com/cryzed" or "websites/github.com". Alternatively the
parameter `--unfiltered` may be used to get a list of all passwords. How the
username and password are determined is freely configurable using the CLI
arguments. As an example, if you instead store the username as part of the
secret (and use a site's name as filename), instead of the default configuration,
use `--username-target secret` and `--username-pattern "username: (.+)"`.
The login information is inserted by emulating key events using qutebrowser's
fake-key command in this manner: [USERNAME]<Tab>[PASSWORD], which is compatible
with almost all login forms.
If you use gopass with multiple mounts, use the CLI switch --mode gopass to switch to gopass mode.
Suggested bindings similar to Uzbl's `formfiller` script:
config.bind('<z><l>', 'spawn --userscript qute-pass')
config.bind('<z><u><l>', 'spawn --userscript qute-pass --username-only')
config.bind('<z><p><l>', 'spawn --userscript qute-pass --password-only')
config.bind('<z><o><l>', 'spawn --userscript qute-pass --otp-only')
"""
EPILOG = """Dependencies: tldextract (Python 3 module), pass, pass-otp (optional).
WARNING: The login details are viewable as plaintext in qutebrowser's debug log (qute://log) and might be shared if
you decide to submit a crash report!"""
import argparse
import enum
import fnmatch
import functools
import idna
import os
import re
import shlex
import subprocess
import sys
import unicodedata
from urllib.parse import urlparse
import tldextract
def expanded_path(path):
# Expand potential ~ in paths, since this script won't be called from a shell that does it for us
expanded = os.path.expanduser(path)
# Add trailing slash if not present
return os.path.join(expanded, '')
argument_parser = argparse.ArgumentParser(description=__doc__, usage=USAGE, epilog=EPILOG)
argument_parser.add_argument('url', nargs='?', default=os.getenv('QUTE_URL'))
argument_parser.add_argument('--password-store', '-p',
default=expanded_path(os.getenv('PASSWORD_STORE_DIR', default='~/.password-store')),
help='Path to your pass password-store (only used in pass-mode)', type=expanded_path)
argument_parser.add_argument('--mode', '-M', choices=['pass', 'gopass'], default="pass",
help='Select mode [gopass] to use gopass instead of the standard pass.')
argument_parser.add_argument('--prefix', type=str,
help='Search only the given subfolder of the store (only used in gopass-mode)')
argument_parser.add_argument('--username-pattern', '-u', default=r'.*/(.+)',
help='Regular expression that matches the username')
argument_parser.add_argument('--username-target', '-U', choices=['path', 'secret'], default='path',
help='The target for the username regular expression')
argument_parser.add_argument('--password-pattern', '-P', default=r'(.*)',
help='Regular expression that matches the password')
argument_parser.add_argument('--dmenu-invocation', '-d', default='rofi -dmenu',
help='Invocation used to execute a dmenu-provider')
argument_parser.add_argument('--no-insert-mode', '-n', dest='insert_mode', action='store_false',
help="Don't automatically enter insert mode")
argument_parser.add_argument('--io-encoding', '-i', default='UTF-8',
help='Encoding used to communicate with subprocesses')
argument_parser.add_argument('--merge-candidates', '-m', action='store_true',
help='Merge pass candidates for fully-qualified and registered domain name')
argument_parser.add_argument('--extra-url-suffixes', '-s', default='',
help='Comma-separated string containing extra suffixes (e.g local)')
argument_parser.add_argument('--unfiltered', dest='unfiltered', action='store_true',
help='Show an unfiltered selection of all passwords in the store')
argument_parser.add_argument('--always-show-selection', dest='always_show_selection', action='store_true',
help='Always show selection, even if there is only a single match')
group = argument_parser.add_mutually_exclusive_group()
group.add_argument('--username-only', '-e', action='store_true', help='Only insert username')
group.add_argument('--password-only', '-w', action='store_true', help='Only insert password')
group.add_argument('--otp-only', '-o', action='store_true', help='Only insert OTP code')
stderr = functools.partial(print, file=sys.stderr)
class ExitCodes(enum.IntEnum):
SUCCESS = 0
FAILURE = 1
# 1 is automatically used if Python throws an exception
NO_PASS_CANDIDATES = 2
COULD_NOT_MATCH_USERNAME = 3
COULD_NOT_MATCH_PASSWORD = 4
class CouldNotMatchUsername(Exception):
pass
class CouldNotMatchPassword(Exception):
pass
def qute_command(command):
with open(os.environ['QUTE_FIFO'], 'w') as fifo:
fifo.write(command + '\n')
fifo.flush()
# Encode candidate string parts as Internationalized Domain Name, doing
# Unicode normalization before. This allows to properly match (non-ASCII)
# pass entries with the corresponding domain names.
def idna_encode(name):
# Do Unicode normalization first, we use form NFKC because:
# 1. Use the compatibility normalization because these sequences have "the same meaning in some contexts"
# 2. idna.encode() below requires the Unicode strings to be in normalization form C
# See https://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms
unicode_normalized = unicodedata.normalize("NFKC", name)
# Empty strings can not be encoded, they appear for example as empty
# parts in split_path. If something like this happens, we just fall back
# to the unicode representation (which may already be ASCII then).
try:
idna_encoded = idna.encode(unicode_normalized)
except idna.IDNAError:
idna_encoded = unicode_normalized
return idna_encoded
def find_pass_candidates(domain, unfiltered=False):
candidates = []
if arguments.mode == "gopass":
gopass_args = ["gopass", "list", "--flat"]
if arguments.prefix:
gopass_args.append(arguments.prefix)
all_passwords = subprocess.run(gopass_args, stdout=subprocess.PIPE).stdout.decode("UTF-8").splitlines()
for password in all_passwords:
if unfiltered or domain in password:
candidates.append(password)
else:
idna_domain = idna_encode(domain)
for path, directories, file_names in os.walk(arguments.password_store, followlinks=True):
secrets = fnmatch.filter(file_names, '*.gpg')
if not secrets:
continue
# Strip password store path prefix to get the relative pass path
pass_path = path[len(arguments.password_store):]
split_path = pass_path.split(os.path.sep)
idna_split_path = [idna_encode(part) for part in split_path]
for secret in secrets:
secret_base = os.path.splitext(secret)[0]
idna_secret_base = idna_encode(secret_base)
if not unfiltered and idna_domain not in (idna_split_path + [idna_secret_base]):
continue
# Append the unencoded Unicode path/name since this is how pass uses them
candidates.append(os.path.join(pass_path, secret_base))
return candidates
def _run_pass(pass_arguments):
# The executable is conveniently named after it's mode [pass|gopass].
pass_command = [arguments.mode]
env = os.environ.copy()
env['PASSWORD_STORE_DIR'] = arguments.password_store
process = subprocess.run(pass_command + pass_arguments, env=env, stdout=subprocess.PIPE)
return process.stdout.decode(arguments.io_encoding).strip()
def pass_(path):
return _run_pass(['show', path])
def pass_otp(path):
if arguments.mode == "gopass":
return _run_pass(['otp', '-o', path])
return _run_pass(['otp', path])
def dmenu(items, invocation):
command = shlex.split(invocation)
process = subprocess.run(command, input='\n'.join(items).encode(arguments.io_encoding), stdout=subprocess.PIPE)
return process.stdout.decode(arguments.io_encoding).strip()
def fake_key_raw(text):
for character in text:
# Escape all characters by default, space requires special handling
sequence = '" "' if character == ' ' else r'\{}'.format(character)
qute_command('fake-key {}'.format(sequence))
def extract_password(secret, pattern):
match = re.match(pattern, secret)
if not match:
raise CouldNotMatchPassword("Pattern did not match target")
try:
return match.group(1)
except IndexError:
raise CouldNotMatchPassword("Pattern did not contain capture group, please use capture group. Example: (.*)")
def extract_username(target, pattern):
match = re.search(pattern, target, re.MULTILINE)
if not match:
raise CouldNotMatchUsername("Pattern did not match target")
try:
return match.group(1)
except IndexError:
raise CouldNotMatchUsername("Pattern did not contain capture group, please use capture group. Example: (.*)")
def main(arguments):
if not arguments.url:
argument_parser.print_help()
return ExitCodes.FAILURE
extractor = tldextract.TLDExtract(extra_suffixes=arguments.extra_url_suffixes.split(','))
extract_result = extractor(arguments.url)
# Try to find candidates using targets in the following order: fully-qualified domain name (includes subdomains),
# the registered domain name, the IPv4 address if that's what the URL represents and finally the private domain
# (if a non-public suffix was used), and the URL netloc.
candidates = set()
attempted_targets = []
private_domain = ''
if not extract_result.suffix:
private_domain = ('.'.join((extract_result.subdomain, extract_result.domain))
if extract_result.subdomain else extract_result.domain)
netloc = urlparse(arguments.url).netloc
for target in filter(None, [extract_result.fqdn, extract_result.registered_domain, extract_result.ipv4, private_domain, netloc]):
attempted_targets.append(target)
target_candidates = find_pass_candidates(target, unfiltered=arguments.unfiltered)
if not target_candidates:
continue
candidates.update(target_candidates)
if not arguments.merge_candidates:
break
else:
if not candidates:
stderr('No pass candidates for URL {!r} found! (I tried {!r})'.format(arguments.url, attempted_targets))
return ExitCodes.NO_PASS_CANDIDATES
if len(candidates) == 1 and not arguments.always_show_selection:
selection = candidates.pop()
else:
selection = dmenu(sorted(candidates), arguments.dmenu_invocation)
# Nothing was selected, simply return
if not selection:
return ExitCodes.SUCCESS
# If username-target is path and user asked for username-only, we don't need to run pass.
# Or if using otp-only, it will run pass on its own.
secret = None
if not (arguments.username_target == 'path' and arguments.username_only) and not arguments.otp_only:
secret = pass_(selection)
username_target = selection if arguments.username_target == 'path' else secret
try:
if arguments.username_only:
fake_key_raw(extract_username(username_target, arguments.username_pattern))
elif arguments.password_only:
fake_key_raw(extract_password(secret, arguments.password_pattern))
elif arguments.otp_only:
otp = pass_otp(selection)
fake_key_raw(otp)
else:
# Enter username and password using fake-key and <Tab> (which seems to work almost universally), then switch
# back into insert-mode, so the form can be directly submitted by hitting enter afterwards
fake_key_raw(extract_username(username_target, arguments.username_pattern))
qute_command('fake-key <Tab>')
fake_key_raw(extract_password(secret, arguments.password_pattern))
except CouldNotMatchPassword as e:
stderr('Failed to match password, target: secret, error: {}'.format(e))
return ExitCodes.COULD_NOT_MATCH_PASSWORD
except CouldNotMatchUsername as e:
stderr('Failed to match username, target: {}, error: {}'.format(arguments.username_target, e))
return ExitCodes.COULD_NOT_MATCH_USERNAME
if arguments.insert_mode:
qute_command('mode-enter insert')
return ExitCodes.SUCCESS
if __name__ == '__main__':
arguments = argument_parser.parse_args()
sys.exit(main(arguments))

900
home/.local/usr/bin/rofi-pass Executable file
View File

@@ -0,0 +1,900 @@
#!/usr/bin/env bash
# rofi-pass
# (c) 2015 Rasmus Steinke <rasi@xssn.at>
basecommand="$0"
# set default settings
_rofi () {
rofi -no-auto-select -i "$@"
}
_pwgen () {
pwgen -y "$@"
}
_image_viewer () {
feh -
}
_clip_in_primary() {
xclip
}
_clip_in_clipboard() {
xclip -selection clipboard
}
_clip_out_primary() {
xclip -o
}
_clip_out_clipboard() {
xclip --selection clipboard -o
}
export PASSWORD_STORE_DIR="${HOME}/.passwords/"
config_dir=${XDG_CONFIG_HOME:-$HOME/.config}
cache_dir=${XDG_CACHE_HOME:-$HOME/.cache}
# We expect to find these fields in pass(1)'s output
URL_field='url'
USERNAME_field='user'
AUTOTYPE_field='autotype'
OTPmethod_field='otp_method'
default_autotype="user :tab pass"
delay=2
wait=0.2
xdotool_delay=12
default_do='menu' # menu, copyPass, typeUser, typePass, copyUser, copyUrl, viewEntry, typeMenu, actionMenu, copyMenu, openUrl
auto_enter='false'
notify='false'
help_color=""
clip=primary
clip_clear=45
default_user="${ROFI_PASS_DEFAULT_USER-$(whoami)}"
default_user2=john_doe
password_length=12
fix_layout=false
# default shortcuts
autotype="Alt+1"
type_user="Alt+2"
type_pass="Alt+3"
open_url="Alt+4"
copy_name="Alt+u"
copy_url="Alt+l"
copy_pass="Alt+p"
show="Alt+o"
copy_menu="Alt+c"
action_menu="Alt+a"
type_menu="Alt+t"
help="Alt+h"
switch="Alt+x"
insert_pass="Alt+n"
qrcode="Alt+q"
previous_root="Shift+Left"
next_root="Shift+Right"
# Safe permissions
umask 077
has_qrencode() {
command -v qrencode >/dev/null 2>&1
}
listgpg () {
mapfile -d '' pw_list < <(find -L . -name '*.gpg' -print0)
pw_list=("${pw_list[@]#./}")
printf '%s\n' "${pw_list[@]}" | sort -n
}
# get all password files and output as newline-delimited text
list_passwords() {
cd "${root}" || exit
mapfile -t pw_list < <(listgpg)
printf '%s\n' "${pw_list[@]%.gpg}" | sort -n
}
doClip () {
case "$clip" in
"primary") _clip_in_primary ;;
"clipboard") _clip_in_clipboard ;;
"both") _clip_in_primary; _clip_out_primary | _clip_in_clipboard;;
esac
}
checkIfPass () {
printf '%s\n' "${root}: $selected_password" >| "$cache_dir/rofi-pass/last_used"
}
autopass () {
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
xset r off
rm -f "$cache_dir/rofi-pass/last_used"
printf '%s\n' "${root}: $selected_password" > "$cache_dir/rofi-pass/last_used"
for word in ${stuff["$AUTOTYPE_field"]}; do
case "$word" in
":tab") xdotool key Tab;;
":space") xdotool key space;;
":delay") sleep "${delay}";;
":enter") xdotool key Return;;
":otp") printf '%s' "$(generateOTP)" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
"pass") printf '%s' "${password}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
"path") printf '%s' "${selected_password}" | rev | cut -d'/' -f1 | rev | xdotool type --clearmodifiers --file -;;
*) printf '%s' "${stuff[${word}]}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
esac
done
if [[ ${auto_enter} == "true" ]]; then
xdotool key Return
fi
xset r "$x_repeat_enabled"
unset x_repeat_enabled
clearUp
}
generateQrCode() {
has_qrencode
if [[ $? -eq "1" ]]; then
printf '%s\n' "qrencode not found" | _rofi -dmenu
exit_code=$?
if [[ $exit_code -eq "1" ]]; then
exit
else
"${basecommand}"
fi
fi
checkIfPass
pass "$selected_password" | head -n 1 | qrencode -d 300 -v 8 -l H -o - | _image_viewer
if [[ $? -eq "1" ]]; then
printf '%s\n' "" | _rofi -dmenu -mesg "Image viewer not defined or cannot read from pipe"
exit_value=$?
if [[ $exit_value -eq "1" ]]; then
exit
else
"${basecommand}"
fi
fi
clearUp
}
openURL () {
checkIfPass
$BROWSER "$(PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep "${URL_field}: " | gawk '{sub(/:/,"")}{print $2}1' | head -1)"; exit;
clearUp
}
typeUser () {
checkIfPass
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
xset r off
printf '%s' "${stuff[${USERNAME_field}]}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
xset r "$x_repeat_enabled"
unset x_repeat_enabled
clearUp
}
typePass () {
checkIfPass
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
xset r off
printf '%s' "${password}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
if [[ $notify == "true" ]]; then
if [[ "${stuff[notify]}" == "false" ]]; then
:
else
notify-send "rofi-pass" "finished typing password";
fi
elif [[ $notify == "false" ]]; then
if [[ "${stuff[notify]}" == "true" ]]; then
notify-send "rofi-pass" "finished typing password";
else
:
fi
fi
xset r "$x_repeat_enabled"
unset x_repeat_enabled
clearUp
}
typeField () {
checkIfPass
local to_type
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
xset r off
case $typefield in
"OTP") to_type="$(generateOTP)" ;;
*) to_type="${stuff[${typefield}]}" ;;
esac
printf '%s' "$to_type" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
xset r "$x_repeat_enabled"
unset x_repeat_enabled
unset to_type
clearUp
}
generateOTP () {
checkIfPass
# First, we check if there is a non-conventional OTP command in the pass file
if PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep -q "${OTPmethod_field}: "; then
# We execute the commands after otp_method: AS-IS
bash -c "$(PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep "${OTPmethod_field}: " | cut -d' ' -f2-)"
else
# If there is no method defined, fallback to pass-otp
PASSWORD_STORE_DIR="${root}" pass otp "$selected_password"
fi
clearUp
}
copyUser () {
checkIfPass
printf '%s' "${stuff[${USERNAME_field}]}" | doClip
clearUp
}
copyField () {
checkIfPass
printf '%s' "${stuff[${copyfield}]}" | doClip
clearUp
}
copyURL () {
checkIfPass
printf '%s' "${stuff[${URL_field}]}" | doClip
clearUp
}
copyPass () {
checkIfPass
printf '%s' "$password" | doClip
if [[ $notify == "true" ]]; then
notify-send "rofi-pass" "Copied Password\\nClearing in $clip_clear seconds"
fi
if [[ $notify == "true" ]]; then
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard | notify-send "rofi-pass" "Clipboard cleared") &
elif [[ $notify == "false" ]]; then
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard) &
fi
}
viewEntry () {
checkIfPass
showEntry "${selected_password}"
}
generatePass () {
askmenu_content=(
"Yes"
"No"
)
askGenMenu=$(printf '%s\n' "${askmenu_content[@]}" | _rofi -dmenu -p "Generate new Password for ${selected_password}? > ")
askgen_exit=$?
if [[ $askgen_exit -eq 1 ]]; then
exit
fi
if [[ $askGenMenu == "Yes" ]]; then
true
elif [[ $askGenMenu == "No" ]]; then
actionMenu
fi
checkIfPass
symbols_content=(
"0 Cancel"
"1 Yes"
"2 No"
)
symbols=$(printf '%s\n' "${symbols_content[@]}" | _rofi -dmenu -p "Use Symbols? > ")
symbols_val=$?
if [[ $symbols_val -eq 1 ]]; then
exit
fi
if [[ $symbols == "0 Cancel" ]]; then
mainMenu;
elif [[ $symbols == "1 Yes" ]]; then
symbols="";
elif [[ $symbols == "2 No" ]]; then
symbols="-n";
fi
HELP="<span color='$help_color'>Enter Number or hit Enter to use default length</span>"
length=$(printf '%s' "" | _rofi -dmenu -mesg "${HELP}" -p "Password length? (Default: ${password_length}) > ")
length_exit=$?
if [[ $length_exit -eq 1 ]]; then
exit
fi
if [[ $length == "" ]]; then
PASSWORD_STORE_DIR="${root}" pass generate ${symbols} -i "$selected_password" "${password_length}" > /dev/null;
else
PASSWORD_STORE_DIR="${root}" pass generate ${symbols} -i "$selected_password" "${length}" > /dev/null;
fi
}
# main Menu
mainMenu () {
if [[ $1 == "--bmarks" ]]; then
selected_password="$(list_passwords 2>/dev/null \
| _rofi -mesg "Bookmarks Mode. ${switch} to switch" \
-dmenu \
-kb-custom-10 "${switch}" \
-select "$entry" \
-p "rofi-pass > ")"
rofi_exit=$?
if [[ $rofi_exit -eq 1 ]]; then
exit
elif [[ $rofi_exit -eq 19 ]]; then
${basecommand}
elif [[ $rofi_exit -eq 0 ]]; then
openURL
fi
else
unset selected_password
args=( -dmenu
-kb-custom-1 "${autotype}"
-kb-custom-2 "${type_user}"
-kb-custom-3 "${type_pass}"
-kb-custom-4 "${open_url}"
-kb-custom-5 "${copy_name}"
-kb-custom-6 "${copy_pass}"
-kb-custom-7 "${show}"
-kb-custom-8 "${copy_url}"
-kb-custom-9 "${type_menu}"
-kb-custom-10 "${previous_root}"
-kb-custom-11 "${next_root}"
-kb-custom-14 "${action_menu}"
-kb-custom-15 "${copy_menu}"
-kb-custom-16 "${help}"
-kb-custom-17 "${switch}"
-kb-custom-18 "${insert_pass}"
-kb-custom-19 "${qrcode}"
)
args+=( -kb-mode-previous "" # These keyboard shortcut options are needed, because
-kb-mode-next "" # Shift+<Left|Right> are otherwise taken by rofi.
-select "$entry"
-p "> " )
if [[ ${#roots[@]} -gt "1" || $custom_root == "true" ]]; then
args+=(-mesg "PW Store: ${root}")
fi
selected_password="$(list_passwords 2>/dev/null | _rofi "${args[@]}")"
rofi_exit=$?
if [[ $rofi_exit -eq 1 ]]; then
exit
fi
# Actions based on exit code, which do not need the entry.
# The exit code for -kb-custom-X is X+9.
case "${rofi_exit}" in
19) roots_index=$(( (roots_index-1+roots_length) % roots_length)); root=${roots[$roots_index]}; mainMenu; return;;
20) roots_index=$(( (roots_index+1) % roots_length)); root=${roots[$roots_index]}; mainMenu; return;;
25) helpMenu; return;;
26) ${basecommand} --bmarks; return;;
esac
mapfile -t password_temp < <(PASSWORD_STORE_DIR="${root}" pass show "$selected_password")
password=${password_temp[0]}
if [[ ${password} == "#FILE="* ]]; then
pass_file="${password#*=}"
mapfile -t password_temp2 < <(PASSWORD_STORE_DIR="${root}" pass show "${pass_file}")
password=${password_temp2[0]}
fi
fields=$(printf '%s\n' "${password_temp[@]:1}" | awk '$1 ~ /:$/ || /otpauth:\/\// {$1=$1;print}')
declare -A stuff
stuff["pass"]=${password}
if [[ -n $fields ]]; then
while read -r LINE; do
unset _id _val
case "$LINE" in
"otpauth://"*|"${OTPmethod_field}"*)
_id="OTP"
_val=""
;;
*)
_id="${LINE%%: *}"
_val="${LINE#* }"
;;
esac
if [[ -n "$_id" ]]; then
stuff["${_id}"]=${_val}
fi
done < <(printf '%s\n' "${fields}")
if test "${stuff['autotype']+autotype}"; then
:
else
stuff["autotype"]="${USERNAME_field} :tab pass"
fi
fi
fi
if [[ -z "${stuff["${AUTOTYPE_field}"]}" ]]; then
if [[ -n $default_autotype ]]; then
stuff["${AUTOTYPE_field}"]="${default_autotype}"
fi
fi
if [[ -z "${stuff["${USERNAME_field}"]}" ]]; then
if [[ -n $default_user ]]; then
if [[ "$default_user" == ":filename" ]]; then
stuff["${USERNAME_field}"]="$(basename "$selected_password")"
else
stuff["${USERNAME_field}"]="${default_user}"
fi
fi
fi
pass_content="$(for key in "${!stuff[@]}"; do printf '%s\n' "${key}: ${stuff[$key]}"; done)"
# actions based on keypresses
# The exit code for -kb-custom-X is X+9.
case "${rofi_exit}" in
0) typeMenu;;
10) sleep $wait; autopass;;
11) sleep $wait; typeUser;;
12) sleep $wait; typePass;;
13) openURL;;
14) copyUser;;
15) copyPass;;
16) viewEntry;;
17) copyURL;;
18) default_do="menu" typeMenu;;
23) actionMenu;;
24) copyMenu;;
27) insertPass;;
28) generateQrCode;;
esac
clearUp
}
clearUp () {
password=''
selected_password=''
unset stuff
unset password
unset selected_password
unset password_temp
unset stuff
}
helpMenu () {
_rofi -dmenu -mesg "Hint: All hotkeys are configurable in config file" -p "Help > " <<- EOM
${autotype}: Autotype
${type_user}: Type Username
${type_pass}: Type Password
${qrcode}: Generate and display qrcode
---
${copy_name}: Copy Username
${copy_pass}: Copy Password
${copy_url}: Copy URL
${open_url}: Open URL
${copy_menu}: Copy Custom Field
---
${action_menu}: Edit, Move, Delete, Re-generate Submenu
${show}: Show Password File
${insert_pass}: Insert new Pass Entry
${switch}: Switch Pass/Bookmark Mode
---
${previous_root}: Switch to previous password store (--root)
${next_root}: Switch to next password store (--root)
EOM
help_val=$?
if [[ $help_val -eq 1 ]]; then
exit;
else
unset helptext; mainMenu;
fi
}
typeMenu () {
if [[ -n $default_do ]]; then
if [[ $default_do == "menu" ]]; then
checkIfPass
local -a keys=("${!stuff[@]}")
keys=("${keys[@]/$AUTOTYPE_field}")
typefield=$({ printf '%s' "${AUTOTYPE_field}" ; printf '%s\n' "${keys[@]}" | sort; } | _rofi -dmenu -p "Choose Field to type > ")
typefield_exit=$?
if [[ $typefield_exit -eq 1 ]]; then
exit
fi
case "$typefield" in
'') exit;;
'pass') sleep $wait; typePass;;
"${AUTOTYPE_field}") sleep $wait; autopass;;
*) sleep $wait; typeField
esac
clearUp
elif [[ $default_do == "${AUTOTYPE_field}" ]]; then
sleep $wait; autopass
else
${default_do}
fi
fi
}
copyMenu () {
checkIfPass
copyfield=$(printf '%s\n' "${!stuff[@]}" | sort | _rofi -dmenu -p "Choose Field to copy > ")
val=$?
if [[ $val -eq 1 ]]; then
exit;
fi
if [[ $copyfield == "pass" ]]; then
copyPass;
else
copyField
fi
clearUp
}
actionMenu () {
checkIfPass
action_content=("< Return"
"---"
"1 Move Password File"
"2 Copy Password File"
"3 Delete Password File"
"4 Edit Password File"
"5 Generate New Password"
)
action=$(printf '%s\n' "${action_content[@]}" | _rofi -dmenu -p "Choose Action > ")
if [[ ${action} == "1 Move Password File" ]]; then
manageEntry move;
elif [[ ${action} == "3 Delete Password File" ]]; then
manageEntry delete;
elif [[ ${action} == "2 Copy Password File" ]]; then
manageEntry copy;
elif [[ ${action} == "4 Edit Password File" ]]; then
manageEntry edit;
elif [[ ${action} == "5 Generate New Password" ]]; then
generatePass;
elif [[ ${action} == "< Return" ]]; then
mainMenu;
elif [[ ${action} == "" ]]; then
exit
fi
}
showEntry () {
if [[ -z $pass_content ]]; then
pass_temp=$(PASSWORD_STORE_DIR="${root}" pass show "$selected_password")
password="${pass_temp%%$'\n'*}"
pass_key_value=$(printf '%s\n' "${pass_temp}" | tail -n+2 | grep ': ')
declare -A stuff
while read -r LINE; do
_id="${LINE%%: *}"
_val="${LINE#* }"
stuff["${_id}"]=${_val}
done < <(printf '%s\n' "${pass_key_value}")
stuff["pass"]=${password}
if test "${stuff['autotype']+autotype}"; then
:
else
stuff["autotype"]="${USERNAME_field} :tab pass"
fi
pass_content="$(for key in "${!stuff[@]}"; do printf '%s\n' "${key}: ${stuff[$key]}"; done)"
fi
bla_content=("< Return"
"${pass_content}"
)
bla=$(printf '%s\n' "${bla_content[@]}" | _rofi -dmenu -mesg "Enter: Copy entry to clipboard" -p "> ")
rofi_exit=$?
word=$(printf '%s' "$bla" | gawk -F': ' '{print $1}')
if [[ ${rofi_exit} -eq 1 ]]; then
exit
elif [[ ${rofi_exit} -eq 0 ]]; then
if [[ ${bla} == "< Return" ]]; then
mainMenu
else
if [[ -z $(printf '%s' "${stuff[${word}]}") ]]; then
printf '%s' "$word" | doClip
else
printf '%s' "${stuff[${word}]}" | doClip
fi
if [[ $notify == "true" ]]; then
notify-send "rofi-pass" "Copied Password\\nClearing in $clip_clear seconds"
fi
if [[ $notify == "true" ]]; then
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard | notify-send "rofi-pass" "Clipboard cleared") &
elif [[ $notify == "false" ]]; then
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard) &
fi
exit
fi
fi
exit
unset stuff
unset password
unset selected_password
unset password_temp
unset stuff
exit
}
manageEntry () {
if [[ "$1" == "edit" ]]; then
EDITOR=$EDITOR PASSWORD_STORE_DIR="${root}" pass edit "${selected_password}"
mainMenu
elif [[ $1 == "move" ]]; then
cd "${root}" || exit
group_array=(*/)
group=$(printf '%s\n' "${group_array[@]%/}" | _rofi -dmenu -p "Choose Group > ")
if [[ $group == "" ]]; then
exit
fi
PASSWORD_STORE_DIR="${root}" pass mv "$selected_password" "${group}"
mainMenu
elif [[ $1 == "copy" ]]; then
cd "${root}" || exit
group_array=(*/)
group=$(printf '%s\n' "${group_array[@]%/}" | _rofi -dmenu -p "Choose Group > ")
if [[ $group == "" ]]; then
exit
else
new_name="$(listgpg | _rofi -dmenu -format 'f' -mesg "Copying to same Group. Please enter a name for the new entry" -p "> ")"
fi
PASSWORD_STORE_DIR="${root}" pass cp "$selected_password" "${group}/${new_name}"
mainMenu
elif [[ "$1" == "delete" ]]; then
HELP="<span color='$help_color'>Selected entry: ${selected_password}</span>"
ask_content=("Yes"
"No"
)
ask=$(printf '%s\n' "${ask_content[@]}" | _rofi -mesg "${HELP}" -dmenu -p "Are You Sure? > ")
if [[ "$ask" == "Yes" ]]; then
PASSWORD_STORE_DIR="${root}" pass rm --force "${selected_password}"
elif [[ "$ask" == "No" ]]; then
mainMenu
elif [[ -z "$ask" ]]; then
exit
fi
else
mainMenu
fi
}
edit_pass() {
if [[ $edit_new_pass == "true" ]]; then
PASSWORD_STORE_DIR="${root}" pass edit "${1}"
fi
}
insertPass () {
url=$(_clip_out_clipboard)
if [[ "${url:0:4}" == "http" ]]; then
domain_name="$(printf '%s\n' "${url}" | awk -F / '{l=split($3,a,"."); print (a[l-1]=="com"?a[l-2] OFS:X) a[l-1] OFS a[l]}' OFS=".")"
help_content="Domain: ${domain_name}
Type name, make sure it is unique"
else
help_content="Hint: Copy URL to clipboard before calling this menu.
Type name, make sure it is unique"
fi
cd "${root}" || exit
group_array=(*/)
grouplist=$(printf '%s\n' "${group_array[@]%/}")
name="$(listgpg | _rofi -dmenu -format 'f' -filter "${domain_name}" -mesg "${help_content}" -p "> ")"
val=$?
if [[ $val -eq 1 ]]; then
exit
fi
user_content=("${default_user2}"
"${USER}"
"${default_user}"
)
user=$(printf '%s\n' "${user_content[@]}" | _rofi -dmenu -mesg "Chose Username or type" -p "> ")
val=$?
if [[ $val -eq 1 ]]; then
exit
fi
group_content=("No Group"
"---"
"${grouplist}"
)
group=$(printf '%s\n' "${group_content[@]}" | _rofi -dmenu -p "Choose Group > ")
val=$?
if [[ $val -eq 1 ]]; then
exit
fi
pw=$(printf '%s' "Generate" | _rofi -dmenu -password -p "Password > " -mesg "Type Password or hit Enter to generate one")
if [[ $pw == "Generate" ]]; then
pw=$(_pwgen "${password_length}")
fi
clear
if [[ "$group" == "No Group" ]]; then
if [[ $url == http* ]]; then
pass_content=("${pw}"
"---"
"${USERNAME_field}: ${user}"
"${URL_field}: ${url}"
)
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${name}" > /dev/null && edit_pass "${name}"
else
pass_content=("${pw}"
"---"
"${USERNAME_field}: ${user}"
)
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${name}" > /dev/null && edit_pass "${name}"
fi
else
if [[ $url == http* ]]; then
pass_content=("${pw}"
"---"
"${USERNAME_field}: ${user}"
"${URL_field}: ${url}"
)
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${name}" > /dev/null && edit_pass "${group}/${name}"
else
pass_content=("${pw}"
"---"
"${USERNAME_field}: ${user}"
)
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${name}" > /dev/null && edit_pass "${group}/${name}"
fi
fi
}
help_msg () {
cat <<'EOF'
Usage:
rofi-pass [command]
Commands:
--insert insert new entry to password store
--root set custom root directories (colon separated)
--last-used highlight last used item
--show-last show details of last used Entry
--bmarks start in bookmarks mode
rofi-pass version 1.5.3
EOF
}
get_config_file () {
configs=("$ROFI_PASS_CONFIG"
"$config_dir/rofi-pass/config"
"/etc/rofi-pass.conf")
# return the first config file with a valid path
for config in "${configs[@]}"; do
# '-n' is needed in case ROFI_PASS_CONFIG is not set
if [[ -n "${config}" && -f "${config}" ]]; then
printf "%s" "$config"
return
fi
done
}
main () {
# load config file
config_file="$(get_config_file)"
[[ -n "$config_file" ]] && source "$config_file"
# create tmp dir
if [[ ! -d "$cache_dir/rofi-pass" ]]; then
mkdir -p "$cache_dir/rofi-pass"
fi
# fix keyboard layout if enabled in config
if [[ $fix_layout == "true" ]]; then
layout_cmd
fi
# set help color
if [[ $help_color == "" ]]; then
help_color=$(rofi -dump-xresources | grep 'rofi.color.normal' | gawk -F ',' '/,/{gsub(/ /, "", $2); print $2}')
fi
# check for BROWSER variable, use xdg-open as fallback
if [[ -z $BROWSER ]]; then
export BROWSER=xdg-open
fi
# check if alternative root directory was given on commandline
if [[ -r "$cache_dir/rofi-pass/last_used" ]] && [[ $1 == "--last-used" || $1 == "--show-last" ]]; then
roots=("$(awk -F ': ' '{ print $1 }' "$cache_dir/rofi-pass/last_used")")
elif [[ -n "$2" && "$1" == "--root" ]]; then
custom_root=true; IFS=: read -r -a roots <<< "$2"
elif [[ -n $root ]]; then
custom_root=true; IFS=: read -r -a roots <<< "${root}"
elif [[ -n ${PASSWORD_STORE_DIR} ]]; then
roots=("${PASSWORD_STORE_DIR}")
else
roots=("$HOME/.password-store")
fi
roots_index=0
roots_length=${#roots[@]}
export root=${roots[$roots_index]}
export PASSWORD_STORE_DIR="${root}"
case $1 in
--insert)
insertPass
;;
--root)
mainMenu
;;
--help)
help_msg
;;
--last-used)
if [[ -r "$cache_dir/rofi-pass/last_used" ]]; then
entry="$(awk -F ': ' '{ print $2 }' "$cache_dir/rofi-pass/last_used")"
fi
mainMenu
;;
--show-last)
if [[ -r "$cache_dir/rofi-pass/last_used" ]]; then
selected_password="$(awk -F ': ' '{ print $2 }' "$cache_dir/rofi-pass/last_used")" viewEntry
else
mainMenu
fi
;;
--bmarks)
mainMenu --bmarks;
;;
*)
mainMenu
;;
esac
}
main "$@"

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/raelon/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 ') 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 ') 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 ' && 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 ' && 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

2
home/.local/usr/bin/screenshot Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
scrot ~/Pictures/Screenshots/'%y%m%d-%H:%M'.png -f -s -e 'xclip -selection clipboard -t image/png -i $f'

View File

@@ -0,0 +1,47 @@
#!/bin/bash
#changelog
#v0.3
#added 1. Notifications 2.unique names for each type (for quick launch) 3.better photo editor (pinta) 4.dmenu title
#v0.4
#1.Added variable for notification timeouts. 2. Show link in notification
IMG_PATH=$HOME/Pictures/Screenshots
UL=fb
EDIT=gimp
TIME=3000 #Miliseconds notification should remain visible
prog="
---Local screenshots (saved at IMG_PATH)---
1.quick_fullscreen
2.delayed_fullscreen
3.section
4.edit_fullscreen
---Upload to remote service (images will be deleted)---
a.upload_fullscreen
u.upload_delayed_fullscreen
e.edit_upload_fullscreen
s.upload_section
p.edit_upload_section
"
cmd=$(dmenu -l 20 -nf '#999' -nb '#292d3e' -sf '#eee' -sb '#0077bb' -p 'Choose Screenshot Type' <<< "$prog")
cd $IMG_PATH
case ${cmd%% *} in
1.quick_fullscreen) scrot -d 1 '%Y-%m-%d-@%H-%M-%S-scrot.png' && notify-send -u low -t $TIME 'Scrot' 'Fullscreen taken and saved' ;;
2.delayed_fullscreen) scrot -d 4 '%Y-%m-%d-@%H-%M-%S-scrot.png' && notify-send -u low -t $TIME 'Scrot' 'Fullscreen Screenshot saved' ;;
3.section) scrot -s '%Y-%m-%d-@%H-%M-%S-scrot.png' && notify-send -u low -t $TIME 'Scrot' 'Screenshot of section saved' ;;
4.edit_fullscreen) scrot -d 1 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$EDIT \$f" && notify-send -u low -t $TIME 'Scrot' 'Screenshot edited and saved' ;;
a.upload_fullscreen) scrot -d 1 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$UL \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb) - $(xclip -o;echo)" ;;
u.upload_delayed_fullscreen) scrot -d 4 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$UL \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb) - $(xclip -o)" ;;
e.edit_upload_fullscreen) scrot -d 4 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$EDIT \$f && $UL \$f && rm -f \$f" && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb) - $(xclip -o)" ;;
s.upload_section) scrot -s '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$UL \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb - $(xclip -o)";;
p.edit_upload_section) scrot -s '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$EDIT \$f && $UL \$f && rm -f \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by FB) - $(xclip -o)" ;;
*) exec "'${cmd}'" ;;
esac

View File

@@ -0,0 +1,33 @@
#!/bin/sh
#
# See the LICENSE file for copyright and license details.
#
# xidfile="$HOME/tmp/tabbed-surf.xid"
xidfile="$HOME/.local/state/tabbed-surf.xid"
uri="https://duckduckgo.com/lite"
if [ "$#" -gt 0 ];
then
uri="$1"
fi
runtabbed() {
tabbed -dn tabbed-surf -r 2 surf -e '' "$uri" >"$xidfile" \
2>/dev/null &
}
if [ ! -r "$xidfile" ];
then
runtabbed
else
xid=$(cat "$xidfile")
xprop -id "$xid" >/dev/null 2>&1
if [ $? -gt 0 ];
then
runtabbed
else
surf -e "$xid" "$uri" >/dev/null 2>&1 &
fi
fi

4
home/.local/usr/bin/swapesc.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Swap ESC and Caps Lock
eval "setxkbmap -option caps:swapescape"

34
home/.local/usr/bin/taskadd Executable file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
#
# Behavior:
# Userscript for qutebrowser which adds a task to taskwarrior.
# If run as a command (:spawn --userscript taskadd), it creates a new task
# with the description equal to the current page title and annotates it with
# the current page url. Additional arguments are passed along so you can add
# mods to the task (e.g. priority, due date, tags).
#
# Example:
# :spawn --userscript taskadd due:eod pri:H
#
# To enable passing along extra args, I suggest using a mapping like:
# :bind <somekey> cmd-set-text -s :spawn --userscript taskadd
#
# If run from hint mode, it uses the selected hint text as the description
# and the selected hint url as the annotation.
#
# Ryan Roden-Corrent (rcorre), 2016
# Any feedback is welcome!
#
# For more info on Taskwarrior, see https://taskwarrior.org/
# use either the current page title or the hint text as the task description
[[ $QUTE_MODE == 'hints' ]] && title=$QUTE_SELECTED_TEXT || title=$QUTE_TITLE
# try to add the task and grab the output
if msg="$(task add "$title" "$*" 2>&1)"; then
# annotate the new task with the url, send the output back to the browser
task +LATEST annotate "$QUTE_URL"
echo "message-info '$(echo "$msg" | head -n 1)'" >> "$QUTE_FIFO"
else
echo "message-error '$(echo "$msg" | head -n 1)'" >> "$QUTE_FIFO"
fi

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Description: A script to list and start tmuxinator projects using fzf.
# Set the directory where your tmuxinator configuration files are located
TMUXINATOR_CONFIG_DIR="${HOME}/.config/tmuxinator/"
# Find all tmuxinator `.yml` files in the specified directory, remove path and extensions
# project=$(find "$TMUXINATOR_CONFIG_DIR" -type f -name "*.yml" | sed 's|.*/||;s|\.yml$||' | \
# fzf --prompt="Session: " --preview-label="pyTui Tmuxinator Picker" --preview-label-pos=bottom \
# --preview="bat --style=full --color=always" --preview-window=up \
# )
# project=$(find "$TMUXINATOR_CONFIG_DIR" -type f -name "*.yml" | sed 's|.*/||;s|\.yml$||' | fzf --prompt="Session: " --tmux bottom,5%)
project=$(find "$TMUXINATOR_CONFIG_DIR" -type f -name "*.yml" | sed 's|.*/||;s|\.yml$||' | fzf --prompt="Session 󰓾 " --tmux left,25 --reverse)
# Check if a project was selected
if [[ -n "$project" ]]; then
# Start the selected tmuxinator project
tmuxinator start "$project"
# else
# echo "No project selected. Exiting..."
# exit 1
fi

View File

@@ -0,0 +1,6 @@
#!/usr/bin/bash
fastfetch --logo small --structure "title:os:kernel:cpu:memory:disk:uptime"
misfortune|cowsay|lolcat
exec zsh

6
home/.local/usr/bin/touchpad Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
idd=$(xinput --list | grep "DELL07E6:00 06CB:76AF Touchpad" | awk '{print $6}' | cut -d'=' -f2)
sudo xinput set-prop $idd 318 1
sudo xinput set-prop $idd 300 1
sudo xinput set-prop $idd 307 1
sudo xinput set-prop $idd 309 .5

View File

@@ -0,0 +1,120 @@
#! /bin/bash
# Copyright (c) 1998 Martin Schulze <joey@debian.org>
# Slightly modified by Luis Francisco Gonzalez <luisgh@debian.org>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###########################################################################
# Configurable section
###########################################################################
#
# Any entry in the lists of programs that urlview handler will try out will
# be made of /path/to/program + ':' + TAG where TAG is one of
# XW: XWindows program
# XT: Launch with an xterm if possible or as VT if not
# VT: Launch in the same terminal
# The lists of programs to be executed are
https_prgs="/usr/bin/qutebrowser:XW /usr/bin/w3m:XT"
http_prgs="/usr/bin/qutebrowser:XW /usr/bin/w3m:XT"
mailto_prgs="/usr/bin/neomutt:VT /usr/bin/elm:VT /usr/bin/pine:VT /usr/bin/mail:VT"
gopher_prgs="/usr/bin/lynx:XT /usr/bin/gopher:XT"
ftp_prgs="/usr/bin/ranger:XT /usr/bin/ncftp:XT"
# Program used as an xterm (if it doesn't support -T you'll need to change
# the command line in getprg)
XTERM=/usr/bin/kitty
###########################################################################
# Change bellow this at your own risk
###########################################################################
function getprg()
{
local ele tag prog
for ele in $*
do
tag=${ele##*:}
prog=${ele%%:*}
if [ -x $prog ]; then
case $tag in
XW)
[ -n "$DISPLAY" ] && echo "X:$prog" && return 0
;;
XT)
[ -n "$DISPLAY" ] && [ -x "$XTERM" ] && \
echo "X:$XTERM -e $prog" && return 0
echo "$prog" && return 0
;;
VT)
echo "$prog" && return 0
;;
esac
fi
done
}
url="$1"; shift
type="${url%%:*}"
if [ "$url" = "$type" ]; then
type="${url%%.*}"
case "$type" in
www|web)
type=http
;;
esac
url="$type://$url"
fi
case $type in
https)
prg=`getprg $https_prgs`
;;
http)
prg=`getprg $http_prgs`
;;
ftp)
prg=`getprg $ftp_prgs`
;;
mailto)
prg=`getprg $mailto_prgs`
url="${url#mailto:}"
;;
gopher)
prg=`getprg $gopher_prgs`
;;
*)
echo "Unknown URL type. Please report URL and viewer to:"
echo "joey@debian.org."
echo -n "Press enter to continue."; read x
exit
;;
esac
if [ -n "$prg" ]; then
if [ "${prg%:*}" = "X" ]; then
${prg#*:} "$url" 2>/dev/null &
else
$prg "$url"
fi
fi

28
home/.local/usr/bin/win98 Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/sh
# Enable basic sound output via pulseaudio
# Run "pacmd list-sinks | grep -e 'name:' -e 'index'" to find your QEMU_PA_SINK
export QEMU_AUDIO_DRV=pa
export QEMU_PA_SINK=alsa_output.pci-0000_00_1f.3.analog-stereo
export QEMU_PA_SOURCE=input
# Start QEMU
qemu-system-x86_64 \
-enable-kvm \
-m 3G \
-smp cores=2,threads=2,sockets=1,maxcpus=4 \
-cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time \
-machine type=pc,accel=kvm,kernel_irqchip=on \
-global PIIX4_PM.disable_s3=1 \
-global PIIX4_PM.disable_s4=1 \
-name windows-98-guest \
-cdrom '/home/raelon/isos/win98se.iso' \
-drive file='/home/raelon/usd/win98',format=qcow2,l2-cache-size=8M \
-boot order=d \
-soundhw hda \
-usb \
-device usb-tablet \
# -nic none \
-vga qxl \
-display gtk,gl=on \
-device vfio-pci,sysfsdev=/sys/devices/pci0000:00/0000:00:02.0/87c17a7c-972b-407a-b14a-74779f799b8d,x-igd-opregion=on,display=on \

View File

@@ -0,0 +1,41 @@
local mapfile = "/home/th3r00t/.local/share/blightmud/empiremud.map"
Map = Mapper.create("empiremud")
local function file_exists(file)
local f = io.open(file, "r")
if f then
f:close()
return true
else
return false
end
end
local function load_map()
if file_exists(mapfile) then
blight.status_line(1, "Loading map...")
Map:load(mapfile)
end
end
local function empiremud_connect()
blight.status_height(1)
blight.status_line(0, "Connecting to Enpire Mud...")
blight.status_line(1, "Logging in...")
mud.send("Raelon")
mud.send("b2edxfrr1")
blight.status_line(1, "Connected To Enpire Mud.")
blight.status_line(0, "Enpire Mud")
load_map()
Map:print()
end
mud.on_disconnect(function()
blight.status_line(0, "Disconnected.")
if Map then
Map:save(mapfile)
end
end)
empiremud_connect()

View File

@@ -0,0 +1,40 @@
local mapfile = "/home/th3r00t/.local/share/blightmud/sindome.map"
Map = Mapper.create("sindome")
local function file_exists(file)
local f = io.open(file, "r")
if f then
f:close()
return true
else
return false
end
end
local function load_map()
if file_exists(mapfile) then
blight.status_line(1, "Loading map...")
Map:load(mapfile)
end
end
local function sindome_connect()
blight.status_height(1)
blight.status_line(0, "Connecting to Sindome...")
blight.status_line(1, "Logging in...")
mud.send("connect ryn XeGEb")
blight.status_line(1, "Connected To Sindome.")
blight.status_line(0, "Sindome")
load_map()
Map:print()
end
mud.on_disconnect(function()
blight.status_line(0, "Disconnected.")
if Map then
Map:save(mapfile)
end
end)
sindome_connect()

View File

@@ -0,0 +1,40 @@
local mapfile = "/home/th3r00t/.local/share/blightmud/sindome.map"
Map = Mapper.create("untolddawn")
local function file_exists(file)
local f = io.open(file, "r")
if f then
f:close()
return true
else
return false
end
end
local function load_map()
if file_exists(mapfile) then
blight.status_line(1, "Loading map...")
Map:load(mapfile)
end
end
local function untolddawn_connect()
blight.status_height(1)
blight.status_line(0, "Connecting to Untold Dawn...")
blight.status_line(1, "Logging in...")
mud.send("login th3r00t b2edxfrr1")
blight.status_line(1, "Connected To Untold Dawn.")
blight.status_line(0, "Untold Dawn")
load_map()
Map:print()
end
mud.on_disconnect(function()
blight.status_line(0, "Disconnected.")
if Map then
Map:save(mapfile)
end
end)
untolddawn_connect()