@@ -0,0 +1,144 @@ | |||
#!/usr/bin/env bash | |||
declare esc=$(printf '\033') | |||
declare c_reset="${esc}[0m" | |||
declare c_red="${esc}[31m" | |||
err() { | |||
echo -e "${c_red}$1${c_reset}" >&2 | |||
} | |||
die() { | |||
[[ -n "$1" ]] && err "$1" | |||
exit 1 | |||
} | |||
has() { | |||
local verbose=false | |||
if [[ $1 == '-v' ]]; then | |||
verbose=true | |||
shift | |||
fi | |||
for c in "$@"; do c="${c%% *}" | |||
if ! command -v "$c" &> /dev/null; then | |||
[[ "$verbose" == true ]] && err "$c not found" | |||
return 1 | |||
fi | |||
done | |||
} | |||
usage() { | |||
more <<'HELP' | |||
fv [OPTIONS] [SEARCH] | |||
fuzzy file filtering and command executing | |||
-c command to execute [defaults to vim] | |||
-a search all dirs and hidden files (still quirky) | |||
-d detach from terminal via nohup | |||
HELP | |||
} | |||
setCmd() { | |||
if has "$1"; then | |||
cmd="$1" | |||
else | |||
die "$1 is not a valid command" | |||
fi | |||
} | |||
declare cmd='vim' | |||
declare cmdopts=() | |||
declare searchstr='' | |||
declare searchcmd='' | |||
declare searchopts=() | |||
declare allfiles=0 | |||
while getopts "hadlc:" opt; do | |||
case "$opt" in | |||
h) usage; exit 0 ;; | |||
a) allfiles=1 ;; | |||
c) setCmd "$OPTARG" ;; | |||
d) unset detach ;; | |||
l) searchopts+=( '-l' ) ;; | |||
esac | |||
done | |||
shift "$((OPTIND-1))" | |||
has -v 'fzf' || die | |||
for c in 'ag' 'ack' 'grep'; do | |||
if has "$c"; then | |||
searchcmd="$c" | |||
break | |||
fi | |||
done | |||
if [[ $searchcmd == 'grep' ]]; then | |||
err 'grep is slow, you should strongly consider installing ag or ack' | |||
sleep .5 | |||
fi | |||
if [[ -n "$1" ]]; then | |||
if [[ -d "$1" ]]; then | |||
searchopts+=( "$1" ) | |||
else | |||
searchstr="$1" | |||
fi | |||
shift | |||
fi | |||
case "$searchcmd" in | |||
'ag') | |||
searchopts+=( '--color' ) | |||
if [[ "$allfiles" == 1 ]]; then | |||
searchopts+=( '-u' '--hidden' ) | |||
fi | |||
if [[ "$searchstr" == '' ]]; then | |||
searchopts+=( '-l' ) | |||
fi | |||
;; | |||
'ack') | |||
if [[ "$searchstr" == '' ]]; then | |||
if [[ "$allfiles" == 0 ]]; then | |||
searchopts+=( '-g' '^[^\.]' ) | |||
else | |||
searchopts+=( '-f' ) | |||
fi | |||
else | |||
searchopts+=( '-l' ) | |||
# searchopts+=( '--match' ) | |||
fi | |||
;; | |||
'grep') | |||
searchopts+=( '-r' '-I' ) | |||
if [[ "$allfiles" == 0 ]]; then | |||
searchopts+=( '--exclude-dir=bower_components' ) | |||
searchopts+=( '--exclude-dir=node_modules' ) | |||
searchopts+=( '--exclude-dir=jspm_packages' ) | |||
searchopts+=( '--exclude-dir=.cvs' ) | |||
searchopts+=( '--exclude-dir=.git' ) | |||
searchopts+=( '--exclude-dir=.hg' ) | |||
searchopts+=( '--exclude-dir=.svn' ) | |||
fi | |||
if [[ "$searchstr" == '' ]]; then | |||
searchopts+=( '' ) | |||
fi | |||
;; | |||
esac | |||
if [[ "$searchstr" != '' ]]; then | |||
searchopts+=( "$searchstr" ) | |||
fi | |||
choices=$($searchcmd "${searchopts[@]}" 2> /dev/null | | |||
fzf --ansi --cycle --multi) || exit 1 | |||
if [[ "$searchstr" != '' ]]; then | |||
if [[ $searchcmd == 'ag' ]]; then | |||
choices=$(cut -d: -f1 <<< "$choices") | |||
fi | |||
fi | |||
mapfile -t choices <<< "$choices" | |||
$cmd ${cmdopts[*]} "${choices[@]}" |
@@ -0,0 +1,282 @@ | |||
#!/usr/bin/env bash | |||
# /usr/share/bash-completion/completions/git | |||
# https://github.com/junegunn/fzf/wiki/examples#git | |||
has() { # {{{ | |||
command -v "$1" &> /dev/null | |||
} | |||
# }}} | |||
ask() { # {{{ | |||
read -r -n1 -p "$* " ans | |||
echo | |||
[[ ${ans^} == Y* ]] | |||
} | |||
# }}} | |||
err() { # {{{ | |||
echo -e "\e[31m$1\e[0m" >&2 | |||
} | |||
# }}} | |||
die() { # {{{ | |||
[[ -n "$1" ]] && err "$1" | |||
exit 1 | |||
} | |||
# }}} | |||
has fzf || die 'fzf not found' | |||
# [[ -d "$PWD/.git" ]] || die 'not a git repo' | |||
fzf() { # {{{ | |||
local prompt | |||
if [[ $1 == --prompt=* ]]; then | |||
prompt="${1##*=}>" | |||
shift | |||
fi | |||
branch=$(git status 2> /dev/null | sed 's/On branch />/;q') | |||
$(which fzf) --ansi --cycle --prompt="fzgit${branch}>${prompt}" "$@" | |||
} | |||
# }}} | |||
# BOLD=$(tput bold || tput md) | |||
RESET="\e[0m" | |||
GREEN=$(tput setaf 2 || tput AF 2) | |||
# RED=$(tput setaf 1 || tput AF 1) | |||
# WHITE=$(tput setaf 7 || tput AF 7) | |||
declare -A git_cmds_descriptions=( # {{{ | |||
['add']='Add file contents to the index' | |||
['am']='Apply a series of patches from a mailbox' | |||
['annotate']='Annotate file lines with commit information' | |||
['apply']='Apply a patch to files and/or to the index' | |||
['archive']='Create an archive of files from a named tree' | |||
['bisect']='Find by binary search the change that introduced a bug' | |||
['blame']='Show what revision and author last modified each line of a' | |||
['branch']='List, create, or delete branches' | |||
['bundle']='Move objects and refs by archive' | |||
['cat-file']='Provide content or type and size information for' | |||
['check-attr']='Display gitattributes information' | |||
['check-ignore']='Debug gitignore / exclude files' | |||
['check-mailmap']='Show canonical names and email addresses of' | |||
['check-ref-format']='Ensures that a reference name is well formed' | |||
['checkout']='Checkout a branch or paths to the working tree' | |||
['checkout-index']='Copy files from the index to the working tree' | |||
['cherry']='Find commits yet to be applied to upstream' | |||
['cherry-pick']='Apply the changes introduced by some existing commits' | |||
['citool']='Graphical alternative to git-commit' | |||
['clean']='Remove untracked files from the working tree' | |||
['clone']='Clone a repository into a new directory' | |||
['column']='Display data in columns' | |||
['commit']='Record changes to the repository' | |||
['commit-tree']='Create a new commit object' | |||
['config']='Get and set repository or global options' | |||
['count-objects']='Count unpacked number of objects and their disk' | |||
['credential']='Retrieve and store user credentials' | |||
['daemon']='A really simple server for Git repositories' | |||
['describe']='Show the most recent tag that is reachable from a commit' | |||
['diff']='Show changes between commits, commit and working tree, etc' | |||
['diff-files']='Compares files in the working tree and the index' | |||
['diff-index']='Compare a tree to the working tree or index' | |||
['diff-tree']='Compares the content and mode of blobs found via two' | |||
['difftool']='Show changes using common diff tools' | |||
['fast-export']='Git data exporter' | |||
['fast-import']='Backend for fast Git data importers' | |||
['fetch']='Download objects and refs from another repository' | |||
['fetch-pack']='Receive missing objects from another repository' | |||
['filter-branch']='Rewrite branches' | |||
['fmt-merge-msg']='Produce a merge commit message' | |||
['for-each-ref']='Output information on each ref' | |||
['format-patch']='Prepare patches for e-mail submission' | |||
['fsck']='Verifies the connectivity and validity of the objects in the' | |||
['fsck-objects']='Verifies the connectivity and validity of the' | |||
['gc']='Cleanup unnecessary files and optimize the local repository' | |||
['get-tar-commit-id']='Extract commit ID from an archive created using' | |||
['grep']='Print lines matching a pattern' | |||
['gui']='A portable graphical interface to Git' | |||
['hash-object']='Compute object ID and optionally creates a blob from' | |||
['help']='Display help information about Git' | |||
['http-backend']='Server side implementation of Git over HTTP' | |||
['http-fetch']='Download from a remote Git repository via HTTP' | |||
['http-push']='Push objects over HTTP/DAV to another repository' | |||
['imap-send']='Send a collection of patches from stdin to an IMAP' | |||
['index-pack']='Build pack index file for an existing packed archive' | |||
['init']='Create an empty Git repository or reinitialize an existing' | |||
['init-db']='Creates an empty Git repository' | |||
['instaweb']='Instantly browse your working repository in gitweb' | |||
['log']='Show commit logs' | |||
['ls-files']='Show information about files in the index and the' | |||
['ls-remote']='List references in a remote repository' | |||
['ls-tree']='List the contents of a tree object' | |||
['mailinfo']='Extracts patch and authorship from a single e-mail' | |||
['mailsplit']='Simple UNIX mbox splitter program' | |||
['merge']='Join two or more development histories together' | |||
['merge-base']='Find as good common ancestors as possible for a merge' | |||
['merge-file']='Run a three-way file merge' | |||
['merge-index']='Run a merge for files needing merging' | |||
['merge-one-file']='The standard helper program to use with' | |||
['merge-tree']='Show three-way merge without touching index' | |||
['mergetool']='Run merge conflict resolution tools to resolve merge' | |||
['mktag']='Creates a tag object' | |||
['mktree']='Build a tree-object from ls-tree formatted text' | |||
['mv']='Move or rename a file, a directory, or a symlink' | |||
['notes']='Add or inspect object notes' | |||
['pack-objects']='Create a packed archive of objects' | |||
['pack-redundant']='Find redundant pack files' | |||
['pack-refs']='Pack heads and tags for efficient repository access' | |||
['patch-id']='Compute unique ID for a patch' | |||
['prune']='Prune all unreachable objects from the object database' | |||
['prune-packed']='Remove extra objects that are already in pack files' | |||
['pull']='Fetch from and integrate with another repository or a local' | |||
['push']='Update remote refs along with associated objects' | |||
['quiltimport']='Applies a quilt patchset onto the current branch' | |||
['read-tree']='Reads tree information into the index' | |||
['rebase']='Forward-port local commits to the updated upstream head' | |||
['receive-pack']='Receive what is pushed into the repository' | |||
['reflog']='Manage reflog information' | |||
['relink']='Hardlink common objects in local repositories' | |||
['remote']='Manage set of tracked repositories' | |||
['remote-ext']='Bridge smart transport to external command.' | |||
['remote-fd']='Reflect smart transport stream back to caller' | |||
['repack']='Pack unpacked objects in a repository' | |||
['replace']='Create, list, delete refs to replace objects' | |||
['request-pull']='Generates a summary of pending changes' | |||
['rerere']='Reuse recorded resolution of conflicted merges' | |||
['reset']='Reset current HEAD to the specified state' | |||
['rev-list']='Lists commit objects in reverse chronological order' | |||
['rev-parse']='Pick out and massage parameters' | |||
['revert']='Revert some existing commits' | |||
['rm']='Remove files from the working tree and from the index' | |||
['send-pack']='Push objects over Git protocol to another repository' | |||
['sh-i18n--envsubst']="Git's own envsubst(1) for i18n fallbacks" | |||
['shell']='Restricted login shell for Git-only SSH access' | |||
['shortlog']="Summarize 'git log' output" | |||
['show']='Show various types of objects' | |||
['show-branch']='Show branches and their commits' | |||
['show-index']='Show packed archive index' | |||
['show-ref']='List references in a local repository' | |||
['stage']='Add file contents to the staging area' | |||
['stash']='Stash the changes in a dirty working directory away' | |||
['status']='Show the working tree status' | |||
['stripspace']='Remove unnecessary whitespace' | |||
['submodule']='Initialize, update or inspect submodules' | |||
['subtree']='Merge subtrees together and split repository into' | |||
['symbolic-ref']='Read, modify and delete symbolic refs' | |||
['tag']='Create, list, delete or verify a tag object signed with GPG' | |||
['unpack-file']="Creates a temporary file with a blob's contents" | |||
['unpack-objects']='Unpack objects from a packed archive' | |||
['update-index']='Register file contents in the working tree to the' | |||
['update-ref']='Update the object name stored in a ref safely' | |||
['update-server-info']='Update auxiliary info file to help dumb' | |||
['upload-archive']='Send archive back to git-archive' | |||
['upload-pack']='Send objects packed back to git-fetch-pack' | |||
['var']='Show a Git logical variable' | |||
['verify-commit']='Check the GPG signature of commits' | |||
['verify-pack']='Validate packed Git archive files' | |||
['verify-tag']='Check the GPG signature of tags' | |||
['web--browse']='Git helper script to launch a web browser' | |||
['whatchanged']='Show logs with difference each commit introduces' | |||
['write-tree']='Create a tree object from the current index' | |||
) | |||
# }}} | |||
declare -A implemented_git_cmds=( | |||
['stash']='git_stash' | |||
['add']='git_add' | |||
['checkout']='git_checkout' | |||
['commit']='git commit -e' | |||
['push']='git push' | |||
['log']='git_log' | |||
) | |||
git_log() { # {{{ | |||
local out commit | |||
while out=$(git log --graph --color=always \ | |||
--format="%C(auto)%h%d %s %C(black)%C(bold)%cr" "$@" | | |||
fzf -e --prompt='log' --no-sort --tiebreak=index --toggle-sort=\`) | |||
do | |||
commit=$(grep -m1 -o '[a-f0-9]\{7\}' <<< "$out") | |||
git show --color=always "$commit" | less -R | |||
done | |||
} | |||
# }}} | |||
git_checkout() { # {{{ | |||
local list response key branch header | |||
list=$(git branch --all --color -vv; git tag) || return 1 | |||
mapfile -t response < <(fzf --prompt='checkout' \ | |||
--header="$header" --expect=ctrl-x <<< "$list") | |||
key="${response[0]}" | |||
branch=$(perl -pe 's/^\*?\s*(remotes\/[^\/]*\/)?([^ ]+).*/\2/' <<< "${response[1]}") | |||
git checkout "$branch" || return 1 | |||
} | |||
# }}} | |||
git_add() { # {{{ | |||
local out response query key header | |||
header='use ctrl-p to add in patch mode' | |||
# TODO: needs better filtering | |||
while out=$(git ls-files --exclude-standard | | |||
fzf --prompt='add' --tac --multi \ | |||
--header="$header" --query="$query" --print-query \ | |||
--bind=ctrl-p:accept --expect=ctrl-p) | |||
do | |||
mapfile -t response <<< "$out" | |||
query="${response[0]}" && unset response[0] | |||
key="${response[1]}" && unset response[1] | |||
[[ "${#response[@]}" == 0 ]] && continue | |||
if [[ "$key" == 'ctrl-p' ]]; then | |||
git add -p "${response[@]}"; | |||
else | |||
git add "${response[@]}" | |||
fi | |||
done | |||
} | |||
# }}} | |||
git_stash() { # {{{ | |||
local out response query key sha header | |||
header='use ctrl-d to show a diff or ctrl-b to create a new branch' | |||
while out=$(git stash list \ | |||
--pretty="%C(yellow)%h %>(14)%Cgreen%cr %C(blue)%gs" | | |||
fzf --prompt='stash' --no-sort --header="$header" | |||
--query="$query" --print-query \ | |||
--expect=ctrl-d,ctrl-b) | |||
do | |||
mapfile -t response <<< "$out" | |||
query="${response[0]}" && unset response[0] | |||
key="${response[1]}" && unset response[1] | |||
sha="${response[-1]}" | |||
sha="${sha%% *}" | |||
[[ -z "$sha" ]] && continue | |||
if [[ "$key" == 'ctrl-d' ]]; then | |||
PAGER='less' git diff "$sha" | |||
elif [[ "$key" == 'ctrl-b' ]]; then | |||
git stash branch "stash-$sha" "$sha" | |||
break; | |||
else | |||
PAGER='less' git stash show -p "$sha" | |||
fi | |||
done | |||
} | |||
# }}} | |||
pick_cmd() { | |||
for c in "${!implemented_git_cmds[@]}"; do | |||
printf "${GREEN}%s${RESET}| -- %s\n" "$c" "${git_cmds_descriptions[$c]}" | |||
done | column -s'|' -t | fzf | awk '{print $1}' | |||
} | |||
main() { | |||
local pick | |||
while pick=$(pick_cmd); do | |||
if [[ -n $pick ]] && has "${implemented_git_cmds[${pick%% *}]}"; then | |||
${implemented_git_cmds[$pick]} | |||
else | |||
break | |||
fi | |||
done | |||
} | |||
main |
@@ -0,0 +1,106 @@ | |||
#!/usr/bin/env bash | |||
declare esc=$(printf '\033') | |||
declare c_reset="${esc}[0m" | |||
declare c_red="${esc}[31m" | |||
isRunning() { | |||
pgrep "$1" &> /dev/null | |||
} | |||
err() { | |||
echo -e "${c_red}$1${c_reset}" >&2 | |||
} | |||
die() { | |||
[[ -n "$1" ]] && err "$1" | |||
exit 1 | |||
} | |||
has() { | |||
local verbose=false | |||
if [[ $1 == '-v' ]]; then | |||
verbose=true | |||
shift | |||
fi | |||
for c in "$@"; do c="${c%% *}" | |||
if ! command -v "$c" &> /dev/null; then | |||
[[ "$verbose" == true ]] && err "$c not found" | |||
return 1 | |||
fi | |||
done | |||
} | |||
fzf() { | |||
command fzf -e --reverse --cycle +s --inline-info "$@" | |||
} | |||
filterAll() { | |||
mpc search -f '[[[%artist% / ][[(%date%) ]%album% / ][%track%] [%title%]]|%file%] \t%file%' filename '' | | |||
fzf -m --with-nth='..-2' --delimiter='\t' | | |||
cut -f2 | |||
} | |||
filterByArtist() { | |||
local artist | |||
artist=$(mpc list artist | sort -h | fzf) | |||
[[ -z "$artist" ]] && die | |||
filterByAlbum "$artist" | |||
} | |||
filterByAlbum() { | |||
local album artist | |||
[[ -z "$1" ]] && die | |||
artist="$1" | |||
album=$(mpc search -f '[(%date%)]\t%album%' artist "${artist}" | | |||
sort -u | | |||
fzf --prompt="$artist > " | | |||
cut -f2 ) | |||
if [[ -z "$album" ]]; then | |||
filterByArtist | |||
return 0 | |||
fi | |||
filterBySong "$artist" "$album" | |||
} | |||
filterBySong() { | |||
local album artist | |||
[[ -z "$1" || -z "$2" ]] && die | |||
artist="$1" | |||
album="$2" | |||
songs=$(mpc search -f '[[[%track% - ][%title%]]|%file%] \t%file%' artist "${artist}" album "${album}" | | |||
fzf --prompt="$artist - $album > " -m --with-nth='..-2' --delimiter='\t' | | |||
cut -f2) | |||
if [[ -z "$songs" ]]; then | |||
filterByAlbum "$artist" | |||
return 0 | |||
fi | |||
echo "$songs" | |||
} | |||
filterByPlayist() { | |||
mpc playlist -f '[%artist% / ][[(%date%) ]%album% / ][%title%|%file%] \t%file%' | | |||
fzf --prompt='playlist> ' -m --with-nth='..-2' --delimiter='\t' | | |||
cut -f2 | |||
} | |||
has -v fzf mpc || die | |||
isRunning mpd || die 'mpd not running' | |||
declare filter='filterAll' | |||
while true; do | |||
case "$1" in | |||
-a|--artist) filter='filterByArtist' ; shift ;; | |||
-p|--playlist) filter='filterByPlayist' ; shift ;; | |||
*) break | |||
esac | |||
done | |||
mapfile -t songs < <("$filter") | |||
(( ${#songs[@]} > 0 )) || die | |||
printf '%s\n' "${songs[@]}" | mpc -q add | |||
index=$(mpc playlist | wc -l) | |||
if (( ${#songs[@]} > 1 )); then | |||
index=$(( index - ${#songs[@]} + 1)) | |||
fi | |||
mpc play "$index" |
@@ -0,0 +1,87 @@ | |||
#!/usr/bsoupwhalein/env bash | |||
declare esc=$(printf '\033') | |||
declare c_reset="${esc}[0m" | |||
declare c_red="${esc}[31m" | |||
err() { | |||
echo -e "${c_red}$1${c_reset}" >&2 | |||
} | |||
die() { | |||
exit 1 | |||
} | |||
has() { | |||
local verbose=false | |||
if [[ $1 == '-v' ]]; then | |||
verbose=true | |||
shift | |||
fi | |||
for c in "$@"; do c="${c%% *}" | |||
if ! command -v "$c" &> /dev/null; then | |||
[[ "$verbose" == true ]] && err "$c not found" | |||
return 1 | |||
fi | |||
done | |||
} | |||
has -v fzf || die | |||
fzf() { | |||
command fzf --cycle "$@" | |||
} | |||
pick_files() { | |||
local files fzpick | |||
mapfile -t files < <(find . -maxdepth 1 2> /dev/null | sort | sed '1d; s|^\./||') | |||
fzpick=$( for f in "${files[@]}"; do | |||
if [[ -d "$f" ]]; then | |||
printf '%s/\n' "$f" | |||
elif [[ -L "$f" ]]; then | |||
printf '%s@\n' "$f" | |||
else | |||
printf '%s\n' "$f" | |||
fi | |||
done | fzf --multi --header='move these files' ) || return 1 | |||
for f in "${fzpick[@]}"; do | |||
realpath -s "$f" | |||
done | |||
} | |||
pick_destination() { | |||
local cwd browsedir browseinfo query dirs | |||
cwd=$(pwd) | |||
while [[ "$browsedir" != "$cwd" ]]; do | |||
dirs=$( (echo '..'; find -maxdepth 1 -type d 2> /dev/null ) | | |||
sed 's|./||' | | |||
sort) | |||
mapfile -t browseinfo < <( | |||
fzf --print-query \ | |||
--history="${HOME}/.cache/fzmv_history" \ | |||
--header="${errors:-move files here}" <<< "$dirs") | |||
query=${browseinfo[0]} | |||
browsedir=${browseinfo[1]} | |||
[[ -d "$query" ]] && browsedir="$query" | |||
[[ ! -d "$browsedir" ]] && return 1 | |||
if [[ "$browsedir" == '.' && $(realpath "$browsedir") != "$cwd" ]]; then | |||
realpath "$browsedir" | |||
break | |||
else | |||
cd "$browsedir" || die | |||
continue | |||
fi | |||
done | |||
} | |||
while (( $# > 0 )); do | |||
case $1 in | |||
-t|--test) dryrun=true ;; | |||
esac | |||
shift | |||
done | |||
mapfile -t files < <(pick_files) | |||
(( ${#files[@]} > 0 )) || exit 1 | |||
destination=$(pick_destination) || exit 1 | |||
${dryrun:+echo} mv -t "$destination" "${files[@]}" |
@@ -0,0 +1,78 @@ | |||
#!/usr/bin/env bash | |||
declare OPTIND | |||
declare opts=() | |||
declare id | |||
set -e | |||
usage() { | |||
echo TODO | |||
exit | |||
} | |||
hasAccount() { | |||
grep -qF 'ix.io' ~/.netrc | |||
} | |||
createAccount() { | |||
echo "It seems you don't have a ~/.netrc with ix.io in it. Let's make one!" | |||
read -r -p 'enter a username: ' username | |||
read -rs -p 'enter a password (this will be hashed with sha256sum): ' password | |||
password=$(sha256sum <<< "$password" | awk '{print $1}') | |||
echo '' | |||
tee -a ~/.netrc <<< "machine ix.io login $username password $password" | |||
chmod 600 ~/.netrc | |||
echo "$username" | |||
} | |||
getUserName() { | |||
awk '"ix.io"==$2{print $4}' ~/.netrc | |||
} | |||
listPastes() { | |||
# TODO: needs better output. how should I extract dates, etc? | |||
curl -s "http://ix.io/user/$1" | | |||
grep -Po '\<a href="\/[a-zA-Z0-9]+"\>' | | |||
sed -r 's|<a href="/(\w+)">|http://ix.io/\1|' | |||
} | |||
hasAccount || createAccount | |||
[[ -e ~/.netrc ]] && opts+=( '-n' ) | |||
while getopts ":hld:i:n:" x; do | |||
case "$x" in | |||
d) curl "${opts[@]}" -X DELETE "ix.io/$OPTARG"; exit ;; | |||
l) | |||
if [[ -z "$OPTARG" && -e ~/.netrc ]]; then | |||
listPastes "$(getUserName)" | nl -p -s' ' -w1 | fzf \ | |||
--inline-info --cycle \ | |||
--header='Ctrl-E = edit; Ctrl-V = view; Ctrl-D = delete' \ | |||
--bind 'j:down' \ | |||
--bind 'k:up' \ | |||
--bind 'q:abort' \ | |||
--bind 'Ctrl-V:execute:p={}; less < <(curl -s "${p##* }")' \ | |||
--bind 'Ctrl-E:execute:p={}; curl -s "${p##* }" | vipe | ix -i "${p##*/}"' \ | |||
--bind 'Ctrl-D:execute:p={}; ix -d "${p##*/}"' | |||
else | |||
die 'no netrc found' | |||
fi | |||
exit ;; | |||
i) opts+=( -X PUT ); id="$OPTARG" ;; | |||
n) opts+=( -F "read:1=$OPTARG" ) ;; | |||
esac | |||
done | |||
shift $(( OPTIND - 1)) | |||
if [[ -t 0 ]]; then | |||
if [[ -n "$1" ]]; then | |||
filename="$1" | |||
shift | |||
curl "${opts[@]}" -F f:1=@"$filename" "$@" "ix.io/$id" | |||
exit | |||
fi | |||
echo "^C to cancel, ^D to send." | |||
fi | |||
curl "${opts[@]}" -F f:1='<-' "$@" "ix.io/$id" |
@@ -0,0 +1,86 @@ | |||
#!/usr/bin/env bash | |||
declare esc=$(printf '\033') | |||
declare c_reset="${esc}[0m" | |||
declare c_red="${esc}[31m" | |||
declare c_green="${esc}[32m" | |||
declare c_blue="${esc}[34m" | |||
err() { | |||
echo -e "${c_red}$1${c_reset}" >&2 | |||
} | |||
die() { | |||
exit 1 | |||
} | |||
has() { | |||
local verbose=false | |||
if [[ $1 == '-v' ]]; then | |||
verbose=true | |||
shift | |||
fi | |||
for c in "$@"; do c="${c%% *}" | |||
if ! command -v "$c" &> /dev/null; then | |||
[[ "$verbose" == true ]] && err "$c not found" | |||
return 1 | |||
fi | |||
done | |||
} | |||
select-from() { | |||
local cmd='command -v' | |||
for a in "$@"; do | |||
case "$a" in | |||
-c) | |||
cmd="$2" | |||
shift 2 | |||
;; | |||
esac | |||
done | |||
for c in "$@"; do | |||
if $cmd "${c%% *}" &> /dev/null; then | |||
echo "$c" | |||
return 0 | |||
fi | |||
done | |||
return 1 | |||
} | |||
has -v fzf || die | |||
declare search | |||
declare out | |||
declare -a pkgs | |||
fzf() { | |||
command fzf -e +s --multi --cycle --ansi --no-hscroll --inline-info --reverse "$@" | |||
} | |||
if [[ -f /etc/debian_version ]]; then | |||
out=$(fzf --query="$*" < <( \ | |||
apt-cache search '' | | |||
sort | | |||
sed -u -r "s|^([^ ]+)|${c_green}\1${c_reset}|" ) ) | |||
mapfile -t pkgs < <( awk '{print $1}' <<< "$out" ) | |||
(( ${#pkgs} > 0 )) || exit | |||
sudo $(select-from 'apt' 'apt-get') install "${pkgs[@]}" | |||
elif [[ -f /etc/arch-release ]]; then | |||
search='pacman' | |||
(( $# > 0)) && search=$(select-from 'pacaur' 'yaourt' 'packer' 'apacman' 'pacman') | |||
out=$(fzf < <( $search -Ss "$@" | | |||
awk '{ | |||
getline descr; | |||
sub(/ */,"", descr); | |||
repo = "[" blue gensub(/\/.*/, "", 1) reset "]"; | |||
name = green gensub(/.*\//, "", 1, $1) reset; | |||
info = gensub(/[^ ]* /, "", 1); | |||
print repo, name, info, descr; | |||
}' blue="$c_blue" green="$c_green" reset="$c_reset" | |||
) | |||
) | |||
mapfile -t pkgs < <(awk '{print $2}' <<< "out") | |||
(( ${#pkgs} > 0 )) || exit | |||
echo "installing ${pkgs[*]}" | |||
${search/pacman/sudo pacman} -S "${pkgs[@]}" | |||
fi |
@@ -0,0 +1,34 @@ | |||
#!/usr/bin/env bash | |||
declare -r fifo='/tmp/sshget.fifo' | |||
declare -A domains=() | |||
declare -A paths=() | |||
declare -a files=() | |||
declare -A requests=() | |||
cleanup() { | |||
[[ -e "$fifo" ]] && rm "$fifo" | |||
} | |||
trap cleanup SIGHUP SIGINT SIGTERM | |||
mkfifo "$fifo" | |||
for a in "$@"; do | |||
host="${a%%:*}" | |||
path="${a##*:}" | |||
domains+=( ["$a"]="$host" ) | |||
paths+=( ["$a"]="$path" ) | |||
shift | |||
done | |||
for s in "${!domains[@]}"; do | |||
ssh "${domains[$s]}" "find ${paths[$s]}" | sed -r "s|^(.*)|${domains[$s]}:\"\1\"|" >> "$fifo" & | |||
done | |||
mapfile -t files < <( fzf -e --inline-info --multi --cycle --query="$*" < "$fifo" ) | |||
if (( ${#files[@]} )); then | |||
rsync -auvzP -e ssh "${files[@]}" . | |||
fi | |||
cleanup |
@@ -0,0 +1,64 @@ | |||
#!/usr/bin/env bash | |||
ask() { | |||
local opts=() | |||
if [[ "$1" == '-1' ]]; then | |||
opts+=( '-n1' ) | |||
one=1 | |||
shift | |||
fi | |||
if [[ "$1" == '-s' ]]; then | |||
opts+=( '-s' ) | |||
shift | |||
fi | |||
read -e -r "${opts[@]}" -p "$* " ans | |||
if [[ $one == 1 ]]; then | |||
echo | |||
[[ ${ans,} == y ]] | |||
else | |||
echo "$ans" | |||
fi | |||
} | |||
has() { | |||
local verbose=false | |||
if [[ $1 == '-v' ]]; then | |||
verbose=true | |||
shift | |||
fi | |||
for c in "$@"; do c="${c%% *}" | |||
if ! command -v "$c" &> /dev/null; then | |||
[[ "$verbose" == true ]] && err "$c not found" | |||
return 1 | |||
fi | |||
done | |||
} | |||
err() { | |||
echo -e "\e[31m$1\e[0m" >&2 | |||
} | |||
info() { | |||
echo -e "\e[34m$1\e[0m" >&2 | |||
} | |||
die() { | |||
[[ -n "$1" ]] && err "$1" | |||
exit 1 | |||
} | |||
has -v nmcli fzf || die | |||
network=$(nmcli d wifi | fzf --header-lines=1 | sed -r 's/^\s*\*?\s*//; s/\s*Infra.*//') | |||
[[ -z "$network" ]] && exit | |||
password=$(ask -s 'Password:') | |||
echo | |||
connect=$(nmcli device wifi connect "$network" password "$password") | |||
if [[ "$connect" == *'successfully activated'* ]]; then | |||
info "successfully connected to $network" | |||
else | |||
err "failed to connect to $network" | |||
err "$connect" | |||
fi |