|
# ============================================================================== |
|
# CUSTOM UTILITY FUNCTIONS FOR ZSH (Loaded from ~/.zsh_functions) |
|
# https://gist.github.com/YOUR_USERNAME/YOUR_GIST_ID |
|
# |
|
# Install: |
|
# curl -o ~/.zsh_functions <raw-gist-url> |
|
# echo '[[ -f "$HOME/.zsh_functions" ]] && source "$HOME/.zsh_functions"' >> ~/.zshrc |
|
# source ~/.zshrc |
|
# |
|
# Then run `myfuncs` to see everything, or any command with -h for details. |
|
# Note: written for macOS (uses pbcopy, caffeinate, osascript, BSD sed). |
|
# ============================================================================== |
|
|
|
# Global color variables |
|
export C_RED=$'\e[0;31m' |
|
export C_GREEN=$'\e[0;32m' |
|
export C_YELLOW=$'\e[0;33m' |
|
export C_CYAN=$'\e[0;36m' |
|
export C_MAGENTA=$'\e[0;35m' |
|
export C_NC=$'\e[0m' |
|
|
|
myfuncs() { |
|
echo "${C_CYAN}====================================================${C_NC}" |
|
echo "${C_MAGENTA} π οΈ Custom ZSH Utilities Cheat Sheet ${C_NC}" |
|
echo "${C_CYAN}====================================================${C_NC}" |
|
echo "Run any command with ${C_YELLOW}-h${C_NC} or ${C_YELLOW}help${C_NC} for detailed usage." |
|
echo "" |
|
echo "${C_YELLOW}π File & Directory Ops${C_NC}" |
|
echo " ${C_GREEN}mkcd${C_NC} - Create a directory and enter it immediately" |
|
echo " ${C_GREEN}extract${C_NC} - Unzip/Extract ANY archive file(s) instantly" |
|
echo " ${C_GREEN}ql${C_NC} - Open a file in macOS Quick Look" |
|
echo "" |
|
echo "${C_YELLOW}π» Developer Tools${C_NC}" |
|
echo " ${C_GREEN}glit${C_NC} - One-step git add, commit, push, and cleanup" |
|
echo " ${C_GREEN}cbjson${C_NC} - Format unreadable JSON in your clipboard or file" |
|
echo " ${C_GREEN}genpass${C_NC} - Generate a secure password & copy to clipboard" |
|
echo "" |
|
echo "${C_YELLOW}π Networking & Web${C_NC}" |
|
echo " ${C_GREEN}webshare${C_NC} - Share current directory over local network HTTP" |
|
echo " ${C_GREEN}port${C_NC} - Check what's running on a port (and optionally kill it)" |
|
echo " ${C_GREEN}myip${C_NC} - Show local & public IP, plus geolocation" |
|
echo " ${C_GREEN}pingmap${C_NC} - Detailed network latency and status breakdown" |
|
echo "" |
|
echo "${C_YELLOW}β±οΈ Productivity & System${C_NC}" |
|
echo " ${C_GREEN}todo${C_NC} - Manage a persistent CLI task list" |
|
echo " ${C_GREEN}countdown${C_NC} - Start a timer with UI notifications (supports s/m/h)" |
|
echo " ${C_GREEN}keepawake${C_NC} - Prevent your Mac from sleeping" |
|
echo " ${C_GREEN}weather${C_NC} - Get terminal weather forecast" |
|
echo "${C_CYAN}====================================================${C_NC}" |
|
} |
|
|
|
# ============================================================================== |
|
# FILE & DIRECTORY OPS |
|
# ============================================================================== |
|
|
|
mkcd() { |
|
if [[ "$1" == "help" || "$1" == "-h" || -z "$1" ]]; then |
|
echo "${C_CYAN}π mkcd${C_NC}: Create a directory and enter it in one step." |
|
echo "Usage: ${C_YELLOW}mkcd <directory_name>${C_NC}" |
|
return 0 |
|
fi |
|
mkdir -p "$1" && cd "$1" || return |
|
echo "${C_GREEN}π Directory created. Now in: $(pwd)${C_NC}" |
|
} |
|
|
|
extract() { |
|
if [[ "$1" == "help" || "$1" == "-h" || -z "$1" ]]; then |
|
echo "${C_CYAN}π¦ extract${C_NC}: Universal archive extractor (supports multiple files)." |
|
echo "Usage: ${C_YELLOW}extract <file1> [file2] [file3]${C_NC}" |
|
return 0 |
|
fi |
|
|
|
for file in "$@"; do |
|
if [ -f "$file" ] ; then |
|
echo "${C_CYAN}Extracting '$file'...${C_NC}" |
|
case "$file" in |
|
*.tar.bz2) tar xjf "$file" ;; |
|
*.tar.gz) tar xzf "$file" ;; |
|
*.bz2) bunzip2 "$file" ;; |
|
*.rar) unrar x "$file" ;; |
|
*.gz) gunzip "$file" ;; |
|
*.tar) tar xf "$file" ;; |
|
*.tbz2) tar xjf "$file" ;; |
|
*.tgz) tar xzf "$file" ;; |
|
*.zip) unzip "$file" ;; |
|
*.Z) uncompress "$file" ;; |
|
*.7z) 7z x "$file" ;; |
|
*) echo "${C_RED}β '$file' cannot be extracted via extract().${C_NC}" ;; |
|
esac |
|
else |
|
echo "${C_RED}β '$file' is not a valid file.${C_NC}" |
|
fi |
|
done |
|
echo "${C_GREEN}β
Extraction complete!${C_NC}" |
|
} |
|
|
|
ql() { |
|
if [[ "$1" == "help" || "$1" == "-h" || -z "$1" ]]; then |
|
echo "${C_CYAN}ποΈ ql${C_NC}: Open file(s) in macOS Quick Look (like pressing Space in Finder)." |
|
echo "Usage: ${C_YELLOW}ql <file> [file2] ...${C_NC}" |
|
return 0 |
|
fi |
|
qlmanage -p "$@" >/dev/null 2>&1 & |
|
} |
|
|
|
# ============================================================================== |
|
# DEVELOPER PRODUCTIVITY |
|
# ============================================================================== |
|
|
|
cbjson() { |
|
if [[ "$1" == "help" || "$1" == "-h" ]]; then |
|
echo "${C_CYAN}π cbjson${C_NC}: Formats minified JSON." |
|
echo "Usage:" |
|
echo " ${C_YELLOW}cbjson${C_NC} - Formats JSON currently in your clipboard" |
|
echo " ${C_YELLOW}cbjson <file>${C_NC} - Formats a specific JSON file" |
|
return 0 |
|
fi |
|
|
|
local input_data |
|
local source_name |
|
|
|
if [[ -n "$1" ]]; then |
|
if [[ ! -f "$1" ]]; then |
|
echo "${C_RED}β Error: File '$1' not found.${C_NC}" |
|
return 1 |
|
fi |
|
input_data=$(cat "$1") |
|
source_name="file '$1'" |
|
else |
|
input_data=$(pbpaste) |
|
source_name="clipboard" |
|
fi |
|
|
|
# Format JSON using Python safely |
|
local formatted=$(echo "$input_data" | python3 -c 'import sys, json; print(json.dumps(json.load(sys.stdin), indent=2))' 2>/dev/null) |
|
|
|
if [[ -n "$formatted" ]]; then |
|
echo "$formatted" | pbcopy |
|
echo "${C_GREEN}β
JSON from $source_name formatted and copied to clipboard!${C_NC}" |
|
echo "${C_CYAN}Preview:${C_NC}" |
|
# If jq is installed, use it for color output in terminal, otherwise just echo |
|
if command -v jq >/dev/null 2>&1; then |
|
echo "$formatted" | jq -C '.' | head -n 15 |
|
else |
|
echo "$formatted" | head -n 15 |
|
fi |
|
echo "${C_YELLOW}... (truncated) ...${C_NC}" |
|
else |
|
echo "${C_RED}β Error: $source_name does not contain valid JSON data.${C_NC}" |
|
fi |
|
} |
|
|
|
glit() { |
|
if [[ "$1" == "help" || "$1" == "-h" || -z "$1" ]]; then |
|
echo "${C_CYAN}π glit${C_NC}: The lazy way to git." |
|
echo "Usage:" |
|
echo " ${C_YELLOW}glit <message>${C_NC} - Add all, commit, and push (quotes optional)" |
|
echo " ${C_YELLOW}glit amend${C_NC} - Add all, amend last commit, and safely force push" |
|
echo " ${C_YELLOW}glit wip${C_NC} - Add all, commit as 'WIP' with timestamp, and push" |
|
echo " ${C_YELLOW}glit undo${C_NC} - Undo the last local commit (keeps your file changes)" |
|
echo " ${C_YELLOW}glit clean${C_NC} - Delete local branches merged to main/master" |
|
echo " ${C_YELLOW}glit merge <branch>${C_NC} - Fetch and merge a remote branch into your current branch" |
|
echo " ${C_YELLOW}glit status${C_NC} - Show full git status" |
|
echo " ${C_YELLOW}glit log [num]${C_NC} - Show a beautiful, colorized git history tree" |
|
echo "" |
|
echo "${C_YELLOW}Quick Status:${C_NC}" |
|
git rev-parse --is-inside-work-tree >/dev/null 2>&1 && git status -s || echo "Not a git repository." |
|
return 0 |
|
fi |
|
|
|
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then |
|
echo "${C_RED}β Error: You are not in a git repository.${C_NC}" |
|
return 1 |
|
fi |
|
|
|
local branch_name=$(git rev-parse --abbrev-ref HEAD) |
|
|
|
case "$1" in |
|
"amend") |
|
echo "${C_CYAN}Adding changes and amending last commit...${C_NC}" |
|
git add . |
|
git commit --amend --no-edit |
|
echo "${C_CYAN}Force pushing to origin $branch_name...${C_NC}" |
|
git push origin "$branch_name" --force-with-lease |
|
echo "${C_GREEN}β
Amend & push complete!${C_NC}" |
|
;; |
|
"undo") |
|
echo "${C_YELLOW}Undoing last commit (your files remain changed)...${C_NC}" |
|
git reset HEAD~1 |
|
echo "${C_GREEN}β
Last commit undone. You can now make changes and commit again.${C_NC}" |
|
;; |
|
"wip") |
|
echo "${C_CYAN}Committing as WIP...${C_NC}" |
|
git add . |
|
git commit -m "WIP: $(date '+%Y-%m-%d %H:%M:%S')" |
|
git push origin "$branch_name" |
|
echo "${C_GREEN}β
WIP pushed!${C_NC}" |
|
;; |
|
"clean") |
|
echo "${C_CYAN}Searching for merged local branches...${C_NC}" |
|
local merged_branches=$(git branch --merged | egrep -v "(^\*|master|main|dev)") |
|
if [[ -z "$merged_branches" ]]; then |
|
echo "${C_GREEN}β¨ Your local repository is already perfectly clean!${C_NC}" |
|
else |
|
echo "$merged_branches" | xargs git branch -d |
|
echo "${C_GREEN}β
Cleaned up merged branches!${C_NC}" |
|
fi |
|
;; |
|
"status") |
|
echo "${C_CYAN}π Current Git Status for branch '${C_YELLOW}$branch_name${C_CYAN}':${C_NC}" |
|
echo "------------------------------------------------------------" |
|
git status |
|
;; |
|
"merge") |
|
local target_branch=$2 |
|
if [[ -z "$target_branch" ]]; then |
|
echo "${C_RED}β Error: Please specify a branch to merge.${C_NC}" |
|
echo "Usage: ${C_YELLOW}glit merge <branch_name>${C_NC}" |
|
return 1 |
|
fi |
|
|
|
echo "${C_CYAN}Fetching latest changes for '$target_branch' from origin...${C_NC}" |
|
git fetch origin "$target_branch" |
|
|
|
echo "${C_CYAN}Merging origin/$target_branch into $branch_name...${C_NC}" |
|
if git merge "origin/$target_branch"; then |
|
echo "${C_GREEN}β
Successfully merged '$target_branch' into '$branch_name'!${C_NC}" |
|
else |
|
echo "" |
|
echo "${C_RED}β οΈ Merge conflicts detected!${C_NC}" |
|
echo "Please resolve the conflicts in your editor, then run ${C_YELLOW}glit \"Merge resolution\"${C_NC} to finish." |
|
fi |
|
;; |
|
"log") |
|
local count=${2:-15} |
|
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit -n "$count" |
|
;; |
|
*) |
|
echo "${C_CYAN}Executing: git add .${C_NC}" |
|
git add . |
|
echo "${C_CYAN}Executing: git commit -m \"$*\"${C_NC}" |
|
git commit -m "$*" |
|
echo "${C_CYAN}Executing: git push origin $branch_name${C_NC}" |
|
git push origin "$branch_name" |
|
echo "${C_GREEN}β
All done! Code pushed successfully.${C_NC}" |
|
;; |
|
esac |
|
} |
|
|
|
genpass() { |
|
if [[ "$1" == "help" || "$1" == "-h" ]]; then |
|
echo "${C_CYAN}π genpass${C_NC}: Generate a secure password and copy to clipboard." |
|
echo "Usage: ${C_YELLOW}genpass [length]${C_NC}" |
|
echo "Example: genpass 24" |
|
return 0 |
|
fi |
|
|
|
local len=${1:-16} |
|
local pass=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*' | fold -w "$len" | head -n 1) |
|
|
|
echo "$pass" | pbcopy |
|
echo "${C_GREEN}β
Password generated and copied to clipboard!${C_NC}" |
|
echo "Length: $len chars" |
|
} |
|
|
|
# ============================================================================== |
|
# NETWORKING & WEB |
|
# ============================================================================== |
|
|
|
port() { |
|
if [[ "$1" == "help" || "$1" == "-h" || -z "$1" ]]; then |
|
echo "${C_CYAN}π port${C_NC}: See what's running on a port and optionally kill it." |
|
echo "Usage: ${C_YELLOW}port <number> [kill]${C_NC}" |
|
echo "Examples:" |
|
echo " port 8080 (Views processes on port 8080)" |
|
echo " port 3000 kill (Kills the process running on port 3000)" |
|
return 0 |
|
fi |
|
|
|
local target_port=$1 |
|
if [[ "$2" == "kill" ]]; then |
|
echo "${C_RED}Attempting to kill process on port $target_port...${C_NC}" |
|
local pid=$(lsof -t -i:"$target_port") |
|
if [[ -n "$pid" ]]; then |
|
kill -9 $pid |
|
echo "${C_GREEN}β
Process $pid killed successfully.${C_NC}" |
|
else |
|
echo "${C_YELLOW}β οΈ No process found running on port $target_port.${C_NC}" |
|
fi |
|
else |
|
echo "${C_CYAN}Processes listening on port $target_port:${C_NC}" |
|
lsof -i :"$target_port" || echo "${C_YELLOW}No active processes on this port.${C_NC}" |
|
fi |
|
} |
|
|
|
webshare() { |
|
if [[ "$1" == "help" || "$1" == "-h" || "$1" == "--help" ]]; then |
|
echo "${C_CYAN}π webshare${C_NC}: Instantly serve the current directory over HTTP with a beautiful UI." |
|
echo "Usage: ${C_YELLOW}webshare [port] [-o]${C_NC}" |
|
echo "" |
|
echo "Options:" |
|
echo " ${C_YELLOW}-o, --open${C_NC} Automatically open the server in your default browser" |
|
echo "" |
|
echo "Examples:" |
|
echo " webshare (Serves on port 8000 by default)" |
|
echo " webshare 3000 (Serves on port 3000)" |
|
echo " webshare 8080 -o (Serves on 8080 and opens browser)" |
|
return 0 |
|
fi |
|
|
|
local port=8000 |
|
local open_browser=0 |
|
|
|
for arg in "$@"; do |
|
case "$arg" in |
|
-o|--open) open_browser=1 ;; |
|
-*) echo "${C_RED}β Unknown option: $arg${C_NC}"; return 1 ;; |
|
*) |
|
if [[ "$arg" =~ ^[0-9]+$ ]]; then port=$arg |
|
else echo "${C_RED}β Invalid port: $arg${C_NC}"; return 1; fi |
|
;; |
|
esac |
|
done |
|
|
|
while lsof -Pi :$port -sTCP:LISTEN -t >/dev/null; do |
|
echo "${C_YELLOW}β οΈ Port $port is in use. Trying $((port+1))...${C_NC}" |
|
port=$((port+1)) |
|
done |
|
|
|
local local_ip=$(route -n get default 2>/dev/null | grep 'interface:' | awk '{print $2}' | xargs ipconfig getifaddr 2>/dev/null) |
|
[[ -z "$local_ip" ]] && local_ip="127.0.0.1" |
|
|
|
# Friendly Bonjour hostname, detected dynamically (e.g. http://my-macbook.local:8000) |
|
local host_name=$(scutil --get LocalHostName 2>/dev/null) |
|
local local_alias="" |
|
[[ -n "$host_name" ]] && local_alias="http://${host_name}.local:$port" |
|
|
|
echo "${C_GREEN}β
Web server is running!${C_NC}" |
|
echo "${C_CYAN}π Serving path:${C_NC} $(pwd)" |
|
echo "------------------------------------------------------------" |
|
echo "${C_MAGENTA}π± How to use & share:${C_NC}" |
|
echo " β’ ${C_YELLOW}For yourself:${C_NC} Click or open ${C_GREEN}http://localhost:$port${C_NC}" |
|
echo " β’ ${C_YELLOW}For others:${C_NC} Tell them to go to one of these links on their device:" |
|
echo " ${C_GREEN}http://$local_ip:$port${C_NC} (Always works)" |
|
if [[ -n "$local_alias" ]]; then |
|
echo " ${C_CYAN}$local_alias${C_NC} (Friendly name, works on most devices)" |
|
fi |
|
echo " ${C_YELLOW}(Note: They must be on the same Wi-Fi/network)${C_NC}" |
|
echo "------------------------------------------------------------" |
|
echo "${C_YELLOW}Press Ctrl+C to stop the server${C_NC}" |
|
echo "" |
|
|
|
if [[ $open_browser -eq 1 ]]; then |
|
open "http://localhost:$port" |
|
fi |
|
|
|
local py_script=$(cat <<'EOF' |
|
import http.server, socketserver, os, sys, urllib.parse, html, io |
|
|
|
PORT = int(sys.argv[1]) |
|
|
|
class BeautifulHandler(http.server.SimpleHTTPRequestHandler): |
|
def list_directory(self, path): |
|
try: |
|
files = os.listdir(path) |
|
except os.error: |
|
self.send_error(404, "No permission to list directory") |
|
return None |
|
|
|
files.sort(key=lambda a: a.lower()) |
|
|
|
displaypath = html.escape(urllib.parse.unquote(self.path)) |
|
enc = sys.getfilesystemencoding() |
|
|
|
r = [] |
|
r.append('<!DOCTYPE html><html><head><meta charset="utf-8">') |
|
r.append('<meta name="viewport" content="width=device-width, initial-scale=1">') |
|
r.append('<title>Shared Files</title>') |
|
r.append('''<style> |
|
body { font-family: system-ui, -apple-system, sans-serif; background: #121212; color: #e0e0e0; margin: 0; padding: 20px; } |
|
.container { max-width: 800px; margin: 0 auto; background: #1e1e1e; border-radius: 12px; padding: 20px; box-shadow: 0 8px 16px rgba(0,0,0,0.5); } |
|
h1 { margin-top: 0; font-size: 1.4rem; border-bottom: 1px solid #333; padding-bottom: 15px; color: #fff; word-break: break-all; } |
|
ul { list-style: none; padding: 0; margin: 0; } |
|
li { border-bottom: 1px solid #2a2a2a; } |
|
li:last-child { border-bottom: none; } |
|
a { display: flex; align-items: center; padding: 12px 10px; color: #bbb; text-decoration: none; font-size: 16px; border-radius: 8px; transition: all 0.2s; word-break: break-word; } |
|
a:hover { background: #2a2a2a; color: #fff; transform: translateX(4px); } |
|
.icon { font-size: 24px; margin-right: 15px; min-width: 30px; text-align: center; } |
|
@media (max-width: 600px) { body { padding: 10px; } .container { padding: 15px; } } |
|
</style>''') |
|
r.append('</head><body><div class="container">') |
|
r.append('<h1>π‘ Network Share <br><span style="color:#888; font-size:1rem; font-weight:normal;">%s</span></h1>' % displaypath) |
|
r.append('<ul>') |
|
|
|
if self.path != "/": |
|
r.append('<li><a href=".."><span class="icon">π</span> Parent Directory</a></li>') |
|
|
|
for name in files: |
|
if name.startswith('.'): |
|
continue |
|
|
|
fullname = os.path.join(path, name) |
|
displayname = linkname = name |
|
icon = "π" |
|
|
|
if os.path.isdir(fullname): |
|
displayname = name + "/" |
|
linkname = name + "/" |
|
icon = "π" |
|
else: |
|
ext = name.lower().split('.')[-1] if '.' in name else '' |
|
if ext in ['mkv', 'mp4', 'avi', 'mov', 'webm']: icon = "π¬" |
|
elif ext in ['jpg', 'jpeg', 'png', 'gif', 'webp']: icon = "πΌοΈ" |
|
elif ext in ['mp3', 'wav', 'flac', 'm4a']: icon = "π΅" |
|
elif ext in ['zip', 'rar', '7z', 'tar', 'gz']: icon = "π¦" |
|
elif ext in ['pdf']: icon = "π" |
|
elif ext in ['txt', 'md', 'csv', 'json']: icon = "π" |
|
elif ext in ['py', 'js', 'html', 'css', 'java', 'cpp', 'sh']: icon = "π»" |
|
|
|
r.append('<li><a href="%s"><span class="icon">%s</span> %s</a></li>' |
|
% (urllib.parse.quote(linkname, errors='surrogatepass'), icon, html.escape(displayname))) |
|
|
|
r.append('</ul></div></body></html>') |
|
|
|
encoded = ''.join(r).encode(enc, 'surrogateescape') |
|
f = io.BytesIO() |
|
f.write(encoded) |
|
f.seek(0) |
|
self.send_response(200) |
|
self.send_header("Content-type", "text/html; charset=%s" % enc) |
|
self.send_header("Content-Length", str(len(encoded))) |
|
self.end_headers() |
|
return f |
|
|
|
class QuietServer(socketserver.TCPServer): |
|
allow_reuse_address = True |
|
|
|
def handle_error(self, request, client_address): |
|
import sys |
|
if issubclass(sys.exc_info()[0], (BrokenPipeError, ConnectionResetError)): |
|
return |
|
super().handle_error(request, client_address) |
|
|
|
with QuietServer(("", PORT), BeautifulHandler) as httpd: |
|
httpd.serve_forever() |
|
EOF |
|
) |
|
|
|
python3 -c "$py_script" "$port" |
|
} |
|
|
|
myip() { |
|
if [[ "$1" == "help" || "$1" == "-h" ]]; then |
|
echo "${C_CYAN}π myip${C_NC}: Fetches your networking info." |
|
echo "Usage: ${C_YELLOW}myip${C_NC}" |
|
return 0 |
|
fi |
|
|
|
echo "${C_CYAN}Fetching IP details...${C_NC}" |
|
local local_ip=$(route -n get default 2>/dev/null | grep 'interface:' | awk '{print $2}' | xargs ipconfig getifaddr 2>/dev/null) |
|
[[ -z "$local_ip" ]] && local_ip="127.0.0.1" |
|
local public_ip=$(curl -s https://ifconfig.me) |
|
local geo_info=$(curl -s "https://ipinfo.io/${public_ip}/city") |
|
local country_info=$(curl -s "https://ipinfo.io/${public_ip}/country") |
|
|
|
echo "π ${C_YELLOW}Local IP:${C_NC} $local_ip" |
|
echo "π ${C_YELLOW}Public IP:${C_NC} $public_ip" |
|
echo "π ${C_YELLOW}Location:${C_NC} $geo_info, $country_info" |
|
} |
|
|
|
pingmap() { |
|
if [[ "$1" == "help" || "$1" == "-h" || -z "$1" ]]; then |
|
echo "${C_CYAN}π pingmap${C_NC}: Detailed connection latency breakdown." |
|
echo "Usage: ${C_YELLOW}pingmap <url>${C_NC}" |
|
echo "Example: pingmap google.com" |
|
return 0 |
|
fi |
|
|
|
local url="$1" |
|
# Auto-prepend https:// if missing |
|
[[ "$url" != http* ]] && url="https://$url" |
|
|
|
echo "${C_CYAN}Mapping network route to: $url${C_NC}" |
|
echo "----------------------------------------" |
|
curl -w " HTTP Status : %{http_code}\n DNS Lookup : %{time_namelookup}s\n TCP Connect : %{time_connect}s\n TLS Handshake : %{time_appconnect}s\n Pre-Transfer : %{time_pretransfer}s\n First Byte : %{time_starttransfer}s\n----------------------------------------\n ${C_GREEN}Total Time : %{time_total}s${C_NC}\n\n" -o /dev/null -s "$url" |
|
} |
|
|
|
# ============================================================================== |
|
# PRODUCTIVITY & SYSTEM |
|
# ============================================================================== |
|
|
|
todo() { |
|
local todo_file="$HOME/.todo_list.txt" |
|
touch "$todo_file" |
|
|
|
check_bounds() { |
|
local target=$1 |
|
local max_line |
|
max_line=$(wc -l < "$todo_file" | awk '{print $1}') |
|
if (( target > max_line || target < 1 )); then |
|
echo "${C_RED}β Task number $target not found.${C_NC}" |
|
return 1 |
|
fi |
|
return 0 |
|
} |
|
|
|
case "$1" in |
|
"help"|"-h"|"--help") |
|
echo "${C_CYAN}π‘ CLI Todo List β Help Menu${C_NC}" |
|
echo "Usage: todo [command] [arguments]" |
|
echo "" |
|
echo " ${C_YELLOW}todo <text>${C_NC} Add a task" |
|
echo " ${C_YELLOW}todo list${C_NC} Display tasks" |
|
echo " ${C_YELLOW}todo done <num>${C_NC} Mark task completed" |
|
echo " ${C_YELLOW}todo undo <num>${C_NC} Revert task to pending" |
|
echo " ${C_YELLOW}todo edit <num> <txt>${C_NC} Update task" |
|
echo " ${C_YELLOW}todo rm <num>${C_NC} Delete task" |
|
echo " ${C_YELLOW}todo clear done${C_NC} Remove completed tasks" |
|
echo " ${C_YELLOW}todo clear${C_NC} Wipe entire list" |
|
;; |
|
"list"|"") |
|
if [ ! -s "$todo_file" ]; then |
|
echo "${C_GREEN}π No tasks! Live free.${C_NC}" |
|
else |
|
echo "${C_CYAN}π Your Todo List:${C_NC}" |
|
local count=1 |
|
while IFS= read -r line || [ -n "$line" ]; do |
|
local stripped="${line//[[:space:]]/}" |
|
|
|
if [[ -z "$stripped" || "$stripped" == "+children"* || "$stripped" == "--format"* || "$stripped" == "display="* || "$stripped" == "-[ ]-f" ]]; then |
|
continue |
|
fi |
|
|
|
if [[ "$line" == *"[ ]"* ]]; then |
|
line="${line//"[ ]"/${C_YELLOW}[ ]${C_NC}}" |
|
elif [[ "$line" == *"[x]"* ]]; then |
|
line="${line//"[x]"/${C_GREEN}[x]${C_NC}}" |
|
fi |
|
|
|
printf "%2d. %s\n" "$count" "$line" |
|
((count++)) |
|
done < "$todo_file" |
|
|
|
if [ "$count" -eq 1 ]; then |
|
echo "${C_GREEN}π No tasks! Live free.${C_NC}" |
|
fi |
|
fi |
|
;; |
|
"done") |
|
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then |
|
check_bounds "$2" || return 1 |
|
sed -i "" "${2}s/\[ \]/\[x\]/" "$todo_file" |
|
echo "${C_GREEN}β
Task $2 marked as done!${C_NC}" |
|
else |
|
echo "${C_YELLOW}β οΈ Usage: todo done <task_number>${C_NC}" |
|
fi |
|
;; |
|
"undo") |
|
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then |
|
check_bounds "$2" || return 1 |
|
sed -i "" "${2}s/\[x\]/\[ \]/" "$todo_file" |
|
echo "${C_YELLOW}βͺ Task $2 marked as pending!${C_NC}" |
|
else |
|
echo "${C_YELLOW}β οΈ Usage: todo undo <task_number>${C_NC}" |
|
fi |
|
;; |
|
"rm") |
|
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then |
|
check_bounds "$2" || return 1 |
|
sed -i "" "${2}d" "$todo_file" |
|
echo "${C_RED}ποΈ Task $2 deleted!${C_NC}" |
|
else |
|
echo "${C_YELLOW}β οΈ Usage: todo rm <task_number>${C_NC}" |
|
fi |
|
;; |
|
"edit") |
|
if [[ -n "$2" && "$2" =~ ^[0-9]+$ && -n "$3" ]]; then |
|
local line_num=$2 |
|
check_bounds "$line_num" || return 1 |
|
shift 2 |
|
sed -i "" "${line_num}s|.*|- [ ] $*|" "$todo_file" |
|
echo "${C_CYAN}βοΈ Task $line_num updated!${C_NC}" |
|
else |
|
echo "${C_YELLOW}β οΈ Usage: todo edit <task_number> <new text>${C_NC}" |
|
fi |
|
;; |
|
"clear") |
|
if [ "$2" = "done" ]; then |
|
grep -v '\[x\]' "$todo_file" > "$todo_file.tmp" |
|
mv "$todo_file.tmp" "$todo_file" |
|
echo "${C_GREEN}π§Ή Cleared completed tasks!${C_NC}" |
|
elif [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then |
|
echo "${C_YELLOW}β οΈ Did you mean 'todo rm $2'?${C_NC}" |
|
elif [ -n "$2" ]; then |
|
echo "${C_YELLOW}β οΈ Unknown argument. Use 'todo clear done' or 'todo clear'.${C_NC}" |
|
else |
|
echo -n "${C_RED}β οΈ Wipe ENTIRE todo list? (y/N): ${C_NC}" |
|
read -r response |
|
if [[ "$response" == [Yy]* ]]; then |
|
rm -f "$todo_file" && touch "$todo_file" |
|
echo "${C_RED}π₯ Todo list wiped completely clean!${C_NC}" |
|
else |
|
echo "${C_CYAN}β Action aborted.${C_NC}" |
|
fi |
|
fi |
|
;; |
|
-*) |
|
return 0 |
|
;; |
|
*) |
|
echo "- [ ] $*" >> "$todo_file" |
|
echo "${C_GREEN}β Task added!${C_NC}" |
|
;; |
|
esac |
|
} |
|
|
|
countdown() { |
|
if [[ "$1" == "help" || "$1" == "-h" ]]; then |
|
echo "${C_CYAN}β³ countdown${C_NC}: A simple terminal timer with notifications." |
|
echo "Usage: ${C_YELLOW}countdown <time>[s|m|h]${C_NC}" |
|
echo "Examples: countdown 45, countdown 5m, countdown 1h" |
|
return 0 |
|
fi |
|
|
|
local input=${1:-60} |
|
local seconds=0 |
|
|
|
if [[ $input == *m ]]; then seconds=$((${input%m} * 60)) |
|
elif [[ $input == *h ]]; then seconds=$((${input%h} * 3600)) |
|
elif [[ $input == *s ]]; then seconds=${input%s} |
|
else seconds=$input; fi |
|
|
|
if ! [[ "$seconds" =~ ^[0-9]+$ ]]; then |
|
echo "${C_RED}β Invalid time format.${C_NC} Use numbers, optionally followed by m or h." |
|
return 1 |
|
fi |
|
|
|
echo "${C_CYAN}Starting timer for $input...${C_NC}" |
|
while [ "$seconds" -gt 0 ]; do |
|
printf "\r${C_YELLOW}β³ Time remaining: %02d:%02d${C_NC}\033[0K" $((seconds/60)) $((seconds%60)) |
|
sleep 1 |
|
: $((seconds--)) |
|
done |
|
|
|
printf "\r\033[0K" |
|
echo "${C_GREEN}π Time's up! ($input)${C_NC}" |
|
|
|
if [[ "$OSTYPE" == "darwin"* ]]; then |
|
osascript -e "display notification \"Your $input timer has finished!\" with title \"β³ Countdown\" sound name \"Glass\"" |
|
say "Timer is done" >/dev/null 2>&1 &! |
|
else |
|
echo -e "\a" |
|
fi |
|
} |
|
|
|
keepawake() { |
|
if [[ "$1" == "help" || "$1" == "-h" ]]; then |
|
echo "${C_CYAN}β keepawake${C_NC}: Prevent your Mac from sleeping." |
|
echo "Usage: ${C_YELLOW}keepawake [time | -p PID | -c command | stop]${C_NC}" |
|
echo "" |
|
echo "Options:" |
|
echo " ${C_YELLOW}[time]${C_NC} Keep awake for duration (e.g., 2h, 30m) and notify when done" |
|
echo " ${C_YELLOW}-p <PID>${C_NC} Keep awake until a Process ID finishes, then notify" |
|
echo " ${C_YELLOW}-c <cmd>${C_NC} Run a command, keep awake until it completes, then notify" |
|
echo " ${C_YELLOW}-s${C_NC} System-only mode: Keep tasks running, but let the screen turn off" |
|
echo " ${C_YELLOW}stop${C_NC} Kill any existing keepawake sessions running in the background" |
|
echo " ${C_YELLOW}(none)${C_NC} Keep awake indefinitely (Ctrl+C to stop)" |
|
echo "" |
|
echo "Examples:" |
|
echo " keepawake -c npm run build" |
|
echo " keepawake -s 2h" |
|
return 0 |
|
fi |
|
|
|
# Helper function for macOS notifications |
|
notify_done() { |
|
local msg="$1" |
|
if [[ "$OSTYPE" == "darwin"* ]]; then |
|
osascript -e "display notification \"$msg\" with title \"β Keepawake\" sound name \"Glass\"" |
|
say "Task finished" >/dev/null 2>&1 &! |
|
else |
|
echo -e "\a" |
|
fi |
|
} |
|
|
|
# The Kill Switch |
|
if [[ "$1" == "stop" ]]; then |
|
killall caffeinate 2>/dev/null |
|
echo "${C_GREEN}π Stopped all active keepawake sessions. Mac can sleep normally.${C_NC}" |
|
return 0 |
|
fi |
|
|
|
# Determine caffeinate flags (default includes -d for display, -s drops -d) |
|
local flags="-dism" |
|
if [[ "$1" == "-s" || "$1" == "--system" ]]; then |
|
flags="-ism" |
|
shift |
|
echo "${C_YELLOW}π System-only mode: Display will sleep, but background processes will run.${C_NC}" |
|
fi |
|
|
|
if [[ -z "$1" ]]; then |
|
echo "${C_GREEN}β Mac is now caffeinated. Press Ctrl+C to let it sleep.${C_NC}" |
|
caffeinate $flags |
|
echo "${C_CYAN}π Mac can sleep normally now.${C_NC}" |
|
return 0 |
|
fi |
|
|
|
case "$1" in |
|
-p|--pid) |
|
local pid=$2 |
|
if [[ -z "$pid" || ! "$pid" =~ ^[0-9]+$ ]]; then |
|
echo "${C_RED}β Error: Please provide a valid Process ID.${C_NC}" |
|
return 1 |
|
fi |
|
echo "${C_GREEN}β Mac will stay awake until process $pid finishes...${C_NC}" |
|
caffeinate $flags -w "$pid" |
|
echo "${C_CYAN}π Process $pid finished. Mac can sleep normally now.${C_NC}" |
|
notify_done "Process $pid has finished!" |
|
;; |
|
-c|--command) |
|
shift |
|
if [[ -z "$*" ]]; then |
|
echo "${C_RED}β Error: Please provide a command to run.${C_NC}" |
|
return 1 |
|
fi |
|
echo "${C_GREEN}β Mac will stay awake while running: ${C_YELLOW}$*${C_NC}" |
|
echo "------------------------------------------------------------" |
|
caffeinate $flags "$@" |
|
echo "------------------------------------------------------------" |
|
echo "${C_CYAN}π Command finished. Mac can sleep normally now.${C_NC}" |
|
notify_done "Your command has finished running!" |
|
;; |
|
*) |
|
local input=$1 |
|
local seconds=0 |
|
if [[ $input == *m ]]; then seconds=$((${input%m} * 60)) |
|
elif [[ $input == *h ]]; then seconds=$((${input%h} * 3600)) |
|
elif [[ $input == *s ]]; then seconds=${input%s} |
|
else seconds=$input; fi |
|
|
|
if ! [[ "$seconds" =~ ^[0-9]+$ ]]; then |
|
echo "${C_RED}β Invalid format.${C_NC} Use a time (30m), -p <PID>, or -c <cmd>." |
|
return 1 |
|
fi |
|
|
|
echo "${C_GREEN}β Mac will stay awake for $input. Press Ctrl+C to cancel.${C_NC}" |
|
caffeinate $flags -t "$seconds" |
|
echo "${C_CYAN}π Timer finished. Mac can sleep normally now.${C_NC}" |
|
notify_done "Your $input keepawake timer has finished!" |
|
;; |
|
esac |
|
} |
|
|
|
weather() { |
|
if [[ "$1" == "help" || "$1" == "-h" ]]; then |
|
echo "${C_CYAN}βοΈ weather${C_NC}: Advanced terminal weather and forecast." |
|
echo "Usage: ${C_YELLOW}weather [options] [location]${C_NC}" |
|
echo "" |
|
echo "Options:" |
|
echo " ${C_YELLOW}-s, --short${C_NC} Single-line compact format (Temp & Condition)" |
|
echo " ${C_YELLOW}-o, --oneline${C_NC} Rich single-line format (Temp, Wind, Humidity)" |
|
echo " ${C_YELLOW}-f, --forecast${C_NC} Detailed visual graph forecast" |
|
echo " ${C_YELLOW}-m, --moon${C_NC} Show current moon phase" |
|
echo "" |
|
echo "Examples:" |
|
echo " weather London (Default 3-day text forecast)" |
|
echo " weather -o New York (One-line rich weather)" |
|
echo " weather -f (Detailed forecast for your current IP)" |
|
return 0 |
|
fi |
|
|
|
local format="" |
|
local args=() |
|
|
|
for arg in "$@"; do |
|
case "$arg" in |
|
-s|--short) format="?format=3" ;; |
|
-o|--oneline) format="?format=4" ;; |
|
-f|--forecast) format="?format=v2" ;; |
|
-m|--moon) format="?Moon" ;; |
|
-*) |
|
echo "${C_RED}β Unknown option: $arg${C_NC}" |
|
echo "Run ${C_YELLOW}weather -h${C_NC} for usage." |
|
return 1 |
|
;; |
|
*) args+=("$arg") ;; |
|
esac |
|
done |
|
|
|
local loc="${args[*]}" |
|
loc="${loc// /+}" |
|
|
|
echo "${C_CYAN}Fetching weather data...${C_NC}" |
|
curl -s "https://wttr.in/${loc}${format}" |
|
} |