Skip to content

Commit

Permalink
Merge branch 'master' into fix-functional-helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
Qubut authored Oct 24, 2024
2 parents 8bba26a + 4ee1c80 commit 01481bd
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
| :---: | :---: |
| autoname-workspaces.py | Adds icons to the workspace name for each open window |
| firefox-focus-monitor.py | Utility to selectively disable keypresses to specific windows |
| grimpicker | A simple color picker for wlroots |
| grimshot | A helper for screenshots within sway |
| inactive-windows-transparency.py | Makes inactive windows transparent |
| layout-per-window.py | A script keeps track of the active layout for each window |
Expand Down
15 changes: 15 additions & 0 deletions grimpicker/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
PKGNAME = "grimpicker"
DESTDIR ?= ""
PREFIX ?= "/usr"

.PHONY: build install

build:
scdoc <"${PKGNAME}.1.scd" >"${PKGNAME}.1"

install:
# Not installing zsh completion here as its destination depends on the distribution
install -D -m 755 "${PKGNAME}" "${DESTDIR}${PREFIX}/bin/${PKGNAME}"
install -D -m 644 "completion.bash" "${DESTDIR}${PREFIX}/share/bash-completion/completions/${PKGNAME}"
install -D -m 644 "completion.fish" "${DESTDIR}${PREFIX}/share/fish/vendor_completions.d/${PKGNAME}.fish"
install -D -m 644 "${PKGNAME}.1" "${DESTDIR}${PREFIX}/share/man/man1/${PKGNAME}.1"
15 changes: 15 additions & 0 deletions grimpicker/completion.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
_grimpicker() {
local cur="${COMP_WORDS[COMP_CWORD]}"

short=(-p -d -e -c -n -h -v)
long=(--print --draw --escape --copy --notify --help --version)

if [[ $cur == --* ]]; then
COMPREPLY=($(compgen -W "${long[*]}" -- "$cur"))
else
COMPREPLY=($(compgen -W "${short[*]}" -- "$cur"))
COMPREPLY+=($(compgen -W "${long[*]}" -- "$cur"))
fi
}

complete -F _grimpicker grimpicker
8 changes: 8 additions & 0 deletions grimpicker/completion.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
complete -c grimpicker -f
complete -c grimpicker -s p -l print -d "Print to stdout"
complete -c grimpicker -s d -l draw -d "Draw a colored block"
complete -c grimpicker -s e -l escape -d "Print shell escape sequences"
complete -c grimpicker -s c -l copy -d "Copy to clipboard"
complete -c grimpicker -s n -l notify -d "Send a notification"
complete -c grimpicker -s h -l help -d "Show help message and quit"
complete -c grimpicker -s v -l version -d "Show version number and quit"
10 changes: 10 additions & 0 deletions grimpicker/completion.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#compdef grimpicker

_arguments -s \
{-d,--print}'[Print to stdout]' \
{-d,--draw}'[Draw a colored block]' \
{-e,--escape}'[Print shell escape sequences]' \
{-c,--copy}'[Copy to clipboard]' \
{-n,--notify}'[Send a notification]' \
{-h,--help}'[Show help message and quit]' \
{-v,--version}'[Show version number and exit]' \
109 changes: 109 additions & 0 deletions grimpicker/grimpicker
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env python3

'''
grimpicker: a simple color picker for wlroots
Dependencies:
`slurp`: utility to select a region
`grim`: utility to make screenshots
Recommendations:
`wl-copy`: clipboard utility
`notify-send`: desktop notifications sender
'''

__pkgname__ = 'grimpicker'
__version__ = '1.0.0'

import argparse
import subprocess
import sys


class Color:
escape = b'\x1b'
reset_fg = escape + b'[39m'
reset_bg = escape + b'[49m'
reset_all = escape + b'[0m'

escape_str = '\\e'
reset_fg_str = escape_str + '[39m'
reset_bg_str = escape_str + '[49m'
reset_all_str = escape_str + '[0m'

def __init__(self, r: int, g: int, b: int):
(self.r, self.g, self.b) = (r, g, b)

@classmethod
def decode_ppm_pixel(cls, ppm: bytes):
ppm_lines = ppm.splitlines()
if not (len(ppm_lines) == 4 and ppm_lines[:3] == [b'P6', b'1 1', b'255'] and len(ppm_lines[3]) == 3):
raise ValueError('only 1x1 pixel ppm P6 format without comments is supported, no HDR')
return cls(*ppm_lines[3])

def to_hex(self) -> str:
return '#{:0>2X}{:0>2X}{:0>2X}'.format(self.r, self.g, self.b)

def to_escape_fg(self) -> bytes:
return b'%b[38;2;%d;%d;%dm' % (self.escape, self.r, self.g, self.b)

def to_escape_bg(self) -> bytes:
return b'%b[48;2;%d;%d;%dm' % (self.escape, self.r, self.g, self.b)

def to_escape_fg_str(self) -> str:
return '{}[38;2;{};{};{}m'.format(self.escape_str, self.r, self.g, self.b)

