upload to github
This commit is contained in:
commit
7d3dfb9c69
6 changed files with 455 additions and 0 deletions
205
.bashrc
Normal file
205
.bashrc
Normal file
|
|
@ -0,0 +1,205 @@
|
||||||
|
# ~/.bashrc: executed by bash(1) for non-login shells.
|
||||||
|
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
|
||||||
|
|
||||||
|
# If not running interactively, don't do anything
|
||||||
|
case $- in
|
||||||
|
*i*) ;;
|
||||||
|
*) return;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Source bash aliases if available
|
||||||
|
if [ -f ~/.bash_aliases ]; then
|
||||||
|
. ~/.bash_aliases
|
||||||
|
fi
|
||||||
|
|
||||||
|
# History configuration
|
||||||
|
HISTCONTROL=ignoreboth:erasedups # ignore duplicates and remove duplicates from history
|
||||||
|
HISTSIZE=10000 # increased from 1000
|
||||||
|
HISTFILESIZE=20000 # increased from 2000
|
||||||
|
HISTTIMEFORMAT="%F %T " # add timestamps to history
|
||||||
|
shopt -s histappend # append to history file, don't overwrite
|
||||||
|
shopt -s histverify # verify history expansions before executing
|
||||||
|
|
||||||
|
# Shell options
|
||||||
|
shopt -s checkwinsize # update LINES and COLUMNS after each command
|
||||||
|
shopt -s cdspell # correct minor spelling errors in cd commands
|
||||||
|
shopt -s dirspell # correct minor spelling errors in directory names
|
||||||
|
shopt -s autocd # cd into directories by just typing the name
|
||||||
|
|
||||||
|
# Make less more friendly for non-text input files
|
||||||
|
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
||||||
|
|
||||||
|
# Set variable identifying the chroot (used in the prompt below)
|
||||||
|
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
||||||
|
debian_chroot=$(cat /etc/debian_chroot)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to get git branch and status
|
||||||
|
git_prompt_info() {
|
||||||
|
local branch
|
||||||
|
if branch=$(git symbolic-ref --short HEAD 2>/dev/null); then
|
||||||
|
local status=""
|
||||||
|
local git_status=$(git status --porcelain 2>/dev/null)
|
||||||
|
|
||||||
|
# Check for various git states
|
||||||
|
if [ -n "$git_status" ]; then
|
||||||
|
if echo "$git_status" | grep -q "^M"; then
|
||||||
|
status="${status}*" # modified files
|
||||||
|
fi
|
||||||
|
if echo "$git_status" | grep -q "^A"; then
|
||||||
|
status="${status}+" # added files
|
||||||
|
fi
|
||||||
|
if echo "$git_status" | grep -q "^D"; then
|
||||||
|
status="${status}-" # deleted files
|
||||||
|
fi
|
||||||
|
if echo "$git_status" | grep -q "^??"; then
|
||||||
|
status="${status}?" # untracked files
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if we're ahead/behind remote
|
||||||
|
local ahead_behind
|
||||||
|
ahead_behind=$(git rev-list --count --left-right @{upstream}...HEAD 2>/dev/null)
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
local behind=$(echo "$ahead_behind" | cut -f1)
|
||||||
|
local ahead=$(echo "$ahead_behind" | cut -f2)
|
||||||
|
if [ "$ahead" -gt 0 ] && [ "$behind" -gt 0 ]; then
|
||||||
|
status="${status}⇅"
|
||||||
|
elif [ "$ahead" -gt 0 ]; then
|
||||||
|
status="${status}↑"
|
||||||
|
elif [ "$behind" -gt 0 ]; then
|
||||||
|
status="${status}↓"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
printf " \001\033[93m\002(%s\001\033[91m\002%s\001\033[93m\002)\001\033[00m\002" "$branch" "$status"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set colored prompt based on terminal capability
|
||||||
|
case "$TERM" in
|
||||||
|
xterm-color|*-256color) color_prompt=yes;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
force_color_prompt=yes
|
||||||
|
|
||||||
|
if [ -n "$force_color_prompt" ]; then
|
||||||
|
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
||||||
|
color_prompt=yes
|
||||||
|
else
|
||||||
|
color_prompt=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure prompt with git integration
|
||||||
|
if [ "$color_prompt" = yes ]; then
|
||||||
|
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]$(git_prompt_info)\$ '
|
||||||
|
else
|
||||||
|
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w$(git_prompt_info)\$ '
|
||||||
|
fi
|
||||||
|
unset color_prompt force_color_prompt
|
||||||
|
|
||||||
|
# Set terminal title for xterm-compatible terminals
|
||||||
|
case "$TERM" in
|
||||||
|
xterm*|rxvt*)
|
||||||
|
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Enable colored output for common commands
|
||||||
|
if [ -x /usr/bin/dircolors ]; then
|
||||||
|
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
|
||||||
|
alias ls='ls --color=auto'
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
alias fgrep='fgrep --color=auto'
|
||||||
|
alias egrep='egrep --color=auto'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Colored GCC warnings and errors
|
||||||
|
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
|
||||||
|
|
||||||
|
# GPG TTY configuration for proper GPG agent functionality
|
||||||
|
export GPG_TTY=$(tty)
|
||||||
|
|
||||||
|
# Enable programmable completion features
|
||||||
|
if ! shopt -oq posix; then
|
||||||
|
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
||||||
|
. /usr/share/bash-completion/bash_completion
|
||||||
|
elif [ -f /etc/bash_completion ]; then
|
||||||
|
. /etc/bash_completion
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Common useful aliases (add more to ~/.bash_aliases for user-specific ones)
|
||||||
|
alias ll='ls -alF'
|
||||||
|
alias la='ls -A'
|
||||||
|
alias l='ls -CF'
|
||||||
|
alias ..='cd ..'
|
||||||
|
alias ...='cd ../..'
|
||||||
|
alias ....='cd ../../..'
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
alias mkdir='mkdir -pv'
|
||||||
|
alias h='history'
|
||||||
|
alias c='clear'
|
||||||
|
alias df='df -h'
|
||||||
|
alias du='du -h'
|
||||||
|
alias free='free -h'
|
||||||
|
alias ps='ps auxf'
|
||||||
|
alias less='less -R'
|
||||||
|
|
||||||
|
# Safety aliases
|
||||||
|
alias rm='rm -i'
|
||||||
|
alias cp='cp -i'
|
||||||
|
alias mv='mv -i'
|
||||||
|
|
||||||
|
# Development shortcuts
|
||||||
|
alias g='git'
|
||||||
|
alias gs='git status'
|
||||||
|
alias ga='git add'
|
||||||
|
alias gc='git commit'
|
||||||
|
alias gp='git push'
|
||||||
|
alias gl='git log --oneline --graph --decorate'
|
||||||
|
alias gd='git diff'
|
||||||
|
|
||||||
|
# Extract function for various archive types
|
||||||
|
extract() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
case $1 in
|
||||||
|
*.tar.bz2) tar xjf "$1" ;;
|
||||||
|
*.tar.gz) tar xzf "$1" ;;
|
||||||
|
*.bz2) bunzip2 "$1" ;;
|
||||||
|
*.rar) unar "$1" ;;
|
||||||
|
*.gz) gunzip "$1" ;;
|
||||||
|
*.tar) tar xf "$1" ;;
|
||||||
|
*.tbz2) tar xjf "$1" ;;
|
||||||
|
*.tgz) tar xzf "$1" ;;
|
||||||
|
*.zip) unzip "$1" ;;
|
||||||
|
*.Z) uncompress "$1" ;;
|
||||||
|
*.7z) 7z x "$1" ;;
|
||||||
|
*) echo "'$1' cannot be extracted via extract()" ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo "'$1' is not a valid file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create directory and cd into it
|
||||||
|
mkcd() {
|
||||||
|
mkdir -p "$1" && cd "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find and kill process by name
|
||||||
|
psgrep() {
|
||||||
|
ps aux | grep -v grep | grep "$@" -i --color=auto
|
||||||
|
}
|
||||||
|
|
||||||
|
# Quick backup function
|
||||||
|
backup() {
|
||||||
|
cp "$1"{,.bak}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show PATH in readable format
|
||||||
|
path() {
|
||||||
|
echo $PATH | tr ':' '\n'
|
||||||
|
}
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 jroshthen1
|
||||||
|
|
||||||
|
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.
|
||||||
14
Readme.md
Normal file
14
Readme.md
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# dotfiles
|
||||||
|
|
||||||
|
My generic dotfiles
|
||||||
|
|
||||||
|
`user@host:~/pwd/ (branch+?)$ `
|
||||||
|
|
||||||
|
## Extract archives
|
||||||
|
extract ~/Downloads/file.tar.gz, .zip, .7z, .rar
|
||||||
|
|
||||||
|
## Check what's running
|
||||||
|
psgrep bash
|
||||||
|
|
||||||
|
## Backup file
|
||||||
|
backup file.json
|
||||||
21
pwgen.sh
Executable file
21
pwgen.sh
Executable file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Function to generate a random password
|
||||||
|
generate_password() {
|
||||||
|
local length=$1
|
||||||
|
if ! [[ "$length" =~ ^[0-9]+$ ]] || [ "$length" -le 0 ]; then
|
||||||
|
echo "Please provide a valid positive integer for password length."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local charset='A-Z:a-z:0-9:!@#$%^&*()_+[]{}|;:,.<>?'
|
||||||
|
# Generate the password
|
||||||
|
local password=$(cat /dev/urandom | tr -dc "$charset" | fold -w "$length" | head -n 1)
|
||||||
|
echo "$password"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <length>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
generate_password "$1"
|
||||||
29
scramble_email.sh
Normal file
29
scramble_email.sh
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/bin/bash
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
read -p "Enter an email to scramble: " clean_email
|
||||||
|
elif [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
||||||
|
echo 'Usage: scramble_email.sh [emailtoscramble]
|
||||||
|
|
||||||
|
$ scramble_email.sh "address@email.com"
|
||||||
|
outputs: address at email dot com
|
||||||
|
|
||||||
|
$ echo "address@email.com" | scramble_email.sh
|
||||||
|
outputs: address at email dot com
|
||||||
|
|
||||||
|
$ xargs -I {} -a email_list.txt scramble_email.sh {} > scrambled_emails.txt
|
||||||
|
input a txt file with emails and scramble them into a new txt file
|
||||||
|
'
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
clean_email="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
email_pattern="^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z.]{2,8}$"
|
||||||
|
|
||||||
|
if [[ $clean_email =~ $email_pattern ]]; then
|
||||||
|
scrambled_email="${clean_email//./' dot '}"
|
||||||
|
scrambled_email="${scrambled_email//@/' at '}"
|
||||||
|
echo $scrambled_email
|
||||||
|
else
|
||||||
|
echo "Invalid email address. Please enter a valid email."
|
||||||
|
fi
|
||||||
165
speak.sh
Executable file
165
speak.sh
Executable file
|
|
@ -0,0 +1,165 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Chunked TTS processor - Divides text into chunks, processes and plays them sequentially
|
||||||
|
|
||||||
|
EXEC_PATH="$HOME/kokoros/target/release/koko"
|
||||||
|
MODEL_PATH="$HOME/kokoros/checkpoints/kokoro-v1.0.onnx"
|
||||||
|
VOICE_DATA="$HOME/kokoros/voices-v1.0.bin"
|
||||||
|
SPEED=1.1
|
||||||
|
VOICE_STYLE="af_heart"
|
||||||
|
# Style mixing supported for Kokoros: "af_sky.4+af_nicole.5"
|
||||||
|
# https://github.com/hexgrad/kokoro/tree/main/kokoro.js/voices
|
||||||
|
|
||||||
|
# Chunking parameters
|
||||||
|
MIN_CHUNK_SIZE=80
|
||||||
|
MAX_CHUNK_SIZE=200
|
||||||
|
MIN_SENTENCES=2
|
||||||
|
|
||||||
|
export LC_ALL=en_US.UTF-8
|
||||||
|
export LANG=en_US.UTF-8
|
||||||
|
|
||||||
|
clipboard_content=$(xclip -o)
|
||||||
|
filtered_content=$(echo "$clipboard_content" | sed -E '
|
||||||
|
s/-(\r|\n)//g
|
||||||
|
s/\r|\n/ /g
|
||||||
|
s/ +/ /g
|
||||||
|
s/^ *//g
|
||||||
|
s/ *$//g
|
||||||
|
s/--/ — /g
|
||||||
|
s/ - / — /g
|
||||||
|
s/\.\.\./…/g
|
||||||
|
s/([0-9]),([0-9])/\1\2/g
|
||||||
|
s/([.,;:])([^ ])/\1 \2/g
|
||||||
|
')
|
||||||
|
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
echo "Using temporary directory: $TEMP_DIR"
|
||||||
|
|
||||||
|
# Save the cleaned text to a file
|
||||||
|
echo "$filtered_content" > "$TEMP_DIR/full_text.txt"
|
||||||
|
|
||||||
|
# Smart chunking: Split text into optimal chunks
|
||||||
|
cat "$TEMP_DIR/full_text.txt" |
|
||||||
|
sed -E 's/([.!?]) +/\1\n/g' |
|
||||||
|
awk -v min_size="$MIN_CHUNK_SIZE" -v max_size="$MAX_CHUNK_SIZE" -v min_sentences="$MIN_SENTENCES" '
|
||||||
|
BEGIN {
|
||||||
|
chunk = "";
|
||||||
|
sentence_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NF > 0 {
|
||||||
|
sentence = $0;
|
||||||
|
|
||||||
|
if (length(chunk) > 0) {
|
||||||
|
test_chunk = chunk " " sentence;
|
||||||
|
} else {
|
||||||
|
test_chunk = sentence;
|
||||||
|
}
|
||||||
|
|
||||||
|
should_output = 0;
|
||||||
|
|
||||||
|
# If adding this sentence would exceed max size, output current chunk first
|
||||||
|
if (length(test_chunk) > max_size && length(chunk) > 0) {
|
||||||
|
should_output = 1;
|
||||||
|
}
|
||||||
|
# If we have minimum sentences and minimum size, we can output
|
||||||
|
else if (sentence_count >= min_sentences && length(chunk) >= min_size) {
|
||||||
|
if (length(sentence) > (max_size - min_size)) {
|
||||||
|
should_output = 1;
|
||||||
|
}
|
||||||
|
else if (length(test_chunk) >= min_size * 1.5) {
|
||||||
|
chunk = test_chunk;
|
||||||
|
sentence_count++;
|
||||||
|
should_output = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_output && length(chunk) > 0) {
|
||||||
|
print chunk;
|
||||||
|
chunk = "";
|
||||||
|
sentence_count = 0;
|
||||||
|
|
||||||
|
if (length(test_chunk) > max_size) {
|
||||||
|
chunk = sentence;
|
||||||
|
sentence_count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chunk = test_chunk;
|
||||||
|
sentence_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
if (length(chunk) > 0) {
|
||||||
|
print chunk;
|
||||||
|
}
|
||||||
|
}' > "$TEMP_DIR/chunks.txt"
|
||||||
|
|
||||||
|
process_chunk() {
|
||||||
|
local chunk="$1"
|
||||||
|
local output_file="$2"
|
||||||
|
echo "Processing: ${chunk:0:40}..."
|
||||||
|
echo "$chunk" > "$TEMP_DIR/current_chunk.txt"
|
||||||
|
|
||||||
|
"$EXEC_PATH" \
|
||||||
|
--model "$MODEL_PATH" \
|
||||||
|
--data "$VOICE_DATA" \
|
||||||
|
--speed "$SPEED" \
|
||||||
|
--style "$VOICE_STYLE" \
|
||||||
|
text "$(cat "$TEMP_DIR/current_chunk.txt")" \
|
||||||
|
--output "$output_file"
|
||||||
|
|
||||||
|
if [ ! -f "$output_file" ]; then
|
||||||
|
echo "Error: Failed to create audio file for chunk. Skipping..."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process the first chunk immediately
|
||||||
|
FIRST_CHUNK=$(head -n 1 "$TEMP_DIR/chunks.txt")
|
||||||
|
FIRST_OUTPUT="$TEMP_DIR/chunk_0.wav"
|
||||||
|
process_chunk "$FIRST_CHUNK" "$FIRST_OUTPUT"
|
||||||
|
|
||||||
|
if [ -f "$FIRST_OUTPUT" ]; then
|
||||||
|
aplay "$FIRST_OUTPUT" &
|
||||||
|
PLAY_PID=$!
|
||||||
|
else
|
||||||
|
echo "Failed to process first chunk. Continuing with next chunks..."
|
||||||
|
PLAY_PID=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Process remaining chunks
|
||||||
|
CHUNK_NUM=1
|
||||||
|
while read -r chunk; do
|
||||||
|
if [ $CHUNK_NUM -eq 1 ]; then
|
||||||
|
CHUNK_NUM=$((CHUNK_NUM + 1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUTPUT_FILE="$TEMP_DIR/chunk_$CHUNK_NUM.wav"
|
||||||
|
|
||||||
|
process_chunk "$chunk" "$OUTPUT_FILE"
|
||||||
|
|
||||||
|
if [ $PLAY_PID -ne 0 ]; then
|
||||||
|
wait $PLAY_PID || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$OUTPUT_FILE" ]; then
|
||||||
|
aplay "$OUTPUT_FILE" &
|
||||||
|
PLAY_PID=$!
|
||||||
|
else
|
||||||
|
echo "Skipping playback of chunk $CHUNK_NUM (file not created)"
|
||||||
|
PLAY_PID=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
CHUNK_NUM=$((CHUNK_NUM + 1))
|
||||||
|
done < "$TEMP_DIR/chunks.txt"
|
||||||
|
|
||||||
|
if [ $PLAY_PID -ne 0 ]; then
|
||||||
|
wait $PLAY_PID || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Processing complete!"
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue