dotfiles

Personal dotfiles
git clone https://git.bracken.jp/dotfiles.git
Log | Files | Refs | LICENSE

grimshot (4240B)


      1 #!/bin/sh
      2 
      3 ## Grimshot: a helper for screenshots within sway
      4 ## Requirements:
      5 ##  - `grim`: screenshot utility for wayland
      6 ##  - `slurp`: to select an area
      7 ##  - `swaymsg`: to read properties of current window
      8 ##  - `wl-copy`: clipboard utility
      9 ##  - `jq`: json utility to parse swaymsg output
     10 ##  - `notify-send`: to show notifications
     11 ## Those are needed to be installed, if unsure, run `grimshot check`
     12 ##
     13 ## See `man 1 grimshot` or `grimshot usage` for further details.
     14 
     15 getTargetDirectory() {
     16   test -f ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs && \
     17     . ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs
     18 
     19   echo ${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}}
     20 }
     21 
     22 if [ "$1" = "--notify" ]; then
     23   NOTIFY=yes
     24   shift 1
     25 else
     26   NOTIFY=no
     27 fi
     28 
     29 ACTION=${1:-usage}
     30 SUBJECT=${2:-screen}
     31 FILE=${3:-$(getTargetDirectory)/$(date -Ins).png}
     32 
     33 if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then
     34   echo "Usage:"
     35   echo "  grimshot [--notify] (copy|save) [active|screen|output|area|window] [FILE|-]"
     36   echo "  grimshot check"
     37   echo "  grimshot usage"
     38   echo ""
     39   echo "Commands:"
     40   echo "  copy: Copy the screenshot data into the clipboard."
     41   echo "  save: Save the screenshot to a regular file or '-' to pipe to STDOUT."
     42   echo "  check: Verify if required tools are installed and exit."
     43   echo "  usage: Show this message and exit."
     44   echo ""
     45   echo "Targets:"
     46   echo "  active: Currently active window."
     47   echo "  screen: All visible outputs."
     48   echo "  output: Currently active output."
     49   echo "  area: Manually select a region."
     50   echo "  window: Manually select a window."
     51   exit
     52 fi
     53 
     54 notify() {
     55   notify-send -t 3000 -a grimshot "$@"
     56 }
     57 notifyOk() {
     58   [ "$NOTIFY" = "no" ] && return
     59 
     60   TITLE=${2:-"Screenshot"}
     61   MESSAGE=${1:-"OK"}
     62   notify "$TITLE" "$MESSAGE"
     63 }
     64 notifyError() {
     65   if [ $NOTIFY = "yes" ]; then
     66     TITLE=${2:-"Screenshot"}
     67     MESSAGE=${1:-"Error taking screenshot with grim"}
     68     notify -u critical "$TITLE" "$MESSAGE"
     69   else
     70     echo $1
     71   fi
     72 }
     73 
     74 die() {
     75   MSG=${1:-Bye}
     76   notifyError "Error: $MSG"
     77   exit 2
     78 }
     79 
     80 check() {
     81   COMMAND=$1
     82   if command -v "$COMMAND" > /dev/null 2>&1; then
     83     RESULT="OK"
     84   else
     85     RESULT="NOT FOUND"
     86   fi
     87   echo "   $COMMAND: $RESULT"
     88 }
     89 
     90 takeScreenshot() {
     91   FILE=$1
     92   GEOM=$2
     93   OUTPUT=$3
     94 
     95   DIR="$(dirname "$FILE")"
     96   mkdir -p "$DIR"
     97   if [ ! -z "$OUTPUT" ]; then
     98     grim -o "$OUTPUT" "$FILE" || die "Unable to invoke grim"
     99   elif [ -z "$GEOM" ]; then
    100     grim "$FILE" || die "Unable to invoke grim"
    101   else
    102     grim -g "$GEOM" "$FILE" || die "Unable to invoke grim"
    103   fi
    104 }
    105 
    106 if [ "$ACTION" = "check" ] ; then
    107   echo "Checking if required tools are installed. If something is missing, install it to your system and make it available in PATH..."
    108   check grim
    109   check slurp
    110   check swaymsg
    111   check wl-copy
    112   check jq
    113   check notify-send
    114   exit
    115 elif [ "$SUBJECT" = "area" ] ; then
    116   GEOM=$(slurp -d)
    117   # Check if user exited slurp without selecting the area
    118   if [ -z "$GEOM" ]; then
    119     exit 1
    120   fi
    121   WHAT="Area"
    122 elif [ "$SUBJECT" = "active" ] ; then
    123   FOCUSED=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused)')
    124   GEOM=$(echo "$FOCUSED" | jq -r '.rect | "\(.x),\(.y) \(.width)x\(.height)"')
    125   APP_ID=$(echo "$FOCUSED" | jq -r '.app_id')
    126   WHAT="$APP_ID window"
    127 elif [ "$SUBJECT" = "screen" ] ; then
    128   GEOM=""
    129   WHAT="Screen"
    130 elif [ "$SUBJECT" = "output" ] ; then
    131   GEOM=""
    132   OUTPUT=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused)' | jq -r '.name')
    133   WHAT="$OUTPUT"
    134 elif [ "$SUBJECT" = "window" ] ; then
    135   GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp)
    136   # Check if user exited slurp without selecting the area
    137   if [ -z "$GEOM" ]; then
    138    exit 1
    139   fi
    140   WHAT="Window"
    141 else
    142   die "Unknown subject to take a screen shot from" "$SUBJECT"
    143 fi
    144 
    145 if [ "$ACTION" = "copy" ] ; then
    146   takeScreenshot - "$GEOM" "$OUTPUT" | wl-copy --type image/png || die "Clipboard error"
    147   notifyOk "$WHAT copied to buffer"
    148 else
    149   if takeScreenshot "$FILE" "$GEOM" "$OUTPUT"; then
    150     TITLE="Screenshot of $SUBJECT"
    151     MESSAGE=$(basename "$FILE")
    152     notifyOk "$MESSAGE" "$TITLE"
    153     echo $FILE
    154   else
    155     notifyError "Error taking screenshot with grim"
    156   fi
    157 fi