Initial commit
This commit is contained in:
commit
cefd40b6dc
6
README.md
Normal file
6
README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# crater's script collection
|
||||
|
||||
Some scripts that I wrote over the years and wanted to store with versioning
|
||||
somewhere. Maybe some of them are useful for others.
|
||||
|
||||
Documentation may or may not follow, some scripts include a `--help` output.
|
3
bin/alert
Executable file
3
bin/alert
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/zsh
|
||||
time=$1; shift
|
||||
echo "DISPLAY=:0.0 sm \"$@\"" | at $time
|
14
bin/autoless
Executable file
14
bin/autoless
Executable file
|
@ -0,0 +1,14 @@
|
|||
#!/bin/zsh
|
||||
if [[ -n "$@" ]]; then
|
||||
out=$(<"$@")
|
||||
else
|
||||
out=$(cat)
|
||||
fi
|
||||
((lim=$LINES-1))
|
||||
numlines=$(echo $out | wc -l)
|
||||
if (( $numlines > $lim ))
|
||||
then
|
||||
echo $out | less -R
|
||||
else
|
||||
echo $out
|
||||
fi
|
17
bin/dbus-find
Executable file
17
bin/dbus-find
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/bin/zsh
|
||||
|
||||
if [[ $1 == "-u" ]]; then
|
||||
USER=$2
|
||||
SUDO="sudo -u $USER"
|
||||
shift 2
|
||||
else
|
||||
SUDO=
|
||||
fi
|
||||
|
||||
export "$({for i in $(pgrep -u $USER dbus-daemon); grep -z DBUS_SESSION_BUS_ADDRESS /proc/$i/environ} | head -n 1)"
|
||||
if [[ -z $DBUS_SESSION_BUS_ADDRESS ]]; then
|
||||
echo "No DBUS found"
|
||||
exit 1
|
||||
else
|
||||
exec $=SUDO "$@"
|
||||
fi
|
66
bin/dmjavadoc
Executable file
66
bin/dmjavadoc
Executable file
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'dmenu'
|
||||
|
||||
JAVA_DOC_LOCATION = "/usr/share/doc/api"
|
||||
JAVAFX_DOC_LOCATION = "/usr/share/doc/javafx-sdk-docs-*"
|
||||
|
||||
USER_DOC_LOCATION = (ENV['XDG_DATA_HOME'] || ENV['HOME'] + '/.local/share') + '/javadoc/*'
|
||||
|
||||
class DocIndex
|
||||
attr_reader :items
|
||||
|
||||
def initialize(path)
|
||||
@items = []
|
||||
find_entries(path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def gen_candidates(dir)
|
||||
Dir.entries(dir).reject {|e| e == '.' ||
|
||||
e == '..' ||
|
||||
e == 'class-use' ||
|
||||
e == 'src-html' ||
|
||||
(e =~ /^[a-z].*\..*/ && e != 'package-summary.html')}
|
||||
end
|
||||
|
||||
def find_entries(dir, path = [])
|
||||
candidates = gen_candidates(dir)
|
||||
candidates.each do |entry|
|
||||
if entry == "package-summary.html"
|
||||
@items << Dmenu::Item.new(path.join(?.), dir + ?/ + entry)
|
||||
elsif entry.end_with? ".html"
|
||||
@items << Dmenu::Item.new(
|
||||
path.join(?.) + ?. + File.basename(entry, '.html'),
|
||||
dir + ?/ + entry
|
||||
)
|
||||
elsif File.directory?(dir + ?/ + entry)
|
||||
find_entries(dir + ?/ + entry, path + [entry])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
user_libs = Dir.glob(USER_DOC_LOCATION)
|
||||
java_folder = Dir.glob(JAVA_DOC_LOCATION).last
|
||||
jfx_folder = Dir.glob(JAVAFX_DOC_LOCATION).last + "/html"
|
||||
|
||||
|
||||
libmenu = Dmenu.new
|
||||
libmenu.items = [
|
||||
Dmenu::Item.new("Java Standard Library (std)", java_folder),
|
||||
Dmenu::Item.new("javafx", jfx_folder)
|
||||
] + user_libs.map{|f| Dmenu::Item.new(File.basename(f), f)}
|
||||
|
||||
libmenu.case_insensitive = true
|
||||
libmenu.prompt = "Library:"
|
||||
libmenu.lines = 20
|
||||
|
||||
menu = Dmenu.new
|
||||
menu.items = DocIndex.new(libmenu.run.value).items
|
||||
menu.case_insensitive = true
|
||||
menu.prompt = "Javadoc:"
|
||||
menu.lines = 20
|
||||
system("xdg-open #{menu.run.value}")
|
91
bin/dmpc
Executable file
91
bin/dmpc
Executable file
|
@ -0,0 +1,91 @@
|
|||
#!/bin/zsh
|
||||
|
||||
dmenu_opts=("" "-i")
|
||||
replace=("-r")
|
||||
|
||||
zparseopts -E -D -K -help=help \
|
||||
a=artist -artist=artist \
|
||||
b=album -album=album \
|
||||
t=title -title=title \
|
||||
j=jump -jump=jump \
|
||||
r=replace -replace=replace R=replace -no-replace=replace \
|
||||
o:=dmenu_opts -dmenu-opts:=dmenu_opts \
|
||||
h:=host -host:=host \
|
||||
p:=port -port:=port
|
||||
|
||||
if [ -n "$help" ]; then
|
||||
<<-HELP
|
||||
dmpc: manage mpd playlist with dmenu
|
||||
|
||||
Usage: dmpc {-a|-b|-t|-j} [OPTION]
|
||||
|
||||
Options:
|
||||
-a, --artist search for artist
|
||||
-b, --album search for album
|
||||
-t, --title search for title
|
||||
-j, --jump jump to song in current playlist (requires rofi)
|
||||
(if given in addition to searches, jumps after changes)
|
||||
|
||||
-r, --replace replace current playlist
|
||||
-R, --no-replace do not replace current playlist
|
||||
-o, --dmenu-opts additional options for dmenu
|
||||
|
||||
-h, --host MPD host server
|
||||
-p, --port server port
|
||||
|
||||
dmpc lets you select all tracks from an artist or album or a single track.
|
||||
HELP
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "$artist" && -z "$album" && -z "$title" ]]; then
|
||||
<<-ERR
|
||||
At least one of -a, -b, -t or -j must be given. See --help for more information.
|
||||
ERR
|
||||
exit 1
|
||||
fi
|
||||
|
||||
typeset -a queries
|
||||
|
||||
mpc_() {
|
||||
mpc $=host $=port "$@"
|
||||
}
|
||||
|
||||
dmenu_search() {
|
||||
local type=$1
|
||||
mpc_ list $type "${queries[@]}" | dmenu ${=dmenu_opts[2]}
|
||||
}
|
||||
|
||||
add_query() {
|
||||
local type=$1
|
||||
local query=$2
|
||||
|
||||
queries+=$type
|
||||
queries+=$query
|
||||
}
|
||||
|
||||
if [[ -n $artist ]]; then
|
||||
add_query albumartist "$(dmenu_search artist)"
|
||||
fi
|
||||
|
||||
if [[ -n $album ]]; then
|
||||
add_query album "$(dmenu_search album)"
|
||||
fi
|
||||
|
||||
if [[ -n $title ]]; then
|
||||
add_query title "$(dmenu_search title)"
|
||||
fi
|
||||
|
||||
if [[ ${replace[1]} == "-r" || "${replace[1]}" == "--replace" ]]; then
|
||||
mpc_ clear
|
||||
fi
|
||||
|
||||
|
||||
if [[ ${#queries} -gt 0 ]]; then
|
||||
mpc_ search "${queries[@]}" | mpc_ add
|
||||
mpc_ play
|
||||
fi
|
||||
|
||||
if [[ -n $jump ]]; then
|
||||
mpc play "$(mpc playlist | rofi -dmenu -format d)"
|
||||
fi
|
52
bin/dmscaladoc
Executable file
52
bin/dmscaladoc
Executable file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'dmenu'
|
||||
|
||||
JAVA_DOC_LOCATION = "/home/crater2150/manuals/scala-*"
|
||||
|
||||
USER_DOC_LOCATION = (ENV['XDG_DATA_HOME'] || ENV['HOME'] + '/.local') + '/scaladoc/*'
|
||||
|
||||
class DocIndex
|
||||
attr_reader :items
|
||||
|
||||
def initialize(path)
|
||||
@items = []
|
||||
find_entries(path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def gen_candidates(dir)
|
||||
Dir.entries(dir).reject {|e| e == '.' ||
|
||||
e == '..' ||
|
||||
e == 'class-use' ||
|
||||
e == 'src-html' ||
|
||||
(e =~ /^[a-z].*\..*/ && e != 'package-summary.html')}
|
||||
end
|
||||
|
||||
def find_entries(dir, path = [])
|
||||
candidates = gen_candidates(dir)
|
||||
candidates.each do |entry|
|
||||
if entry == "package-summary.html"
|
||||
@items << Dmenu::Item.new(path.join(?.), dir + ?/ + entry)
|
||||
elsif entry.end_with? ".html"
|
||||
@items << Dmenu::Item.new(
|
||||
path.join(?.) + ?. + File.basename(entry, '.html'),
|
||||
dir + ?/ + entry
|
||||
)
|
||||
elsif File.directory?(dir + ?/ + entry)
|
||||
find_entries(dir + ?/ + entry, path + [entry])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
scala_folder = Dir.glob(JAVA_DOC_LOCATION).last + "/api/scala-library/"
|
||||
|
||||
menu = Dmenu.new
|
||||
menu.items = DocIndex.new(scala_folder).items
|
||||
menu.case_insensitive = true
|
||||
menu.prompt = "Javadoc:"
|
||||
menu.lines = 20
|
||||
system("xdg-open #{menu.run.value}")
|
30
bin/dmscrot
Executable file
30
bin/dmscrot
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'dmenu'
|
||||
|
||||
def run_menu(items, prompt)
|
||||
menu = Dmenu.new
|
||||
menu.case_insensitive = true
|
||||
menu.lines = items.length
|
||||
menu.items = items
|
||||
menu.prompt = prompt
|
||||
menu.run.value
|
||||
end
|
||||
modes = [
|
||||
Dmenu::Item.new('multidisp', '-m'),
|
||||
Dmenu::Item.new('select', '-s'),
|
||||
Dmenu::Item.new('focused', '-u -d 1'),
|
||||
Dmenu::Item.new('normal', '')
|
||||
]
|
||||
|
||||
actions = [
|
||||
Dmenu::Item.new('move to screenshots', 'mv $f ~/media/screenshots'),
|
||||
Dmenu::Item.new('view image', 'xdg-open $f'),
|
||||
Dmenu::Item.new('make draggable', 'dragon -x $f'),
|
||||
Dmenu::Item.new('nothing', 'true')
|
||||
]
|
||||
|
||||
mode = run_menu(modes, "Screenshot type")
|
||||
action = run_menu(actions, "and then")
|
||||
|
||||
system('scrot', mode, '-e', action)
|
187
bin/dmsearch
Executable file
187
bin/dmsearch
Executable file
|
@ -0,0 +1,187 @@
|
|||
#!/bin/zsh
|
||||
emulate -L zsh
|
||||
|
||||
SYSTEM_CONFIG_PATH='/etc/dmsearch'
|
||||
CONFIG_PATH="$HOME/.config/dmsearch"
|
||||
CACHE_PATH="$HOME/.cache/dmsearch"
|
||||
mkdir -p "${CACHE_PATH}"
|
||||
|
||||
# required software
|
||||
|
||||
depend() {
|
||||
local script="$1"; shift;
|
||||
local missing
|
||||
local i
|
||||
|
||||
for i in "$@"; do
|
||||
type "$i" &>/dev/null || {
|
||||
echo >&2 "$i is required for ${script}. Please install it"
|
||||
missing=1
|
||||
}
|
||||
done
|
||||
[ -n "$missing" ] && exit 1
|
||||
}
|
||||
|
||||
depend dmsearch \
|
||||
rofi \
|
||||
mv \
|
||||
tail \
|
||||
cut
|
||||
|
||||
|
||||
################################################################################
|
||||
# helpers
|
||||
################################################################################
|
||||
|
||||
urlencode() {
|
||||
setopt extendedglob
|
||||
input=$(</dev/stdin)
|
||||
# by jkramer, source: http://stackoverflow.com/a/187853/928769
|
||||
echo "${${(j: :)input}//(#b)(?)/%$[[##16]##${match[1]}]}"
|
||||
}
|
||||
|
||||
# define a module option
|
||||
# Parameters:
|
||||
# 1: module id
|
||||
# 2: option name
|
||||
# 3: default value
|
||||
# 4: description
|
||||
optdef() {
|
||||
typeset -A -g opts_${1}
|
||||
local optname="opt_${1}_${2}"
|
||||
eval "if [ -z \"\$${optname}\" ]; then
|
||||
${optname}=\"$3\";
|
||||
fi"
|
||||
eval "opts_${1}[$2]=\"${4:-"undocumented"}\""
|
||||
}
|
||||
|
||||
# get history for a search
|
||||
# parameters:
|
||||
# 1: search, for which to get history
|
||||
dmhist() {
|
||||
local search=$1
|
||||
local dmhistfile="$CACHE_PATH/history_$search"
|
||||
if [[ -e "$dmhistfile" ]] then
|
||||
<"$dmhistfile"
|
||||
else
|
||||
</dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# add history for a search.
|
||||
#
|
||||
# Older entries can be truncated by specifying the maximum history length.
|
||||
#
|
||||
# parameters:
|
||||
# 1: search, for which to add history
|
||||
# 2: the new entry for the history file
|
||||
# 3: (optional) maximum number of history items to store
|
||||
dmhistadd() {
|
||||
local search=$1
|
||||
local line=$2
|
||||
[[ -z "$2" ]] && return
|
||||
local truncate=${3:-"+0"}
|
||||
local dmhistfile="$CACHE_PATH/history_$search"
|
||||
echo "$line" >> "$dmhistfile"
|
||||
mv "$dmhistfile" "${dmhistfile}.tmp"
|
||||
tail -n ${truncate} "${dmhistfile}.tmp" > "${dmhistfile}"
|
||||
rm "${dmhistfile}.tmp"
|
||||
}
|
||||
|
||||
# freetext rofi with a default value.
|
||||
#
|
||||
# When called, opens a rofi with only one choice. Pressing enter without any
|
||||
dmdefault() {
|
||||
value=$(echo "$2" | rofi -dmenu -l 1 -p "$1" -sort-method fzf)
|
||||
if [[ "$value" == "$2" ]]; then
|
||||
$=3
|
||||
else
|
||||
echo "$value"
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# plugin loading
|
||||
################################################################################
|
||||
|
||||
# system plugins are loaded first, so they can be overridden by user plugins
|
||||
for i in "(${SYSTEM_CONFIG_PATH}/searchers/"*(N) \
|
||||
"${CONFIG_PATH}/searchers/"*(N); do
|
||||
. "$i"
|
||||
done
|
||||
|
||||
################################################################################
|
||||
# Configurable Options
|
||||
################################################################################
|
||||
|
||||
# querystring
|
||||
|
||||
SERCHILO="https://www.findfind.it/u/crater2150?query="
|
||||
|
||||
# some default values. all of them can be overridden by rc.zsh
|
||||
typeset -A searches
|
||||
searches=( g Google w Wikipedia )
|
||||
webbrowser_cmd="xdg-open"
|
||||
|
||||
[[ -e "${SYSTEM_CONFIG_PATH}/rc.zsh" ]] && . "${SYSTEM_CONFIG_PATH}/rc.zsh"
|
||||
[[ -e "${CONFIG_PATH}/rc.zsh" ]] && . "${CONFIG_PATH}/rc.zsh"
|
||||
|
||||
################################################################################
|
||||
# main script
|
||||
################################################################################
|
||||
|
||||
zparseopts -D -E -help=help h=help
|
||||
|
||||
if [ -n "$help" ]; then
|
||||
<<-HELP
|
||||
dmsearch [-h]
|
||||
Opens dmenu and lets you run web searches
|
||||
|
||||
configured searches:
|
||||
HELP
|
||||
|
||||
for k in ${(k)searches}; do
|
||||
echo " ${k}:\t${(Q)searches[$k]}";
|
||||
done
|
||||
|
||||
<<-HELP
|
||||
|
||||
defined module options:
|
||||
HELP
|
||||
for k in ${(k)searches}; do
|
||||
eval "if [ \"\${#opts_$k}\" -gt 0 ]; then
|
||||
echo \" Module ${(Q)searches[$k]}:\";
|
||||
for o in \${(k)opts_${k}}; do
|
||||
echo \" opt_${k}_\${o}: \${opts_${k}[\$o]}\";
|
||||
done
|
||||
fi"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# start dmenu
|
||||
coproc dmenu -i -l 20 -p 'serchilo widget:'
|
||||
|
||||
# generate menu elements
|
||||
for i in ${(k)searches}; do print -p "${i} - ${searches[$i]}"; done
|
||||
|
||||
# close coproc stdin
|
||||
exec 5>&p 6<&p; coproc exit; exec 5>&-
|
||||
|
||||
# get dmenu result
|
||||
search=$(read -eu 6 | cut -d" " -f1)
|
||||
|
||||
[[ -z "$search" ]] && exit 1 #user aborted
|
||||
|
||||
|
||||
if which "s_${search}" &>/dev/null; then
|
||||
qs=$(s_${search})
|
||||
else
|
||||
qs="${SERCHILO}${search}"
|
||||
result=$(dmhist "$search" | dmenu -i -l 20 -p "params to $search")
|
||||
dmhistadd "$search" "$result"
|
||||
qs+="+$(echo $result| urlencode)"
|
||||
fi
|
||||
|
||||
echo ${webbrowser_cmd} $qs
|
||||
${webbrowser_cmd} $qs
|
17
bin/dmtexdoc
Executable file
17
bin/dmtexdoc
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/bin/zsh
|
||||
zparseopts -D -E -help=help h=help -update=update u=update
|
||||
|
||||
CACHE_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/dtexdoc.list"
|
||||
SOURCES_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/dmtexdoc/sources"
|
||||
|
||||
if [[ -n "$help" ]]; then
|
||||
echo "Usage: $0 [-u|--update]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$update" || ! -e "$CACHE_FILE" ]]; then
|
||||
find -L ${$(which texdoc):h:h:h}/texmf-dist/doc/ "${(@f)$(<$SOURCES_FILE)}" \
|
||||
-iname '*.pdf' -printf "%f\n" \
|
||||
| sed -e 's/\..*//' | sort | uniq > $CACHE_FILE
|
||||
fi
|
||||
texdoc $(dmenu < $CACHE_FILE)
|
5
bin/dmumount
Executable file
5
bin/dmumount
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/zsh
|
||||
device=$(udiskie-info -a -o '{mount_path}' | grep -ve '^$' | dmenu -l 20)
|
||||
if [[ -n "$device" ]]; then
|
||||
udiskie-umount $device
|
||||
fi
|
39
bin/dmxrandr
Executable file
39
bin/dmxrandr
Executable file
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'xrandr'
|
||||
require 'dmenu'
|
||||
|
||||
menu = Dmenu.new
|
||||
menu.case_insensitive = true
|
||||
menu.lines = 20
|
||||
|
||||
outputs = Xrandr::Parser.new.parse[1].group_by(&:connected)
|
||||
|
||||
menu.items = (outputs[true] + outputs[false]).map{
|
||||
|o| Dmenu::Item.new(o.name + (o.connected ? ' (connected)' : ''), o)
|
||||
}
|
||||
menu.prompt = "output:"
|
||||
output = menu.run.value
|
||||
|
||||
menu.items = output.modes.map{
|
||||
|mode|Dmenu::Item.new(mode.resolution, {mode: mode.resolution})
|
||||
}
|
||||
menu.items << Dmenu::Item.new("off", {off: true})
|
||||
|
||||
menu.prompt = "Current resolution: #{output.resolution}"
|
||||
mode = menu.run.value
|
||||
|
||||
unless mode[:off]
|
||||
menu.items = [:"left-of", :"right-of", :"above", :"below"].flat_map{|dir|
|
||||
outputs[true].reject{|o| o == output}.map{|out| [dir,out]}
|
||||
}.map{|setting|
|
||||
Dmenu::Item.new(setting[0].to_s.gsub('-',' ') + " " + setting[1].name,
|
||||
{setting[0] => setting[1].name})
|
||||
}
|
||||
menu.items << Dmenu::Item.new("don't change", {})
|
||||
menu.prompt = "Select position:"
|
||||
mode.merge! menu.run.value
|
||||
end
|
||||
control = Xrandr::Control.new
|
||||
control.configure(output, mode)
|
||||
control.apply!
|
5
bin/fixenc
Executable file
5
bin/fixenc
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/zsh
|
||||
for i in "$@"; do
|
||||
dos2unix $i &>/dev/null
|
||||
iconv -fLATIN1 -tUTF8 $i | sponge $i
|
||||
done
|
6
bin/idea
Executable file
6
bin/idea
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/zsh
|
||||
unset JAVA_HOME
|
||||
source /etc/profile.d/11_oracle-jdk.sh
|
||||
export IBUS_ENABLE_SYNC_MODE=1
|
||||
export XMODIFIERS=""
|
||||
exec $(ls ${XDG_DATA_HOME:-~/.local/share}/idea-IU-*/bin/idea.sh | sort | tail -n 1)
|
20
bin/ipy
Executable file
20
bin/ipy
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/zsh
|
||||
|
||||
if [[ -n $VIRTUAL_ENV ]]; then
|
||||
pip install ipython &>/dev/null
|
||||
else
|
||||
cd ~/toy-projects/playground_venv/
|
||||
. bin/activate
|
||||
fi
|
||||
|
||||
if [[ -e $VIRTUAL_ENV/ipython_profile ]]; then
|
||||
ipy_profile="--profile=$(<$VIRTUAL_ENV/ipython_profile)"
|
||||
fi
|
||||
|
||||
if [[ "$1" == "pip" ]]; then
|
||||
exec "$@"
|
||||
elif [[ $1 == "-s" ]]; then
|
||||
exec $SHELL
|
||||
else
|
||||
exec ipython $ipy_profile "$@"
|
||||
fi
|
11
bin/mdcat
Executable file
11
bin/mdcat
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/zsh
|
||||
|
||||
MDCAT=/usr/bin/mdcat
|
||||
encoding=$(file -i "$1" | sed "s/.*charset=\(.*\)$/\1/")
|
||||
if ! iconv -f $encoding <<<"" &> /dev/null; then
|
||||
cat "$1"
|
||||
elif [[ $encoding != 'utf-8' ]]; then
|
||||
iconv -f $encoding -t 'utf-8' < "$1" | $MDCAT /dev/stdin
|
||||
else
|
||||
$MDCAT $1
|
||||
fi
|
13
bin/mkscript
Executable file
13
bin/mkscript
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/zsh
|
||||
BINDIR=$HOME/.local/bin
|
||||
if [[ -e $BINDIR/$1 ]]; then
|
||||
echo Script $1 exists, opening for edit
|
||||
$EDITOR $BINDIR/$1
|
||||
else
|
||||
touch $BINDIR/$1
|
||||
chmod a+x $BINDIR/$1
|
||||
echo "#!$SHELL" >> $BINDIR/$1
|
||||
$EDITOR $BINDIR/$1
|
||||
exit 0
|
||||
fi
|
||||
|
75
bin/newmails
Executable file
75
bin/newmails
Executable file
|
@ -0,0 +1,75 @@
|
|||
#!/bin/zsh
|
||||
|
||||
DEFAULT=raw
|
||||
ICON=/usr/share/icons/Adwaita/48x48/actions/mail-message-new.png
|
||||
|
||||
opt() {
|
||||
if [ -n "$1" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
contains() {
|
||||
arr=$1
|
||||
value=$2
|
||||
[[ ${${(P)arr}[(ie)$value]} -lt ${#${(P)arr}} ]]
|
||||
}
|
||||
|
||||
zparseopts -D -E h=help -help=help \
|
||||
r=raw -raw=raw \
|
||||
n=number -number=number \
|
||||
p=pretty -pretty=pretty
|
||||
|
||||
if [ -n "$help" ]; then
|
||||
cat <<HELP
|
||||
Usage: newmails [OPTIONS] [MAILDIR]
|
||||
|
||||
Options:
|
||||
-h --help Show this help
|
||||
-r --raw Show full paths to new mail files (default)
|
||||
-n --number Only show number of new mails
|
||||
-p --pretty Show formatted output of new mails (TODO)
|
||||
|
||||
HELP
|
||||
fi
|
||||
|
||||
|
||||
local md=${MAILDIR:-${MAIL:-$HOME/Mail}}
|
||||
local cache=${XDG_CACHE_HOME:-$HOME/.cache}/seen-mails
|
||||
|
||||
newmails=$(find $md/ -type f -a \
|
||||
\( -regex ".*:2,[PRTDF]*" \) -exec realpath \{\} \;)
|
||||
|
||||
decode(){
|
||||
perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | \
|
||||
sed -e 's/&/\&/' -e 's/</\</' -e 's/>/\>/'
|
||||
}
|
||||
|
||||
from() { formail -zcb -xFrom | tail -n 1 | decode }
|
||||
subject() { formail -zcb -xSubject | decode }
|
||||
|
||||
|
||||
if opt $number; then
|
||||
echo -n $newmails | wc -l
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if opt $pretty; then
|
||||
touch $cache
|
||||
seen=$(<$cache)
|
||||
truncate --size 0 $cache
|
||||
notify-send --icon=$ICON "$(
|
||||
echo -n $newmails | while read mail; do
|
||||
if ! contains seen $mail; then
|
||||
echo -n "<b>$(from < $mail):</b> $(subject < $mail)<br>"
|
||||
fi
|
||||
echo $mail >> $cache
|
||||
done
|
||||
)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#otherwise
|
||||
echo -n $newmails
|
7
bin/pdftosvg
Executable file
7
bin/pdftosvg
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/zsh
|
||||
for i in "$@"; do
|
||||
inkscape --without-gui --file=$i --export-plain-svg=/dev/stdout \
|
||||
| tr -d '\n' \
|
||||
| sed -e 's!</\?tspan[^>]*>!!g' \
|
||||
| xmllint --compress /dev/stdin --output ${i:r}.svg
|
||||
done
|
74
bin/pomdep-graph
Executable file
74
bin/pomdep-graph
Executable file
|
@ -0,0 +1,74 @@
|
|||
#!/bin/zsh
|
||||
|
||||
zparseopts -D -K -E h=help -help=help -renderer:=renderer r:=renderer \
|
||||
f:=filter -filter:=filter \
|
||||
o:=output -output:=output \
|
||||
l:=leaf_color -leaf-color:=leaf_color \
|
||||
G=graph_only -graph-only=graph_only
|
||||
|
||||
renderer=${renderer[2]:-dot}
|
||||
output=${output[2]:-deps.png}
|
||||
leaf_color=${leaf_color[2]:-green}
|
||||
|
||||
if [[ $output == "-" ]]; then output=/dev/stdout; fi
|
||||
if [[ -n $graph_only ]]; then
|
||||
renderer=cat
|
||||
output=/dev/stdout
|
||||
fi
|
||||
|
||||
if [[ -z "$2" ]]; then
|
||||
echo "Usage: $0 [options] POM_FILE..."
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " -f, --filter=TEXT only show dependencies with TEXT in their group id"
|
||||
echo " -r, --renderer=PROGRAM use PROGRAM for rendering. May contain additional parameters"
|
||||
echo " e.g. -r \"dot -Goverlap=false\""
|
||||
echo " default: dot -Tpng"
|
||||
echo " -o, --output=FILE output to FILE, defaults to deps.png"
|
||||
echo " -l, --leaf-color=COLOR color of leaf nodes (packages without dependencies)"
|
||||
echo " -G, --graph-only output unlayouted graph code, overrides -r and -o"
|
||||
echo " equivalent to \"-r cat -o /dev/stdout\""
|
||||
|
||||
fi
|
||||
|
||||
if [[ -n $filter ]]; then
|
||||
DEP_PATH="//dependencies//groupId[contains(text(),'${filter[2]}')]/following-sibling::artifactId/text()"
|
||||
else
|
||||
DEP_PATH="//dependencies//groupId/following-sibling::artifactId/text()"
|
||||
fi
|
||||
|
||||
PKG_PATH="/project/artifactId/text()"
|
||||
|
||||
xpath() {
|
||||
xmllint --shell <(sed -e "s/xmlns=/ignore=/" $2) <<<"cat $1" | grep -v '^\(/ >\| --\)'
|
||||
}
|
||||
|
||||
remove-disconnected() {
|
||||
gvpr -c "N[$.degree==0]{delete(NULL, $)}" "$@"
|
||||
}
|
||||
|
||||
color-leaf-deps() {
|
||||
gvpr -c "N[$.outdegree==0]{$.color ='$1'}"
|
||||
}
|
||||
|
||||
graph-from-poms() {
|
||||
echo 'digraph deps {'
|
||||
|
||||
for pom in "$@"; do
|
||||
pkg=$(xpath $PKG_PATH $pom)
|
||||
deps=($(xpath $DEP_PATH $pom | grep '^[a-zA-Z]'))
|
||||
|
||||
echo " \"$pkg\""
|
||||
for i in $deps; do
|
||||
echo " \"$pkg\" -> \"$i\""
|
||||
done
|
||||
done
|
||||
|
||||
echo '}'
|
||||
}
|
||||
|
||||
render() {
|
||||
$=renderer > $output
|
||||
}
|
||||
|
||||
graph-from-poms "$@" | remove-disconnected | color-leaf-deps $leaf_color | render
|
2
bin/qrshow
Executable file
2
bin/qrshow
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/zsh
|
||||
qrencode -s 40 "$*" -o - | feh -ZF -
|
40
bin/re
Executable file
40
bin/re
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/bin/zsh
|
||||
|
||||
SCRIPTDIR=$XDG_CONFIG_HOME/re/
|
||||
|
||||
zparseopts -D h=help -help=help d:=dir -dir:=dir n=dry_run -dry-run=dry_run e=edit -edit=edit
|
||||
if [[ -z "$@" || -n $help ]]; then
|
||||
<<-HELP
|
||||
re - execute regular jobs without cluttering your path
|
||||
|
||||
Usage: re [opts] <scriptname> [scriptopts]
|
||||
1. put script in $SCRIPTDIR
|
||||
2. run "re <scriptname>"
|
||||
3. ...
|
||||
4. PROFIT!
|
||||
|
||||
Options:
|
||||
-d, --dir=DIR change to given directory
|
||||
-n, --dry-run just display the script, that would be executed
|
||||
-e, --edit open the script in an editor
|
||||
HELP
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ -n $dir ]]; then
|
||||
cd $dir[2]
|
||||
fi
|
||||
|
||||
if [[ -e $SCRIPTDIR/$1 ]]; then
|
||||
if [[ -n $dry_run ]]; then
|
||||
$PAGER -F $SCRIPTDIR/$1
|
||||
elif [[ -n $edit ]]; then
|
||||
$EDITOR $SCRIPTDIR/$1
|
||||
else
|
||||
script=$1
|
||||
shift
|
||||
. $SCRIPTDIR/$script "$@"
|
||||
fi
|
||||
else
|
||||
echo "Script \"$1\" not found"
|
||||
fi
|
5
bin/tmux-url-fuzz
Executable file
5
bin/tmux-url-fuzz
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/zsh
|
||||
target=$(tmux capture-pane -e -p -J -S -20 \
|
||||
| grep -oP "(https?://|www\.)[^\"<>') \e]*" \
|
||||
| ifne fzf-tmux --tac)
|
||||
if [[ -n $target ]]; then xdg-open $target; fi
|
56
bin/unlock-parse
Executable file
56
bin/unlock-parse
Executable file
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'time'
|
||||
|
||||
def valid_log(lines)
|
||||
lines.reduce(["L",true]){|acc,line|
|
||||
if acc[1] && line[0] != acc[0] then
|
||||
[line[0], true]
|
||||
else
|
||||
[nil, false]
|
||||
end
|
||||
}[1]
|
||||
end
|
||||
|
||||
if ARGV[0] == '-h' then
|
||||
puts <<~HELP
|
||||
Usage: unlock-parse [-s] DAY...
|
||||
-s short output, total only
|
||||
HELP
|
||||
exit
|
||||
end
|
||||
|
||||
if ARGV[0] == '-s' then
|
||||
short=true
|
||||
days=ARGV[1..-1]
|
||||
else
|
||||
short=false
|
||||
days=ARGV
|
||||
end
|
||||
|
||||
days.empty? && days = [Date.today.iso8601]
|
||||
|
||||
days.each do |logday|
|
||||
|
||||
|
||||
path = if File.exists? logday then logday else ENV['XDG_DATA_HOME'] + '/log/locktime/' + logday end
|
||||
|
||||
log = File.readlines(path)
|
||||
|
||||
if ! valid_log(log) then puts "Invalid log file"; exit 1 end
|
||||
|
||||
if log.length % 2 != 0 then
|
||||
log << "L " + Time.now.iso8601
|
||||
end
|
||||
|
||||
times = log.each_slice(2).map{|e|
|
||||
Time.parse(e[1][2..-1]) - Time.parse(e[0][2..-1])
|
||||
}
|
||||
|
||||
if ! short then
|
||||
times.map{|t| Time.at(t).utc.strftime("%H:%M:%S")}.each{|s|puts s}
|
||||
puts "\nTotal:"
|
||||
end
|
||||
puts Time.at(times.sum).utc.strftime("%H:%M:%S")
|
||||
|
||||
end
|
22
bin/unlock-track
Executable file
22
bin/unlock-track
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/bin/zsh
|
||||
|
||||
lockstate() { pidof slimlock &>/dev/null }
|
||||
|
||||
lockstate; was_locked=$?
|
||||
|
||||
LOGDIR=${XDG_DATA_HOME:-$HOME/.local/share}/log/locktime
|
||||
mkdir -p $LOGDIR
|
||||
logfile=$LOGDIR/$(date --iso-8601)
|
||||
|
||||
while true; do
|
||||
if lockstate && [[ $was_locked -gt 0 ]]; then
|
||||
echo "L $(date --iso-8601=minute)" >> $logfile
|
||||
was_locked=0
|
||||
elif ! lockstate && [[ $was_locked == 0 ]]; then
|
||||
# change daily logfile on first unlock
|
||||
logfile=$LOGDIR/$(date --iso-8601)
|
||||
echo "U $(date --iso-8601=minute)" >> $logfile
|
||||
was_locked=1
|
||||
fi
|
||||
sleep 60
|
||||
done
|
13
bin/update-amm
Executable file
13
bin/update-amm
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/zsh
|
||||
versions=$(curl -L https://api.github.com/repos/lihaoyi/Ammonite/releases/latest)
|
||||
|
||||
download-version() {
|
||||
(
|
||||
echo "#/usr/bin/env python --version sh" && \
|
||||
curl -L $( echo $versions \
|
||||
| jq -r ".assets | map(select(.name | startswith(\"$1\")))[0].browser_download_url")
|
||||
) > $2
|
||||
chmod +x $2
|
||||
}
|
||||
download-version 2.13 $(which amm)
|
||||
download-version 2.12 $(which amm)2.12
|
36
bin/venv
Executable file
36
bin/venv
Executable file
|
@ -0,0 +1,36 @@
|
|||
#!/bin/zsh
|
||||
|
||||
zparseopts -D -E c=cdhere -cdhere=cdhere h=help -help=help
|
||||
if [[ -n $help ]]; then
|
||||
<<-HELP
|
||||
Usage: ${0:t} [-c] [DIR]
|
||||
|
||||
If DIR contains bin/activate, start a shell with that virtualenv.
|
||||
Otherwise recursively look up virtualenvs in DIR (by looking for dirs ending
|
||||
in "venv") and select one with fzf.
|
||||
|
||||
-c, --cdhere Change back to the current working directory instead of the
|
||||
virtual env's base dir
|
||||
HELP
|
||||
exit
|
||||
fi
|
||||
|
||||
ORIGDIR=$PWD
|
||||
|
||||
venvsh() {
|
||||
cd $1
|
||||
. bin/activate
|
||||
if [[ -n $cdhere ]]; then
|
||||
cd $ORIGDIR
|
||||
fi
|
||||
$SHELL
|
||||
}
|
||||
|
||||
if [[ -n $1 && -e $1/bin/activate ]]; then
|
||||
exec venvsh $1
|
||||
fi
|
||||
|
||||
venv=$(fd -I -t d 'venv$' $1 | fzf)
|
||||
if [[ -n $venv ]]; then
|
||||
venvsh $venv
|
||||
fi
|
20
bin/vf
Executable file
20
bin/vf
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/zsh
|
||||
zparseopts -D -E -ext:=ext e:=ext h=help -help=help
|
||||
|
||||
if [[ -n $help ]]; then
|
||||
<<-HELP
|
||||
Usage: ${0:t} [-e EXT | PATTERN] [DIR...]
|
||||
|
||||
Find files with fd, show them with fzf and open selected files via xdg-open.
|
||||
|
||||
Either -e with a file extension or a pattern can be given to narrow search.
|
||||
Any further arguments are passed to fd as search path.
|
||||
HELP
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ -n $ext ]]; then
|
||||
fd -e ${ext[2]} . "$@"
|
||||
else
|
||||
fd "$@"
|
||||
fi | fzf | xargs --null xdg-open
|
10
bin/webapp
Executable file
10
bin/webapp
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/zsh
|
||||
profile="${0:t}"
|
||||
|
||||
need firefox
|
||||
need firejail
|
||||
|
||||
mkdir -p $HOME/.jails/firefox-$profile
|
||||
|
||||
exec firejail --private=$HOME/.jails/firefox-$profile \
|
||||
firefox --no-remote "$@"
|
3
bin/webapp-cp
Executable file
3
bin/webapp-cp
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/zsh
|
||||
profile="${${0:t}%%-cp}"
|
||||
cp "$@" $HOME/.jails/firefox-$profile
|
83
bin/xc
Executable file
83
bin/xc
Executable file
|
@ -0,0 +1,83 @@
|
|||
#!/bin/zsh
|
||||
|
||||
# install this program with the name xc and symlink it as xs.
|
||||
# xc will use the clipboard selection, while xs while use the primary selection
|
||||
|
||||
source $(which need)
|
||||
need xclip
|
||||
|
||||
function get_primary() { xclip -o -selection primary }
|
||||
function get_clipboard() { xclip -o -selection clipboard }
|
||||
function set_primary() { xclip -i -selection primary }
|
||||
function set_clipboard() { xclip -i -selection clipboard }
|
||||
function show_both() {
|
||||
printf "\e[1;94mPrimary\e[0m\n"
|
||||
get_primary
|
||||
echo
|
||||
printf "\e[1;94mClipboard\e[0m\n"
|
||||
get_clipboard
|
||||
}
|
||||
|
||||
function read_both() {
|
||||
need pee moreutils
|
||||
pee "xclip -i -selection primary" "xclip -i -selection clipboard"
|
||||
}
|
||||
|
||||
function common() {
|
||||
cmd=$1
|
||||
getc=$2
|
||||
setc=$3
|
||||
shift 3
|
||||
case "$cmd" in
|
||||
"read") $setc;;
|
||||
"readboth") read_both ;;
|
||||
"showboth") show_both ;;
|
||||
"sed") $getc | sed -e "$@" | $setc; $getc;;
|
||||
"pipe") $getc | "$@" | $setc; $getc;;
|
||||
"edit") need vipe moreutils; $getc | vipe | $setc; $getc;;
|
||||
"") $getc ;;
|
||||
*) <<-HELP
|
||||
Usage: xc [COMMAND]
|
||||
xc fromxs|toxs
|
||||
xs [COMMAND]
|
||||
xs fromxc|toxc
|
||||
|
||||
The used X selection is determined by the name the program is called as:
|
||||
xc: clipboard (Ctrl-C / Ctrl-V)
|
||||
xs: primary selection (middle mouse button)
|
||||
For showboth/readboth, the action is done for both selections.
|
||||
|
||||
Commands:
|
||||
show/showboth: show contents of clipboard (default if no command given)
|
||||
read/readboth: store input to clipboard
|
||||
sed: modify contents using a sed expression
|
||||
pipe: modify contents by piping through a command
|
||||
edit: edit clipboard contents using \$EDITOR
|
||||
|
||||
fromxs/toxs: xc only: copy contents from or to primary selection
|
||||
fromxc/toxc: xs only: copy contents from or to clipboard
|
||||
HELP
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
cmd=$1
|
||||
[[ -n $1 ]] && shift
|
||||
|
||||
case "${0:t}" in
|
||||
xc)
|
||||
case "$cmd" in
|
||||
"fromxs"|"fromXS") get_primary | set_clipboard ;;
|
||||
"toxs"|"toXS") get_clipboard | set_primary ;;
|
||||
*) common "$cmd" get_clipboard set_clipboard "$@";;
|
||||
esac
|
||||
;;
|
||||
xs)
|
||||
case "$cmd" in
|
||||
"fromxc"|"fromXC") get_clipboard | set_primary ;;
|
||||
"toxc"|"toXC") get_primary | set_clipboard ;;
|
||||
*) common "$cmd" get_primary set_primary "$@";;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
Loading…
Reference in a new issue