def to_escape_bg_str(self) -> str:
return '{}[48;2;{};{};{}m'.format(self.escape_str, self.r, self.g, self.b)


def run(args) -> None:
slurp = subprocess.check_output(('slurp', '-p'))
grim = subprocess.check_output(('grim', '-g', '-', '-t', 'ppm', '-'), input=slurp)
color = Color.decode_ppm_pixel(grim)

if not (args.print or args.draw or args.escape or args.copy or args.notify):
args.print = True
args.draw = True

if args.print:
print(color.to_hex())
if args.draw:
sys.stdout.buffer.write(color.to_escape_bg() + b' ' * 7 + color.reset_bg + b'\n')
if args.escape:
sys.stdout.buffer.write(
b'Truecolor terminal shell escape sequences:\n' +

b'%bTo change foreground:%b ' % (color.to_escape_fg(), color.reset_fg) +
b'echo -e "%b", to reset: ' % color.to_escape_fg_str().encode() +
b'echo -e "%b"\n' % color.reset_fg_str.encode() +

b'%bTo change background:%b ' % (color.to_escape_bg(), color.reset_bg) +
b'echo -e "%b", to reset: ' % color.to_escape_bg_str().encode() +
b'echo -e "%b"\n' % color.reset_bg_str.encode() +

b'To reset all attributes: echo -e "%b"\n' % color.reset_all_str.encode()
)
if args.copy:
subprocess.run(('wl-copy', color.to_hex()), check=True)
if args.notify:
subprocess.run(('notify-send', color.to_hex()), check=True)


def parse_args() -> argparse.Namespace:
usage = '{} [OPTIONS]'.format(__pkgname__)
version = '{} {}'.format(__pkgname__, __version__)
epilog = 'See `man 1 grimpicker` for further details'
parser = argparse.ArgumentParser(usage=usage, add_help=False, epilog=epilog)
parser.add_argument('-p', '--print', dest='print', action='store_true', help='Print to stdout')
parser.add_argument('-d', '--draw', dest='draw', action='store_true', help='Draw a colored block')
parser.add_argument('-e', '--escape', dest='escape', action='store_true', help='Print shell escape sequences')
parser.add_argument('-c', '--copy', dest='copy', action='store_true', help='Copy to clipboard')
parser.add_argument('-n', '--notify', dest='notify', action='store_true', help='Send a notification')
parser.add_argument('-h', '--help', action='help', help='Show help message and quit')
parser.add_argument('-v', '--version', action='version', version=version, help='Show version number and quit')
return parser.parse_args()


if __name__ == '__main__':
run(parse_args())
65 changes: 65 additions & 0 deletions grimpicker/grimpicker.1.scd
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
GRIMPICKER(1)

# NAME

grimpicker - a simple color picker for wlroots

# SYNOPSIS

*grimpicker* [_OPTIONS_]

# OPTIONS

*-p*, *--print*
Print to stdout

*-d*, *--draw*
Draw a colored block

*-e*, *--escape*
Print shell escape sequences

*-c*, *--copy*
Copy to clipboard

*-n*, *--notify*
Send a notification

*-h*, *--help*
Show help message and quit

*-v*, *--version*
Show version number and quit

# DESCRIPTION

*grimpicker* is a color picker that uses *slurp* and *grim*.
These programs rely on _zwlr_layer_shell_v1_ and _wlr-screencopy-unstable-v1_
(maybe be replaced with _ext-image-capture-source-v1_ and
_ext-image-copy-capture-v1_ in the future) wayland protocols
(implemented in wlroots-based compositors, e.g. *sway*).

It has several output options, they can be combined.

_--copy_ needs *wl-clipboard* to be installed.

_--draw_ and _--escape_ need a terminal with truecolor support (e.g. *foot*).

_--notify_ needs *libnotify* to be installed
and a notification daemon (e.g. *mako* or *fnott*) to be running.

_--print_ and _--draw_ are selected by default if no arguments are provided.

# EXAMPLES

An example usage pattern is to add this binding to your sway config:

```
# Super+Print: color picker
bindsym --to-code $mod+Print exec grimpicker --notify
```

# SEE ALSO

*slurp*(1), *grim*(1), *grimshot*(1)
33 changes: 33 additions & 0 deletions grimshot/functional-helpers
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#! /bin/sh
when() {
condition=$1
action=$2

if eval "$condition"; then
eval "$action"
fi
}

whenOtherwise() {
condition=$1
true_action=$2
false_action=$3

if eval "$condition"; then
eval "$true_action"
else
eval "$false_action"
fi
}

any() {
for tuple in "$@"; do
condition=$(echo "$tuple" | cut -d: -f1)
action=$(echo "$tuple" | cut -d: -f2-)
if eval "$condition"; then
eval "$action"
return 0
fi
done
return 1 # No conditions matched
}
1 change: 0 additions & 1 deletion grimshot/grimshot
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ any() {
return 1 # No conditions matched
}


NOTIFY=no
CURSOR=
WAIT=no
Expand Down

0 comments on commit 01481bd

Please sign in to comment.