mbxcolors/bin/mbxcolors

438 lines
15 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copyright (C) Daniel Napora 2021-22 <napcok@gmail.com>
# Dependencies: jgmenu, xdotool, xcolor, gcolor3, xdg-utils, xclip, notify-send
# TODO Imagick colors - separate menu big around 700 named colors
# TODO export to .gpl (GIMP,Inkscape)
# TODO PL translation
VERSION="0.3.0"
TEMP_DIR=/tmp/colormenu
ME=${0##*/}
DATA_DIR="/usr/share/$ME"
CNF_DIR="$HOME/.config/mbxcolors"
CNF_FILE="$CNF_DIR/mbxcolors.cfg"
RECENT="$CNF_DIR/recent.clr"
USED="$CNF_DIR/.used"
LASTPAL="$CNF_DIR/.palette"
[ ! -d "$CNF_DIR" ] && mkdir -p "$CNF_DIR"
if [ ! -f $CNF_FILE ]; then
cat <<EOF > ${CNF_FILE}
# Paste mode: hex,rgb or rgba
format=hex
#Action when color is clicked: paste (imadietely) or copy (to clipboard)
action=copy
#What thing to expose on top of main menu: recently picked colors, last used colors or last used palette
expose=picked
#Show HTML colors? yes|no
htmlcolors=yes
#Show built in palettes? (slow)
builtin_palettes=yes
#Position on screen: topleft, top, topright, left, center, right, bottomleft, bottom, bottomright
position=left
EOF
fi
source <(grep = $CNF_FILE)
if [ ! -f $RECENT ]; then
cat <<EOF > ${RECENT}
#FFFFFF White
#C0C0C0 Silver
#808080 Gray
#000000 Black
EOF
fi
fgcolor() {
r=$(printf "%d" 0x${1:1:2}) g=$(printf "%d" 0x${1:3:2}) b=$(printf "%d" 0x${1:5:2})
[ "$((r*299+g*587+b*114))" -gt 149000 ] && echo "#111111" || echo "#EEEEEE"
}
hex2rgb() {
r=$(printf "%d" 0x${1:1:2}) g=$(printf "%d" 0x${1:3:2}) b=$(printf "%d" 0x${1:5:2})
echo "rgb($r, $g, $b)"
}
hex2rgba() {
r=$(printf "%d" 0x${1:1:2}) g=$(printf "%d" 0x${1:3:2}) b=$(printf "%d" 0x${1:5:2})
echo "rgba($r, $g, $b, 1.0)"
}
pickcolor() {
#color=$(colorpicker --short --one-shot --preview)
#color=$(xcolor --preview-size "${preview-size:-255}" --scale "${scale:-8}")
size=${xcolor_preview_size:-255}
scale=${xcolor_scale:-8}
command="xcolor --preview-size ${size} --scale ${scale}"
color="$(${command})"
if [ -n "${color}" ]; then
echo "$color " > "$RECENT".tmp
# add on top deduplicate
awk '!x[$0]++' "$RECENT" >> "$RECENT".tmp
awk '!x[$0]++' "$RECENT".tmp > "$RECENT"
[ -n "$1" ] && file="$1"
echo "$color " >> "$file"
setvar expose=picked
fi
$ME
}
addcolor() {
color=$(gcolor3)
if [ -n "${color}" ]; then
echo "$color " > "$RECENT".tmp
# add on top deduplicate
awk '!x[$0]++' "$RECENT" >> "$RECENT".tmp
awk '!x[$0]++' "$RECENT".tmp > "$RECENT"
[ -n "$1" ] && file="$1"
echo "$color " >> "$file"
setvar expose=picked
fi
$ME
}
getcolorcode() {
if [ $action = "paste" ];then
case "$format" in
rgb) clr=$(hex2rgb $1);xdotool type --delay 0 "$clr";;
rgba) clr=$(hex2rgba $1);xdotool type --delay 0 "$clr";;
*) xdotool type --delay 0 "$1";;
esac
else # copy to clipboard
case "$format" in
rgb) clr=$(hex2rgb $1);echo $clr | tr -d "\n" | xclip -sel c;;
rgba) clr=$(hex2rgba $1);echo $clr | tr -d "\n" | xclip -sel c;;
*) clr="$1";echo "$1" | tr -d "\n" | xclip -sel c;;
esac
mkdir -p $TEMP_DIR
FNAME="$TEMP_DIR/${1:1:6}.png"
convert -size 100x100 xc:"$1" "$FNAME"
notify-send ColorMenu "$clr" --icon="$FNAME" --expire-time=120000
fi
echo "$1" > "$USED".tmp
# add on top and deduplicate
awk '!x[$0]++' "$USED" >> "$USED".tmp
awk '!x[$0]++' "$USED".tmp > "$USED"
[[ $2 ]] && echo "$2" > "$LASTPAL"
}
recent2palette () {
DATE=$(date +"%Y%m%d-%H%M%S")
mkdir -p "$CNF_DIR/palettes/my"
grep ^# $RECENT |tac > "$CNF_DIR/palettes/my/My_palette_$DATE.clr"
}
newpalette() {
DATE=$(date +"%Y%m%d-%H%M%S")
mkdir -p "$CNF_DIR/palettes/my"
touch "$CNF_DIR/palettes/my/My_palette_$DATE.clr"
}
palettes() {
[ -n "$1" ] && pdir="$CNF_DIR/palettes/my/" || pdir="$DATA_DIR/palettes/"
if [[ -n "$1" ]]; then
out2+=("^tag(mypalettes)")
out2+=("^sep(My palettes)")
else
out2+=("^tag(builtpalettes)")
out2+=("^sep(Built-in palettes)")
fi
for file in "$pdir"*.clr ;do
filename=${file##*/}
palette=${filename%.*}
pal=${palette//_/ }
tagname=${palette// /_}
out2+=("${pal^},^checkout($tagname)")
out3+=("^tag($tagname)")
out3+=("^sep(${pal^})")
out3+=("EXPOSE_ON_ROOTMENU,$ME setvar expose=$filename;$ME")
out3+=("^sep()")
while read -r color name;
do
out3+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt>,$ME getcolorcode '$color' '$file',,,#${palette}")
done < "$file"
if [[ -n "$1" ]] ; then
out3+=("^sep()")
out3+=("<b>Add color...</b> from screen,$ME pickcolor '$file'")
if hash gcolor3 2>/dev/null; then
out3+=("^sep()")
out3+=("<b>Add</b> color from selector...,$ME addcolor '$file'")
fi
out3+=("^sep()")
out3+=("<b>Edit</b> palette file,xdg-open '$file'")
out3+=("^sep(Danger zone...)")
out3+=("<b>Delete</b> palette: ${palette^},^checkout($tagname-del)")
out4+=("^tag($tagname-del)")
out4+=("^sep(Are you sure?)")
out4+=("Yes,rm '$file';$ME")
fi
done
#if [[ $# = 0 ]] ; then
if [[ -n "$1" ]] ; then
out2+=("^sep()")
out2+=("<b>Add new</b> palette...,$ME newpalette;$ME")
out2+=("Open palette directory,xdg-open $CNF_DIR/palettes/my/")
fi
}
if [ $htmlcolors = "yes" ]; then
htmlroot="^sep()
<b>HTML</b> colors,^checkout(html)
"
htmlsub="^tag(html)
. ${DATA_DIR}/htmlsub.csv"
htmlclrs=". ${DATA_DIR}/htmlclrs.csv"
else
htmlroot="" htmlsub="" htmlclrs=""
fi
position() {
case "$position" in
ipc) POSITION_MODE="ipc";;
pointer) POSITION_MODE="pointer";;
topleft) POSITION_MODE="fixed" MENU_VALIGN="top" MENU_HALIGN="left";;
top) POSITIOM_MODE="fixed" MENU_VALIGN="top" MENU_HALIGN="center";;
topright) POSITION_MODE="fixed" MENU_VALIGN="top" MENU_HALIGN="right";;
left) POSITION_MODE="fixed" MENU_VALIGN="center" MENU_HALIGN="left";;
right) POSITION_MODE="fixed" MENU_VALIGN="center" MENU_HALIGN="right";;
bottomleft) POSITION_MODE="fixed" MENU_VALIGN="bottom" MENU_HALIGN="left";;
bottom) POSITION_MODE="fixed" MENU_VALIGN="bottom" MENU_HALIGN="center";;
bottomright) POSITION_MODE="fixed" MENU_VALIGN="bottom" MENU_HALIGN="right";;
center|*) POSITION_MODE="center";;
esac
}
main () {
# Mabox Linux
if [[ -f /usr/share/mb-jgtools/pipemenu-standalone.cfg ]];then
. /usr/share/mb-jgtools/pipemenu-standalone.cfg
. $HOME/.config/mabox/mabox.conf
fi
[ "$1" = "ipc" ] && position="ipc"
MENU_PADDING_TOP=${jgtools_padding:-0}
JGWIDTH="220"
ITEM_HALIGN="center"
jgmenu_icon_size=0
menu_margin_x=${submenu_spacing:-0}
[ $(pidof picom) ] && MENU_RADIUS=$jgtools_radius
#jgmenu_font="Noto Sans Medium 10"
position
mkconfigfile
trap "rm -f ${CONFIG_FILE} ${MENU_ITEMS}" EXIT
out+=("^sep(ColorMenu <sup><span font_weight='light'> [$action $format]</span></sup>)")
#out+=("^sep(<span bgcolor='#800000'> </span><span fgcolor='#800000' bgcolor='#FABD2F'> mbx </span><span fgcolor='#FABD2F' bgcolor='#800000'> colors </span><span bgcolor='#FABD2F'> </span> <sup><span font_weight='light'>[$action $format]</span></sup>)")
out+=("<b>Pick</b> color from screen...,$ME pickcolor")
if hash gcolor3 2>/dev/null; then
out+=("^sep()")
out+=("<b>Add</b> color from selector...,$ME addcolor")
fi
# exposed thing
case "$expose" in
palette)
pal=$(cat "$CNF_DIR/.palette")
filename=${pal##*/}
palette=${filename%.*}
out+=("^sep(<i><span font_weight='light'>Last used palette</span> ${palette^}</i>)")
while read -r color name;do
out+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt> ,$ME getcolorcode '$color'")
done < "${pal}"
;;
used)
mapfile -t < $USED
if (( ${#MAPFILE[@]} > 1 )); then
out+=("^sep(<i><small>Recently used colors:</small></i>)")
while read -r color name;do
out+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt> ,$ME getcolorcode '$color'")
done < <(grep ^# $USED)
out+=("^sep()")
out+=("<b>Clear</b> recently used colors,echo > $USED;$ME")
fi
;;
picked)
mapfile -t < $RECENT
if (( ${#MAPFILE[@]} > 1 )); then
out+=("^sep(<i><small>Recently picked colors:</small></i>)")
# for clear/delete
out2+=("^tag(pickeddel)")
out2+=("^sep(Clear All)")
out2+=("<b>Clear</b> all,echo > $RECENT;$ME")
out2+=("^sep(Just remove one color...)")
while read -r color name;do
out+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt> ,$ME getcolorcode '$color'")
out2+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt> ,sed -i '/${color:1:6}/d' $RECENT;$ME")
done < <(grep ^# $RECENT)
out+=("^sep()")
out+=("<b>New palette</b> from recently picked,$ME recent2palette;$ME")
out+=("<b>Clear</b> recently picked,^checkout(pickeddel)")
fi
;;
wallpaper)
read WALLPAPER<<< $(grep file "$HOME/.config/nitrogen/bg-saved.cfg | cut -d'=' -f2")
WALLPALDIR="$HOME/.config/mbxcolors/palettes/wallp"
mkdir -p "$WALLPALDIR"
read WALLPATH<<< $(grep file "$HOME/.config/nitrogen/bg-saved.cfg" | cut -d'=' -f2)
WALLPAPER=${WALLPATH##*/}
if [ ! -f "$WALLPALDIR/$WALLPAPER.clr" ]; then
convert ${WALLPATH} -resize 25% -colors 16 -unique-colors txt:- |grep -v '^#'| awk '{print $3}' > "$WALLPALDIR/$WALLPAPER.clr"
fi
#mapfile -t wallcolors < "$WALLPALDIR/$WALLPAPER.clr"
out+=("^sep(Wallpaper colors)")
while read -r color name;do
out+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt> ,$ME getcolorcode '$color'")
done < "$WALLPALDIR/$WALLPAPER.clr"
;;
*)
if [ -f "$DATA_DIR/palettes/$expose" ];then
palfile="$DATA_DIR/palettes/$expose"
elif [ -f "$CNF_DIR/palettes/my/$expose" ];then
palfile="$CNF_DIR/palettes/my/$expose"
fi
if [ $palfile ];then
palette=${expose%.*}
pal=${palette//_/ }
out+=("^sep(Palette: ${pal^})")
while read -r color name;
do
out+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt>,$ME getcolorcode '$color' '$file';$ME setvar expose=palette,,,#${palette}")
done < "$palfile"
fi
;;
esac
#if [[ "$CNF_DIR"/palettes/my/*.clr ]]; then
out+=("^sep(Color palettes)")
if [ "$(find "$CNF_DIR"/palettes/my/*.clr -maxdepth 1 -type f -iname \*.clr)" ]; then
out+=("My palettes,^checkout(mypalettes)")
palettes my
fi
if [[ $builtin_palettes == "yes" ]];then
out+=("Built-in palettes,^checkout(builtpalettes)")
palettes
fi
# WALLPAPER COLORS
out+=("Current Wallpaper colors,^checkout(wallcolors)")
read WALLPAPER<<< $(grep file "$HOME/.config/nitrogen/bg-saved.cfg | cut -d'=' -f2")
WALLPALDIR="$HOME/.config/mbxcolors/palettes/wallp"
mkdir -p "$WALLPALDIR"
read WALLPATH<<< $(grep file "$HOME/.config/nitrogen/bg-saved.cfg" | cut -d'=' -f2)
WALLPAPER=${WALLPATH##*/}
if [ ! -f "$WALLPALDIR/$WALLPAPER.clr" ]; then
convert ${WALLPATH} -resize 25% -colors 16 -unique-colors txt:- |grep -v '^#'| awk '{print $3}' > "$WALLPALDIR/$WALLPAPER.clr"
fi
#mapfile -t wallcolors < "$WALLPALDIR/$WALLPAPER.clr"
out2+=("^tag(wallcolors)")
out2+=("^sep(Current wallpaper colors)")
out2+=("EXPOSE_IN_ROOTMENU ,$ME setvar expose=wallpaper;$ME")
while read -r color name;do
out2+=("<tt><small>$color</small> <span bgcolor='$color'><sub> </sub> <sup> </sup></span></tt> ,$ME getcolorcode '$color'")
done < "$WALLPALDIR/$WALLPAPER.clr"
out1+=("^sep(Settings)")
out1+=("Preferences,^pipe($ME preferences)")
out1+=("^sep()")
out1+=("QUIT,^quit()")
cat << EOF > ${MENU_ITEMS}
$(printf '%s\n' "${out[@]}")
${htmlroot}
$(printf '%s\n' "${out1[@]}")
${htmlsub}
$(printf '%s\n' "${out2[@]}")
${htmlclrs}
$(printf '%s\n' "${out3[@]}")
$(printf '%s\n' "${out4[@]}")
EOF
jgmenu --config-file=${CONFIG_FILE} --csv-file=${MENU_ITEMS} 2>/dev/null
#printf '%s\n' "${out3[@]}"
exit 0
}
imagick() {
echo "not implemented"
}
preferences() {
out2+=("^sep(Settings)")
out2+=("<tt>$(printf "%-20s %20s" "Color click action:" "[<b>$action</b>]")</tt>,^checkout(action)")
out2+=("<tt>$(printf "%-20s %20s" "Format:" "[<b>$format</b>]")</tt>,^checkout(format)")
out2+=("^sep()")
out2+=("<tt>$(printf "%-20s %20s" "Expose on top:" "[<b>$expose</b>]")</tt>,^checkout(expose)")
out2+=("<tt>$(printf "%-20s %20s" "HTML colors:" "[<b>$htmlcolors</b>]")</tt>,^checkout(showhtml)")
out2+=("<tt>$(printf "%-20s %20s" "Built-in palettes:" "[<b>$builtin_palettes</b>]")</tt>,^checkout(builtinpalettes)")
out2+=("^sep()")
out2+=("<tt>$(printf "%-20s %20s" "Position:" "[<b>$position</b>]")</tt>,^checkout(position)")
out2+=("^sep()")
out2+=("Reset to defaults,rm $CNF_FILE;$ME")
out2+=("^sep()")
out2+=("Edit config file,xdg-open $CNF_FILE")
out2+=("Open config directory,xdg-open $CNF_DIR")
out2+=("^tag(format)")
out2+=("^sep(Output format)")
out2+=("<b>hex</b> <i>#579C8E</i>,$ME setvar format=hex;$ME")
out2+=("<b>rgb</b> <i>rgb(87&#44; 156&#44; 142)</i>,$ME setvar format=rgb;$ME")
out2+=("<b>rgba</b> <i>rgba(87&#44; 156&#44; 142&#44; 1.0)</i>,$ME setvar format=rgba;$ME")
out2+=("^tag(action)")
out2+=("^sep(Color action)")
out2+=("<b>paste</b> (paste color immediately),$ME setvar action=paste;$ME")
out2+=("<b>copy</b> (copy color to clipboard),$ME setvar action=copy;$ME")
out2+=("^tag(expose)")
out2+=("^sep(Show on top of rootmenu)")
out2+=("<b>picked</b> recently picked colors,$ME setvar expose=picked;$ME")
out2+=("<b>used</b> recently used colors,$ME setvar expose=used;$ME")
out2+=("<b>palette</b> recently used palette,$ME setvar expose=palette;$ME")
out2+=("<b>wallpaper</b> colors ,$ME setvar expose=wallpaper;$ME")
out2+=("^tag(showhtml)")
out2+=("^sep(Show HTML colors?)")
out2+=("yes,$ME setvar htmlcolors=yes;$ME")
out2+=("no,$ME setvar htmlcolors=no;$ME")
out2+=("^tag(builtinpalettes)")
out2+=("^sep(Show Built-in palettes?)")
out2+=("yes,$ME setvar builtin_palettes=yes;$ME")
out2+=("no,$ME setvar builtin_palettes=no;$ME")
out2+=("^tag(position)")
out2+=("^sep(Position on screen)")
out2+=("center,$ME setvar position=center;$ME")
out2+=("topleft,$ME setvar position=topleft;$ME")
out2+=("top,$ME setvar position=top;$ME")
out2+=("topright,$ME setvar position=topright;$ME")
out2+=("left,$ME setvar position=left;$ME")
out2+=("right,$ME setvar position=right;$ME")
out2+=("bottomleft,$ME setvar position=bottomleft;$ME")
out2+=("bottom,$ME setvar position=bottom;$ME")
out2+=("bottomright,$ME setvar position=bottomright;$ME")
printf '%s\n' "${out2[@]}"
}
setvar() {
search=$(echo $1|cut -d= -f1)
FILE=${CNF_FILE}
if grep -Rq $search $FILE
then #found
sed -i s/^"$search".*$/"$1"/ $FILE
else #not found
echo $1 >> $FILE
fi
}
case "$1" in
-h|--help|help) usage;;
--pickcolor|pickcolor) pickcolor "$2";;
--addcolor|addcolor) addcolor "$2" ;;
-g|--getcolorcode|getcolorcode) getcolorcode "$2" "$3";;
-p|preferences) preferences;;
-s|setvar) setvar "$2";;
ipc) main "$1";;
recent2palette) recent2palette ;;
newpalette) newpalette;;
imagick) imagick;;
*) main;;
esac
exit 0