GNU bug report logs - #49238
Ytfzf

Previous Next

Package: guix-patches;

Reported by: Raghav Gururajan <rg <at> raghavgururajan.name>

Date: Sun, 27 Jun 2021 05:45:02 UTC

Severity: normal

Done: Raghav Gururajan <rg <at> raghavgururajan.name>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 49238 in the body.
You can then email your comments to 49238 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Sun, 27 Jun 2021 05:45:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Raghav Gururajan <rg <at> raghavgururajan.name>:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Sun, 27 Jun 2021 05:45:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: guix-patches <at> gnu.org
Cc: jgart <at> dismail.de
Subject: Ytfzf
Date: Sun, 27 Jun 2021 01:44:26 -0400
[Message part 1 (text/plain, inline)]
Hello Guix!

This is the patch-series to package Ytfzf, which is a joint effort by 
Jorge (jgart) and I, as a part of LibreMiami.

The Ytfzf app is being placed in image-viewer.scm, as placing it in 
video.scm causes conflict somewhere while importing image-viewer.scm.

Regards,
RG.

[OpenPGP_signature (application/pgp-signature, attachment)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Sun, 27 Jun 2021 05:49:01 GMT) Full text and rfc822 format available.

Message #8 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, jgart <at> dismail.de,
 LibreMiami <packaging-guix <at> libremiami.org>
Subject: [PATCH v1 1/2] gnu: Add python-ueberzug.
Date: Sun, 27 Jun 2021 01:47:36 -0400
From: LibreMiami <packaging-guix <at> libremiami.org>

* gnu/packages/python-xyz.scm (python-ueberzug): New variable.

Co-authored-by: Raghav Gururajan <rg <at> raghavgururajan.name>
Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/packages/python-xyz.scm | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index 7dae6607a0..41761d8b7a 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -101,6 +101,7 @@
 ;;; Copyright © 2021 LibreMiami <packaging-guix <at> libremiami.org>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;; Copyright © 2021 Danial Behzadi <dani.behzi <at> ubuntu.com>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -221,6 +222,42 @@
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26))
 
+(define-public python-ueberzug
+  (package
+    (name "python-ueberzug")
+    (version "18.1.9")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "ueberzug" version))
+       (sha256
+        (base32
+         "1hxd45dnwa9yv908acarr98n2drmar66wzq9z2qd3irj24srzr3w"))))
+    (build-system python-build-system)
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)))
+    (propagated-inputs
+     `(("python-attrs" ,python-attrs)
+       ("python-docopt" ,python-docopt)
+       ("python-pillow" ,python-pillow)
+       ("python-xlib" ,python-xlib)))
+    (home-page "https://github.com/seebye/ueberzug")
+    (synopsis "Command line util to display images in combination with X11")
+    (description "Überzug is a command line util which allows to draw images on
+terminals by using child windows.  The advantages of using Überzug are:
+@itemize
+@item No race conditions as a new window is created to display images.
+@item Expose events will be processed, so images will be redrawn on switch
+workspaces.
+@item Tmux support (excluding multi pane windows).
+@item Terminals without the WINDOWID environment variable are supported.
+@item Chars are used as position - and size unit.
+@item No memory leak (/ unlimited cache).
+@end itemize")
+    (license license:gpl3+)))
+
+
 (define-public python-fire
   (package
     (name "python-fire")
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Sun, 27 Jun 2021 05:49:01 GMT) Full text and rfc822 format available.

Message #11 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, jgart <at> dismail.de,
 LibreMiami <packaging-guix <at> libremiami.org>
Subject: [PATCH v1 2/2] gnu: Add ytfzf.
Date: Sun, 27 Jun 2021 01:47:37 -0400
From: LibreMiami <packaging-guix <at> libremiami.org>

* gnu/packages/image-viewers.scm (ytfzf): New variable.

Co-authored-by: Raghav Gururajan <rg <at> raghavgururajan.name>
Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/local.mk                              |   2 +
 gnu/packages/image-viewers.scm            | 102 ++++++
 gnu/packages/patches/ytfzf-programs.patch | 372 ++++++++++++++++++++++
 gnu/packages/patches/ytfzf-updates.patch  |  41 +++
 4 files changed, 517 insertions(+)
 create mode 100644 gnu/packages/patches/ytfzf-programs.patch
 create mode 100644 gnu/packages/patches/ytfzf-updates.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index f507fe566f..d494663f8e 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1856,6 +1856,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/xsane-support-ipv6.patch			\
   %D%/packages/patches/xsane-tighten-default-umask.patch	\
   %D%/packages/patches/yggdrasil-extra-config.patch	\
+  %D%/packages/patches/ytfzf-programs.patch        \
+  %D%/packages/patches/ytfzf-updates.patch        \
   %D%/packages/patches/ytnef-CVE-2021-3403.patch	\
   %D%/packages/patches/ytnef-CVE-2021-3404.patch	\
   %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch	\
diff --git a/gnu/packages/image-viewers.scm b/gnu/packages/image-viewers.scm
index f01b6a614a..ccbbb3bc2d 100644
--- a/gnu/packages/image-viewers.scm
+++ b/gnu/packages/image-viewers.scm
@@ -18,6 +18,8 @@
 ;;; Copyright © 2021 Rovanion Luckey <rovanion.luckey <at> gmail.com>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Stefan Reichör <stefan <at> xsteve.at>
+;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -46,6 +48,7 @@
   #:use-module (guix build-system python)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages algebra)
+  #:use-module (gnu packages base)
   #:use-module (gnu packages boost)
   #:use-module (gnu packages check)
   #:use-module (gnu packages compression)
@@ -64,6 +67,7 @@
   #:use-module (gnu packages image-processing)
   #:use-module (gnu packages imagemagick)
   #:use-module (gnu packages maths)
+  #:use-module (gnu packages ncurses)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages perl-check)
   #:use-module (gnu packages photo)
@@ -71,10 +75,108 @@
   #:use-module (gnu packages python)
   #:use-module (gnu packages python-xyz)
   #:use-module (gnu packages qt)
+  #:use-module (gnu packages suckless)
+  #:use-module (gnu packages terminals)
+  #:use-module (gnu packages video)
+  #:use-module (gnu packages web)
   #:use-module (gnu packages xdisorg)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages))
 
+(define-public ytfzf
+  (package
+    (name "ytfzf")
+    (version "1.2.0")
+    (home-page "https://github.com/pystardust/ytfzf")
+    (source
+     (origin
+       (method git-fetch)
+       (uri
+        (git-reference
+         (url home-page)
+         (commit (string-append "v" version))))
+       (file-name (git-file-name name version))
+       (sha256
+        (base32 "00d416qb4109pm77ikhnmds8qng90ni2jan9kdnxz7b6sh5f61nz"))
+       (patches
+        (search-patches
+         ;; Prerequisite for 'patch phase.
+         "ytfzf-programs.patch"
+         ;; Disables self-update.
+         "ytfzf-updates.patch"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f                      ; no test suite
+       #:modules
+       ((guix build gnu-build-system)
+        (guix build utils)
+        (srfi srfi-26))
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'patch
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             ;; Use correct $PREFIX path.
+             (substitute* "Makefile"
+               (("/usr/bin")
+                (format #f "~a/bin"
+                        (assoc-ref outputs "out"))))
+             ;; Use absolute path to referenced programs.
+             (substitute* "ytfzf"
+               (("guix-catimg")
+                (format #f "~a/bin/catimg"
+                        (assoc-ref inputs "catimg")))
+               (("guix-chafa")
+                (format #f "~a/bin/chafa"
+                        (assoc-ref inputs "chafa")))
+               (("guix-curl")
+                (format #f "~a/bin/curl"
+                        (assoc-ref inputs "curl")))
+               (("guix-dmenu")
+                (format #f "~a/bin/dmenu"
+                        (assoc-ref inputs "dmenu")))
+               (("guix-fzf")
+                (format #f "~a/bin/fzf"
+                        (assoc-ref inputs "fzf")))
+               (("guix-jp2a")
+                (format #f "~a/bin/jp2a"
+                        (assoc-ref inputs "jp2a")))
+               (("guix-jq")
+                (format #f "~a/bin/jq"
+                        (assoc-ref inputs "jq")))
+               (("guix-mpv")
+                (format #f "~a/bin/mpv"
+                        (assoc-ref inputs "mpv")))
+               (("guix-notify-send")
+                (format #f "~a/bin/notify-send"
+                        (assoc-ref inputs "libnotify")))
+               (("guix-tput")
+                (format #f "~a/bin/tput"
+                        (assoc-ref inputs "ncurses")))
+               (("guix-ueberzug")
+                (format #f "~a/bin/ueberzug"
+                        (assoc-ref inputs "python-ueberzug")))
+               (("guix-youtube-dl")
+                (format #f "~a/bin/youtube-dl"
+                        (assoc-ref inputs "youtube-dl"))))))
+         (delete 'configure))))         ;no configure script
+    (inputs
+     `(("catimg" ,catimg)
+       ("chafa" ,chafa)
+       ("curl" ,curl)
+       ("dmenu" ,dmenu)
+       ("fzf" ,fzf)
+       ("jp2a" ,jp2a)
+       ("jq" ,jq)
+       ("libnotify" ,libnotify)
+       ("mpv" ,mpv)
+       ("ncurses" ,ncurses)
+       ("python-ueberzug" ,python-ueberzug)
+       ("youtube-dl" ,youtube-dl)))
+    (synopsis "Find and watch PeerTube or YouTube videos from the terminal")
+    (description "@code{ytfzf} is a POSIX script that helps you find PeerTube or
+YouTube videos without requiring API and opens/downloads them using mpv/ytdl.")
+    (license license:gpl3+)))
+
 (define-public feh
   (package
     (name "feh")
diff --git a/gnu/packages/patches/ytfzf-programs.patch b/gnu/packages/patches/ytfzf-programs.patch
new file mode 100644
index 0000000000..f744c19aeb
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-programs.patch
@@ -0,0 +1,372 @@
+From a5ed861c4d1ee0902650eb6aa68c5ffa17e7fa48 Mon Sep 17 00:00:00 2001
+From: LibreMiami <packaging-guix <at> libremiami.org>
+Date: Sat, 26 Jun 2021 20:23:11 -0400
+Subject: [PATCH 1/2] Modify the strings of referenced programs.
+
+Prefix the strings of referenced programs with the string "guix-", so that they
+can be easily substituted with absolute paths using a custom-phase.
+---
+ ytfzf | 110 +++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 55 insertions(+), 55 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index f4d2e0d..28e320b 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -49,19 +49,19 @@ cache_dir=${YTFZF_CACHE-${cache_dir-$HOME/.cache/ytfzf}}
+ #video type preference (mp4/1080p, mp4/720p, etc..)
+ video_pref=${YTFZF_PREF-${video_pref-}}
+ #the menu to use instead of fzf when -D is specified
+-external_menu=${YTFZF_EXTMENU-${external_menu-dmenu -i -l 30 -p Search:}}
++external_menu=${YTFZF_EXTMENU-${external_menu-guix-dmenu -i -l 30 -p Search:}}
+ #number of columns (characters on a line) the external menu can have
+ #necessary for formatting text for external menus
+ external_menu_len=${YTFZF_EXTMENU_LEN-${external_menu_len-220}}
+ #player settings (players need to support streaming with youtube-dl)
+ #player to use for watching the video
+-video_player=${YTFZF_PLAYER-${video_player-mpv}}
++video_player=${YTFZF_PLAYER-${video_player-guix-mpv}}
+ #if YTFZF_PREF is specified, use this player instead
+-video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-mpv --ytdl-format=}}
++video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-guix-mpv --ytdl-format=}}
+ #player to use for audio only
+-audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-mpv --no-video}}
++audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-guix-mpv --no-video}}
+ #the command to use for displaying thumbnails
+-thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-ueberzug}}
++thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-guix-ueberzug}}
+ #Storing the argument and location for autogenerated subtitles
+ [ -z "$YTFZF_SUBT_NAME" ] && YTFZF_SUBT_NAME=""
+ #Stores the language for the auto genereated subtitles
+@@ -177,12 +177,12 @@ dep_ck () {
+ 	done
+ 	unset Dep
+ }
+-dep_ck "jq" "youtube-dl" "curl"
++dep_ck "guix-jq" "guix-youtube-dl" "guix-curl"
+ 
+ 
+ #only check for mpv if $YTFZF_PLAYER is set to it
+ #don't check $YTFZF_PLAYER as it could be multiple commands
+-[ "$video_player" = "mpv" ] && dep_ck "mpv"
++[ "$video_player" = "guix-mpv" ] && dep_ck "guix-mpv"
+ 
+ ############################
+ #       Help Texts         #
+@@ -326,8 +326,8 @@ print_info () {
+ }
+ 
+ print_error () {
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
++    [ $ext_menu_notifs -eq 1 ] && guix-notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
++    [ $ext_menu_notifs -eq 1 ] && guix-notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
+ }
+ 
+ ############################
+@@ -398,8 +398,8 @@ format_fzf () {
+ format_menu () {
+ 	if [ "$is_ext_menu" -eq 0 ]; then
+ 		#dep_ck fzf here because it is only necessary to use here
+-		dep_ck "fzf"
+-		menu_command='column -t -s "$tab_space" | fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
++		dep_ck "guix-fzf"
++		menu_command='column -t -s "$tab_space" | guix-fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
+ 		format_fzf
+ 	else
+ 		# Dmenu doesn't render tabs so removing it
+@@ -462,7 +462,7 @@ WIDTH=$FZF_PREVIEW_COLUMNS
+ HEIGHT=$FZF_PREVIEW_LINES
+ start_ueberzug () {
+     [ -e $FIFO ] || { mkfifo "$FIFO" || exit 1 ; }
+-    ueberzug layer --parser json --silent < "$FIFO" &
++    guix-ueberzug layer --parser json --silent < "$FIFO" &
+     exec 3>"$FIFO"
+ }
+ stop_ueberzug () {
+@@ -476,12 +476,12 @@ preview_img () {
+ 	shorturl=${args##*${tab_space}|}
+ 	shorturl="${shorturl%% *}"
+ 
+-	json_obj=$(printf "%s" "$videos_json" | jq '.[]|select( .videoID == "'"$shorturl"'")')
++	json_obj=$(printf "%s" "$videos_json" | guix-jq '.[]|select( .videoID == "'"$shorturl"'")')
+ 
+ 
+ 	IFS=$tab_space read -r title channel duration views date description <<-EOF
+ 	$(
+-		printf "%s" "$json_obj" | jq -r \
++		printf "%s" "$json_obj" | guix-jq -r \
+ 		'
+ 		[.title,.channel,.duration,.views,.date,.description]|@tsv
+ 		'
+@@ -530,31 +530,31 @@ preview_img () {
+ 		} > "$FIFO" ;;
+ 	    catimg)
+ 		printf "\n"
+-		catimg -w "$((thumb_width * 2))" "$IMAGE" ;;
++		guix-catimg -w "$((thumb_width * 2))" "$IMAGE" ;;
+ 	    jp2a)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
++		guix-jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
+ 	    jp2a-8)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
++		guix-jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
+ 	    jp2a-4)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
++		guix-jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
+ 	    jp2a-gray|jp2a-grey)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
++		guix-jp2a --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
+ 	    chafa)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
++		guix-chafa --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
+ 	    chafa-gray|chafa-grey)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
++		guix-chafa --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
+ 	    chafa-4)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
++		guix-chafa --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
+ 	    chafa-8)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
++		guix-chafa --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
+ 	    custom)
+ 		if ! function_exists "handle_display_img"; then
+ 		    printf "\033[031mERROR[#07]: \033[0m\033[1mhandle_display_img\033[0m is not defined" >&2
+@@ -585,17 +585,17 @@ download_thumbnails () {
+ 	if [ "$thumbnail_quality" -eq 1 ]; then
+ 		image_download () {
+ 			# higher quality images
+-			curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
++			guix-curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
+ 		}
+ 	else
+ 		image_download () {
+- 			curl -s "$Url"  > "$thumb_dir/$Name.png"
++			guix-curl -s "$Url"  > "$thumb_dir/$Name.png"
+ 		}
+ 	fi
+ 
+ 	print_info "Downloading Thumbnails...\n"
+ 	thumb_urls=$(printf "%s" "$*" |\
+-		jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
++		guix-jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
+ 
+ 	while IFS=$tab_space read -r Url Name; do
+ 	    sleep 0.001
+@@ -668,7 +668,7 @@ get_yt_html () {
+     link=$1
+     query=$2
+     printf "%s" "$(
+-	curl "$link" -s \
++	guix-curl "$link" -s \
+ 	  -G --data-urlencode "search_query=$query" \
+ 	  -G --data-urlencode "sp=$sp" \
+ 	  -H 'Authority: www.youtube.com' \
+@@ -684,7 +684,7 @@ get_video_data () {
+ 	# outputs tab and pipe separated fields: title, channel, view count, video length, video upload date, and the video id/url
+ 	# from the videos_json
+ 	printf "%s" "$*" |\
+-	    jq -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
++	    guix-jq -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
+ }
+ 
+ scrape_channel () {
+@@ -723,7 +723,7 @@ scrape_channel () {
+ 
+ 	#gets a list of videos
+ 	videos_json=$(printf "%s" "$yt_json" |\
+-	jq '[ .contents | ..|.gridVideoRenderer? |
++	guix-jq '[ .contents | ..|.gridVideoRenderer? |
+ 	select(. !=null) |
+ 	    {
+ 	    	title: .title.runs[0].text,
+@@ -736,7 +736,7 @@ scrape_channel () {
+ 	    }
+ 	]')
+ 
+-	videos_json=$(printf "%s" "$videos_json" | jq '.[0:'$sub_link_count']')
++	videos_json=$(printf "%s" "$videos_json" | guix-jq '.[0:'$sub_link_count']')
+ 	printf "%s\n" "$videos_json" >> "$tmp_video_json_file"
+ 	#checks if it's empty in case it was defined in a config function eg: on_get_search
+ 	[ -z "$videos_data" ] && videos_data=$(get_video_data "$videos_json")
+@@ -768,11 +768,11 @@ get_trending_url_data () {
+ scrape_pt () {
+      #gets a list of videos
+      pt_json=$(
+-     curl \
++     guix-curl \
+          -s "https://sepiasearch.org/api/v1/search/videos" \
+ 	 -G --data-urlencode "search=$*") 
+      videos_json=$(printf "%s" "$pt_json" |\
+-	jq '[ .data | .[] |
++	guix-jq '[ .data | .[] |
+ 	    {
+ 		title: .name,
+ 		channel: .channel.displayName,
+@@ -829,7 +829,7 @@ scrape_yt () {
+ 	fi
+ 
+ 	#gets a list of videos
+-	videos_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	videos_json=$(printf "%s" "$yt_json" | guix-jq '[ .contents|
+ 	..|.videoRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -844,7 +844,7 @@ scrape_yt () {
+ 		}
+ 	]')
+ 
+-	playlist_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	playlist_json=$(printf "%s" "$yt_json" | guix-jq '[ .contents|
+ 	..|.playlistRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -919,16 +919,16 @@ user_selection () {
+ 
+ 	#show thumbnail menu
+ 	elif [ "$show_thumbnails" -eq 1 ] ; then
+-		dep_ck "ueberzug" "fzf"
++		dep_ck "guix-ueberzug" "guix-fzf"
+ 		export YTFZF_THUMB_DISP_METHOD="$thumb_disp_method"
+-		[ "$thumb_disp_method" = "ueberzug" ] && start_ueberzug
++		[ "$thumb_disp_method" = "guix-ueberzug" ] && start_ueberzug
+ 		#thumbnails only work in fzf, use fzf
+-		menu_command="fzf -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
++		menu_command="guix-fzf -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
+ 		--nth=1,2 --expect='$shortcuts' $FZF_DEFAULT_OPTS \
+ 		--layout=reverse --preview \"sh $0 -U {}\" \
+         	--preview-window \"$PREVIEW_SIDE:50%:noborder:wrap\""
+ 		selected_data=$( title_len=200 video_menu "$videos_data" )
+-		[ "$thumb_disp_method" = "ueberzug" ] && stop_ueberzug
++		[ "$thumb_disp_method" = "guix-ueberzug" ] && stop_ueberzug
+ 		# Deletes thumbnails if no video is selected
+ 		[ -z "$selected_data" ] && clean_up
+ 	#show regular menu
+@@ -988,7 +988,7 @@ format_user_selection () {
+ 			11) selected_urls=$selected_urls$new_line'https://www.youtube.com/watch?v='$surl ;;
+ 			34) selected_urls=$selected_urls$new_line'https://www.youtube.com/playlist?list='$surl ;;
+ 			36)
+-			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | jq '.[].url' | grep -F "$surl" | tr -d '"')" ;;
++			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | guix-jq '.[].url' | grep -F "$surl" | tr -d '"')" ;;
+ 			*) continue ;;
+ 		esac
+ 		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | grep "|$surl" )
+@@ -1014,7 +1014,7 @@ print_data () {
+ get_video_format () {
+ 	# select format if flag given
+ 	[ $show_format -eq 0 ] && return
+-        formats=$(youtube-dl -F "$(printf "$selected_urls")") 
++        formats=$(guix-youtube-dl -F "$(printf "$selected_urls")")
+         line_number=$(printf "$formats" | grep -n '.*extension  resolution.*' | cut -d: -f1)
+         quality=$(printf "$formats \n1 2 xAudio" | awk -v lineno=$line_number 'FNR > lineno {print $3}' | sort -n |  awk -F"x" '{print $2 "p"}' | uniq | sed -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | sed "s/p//g")
+ 		[ -z "$quality"  ] && exit;
+@@ -1026,9 +1026,9 @@ get_video_format () {
+ get_sub_lang () {
+     if [ $auto_caption -eq 1 ]; then
+         #Gets the auto generated subs and stores them in a file
+-        sub_list=$(youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
++        sub_list=$(guix-youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
+         if [ -n "$sub_list" ]; then
+-            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
++            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  guix-youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
+         fi
+ 	unset sub_list
+     fi
+@@ -1064,9 +1064,9 @@ open_player () {
+ 		fi
+ 	elif [ $is_download -eq 1 ]; then
+ 		if [ -z "$video_pref" ]; then
+-			youtube-dl "$@"  "$YTFZF_SUBT_NAME"
++			guix-youtube-dl "$@"  "$YTFZF_SUBT_NAME"
+ 		else
+-			youtube-dl -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
++			guix-youtube-dl -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
+ 		fi
+ 	fi
+ }
+@@ -1200,7 +1200,7 @@ search_history_menu () {
+     #when using an external menu, the search history will be done there
+         choice=$( printf "%s\n" "$search_history" | eval "$external_menu" )
+     else
+-        choice="$( printf "%s\n" "$search_history" | fzf --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
++        choice="$( printf "%s\n" "$search_history" | guix-fzf --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
+     fi
+ 
+     # first line is the fzf query (what the user types in fzf)
+@@ -1244,7 +1244,7 @@ search_history_menu () {
+ 
+ 	#if downloading, say Downloading not currently playing
+ 	[ $is_download -eq 1 ] && title="Downloading" || title="Currently playing"
+-	notify-send "$title" "$message" -i "$video_thumb"
++	guix-notify-send "$title" "$message" -i "$video_thumb"
+ 
+ 	unset message video_thumb title
+ }
+@@ -1262,7 +1262,7 @@ EOF
+ update_ytfzf () {
+ 	branch="$1"
+ 	updatefile="/tmp/ytfzf-update"
+-	curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
++	guix-curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
+ 
+ 	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then
+ 		chmod 755 "$updatefile"
+@@ -1346,10 +1346,10 @@ create_subs () {
+     : > "$config_dir/subscriptions"
+ 
+     # check how many subscriptions there are in the file
+-    sublength=$( jq '. | length' < "$yt_sub_import_file" )
++    sublength=$( guix-jq '. | length' < "$yt_sub_import_file" )
+ 
+     for i in $(seq $((sublength - 1))); do
+-        channelInfo=$(jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
++        channelInfo=$(guix-jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
+ 	printf "%s\n" "$(printf "%s" "$channelInfo" | tr -d '[]"\n,')" >> "$subscriptions_file"
+     done
+     exit
+@@ -1486,8 +1486,8 @@ parse_opt () {
+ 			exit ;;
+ 		version)
+ 			printf "\033[1mytfzf:\033[0m %s\n" "$YTFZF_VERSION"
+-			printf "\033[1myoutube-dl:\033[0m %s\n" "$(youtube-dl --version)"
+-			command -v "fzf" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(fzf --version)"
++			printf "\033[1myoutube-dl:\033[0m %s\n" "$(guix-youtube-dl --version)"
++			command -v "guix-fzf" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(guix-fzf --version)"
+ 			exit ;;
+ 
+ 		subt)
+@@ -1559,19 +1559,19 @@ done
+ shift $((OPTIND-1))
+ 
+ #only apply to ext_menu since they dont have a terminal to print to
+-[ $is_ext_menu -eq 1 ] && command -v notify-send 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
++[ $is_ext_menu -eq 1 ] && command -v guix-notify-send 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
+ 
+ #used for thumbnail previews in ueberzug
+ if [ $is_ext_menu -eq 0 ]; then
+-	export TTY_LINES=$(tput lines)
+- 	export TTY_COLS=$(tput cols)
++	export TTY_LINES=$(guix-tput lines)
++	export TTY_COLS=$(guix-tput cols)
+ fi
+ 
+ #if both are true, it defaults to using fzf, and if fzf isnt installed it will throw an error
+ #so print this error instead and set $show_thumbnails to 0
+ if [ $is_ext_menu -eq 1 ] && [ $show_thumbnails -eq 1 ]; then
+ 	[ $ext_menu_notifs -eq 1 ] &&\
+-	    notify-send "warning" "Currently thumbnails do not work in external menus" ||\
++	    guix-notify-send "warning" "Currently thumbnails do not work in external menus" ||\
+ 	    printf "\033[33mWARNING: Currently thumbnails do not work in external menus\033[0m\n" >&2
+ 	show_thumbnails=0
+ fi
+-- 
+2.32.0
+
diff --git a/gnu/packages/patches/ytfzf-updates.patch b/gnu/packages/patches/ytfzf-updates.patch
new file mode 100644
index 0000000000..9811bd64be
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-updates.patch
@@ -0,0 +1,41 @@
+From b39ea2784c7616ca1e00bc605bf84b1360f4125f Mon Sep 17 00:00:00 2001
+From: LibreMiami <packaging-guix <at> libremiami.org>
+Date: Sat, 26 Jun 2021 20:34:39 -0400
+Subject: [PATCH 2/2] Disable updates within the application.
+
+---
+ ytfzf | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index 28e320b..69a6f8e 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -1260,22 +1260,8 @@ EOF
+ }
+ 
+ update_ytfzf () {
+-	branch="$1"
+-	updatefile="/tmp/ytfzf-update"
+-	guix-curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
+-
+-	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then
+-		chmod 755 "$updatefile"
+-		[ "$(uname)" = "Darwin" ] && prefix="/usr/local/bin" || prefix="/usr/bin"
+-		function_exists "sudo" && doasroot="sudo" || doasroot="doas"
+-		$doasroot cp "$updatefile" "$prefix/ytfzf"
+-		unset prefix doasroot
+-	else
+-		printf "%bFailed to update ytfzf. Try again later.%b" "$c_red" "$c_reset"
+-	fi
+-
+-	rm "$updatefile"
+-	exit 0
++       printf "%bUpdates have to be installed with Guix.%b\n" "$c_red" "$c_reset"
++       exit 1
+ }
+ 
+ #gives a value to sort by (this will give the unix time the video was uploaded)
+-- 
+2.32.0
+
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Tue, 29 Jun 2021 19:07:02 GMT) Full text and rfc822 format available.

Message #14 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, jgart <jgart <at> dismail.de>,
 LibreMiami <packaging-guix <at> libremiami.org>
Subject: [PATCH v2 1/2] gnu: Add python-ueberzug.
Date: Tue, 29 Jun 2021 15:06:16 -0400
From: LibreMiami <packaging-guix <at> libremiami.org>

* gnu/packages/python-xyz.scm (python-ueberzug): New variable.

Co-authored-by: Raghav Gururajan <rg <at> raghavgururajan.name>
Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/packages/python-xyz.scm | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index 1aa53b7825..f0fbe91b73 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -101,6 +101,7 @@
 ;;; Copyright © 2021 LibreMiami <packaging-guix <at> libremiami.org>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;; Copyright © 2021 Danial Behzadi <dani.behzi <at> ubuntu.com>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -221,6 +222,42 @@
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26))
 
+(define-public python-ueberzug
+  (package
+    (name "python-ueberzug")
+    (version "18.1.9")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "ueberzug" version))
+       (sha256
+        (base32
+         "1hxd45dnwa9yv908acarr98n2drmar66wzq9z2qd3irj24srzr3w"))))
+    (build-system python-build-system)
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)))
+    (propagated-inputs
+     `(("python-attrs" ,python-attrs)
+       ("python-docopt" ,python-docopt)
+       ("python-pillow" ,python-pillow)
+       ("python-xlib" ,python-xlib)))
+    (home-page "https://github.com/seebye/ueberzug")
+    (synopsis "Command line util to display images in combination with X11")
+    (description "Überzug is a command line util which allows to draw images on
+terminals by using child windows.  The advantages of using Überzug are:
+@itemize
+@item No race conditions as a new window is created to display images.
+@item Expose events will be processed, so images will be redrawn on switch
+workspaces.
+@item Tmux support (excluding multi pane windows).
+@item Terminals without the WINDOWID environment variable are supported.
+@item Chars are used as position - and size unit.
+@item No memory leak (/ unlimited cache).
+@end itemize")
+    (license license:gpl3+)))
+
+
 (define-public python-fire
   (package
     (name "python-fire")
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Tue, 29 Jun 2021 19:07:02 GMT) Full text and rfc822 format available.

Message #17 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, jgart <jgart <at> dismail.de>,
 LibreMiami <packaging-guix <at> libremiami.org>
Subject: [PATCH v2 2/2] gnu: Add ytfzf.
Date: Tue, 29 Jun 2021 15:06:17 -0400
From: LibreMiami <packaging-guix <at> libremiami.org>

* gnu/packages/image-viewers.scm (ytfzf): New variable.

Co-authored-by: Raghav Gururajan <rg <at> raghavgururajan.name>
Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/local.mk                              |   2 +
 gnu/packages/image-viewers.scm            | 102 ++++++
 gnu/packages/patches/ytfzf-programs.patch | 372 ++++++++++++++++++++++
 gnu/packages/patches/ytfzf-updates.patch  |  41 +++
 4 files changed, 517 insertions(+)
 create mode 100644 gnu/packages/patches/ytfzf-programs.patch
 create mode 100644 gnu/packages/patches/ytfzf-updates.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 6b9202cba1..919a0d4a34 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1858,6 +1858,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/xsane-support-ipv6.patch			\
   %D%/packages/patches/xsane-tighten-default-umask.patch	\
   %D%/packages/patches/yggdrasil-extra-config.patch	\
+  %D%/packages/patches/ytfzf-programs.patch        \
+  %D%/packages/patches/ytfzf-updates.patch        \
   %D%/packages/patches/ytnef-CVE-2021-3403.patch	\
   %D%/packages/patches/ytnef-CVE-2021-3404.patch	\
   %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch	\
diff --git a/gnu/packages/image-viewers.scm b/gnu/packages/image-viewers.scm
index f01b6a614a..e6c8cfbe8c 100644
--- a/gnu/packages/image-viewers.scm
+++ b/gnu/packages/image-viewers.scm
@@ -18,6 +18,8 @@
 ;;; Copyright © 2021 Rovanion Luckey <rovanion.luckey <at> gmail.com>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Stefan Reichör <stefan <at> xsteve.at>
+;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -46,6 +48,7 @@
   #:use-module (guix build-system python)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages algebra)
+  #:use-module (gnu packages base)
   #:use-module (gnu packages boost)
   #:use-module (gnu packages check)
   #:use-module (gnu packages compression)
@@ -64,6 +67,7 @@
   #:use-module (gnu packages image-processing)
   #:use-module (gnu packages imagemagick)
   #:use-module (gnu packages maths)
+  #:use-module (gnu packages ncurses)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages perl-check)
   #:use-module (gnu packages photo)
@@ -71,10 +75,108 @@
   #:use-module (gnu packages python)
   #:use-module (gnu packages python-xyz)
   #:use-module (gnu packages qt)
+  #:use-module (gnu packages suckless)
+  #:use-module (gnu packages terminals)
+  #:use-module (gnu packages video)
+  #:use-module (gnu packages web)
   #:use-module (gnu packages xdisorg)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages))
 
+(define-public ytfzf
+  (package
+    (name "ytfzf")
+    (version "1.2.0")
+    (home-page "https://github.com/pystardust/ytfzf")
+    (source
+     (origin
+       (method git-fetch)
+       (uri
+        (git-reference
+         (url home-page)
+         (commit (string-append "v" version))))
+       (file-name (git-file-name name version))
+       (sha256
+        (base32 "00d416qb4109pm77ikhnmds8qng90ni2jan9kdnxz7b6sh5f61nz"))
+       (patches
+        (search-patches
+         ;; Pre-requisite for 'patch' phase.
+         "ytfzf-programs.patch"
+         ;; Disables self-update.
+         "ytfzf-updates.patch"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f                      ; no test suite
+       #:modules
+       ((guix build gnu-build-system)
+        (guix build utils)
+        (srfi srfi-26))
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'patch
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             ;; Use correct $PREFIX path.
+             (substitute* "Makefile"
+               (("/usr/bin")
+                (format #f "~a/bin"
+                        (assoc-ref outputs "out"))))
+             ;; Use absolute path to referenced programs.
+             (substitute* "ytfzf"
+               (("@catimg@")
+                (format #f "~a/bin/catimg"
+                        (assoc-ref inputs "catimg")))
+               (("@chafa@")
+                (format #f "~a/bin/chafa"
+                        (assoc-ref inputs "chafa")))
+               (("@curl@")
+                (format #f "~a/bin/curl"
+                        (assoc-ref inputs "curl")))
+               (("@dmenu@")
+                (format #f "~a/bin/dmenu"
+                        (assoc-ref inputs "dmenu")))
+               (("@fzf@")
+                (format #f "~a/bin/fzf"
+                        (assoc-ref inputs "fzf")))
+               (("@jp2a@")
+                (format #f "~a/bin/jp2a"
+                        (assoc-ref inputs "jp2a")))
+               (("@jq@")
+                (format #f "~a/bin/jq"
+                        (assoc-ref inputs "jq")))
+               (("@mpv@")
+                (format #f "~a/bin/mpv"
+                        (assoc-ref inputs "mpv")))
+               (("@notify-send@")
+                (format #f "~a/bin/notify-send"
+                        (assoc-ref inputs "libnotify")))
+               (("@tput@")
+                (format #f "~a/bin/tput"
+                        (assoc-ref inputs "ncurses")))
+               (("@ueberzug@")
+                (format #f "~a/bin/ueberzug"
+                        (assoc-ref inputs "python-ueberzug")))
+               (("@youtube-dl@")
+                (format #f "~a/bin/youtube-dl"
+                        (assoc-ref inputs "youtube-dl"))))))
+         (delete 'configure))))         ;no configure script
+    (inputs
+     `(("catimg" ,catimg)
+       ("chafa" ,chafa)
+       ("curl" ,curl)
+       ("dmenu" ,dmenu)
+       ("fzf" ,fzf)
+       ("jp2a" ,jp2a)
+       ("jq" ,jq)
+       ("libnotify" ,libnotify)
+       ("mpv" ,mpv)
+       ("ncurses" ,ncurses)
+       ("python-ueberzug" ,python-ueberzug)
+       ("youtube-dl" ,youtube-dl)))
+    (synopsis "Find and watch PeerTube or YouTube videos from the terminal")
+    (description "@code{ytfzf} is a POSIX script that helps you find PeerTube or
+YouTube videos without requiring API and opens/downloads them using mpv/ytdl.")
+    (license license:gpl3+)))
+
 (define-public feh
   (package
     (name "feh")
diff --git a/gnu/packages/patches/ytfzf-programs.patch b/gnu/packages/patches/ytfzf-programs.patch
new file mode 100644
index 0000000000..efcd70823a
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-programs.patch
@@ -0,0 +1,372 @@
+From 8a796549d756a40a174954d2858d4c5042e3808f Mon Sep 17 00:00:00 2001
+From: LibreMiami <packaging-guix <at> libremiami.org>
+Date: Sat, 26 Jun 2021 20:23:11 -0400
+Subject: [PATCH 1/2] Modify the strings of referenced programs.
+
+Pattern the strings of referenced programs, so that they can be easily
+substituted with absolute paths using a custom-phase.
+---
+ ytfzf | 110 +++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 55 insertions(+), 55 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index f4d2e0d..2d917df 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -49,19 +49,19 @@ cache_dir=${YTFZF_CACHE-${cache_dir-$HOME/.cache/ytfzf}}
+ #video type preference (mp4/1080p, mp4/720p, etc..)
+ video_pref=${YTFZF_PREF-${video_pref-}}
+ #the menu to use instead of fzf when -D is specified
+-external_menu=${YTFZF_EXTMENU-${external_menu-dmenu -i -l 30 -p Search:}}
++external_menu=${YTFZF_EXTMENU-${external_menu-@dmenu@ -i -l 30 -p Search:}}
+ #number of columns (characters on a line) the external menu can have
+ #necessary for formatting text for external menus
+ external_menu_len=${YTFZF_EXTMENU_LEN-${external_menu_len-220}}
+ #player settings (players need to support streaming with youtube-dl)
+ #player to use for watching the video
+-video_player=${YTFZF_PLAYER-${video_player-mpv}}
++video_player=${YTFZF_PLAYER-${video_player-@mpv@}}
+ #if YTFZF_PREF is specified, use this player instead
+-video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-mpv --ytdl-format=}}
++video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-@mpv@ --ytdl-format=}}
+ #player to use for audio only
+-audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-mpv --no-video}}
++audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-@mpv@ --no-video}}
+ #the command to use for displaying thumbnails
+-thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-ueberzug}}
++thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-@ueberzug@}}
+ #Storing the argument and location for autogenerated subtitles
+ [ -z "$YTFZF_SUBT_NAME" ] && YTFZF_SUBT_NAME=""
+ #Stores the language for the auto genereated subtitles
+@@ -177,12 +177,12 @@ dep_ck () {
+ 	done
+ 	unset Dep
+ }
+-dep_ck "jq" "youtube-dl" "curl"
++dep_ck "@jq@" "@youtube-dl@" "@curl@"
+ 
+ 
+ #only check for mpv if $YTFZF_PLAYER is set to it
+ #don't check $YTFZF_PLAYER as it could be multiple commands
+-[ "$video_player" = "mpv" ] && dep_ck "mpv"
++[ "$video_player" = "@mpv@" ] && dep_ck "@mpv@"
+ 
+ ############################
+ #       Help Texts         #
+@@ -326,8 +326,8 @@ print_info () {
+ }
+ 
+ print_error () {
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
++    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "error" "$*" || printf "\033[31m$*\033[0m" >&2
++    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
+ }
+ 
+ ############################
+@@ -398,8 +398,8 @@ format_fzf () {
+ format_menu () {
+ 	if [ "$is_ext_menu" -eq 0 ]; then
+ 		#dep_ck fzf here because it is only necessary to use here
+-		dep_ck "fzf"
+-		menu_command='column -t -s "$tab_space" | fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
++		dep_ck "@fzf@"
++		menu_command='column -t -s "$tab_space" | @fzf@ -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
+ 		format_fzf
+ 	else
+ 		# Dmenu doesn't render tabs so removing it
+@@ -462,7 +462,7 @@ WIDTH=$FZF_PREVIEW_COLUMNS
+ HEIGHT=$FZF_PREVIEW_LINES
+ start_ueberzug () {
+     [ -e $FIFO ] || { mkfifo "$FIFO" || exit 1 ; }
+-    ueberzug layer --parser json --silent < "$FIFO" &
++    @ueberzug@ layer --parser json --silent < "$FIFO" &
+     exec 3>"$FIFO"
+ }
+ stop_ueberzug () {
+@@ -476,12 +476,12 @@ preview_img () {
+ 	shorturl=${args##*${tab_space}|}
+ 	shorturl="${shorturl%% *}"
+ 
+-	json_obj=$(printf "%s" "$videos_json" | jq '.[]|select( .videoID == "'"$shorturl"'")')
++	json_obj=$(printf "%s" "$videos_json" | @jq@ '.[]|select( .videoID == "'"$shorturl"'")')
+ 
+ 
+ 	IFS=$tab_space read -r title channel duration views date description <<-EOF
+ 	$(
+-		printf "%s" "$json_obj" | jq -r \
++		printf "%s" "$json_obj" | @jq@ -r \
+ 		'
+ 		[.title,.channel,.duration,.views,.date,.description]|@tsv
+ 		'
+@@ -530,31 +530,31 @@ preview_img () {
+ 		} > "$FIFO" ;;
+ 	    catimg)
+ 		printf "\n"
+-		catimg -w "$((thumb_width * 2))" "$IMAGE" ;;
++		@catimg@ -w "$((thumb_width * 2))" "$IMAGE" ;;
+ 	    jp2a)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
+ 	    jp2a-8)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
+ 	    jp2a-4)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
+ 	    jp2a-gray|jp2a-grey)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
+ 	    chafa)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
+ 	    chafa-gray|chafa-grey)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
+ 	    chafa-4)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
+ 	    chafa-8)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
+ 	    custom)
+ 		if ! function_exists "handle_display_img"; then
+ 		    printf "\033[031mERROR[#07]: \033[0m\033[1mhandle_display_img\033[0m is not defined" >&2
+@@ -585,17 +585,17 @@ download_thumbnails () {
+ 	if [ "$thumbnail_quality" -eq 1 ]; then
+ 		image_download () {
+ 			# higher quality images
+-			curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
++			@curl@ -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
+ 		}
+ 	else
+ 		image_download () {
+- 			curl -s "$Url"  > "$thumb_dir/$Name.png"
++			@curl@ -s "$Url"  > "$thumb_dir/$Name.png"
+ 		}
+ 	fi
+ 
+ 	print_info "Downloading Thumbnails...\n"
+ 	thumb_urls=$(printf "%s" "$*" |\
+-		jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
++		@jq@  -r '.[]|[.thumbs,.videoID]|@tsv' )
+ 
+ 	while IFS=$tab_space read -r Url Name; do
+ 	    sleep 0.001
+@@ -668,7 +668,7 @@ get_yt_html () {
+     link=$1
+     query=$2
+     printf "%s" "$(
+-	curl "$link" -s \
++	@curl@ "$link" -s \
+ 	  -G --data-urlencode "search_query=$query" \
+ 	  -G --data-urlencode "sp=$sp" \
+ 	  -H 'Authority: www.youtube.com' \
+@@ -684,7 +684,7 @@ get_video_data () {
+ 	# outputs tab and pipe separated fields: title, channel, view count, video length, video upload date, and the video id/url
+ 	# from the videos_json
+ 	printf "%s" "$*" |\
+-	    jq -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
++	    @jq@ -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
+ }
+ 
+ scrape_channel () {
+@@ -723,7 +723,7 @@ scrape_channel () {
+ 
+ 	#gets a list of videos
+ 	videos_json=$(printf "%s" "$yt_json" |\
+-	jq '[ .contents | ..|.gridVideoRenderer? |
++	@jq@ '[ .contents | ..|.gridVideoRenderer? |
+ 	select(. !=null) |
+ 	    {
+ 	    	title: .title.runs[0].text,
+@@ -736,7 +736,7 @@ scrape_channel () {
+ 	    }
+ 	]')
+ 
+-	videos_json=$(printf "%s" "$videos_json" | jq '.[0:'$sub_link_count']')
++	videos_json=$(printf "%s" "$videos_json" | @jq@ '.[0:'$sub_link_count']')
+ 	printf "%s\n" "$videos_json" >> "$tmp_video_json_file"
+ 	#checks if it's empty in case it was defined in a config function eg: on_get_search
+ 	[ -z "$videos_data" ] && videos_data=$(get_video_data "$videos_json")
+@@ -768,11 +768,11 @@ get_trending_url_data () {
+ scrape_pt () {
+      #gets a list of videos
+      pt_json=$(
+-     curl \
++     @curl@ \
+          -s "https://sepiasearch.org/api/v1/search/videos" \
+ 	 -G --data-urlencode "search=$*") 
+      videos_json=$(printf "%s" "$pt_json" |\
+-	jq '[ .data | .[] |
++	@jq@ '[ .data | .[] |
+ 	    {
+ 		title: .name,
+ 		channel: .channel.displayName,
+@@ -829,7 +829,7 @@ scrape_yt () {
+ 	fi
+ 
+ 	#gets a list of videos
+-	videos_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	videos_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
+ 	..|.videoRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -844,7 +844,7 @@ scrape_yt () {
+ 		}
+ 	]')
+ 
+-	playlist_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	playlist_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
+ 	..|.playlistRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -919,16 +919,16 @@ user_selection () {
+ 
+ 	#show thumbnail menu
+ 	elif [ "$show_thumbnails" -eq 1 ] ; then
+-		dep_ck "ueberzug" "fzf"
++		dep_ck "@ueberzug@" "@fzf@"
+ 		export YTFZF_THUMB_DISP_METHOD="$thumb_disp_method"
+-		[ "$thumb_disp_method" = "ueberzug" ] && start_ueberzug
++		[ "$thumb_disp_method" = "@ueberzug@" ] && start_ueberzug
+ 		#thumbnails only work in fzf, use fzf
+-		menu_command="fzf -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
++		menu_command="@fzf@ -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
+ 		--nth=1,2 --expect='$shortcuts' $FZF_DEFAULT_OPTS \
+ 		--layout=reverse --preview \"sh $0 -U {}\" \
+         	--preview-window \"$PREVIEW_SIDE:50%:noborder:wrap\""
+ 		selected_data=$( title_len=200 video_menu "$videos_data" )
+-		[ "$thumb_disp_method" = "ueberzug" ] && stop_ueberzug
++		[ "$thumb_disp_method" = "@ueberzug@" ] && stop_ueberzug
+ 		# Deletes thumbnails if no video is selected
+ 		[ -z "$selected_data" ] && clean_up
+ 	#show regular menu
+@@ -988,7 +988,7 @@ format_user_selection () {
+ 			11) selected_urls=$selected_urls$new_line'https://www.youtube.com/watch?v='$surl ;;
+ 			34) selected_urls=$selected_urls$new_line'https://www.youtube.com/playlist?list='$surl ;;
+ 			36)
+-			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | jq '.[].url' | grep -F "$surl" | tr -d '"')" ;;
++			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | @jq@ '.[].url' | grep -F "$surl" | tr -d '"')" ;;
+ 			*) continue ;;
+ 		esac
+ 		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | grep "|$surl" )
+@@ -1014,7 +1014,7 @@ print_data () {
+ get_video_format () {
+ 	# select format if flag given
+ 	[ $show_format -eq 0 ] && return
+-        formats=$(youtube-dl -F "$(printf "$selected_urls")") 
++        formats=$(@youtube-dl@ -F "$(printf "$selected_urls")")
+         line_number=$(printf "$formats" | grep -n '.*extension  resolution.*' | cut -d: -f1)
+         quality=$(printf "$formats \n1 2 xAudio" | awk -v lineno=$line_number 'FNR > lineno {print $3}' | sort -n |  awk -F"x" '{print $2 "p"}' | uniq | sed -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | sed "s/p//g")
+ 		[ -z "$quality"  ] && exit;
+@@ -1026,9 +1026,9 @@ get_video_format () {
+ get_sub_lang () {
+     if [ $auto_caption -eq 1 ]; then
+         #Gets the auto generated subs and stores them in a file
+-        sub_list=$(youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
++        sub_list=$(@youtube-dl@ --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
+         if [ -n "$sub_list" ]; then
+-            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
++            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  @youtube-dl@  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
+         fi
+ 	unset sub_list
+     fi
+@@ -1064,9 +1064,9 @@ open_player () {
+ 		fi
+ 	elif [ $is_download -eq 1 ]; then
+ 		if [ -z "$video_pref" ]; then
+-			youtube-dl "$@"  "$YTFZF_SUBT_NAME"
++			@youtube-dl@ "$@"  "$YTFZF_SUBT_NAME"
+ 		else
+-			youtube-dl -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
++			@youtube-dl@ -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
+ 		fi
+ 	fi
+ }
+@@ -1200,7 +1200,7 @@ search_history_menu () {
+     #when using an external menu, the search history will be done there
+         choice=$( printf "%s\n" "$search_history" | eval "$external_menu" )
+     else
+-        choice="$( printf "%s\n" "$search_history" | fzf --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
++        choice="$( printf "%s\n" "$search_history" | @fzf@ --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
+     fi
+ 
+     # first line is the fzf query (what the user types in fzf)
+@@ -1244,7 +1244,7 @@ search_history_menu () {
+ 
+ 	#if downloading, say Downloading not currently playing
+ 	[ $is_download -eq 1 ] && title="Downloading" || title="Currently playing"
+-	notify-send "$title" "$message" -i "$video_thumb"
++	@notify-send@ "$title" "$message" -i "$video_thumb"
+ 
+ 	unset message video_thumb title
+ }
+@@ -1262,7 +1262,7 @@ EOF
+ update_ytfzf () {
+ 	branch="$1"
+ 	updatefile="/tmp/ytfzf-update"
+-	curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
++	@curl@ -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
+ 
+ 	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then
+ 		chmod 755 "$updatefile"
+@@ -1346,10 +1346,10 @@ create_subs () {
+     : > "$config_dir/subscriptions"
+ 
+     # check how many subscriptions there are in the file
+-    sublength=$( jq '. | length' < "$yt_sub_import_file" )
++    sublength=$( @jq@ '. | length' < "$yt_sub_import_file" )
+ 
+     for i in $(seq $((sublength - 1))); do
+-        channelInfo=$(jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
++        channelInfo=$(@jq@ --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
+ 	printf "%s\n" "$(printf "%s" "$channelInfo" | tr -d '[]"\n,')" >> "$subscriptions_file"
+     done
+     exit
+@@ -1486,8 +1486,8 @@ parse_opt () {
+ 			exit ;;
+ 		version)
+ 			printf "\033[1mytfzf:\033[0m %s\n" "$YTFZF_VERSION"
+-			printf "\033[1myoutube-dl:\033[0m %s\n" "$(youtube-dl --version)"
+-			command -v "fzf" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(fzf --version)"
++			printf "\033[1myoutube-dl:\033[0m %s\n" "$(@youtube-dl@ --version)"
++			command -v "@fzf@" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(@fzf@ --version)"
+ 			exit ;;
+ 
+ 		subt)
+@@ -1559,19 +1559,19 @@ done
+ shift $((OPTIND-1))
+ 
+ #only apply to ext_menu since they dont have a terminal to print to
+-[ $is_ext_menu -eq 1 ] && command -v notify-send 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
++[ $is_ext_menu -eq 1 ] && command -v @notify-send@ 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
+ 
+ #used for thumbnail previews in ueberzug
+ if [ $is_ext_menu -eq 0 ]; then
+-	export TTY_LINES=$(tput lines)
+- 	export TTY_COLS=$(tput cols)
++	export TTY_LINES=$(@tput@ lines)
++	export TTY_COLS=$(@tput@ cols)
+ fi
+ 
+ #if both are true, it defaults to using fzf, and if fzf isnt installed it will throw an error
+ #so print this error instead and set $show_thumbnails to 0
+ if [ $is_ext_menu -eq 1 ] && [ $show_thumbnails -eq 1 ]; then
+ 	[ $ext_menu_notifs -eq 1 ] &&\
+-	    notify-send "warning" "Currently thumbnails do not work in external menus" ||\
++	    @notify-send@ "warning" "Currently thumbnails do not work in external menus" ||\
+ 	    printf "\033[33mWARNING: Currently thumbnails do not work in external menus\033[0m\n" >&2
+ 	show_thumbnails=0
+ fi
+-- 
+2.32.0
+
diff --git a/gnu/packages/patches/ytfzf-updates.patch b/gnu/packages/patches/ytfzf-updates.patch
new file mode 100644
index 0000000000..3cdc12b015
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-updates.patch
@@ -0,0 +1,41 @@
+From 374bd725ad5e52931d9ffeb1563ba31eb298aa5c Mon Sep 17 00:00:00 2001
+From: LibreMiami <packaging-guix <at> libremiami.org>
+Date: Sat, 26 Jun 2021 20:34:39 -0400
+Subject: [PATCH 2/2] Disable updates within the application.
+
+---
+ ytfzf | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index 2d917df..7b0b227 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -1260,22 +1260,8 @@ EOF
+ }
+ 
+ update_ytfzf () {
+-	branch="$1"
+-	updatefile="/tmp/ytfzf-update"
+-	@curl@ -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
+-
+-	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then
+-		chmod 755 "$updatefile"
+-		[ "$(uname)" = "Darwin" ] && prefix="/usr/local/bin" || prefix="/usr/bin"
+-		function_exists "sudo" && doasroot="sudo" || doasroot="doas"
+-		$doasroot cp "$updatefile" "$prefix/ytfzf"
+-		unset prefix doasroot
+-	else
+-		printf "%bFailed to update ytfzf. Try again later.%b" "$c_red" "$c_reset"
+-	fi
+-
+-	rm "$updatefile"
+-	exit 0
++       printf "%bUpdates have to be installed with Guix.%b\n" "$c_red" "$c_reset"
++       exit 1
+ }
+ 
+ #gives a value to sort by (this will give the unix time the video was uploaded)
+-- 
+2.32.0
+
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Wed, 30 Jun 2021 19:39:01 GMT) Full text and rfc822 format available.

Message #20 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: Raghav Gururajan <rg <at> raghavgururajan.name>, 49238 <at> debbugs.gnu.org
Cc: jgart <at> dismail.de, LibreMiami <packaging-guix <at> libremiami.org>
Subject: Re: [bug#49238] [PATCH v1 2/2] gnu: Add ytfzf.
Date: Wed, 30 Jun 2021 21:38:15 +0200
[Message part 1 (text/plain, inline)]
Raghav Gururajan via Guix-patches via schreef op zo 27-06-2021 om 01:47 [-0400]:
> +       (patches
> +        (search-patches
> +         ;; Prerequisite for 'patch phase.
> +         "ytfzf-programs.patch"

That's a neat trick to avoid fragile (substitute* ...).
However, as I understand it, the origin is meant to be
usable as source code (think install dependencies && guix build && tar xzf stuff.tgz
&& ./configure && make && try it out), such that
"guix build --source=transitive stuff" would give all the
source code for building stuff (in the sense of ‘Corresponding Source’
of the GPL), and "guix-mpv", 'guix-jq" ... don't exist anywhere.

I don't know if that has been spelled out somewhere though.

I'd suggest adding "patch" to 'native-inputs', adding the patch
to 'inputs' or 'native-inputs' (doesn't really matter which) and
doing (invoke "patch" OPTIONS "blabla.patch") before the substitute*.

Actually, myself I'm not convinced because you could consider
the package definition itself to be part of the ‘corresponding source’.

> +             (substitute* "ytfzf"
> +               (("guix-catimg")
> +                (format #f "~a/bin/catimg"
> +                        (assoc-ref inputs "catimg")))

I'm wondering if (string-append (assoc-ref inputs "catimg") "/bin/catimg")
would be better, as 'string-append' is less complex than 'format'
and "format" doesn't seem to provide any additional value here.

Now about the patch:

> + ############################
> + #       Help Texts         #
> +@@ -326,8 +326,8 @@ print_info () {
> + }
> + 
> + print_error () {
> +-    [ $ext_menu_notifs -eq 1 ] && notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
> +-    [ $ext_menu_notifs -eq 1 ] && notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
> ++    [ $ext_menu_notifs -eq 1 ] && guix-notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
> ++    [ $ext_menu_notifs -eq 1 ] && guix-notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2

Maybe tell people to report issues at bug-guix <at> gnu.org or #guix? Dunno

> + }
> + 
> + ############################
> +@@ -398,8 +398,8 @@ format_fzf () {
> + format_menu () {
> + 	if [ "$is_ext_menu" -eq 0 ]; then
> + 		#dep_ck fzf here because it is only necessary to use here
> +-		dep_ck "fzf"
> +-		menu_command='column -t -s "$tab_space" | fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
> ++		dep_ck "guix-fzf"
> ++		menu_command='column -t -s "$tab_space" | guix-fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
> + 		format_fzf

Don't forget to patch 'column'.

> + 	else
> + 		# Dmenu doesn't render tabs so removing it
> +@@ -462,7 +462,7 @@ WIDTH=$FZF_PREVIEW_COLUMNS
> + HEIGHT=$FZF_PREVIEW_LINES
> + start_ueberzug () {
> +     [ -e $FIFO ] || { mkfifo "$FIFO" || exit 1 ; }
> +-    ueberzug layer --parser json --silent < "$FIFO" &
> ++    guix-ueberzug layer --parser json --silent < "$FIFO" &
> +     exec 3>"$FIFO"
> + }
> + stop_ueberzug () {

Don't forget to patch "mkfifo".

> +@@ -585,17 +585,17 @@ download_thumbnails () {
> + 	if [ "$thumbnail_quality" -eq 1 ]; then
> + 		image_download () {
> + 			# higher quality images
> +-			curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
> ++			guix-curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
> + 		}
> + 	else
> + 		image_download () {
> +- 			curl -s "$Url"  > "$thumb_dir/$Name.png"
> ++			guix-curl -s "$Url"  > "$thumb_dir/$Name.png"
> + 		}
> + 	fi
> + 
> + 	print_info "Downloading Thumbnails...\n"
> + 	thumb_urls=$(printf "%s" "$*" |\
> +-		jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
> ++		guix-jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
> + 
> + 	while IFS=$tab_space read -r Url Name; do
> + 	    sleep 0.001
> 

Don't forget patching 'sleep'. It is not shell a built-in
(try "type sleep" and "type [" in a terminal").


> +@@ -988,7 +988,7 @@ format_user_selection () {
> + 			11) selected_urls=$selected_urls$new_line'https://www.youtube.com/watch?v='$surl ;;
> + 			34) selected_urls=$selected_urls$new_line'https://www.youtube.com/playlist?list='$surl ;;
> + 			36)
> +-			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | jq '.[].url' | grep -F "$surl" | tr -d '"')" ;;
> ++			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | guix-jq '.[].url' | grep -F "$surl" | tr -d '"')

Don't forget patching 'grep' and 'tr'.

> " ;;
> + 			*) continue ;;
> + 		esac
> + 		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | grep "|$surl" )
> +@@ -1014,7 +1014,7 @@ print_data () {
> + get_video_format () {
> + 	# select format if flag given
> + 	[ $show_format -eq 0 ] && return
> +-        formats=$(youtube-dl -F "$(printf "$selected_urls")") 
> ++        formats=$(guix-youtube-dl -F "$(printf "$selected_urls")")
> +         line_number=$(printf "$formats" | grep -n '.*extension  resolution.*' | cut -d: -f1)

Don't forget 'grep -> guix-grep' and 'cut -> guix-cut'

> +         quality=$(printf "$formats \n1 2 xAudio" | awk -v lineno=$line_number 'FNR > lineno {print $3}' | sort -n |  awk -F"x" '{print $2 "p"}' | uniq | sed -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | sed "s/p//g")

Don't forget 'awk -> guix-awk' and 'sort -> guix-sort' and 'uniq -> 'guix-uniq'

> + 		[ -z "$quality"  ] && exit;
> +@@ -1026,9 +1026,9 @@ get_video_format () {
> + get_sub_lang () {
> +     if [ $auto_caption -eq 1 ]; then
> +         #Gets the auto generated subs and stores them in a file
> +-        sub_list=$(youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
> ++        sub_list=$(guix-youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')

Don't forget 'sed -> guix-sed' and 'awk -> guix-awk'

> +         if [ -n "$sub_list" ]; then
> +-            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
> ++            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  guix-youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."

FWIW, writing to "/tmp/ytfzf" seems to be a potential security problem
and bad behaviour on multiple-user systems.

What would happen if /tmp/ytfzf is a symlink to /etc/passwd an ytfzf is run
as root (yes, running as root is not recommended)? Would that brick the system?
What if /tmp/ytfzf is a symlink to ~/.profile? Would that brick the login?

What if multiple users run ytfzf concurrently? Would they overwrite eaech
other subtitles?  Would a different user be able to see what the other
is downloading?

A relatively easy fix would be to write to, say, $HOME/.cache/ytzf-subs
instead (not sure what the proper directory would be), which is completely
under the user's control.

> +@@ -1262,7 +1262,7 @@ EOF
> + update_ytfzf () {
> + 	branch="$1"
> + 	updatefile="/tmp/ytfzf-update"
> +-	curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
> ++	guix-curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
> + 
> + 	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then

FWIW, as update-ytfzf will be more-or-less deleted
in the next patch, don't forget to patch 'sed' and 'grep'

> + 		chmod 755 "$updatefile"
> +@@ -1346,10 +1346,10 @@ create_subs () {
> +     : > "$config_dir/subscriptions"
> + 
> +     # check how many subscriptions there are in the file
> +-    sublength=$( jq '. | length' < "$yt_sub_import_file" )
> ++    sublength=$( guix-jq '. | length' < "$yt_sub_import_file" )
> + 
> +     for i in $(seq $((sublength - 1))); do
> +-        channelInfo=$(jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
> ++        channelInfo=$(guix-jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
> + 	printf "%s\n" "$(printf "%s" "$channelInfo" | tr -d '[]"\n,')" >> "$subscriptions_file"

And don't forget 'tr'.

Greetings,
Maxime.
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 11:15:01 GMT) Full text and rfc822 format available.

Message #23 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, jgart <jgart <at> dismail.de>
Subject: [PATCH v3 1/2] gnu: Add python-ueberzug.
Date: Mon,  5 Jul 2021 07:14:24 -0400
* gnu/packages/python-xyz.scm (python-ueberzug): New variable.

Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/packages/python-xyz.scm | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index b74b3b808f..aa2406287d 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -101,6 +101,7 @@
 ;;; Copyright © 2021 LibreMiami <packaging-guix <at> libremiami.org>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;; Copyright © 2021 Danial Behzadi <dani.behzi <at> ubuntu.com>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -221,6 +222,41 @@
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26))
 
+(define-public python-ueberzug
+  (package
+    (name "python-ueberzug")
+    (version "18.1.9")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "ueberzug" version))
+       (sha256
+        (base32
+         "1hxd45dnwa9yv908acarr98n2drmar66wzq9z2qd3irj24srzr3w"))))
+    (build-system python-build-system)
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)))
+    (propagated-inputs
+     `(("python-attrs" ,python-attrs)
+       ("python-docopt" ,python-docopt)
+       ("python-pillow" ,python-pillow)
+       ("python-xlib" ,python-xlib)))
+    (home-page "https://github.com/seebye/ueberzug")
+    (synopsis "Command line util to display images in combination with X11")
+    (description "Überzug is a command line util which allows to draw images on
+terminals by using child windows.  The advantages of using Überzug are:
+@itemize
+@item No race conditions as a new window is created to display images.
+@item Expose events will be processed, so images will be redrawn on switch
+workspaces.
+@item Tmux support (excluding multi pane windows).
+@item Terminals without the WINDOWID environment variable are supported.
+@item Chars are used as position - and size unit.
+@item No memory leak (/ unlimited cache).
+@end itemize")
+    (license license:gpl3+)))
+
 (define-public python-fire
   (package
     (name "python-fire")
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 11:15:01 GMT) Full text and rfc822 format available.

Message #26 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, jgart <jgart <at> dismail.de>
Subject: [PATCH v3 2/2] gnu: Add ytfzf.
Date: Mon,  5 Jul 2021 07:14:25 -0400
* gnu/packages/image-viewers.scm (ytfzf): New variable.

Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/local.mk                              |   2 +
 gnu/packages/image-viewers.scm            | 160 ++++++
 gnu/packages/patches/ytfzf-programs.patch | 650 ++++++++++++++++++++++
 gnu/packages/patches/ytfzf-updates.patch  |  44 ++
 4 files changed, 856 insertions(+)
 create mode 100644 gnu/packages/patches/ytfzf-programs.patch
 create mode 100644 gnu/packages/patches/ytfzf-updates.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index beaf99bf71..66687b420c 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1858,6 +1858,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/xsane-support-ipv6.patch			\
   %D%/packages/patches/xsane-tighten-default-umask.patch	\
   %D%/packages/patches/yggdrasil-extra-config.patch	\
+  %D%/packages/patches/ytfzf-programs.patch        \
+  %D%/packages/patches/ytfzf-updates.patch        \
   %D%/packages/patches/ytnef-CVE-2021-3403.patch	\
   %D%/packages/patches/ytnef-CVE-2021-3404.patch	\
   %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch	\
diff --git a/gnu/packages/image-viewers.scm b/gnu/packages/image-viewers.scm
index f01b6a614a..caa4974974 100644
--- a/gnu/packages/image-viewers.scm
+++ b/gnu/packages/image-viewers.scm
@@ -18,6 +18,8 @@
 ;;; Copyright © 2021 Rovanion Luckey <rovanion.luckey <at> gmail.com>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Stefan Reichör <stefan <at> xsteve.at>
+;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -46,6 +48,7 @@
   #:use-module (guix build-system python)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages algebra)
+  #:use-module (gnu packages base)
   #:use-module (gnu packages boost)
   #:use-module (gnu packages check)
   #:use-module (gnu packages compression)
@@ -53,6 +56,7 @@
   #:use-module (gnu packages documentation)
   #:use-module (gnu packages fontutils)
   #:use-module (gnu packages freedesktop)
+  #:use-module (gnu packages gawk)
   #:use-module (gnu packages gettext)
   #:use-module (gnu packages ghostscript)
   #:use-module (gnu packages gl)
@@ -63,7 +67,9 @@
   #:use-module (gnu packages image)
   #:use-module (gnu packages image-processing)
   #:use-module (gnu packages imagemagick)
+  #:use-module (gnu packages linux)
   #:use-module (gnu packages maths)
+  #:use-module (gnu packages ncurses)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages perl-check)
   #:use-module (gnu packages photo)
@@ -71,10 +77,164 @@
   #:use-module (gnu packages python)
   #:use-module (gnu packages python-xyz)
   #:use-module (gnu packages qt)
+  #:use-module (gnu packages suckless)
+  #:use-module (gnu packages terminals)
+  #:use-module (gnu packages video)
+  #:use-module (gnu packages web)
   #:use-module (gnu packages xdisorg)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages))
 
+(define-public ytfzf
+  (package
+    (name "ytfzf")
+    (version "1.2.0")
+    (home-page "https://github.com/pystardust/ytfzf")
+    (source
+     (origin
+       (method git-fetch)
+       (uri
+        (git-reference
+         (url home-page)
+         (commit (string-append "v" version))))
+       (file-name (git-file-name name version))
+       (sha256
+        (base32 "00d416qb4109pm77ikhnmds8qng90ni2jan9kdnxz7b6sh5f61nz"))
+       (patches
+        (search-patches
+         ;; Pre-requisite for 'patch' phase.
+         "ytfzf-programs.patch"
+         ;; Disables self-update.
+         "ytfzf-updates.patch"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f                      ;no test suite
+       #:modules
+       ((guix build gnu-build-system)
+        (guix build utils)
+        (srfi srfi-26))
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'patch
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (binutils (assoc-ref inputs "binutils"))
+                    (catimg (assoc-ref inputs "catimg"))
+                    (chafa (assoc-ref inputs "chafa"))
+                    (coreutils (assoc-ref inputs "coreutils"))
+                    (curl (assoc-ref inputs "curl"))
+                    (dmenu (assoc-ref inputs "dmenu"))
+                    (fzf (assoc-ref inputs "fzf"))
+                    (gawk (assoc-ref inputs "gawk"))
+                    (grep (assoc-ref inputs "grep"))
+                    (jp2a (assoc-ref inputs "jp2a"))
+                    (jq (assoc-ref inputs "jq"))
+                    (libnotify (assoc-ref inputs "libnotify"))
+                    (mpv (assoc-ref inputs "mpv"))
+                    (ncurses (assoc-ref inputs "ncurses"))
+                    (python-ueberzug (assoc-ref inputs "python-ueberzug"))
+                    (sed (assoc-ref inputs "sed"))
+                    (util-linux (assoc-ref inputs "util-linux"))
+                    (youtube-dl (assoc-ref inputs "youtube-dl")))
+               ;; Use correct $PREFIX path.
+               (substitute* "Makefile"
+                 (("/usr/bin")
+                  (string-append out "/bin")))
+               ;; Use absolute path for referenced programs.
+               (substitute* "ytfzf"
+                 (("@awk@")
+                  (string-append gawk "/bin/awk"))
+                 (("@cat@")
+                  (string-append coreutils "/bin/cat"))
+                 (("@catimg@")
+                  (string-append catimg "/bin/catimg"))
+                 (("@chafa@")
+                  (string-append chafa "/bin/chafa"))
+                 (("@chmod@")
+                  (string-append coreutils "/bin/chmod"))
+                 (("@column@")
+                  (string-append util-linux "/bin/column"))
+                 (("@cp@")
+                  (string-append coreutils "/bin/cp"))
+                 (("@cut@")
+                  (string-append coreutils "/bin/cut"))
+                 (("@curl@")
+                  (string-append curl "/bin/curl"))
+                 (("@date@")
+                  (string-append coreutils "/bin/date"))
+                 (("@dmenu@")
+                  (string-append dmenu "/bin/dmenu"))
+                 (("@fzf@")
+                  (string-append fzf "/bin/fzf"))
+                 (("@grep@")
+                  (string-append grep "/bin/grep"))
+                 (("@head@")
+                  (string-append coreutils "/bin/head"))
+                 (("@jp2a@")
+                  (string-append jp2a "/bin/jp2a"))
+                 (("@jq@")
+                  (string-append jq "/bin/jq"))
+                 (("@mkdir@")
+                  (string-append coreutils "/bin/mkdir"))
+                 (("@mkfifo@")
+                  (string-append coreutils "/bin/mkfifo"))
+                 (("@mpv@")
+                  (string-append mpv "/bin/mpv"))
+                 (("@nohup@")
+                  (string-append coreutils "/bin/nohup"))
+                 (("@notify-send@")
+                  (string-append libnotify "/bin/notify-send"))
+                 (("@rm@")
+                  (string-append coreutils "/bin/rm"))
+                 (("@sed@")
+                  (string-append sed "/bin/sed"))
+                 (("@seq@")
+                  (string-append coreutils "/bin/seq"))
+                 (("@setsid@")
+                  (string-append util-linux "/bin/setsid"))
+                 (("@sleep@")
+                  (string-append coreutils "/bin/sleep"))
+                 (("@sort@")
+                  (string-append coreutils "/bin/sort"))
+                 (("@tput@")
+                  (string-append ncurses "/bin/tput"))
+                 (("@tr@")
+                  (string-append coreutils "/bin/tr"))
+                 (("@ueberzug@")
+                  (string-append python-ueberzug "/bin/ueberzug"))
+                 (("@uname@")
+                  (string-append coreutils "/bin/uname"))
+                 (("@uniq@")
+                  (string-append coreutils "/bin/uniq"))
+                 (("@wc@")
+                  (string-append coreutils "/bin/wc"))
+                 (("@youtube-dl@")
+                  (string-append youtube-dl "/bin/youtube-dl"))))))
+         (delete 'configure))))         ;no configure script
+    (inputs
+     `(("binutils" ,binutils)
+       ("catimg" ,catimg)
+       ("chafa" ,chafa)
+       ("coreutils" ,coreutils)
+       ("curl" ,curl)
+       ("dmenu" ,dmenu)
+       ("fzf" ,fzf)
+       ("gawk" ,gawk)
+       ("grep" ,grep)
+       ("jp2a" ,jp2a)
+       ("jq" ,jq)
+       ("libnotify" ,libnotify)
+       ("mpv" ,mpv)
+       ("ncurses" ,ncurses)
+       ("python-ueberzug" ,python-ueberzug)
+       ("sed" ,sed)
+       ("util-linux" ,util-linux)
+       ("youtube-dl" ,youtube-dl)))
+    (synopsis "Watch PeerTube or YouTube videos from the terminal")
+    (description "@code{ytfzf} is a POSIX script that helps you find PeerTube or
+YouTube videos without requiring API and opens/downloads them using mpv/ytdl.")
+    (license license:gpl3+)))
+
 (define-public feh
   (package
     (name "feh")
diff --git a/gnu/packages/patches/ytfzf-programs.patch b/gnu/packages/patches/ytfzf-programs.patch
new file mode 100644
index 0000000000..fc7684d3ef
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-programs.patch
@@ -0,0 +1,650 @@
+From 291a0cd6e24026da0cfd2007e48c00f0824bd0d2 Mon Sep 17 00:00:00 2001
+From: Raghav Gururajan <rg <at> raghavgururajan.name>
+Date: Mon, 5 Jul 2021 06:45:49 -0400
+Subject: [PATCH 1/2] Modify the strings of referenced programs.
+
+Pattern the strings of referenced programs, so that they can be easily
+substituted with absolute paths using a custom-phase.
+
+Co-authored-by: jgart <jgart <at> dismail.de>
+---
+ ytfzf | 202 +++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 101 insertions(+), 101 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index f4d2e0d..0a2c372 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -49,19 +49,19 @@ cache_dir=${YTFZF_CACHE-${cache_dir-$HOME/.cache/ytfzf}}
+ #video type preference (mp4/1080p, mp4/720p, etc..)
+ video_pref=${YTFZF_PREF-${video_pref-}}
+ #the menu to use instead of fzf when -D is specified
+-external_menu=${YTFZF_EXTMENU-${external_menu-dmenu -i -l 30 -p Search:}}
++external_menu=${YTFZF_EXTMENU-${external_menu-@dmenu@ -i -l 30 -p Search:}}
+ #number of columns (characters on a line) the external menu can have
+ #necessary for formatting text for external menus
+ external_menu_len=${YTFZF_EXTMENU_LEN-${external_menu_len-220}}
+ #player settings (players need to support streaming with youtube-dl)
+ #player to use for watching the video
+-video_player=${YTFZF_PLAYER-${video_player-mpv}}
++video_player=${YTFZF_PLAYER-${video_player-@mpv@}}
+ #if YTFZF_PREF is specified, use this player instead
+-video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-mpv --ytdl-format=}}
++video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-@mpv@ --ytdl-format=}}
+ #player to use for audio only
+-audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-mpv --no-video}}
++audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-@mpv@ --no-video}}
+ #the command to use for displaying thumbnails
+-thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-ueberzug}}
++thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-@ueberzug@}}
+ #Storing the argument and location for autogenerated subtitles
+ [ -z "$YTFZF_SUBT_NAME" ] && YTFZF_SUBT_NAME=""
+ #Stores the language for the auto genereated subtitles
+@@ -85,8 +85,8 @@ subscriptions_file=${subscriptions_file-$config_dir/subscriptions}
+ #> stores the pid of running ytfzf sessions
+ pid_file="$cache_dir/.pid"
+ #> make folders that don't exist
+-[ -d "$cache_dir" ] || mkdir -p "$cache_dir"
+-[ -d "$thumb_dir" ] || mkdir -p "$thumb_dir"
++[ -d "$cache_dir" ] || @mkdir@ -p "$cache_dir"
++[ -d "$thumb_dir" ] || @mkdir@ -p "$thumb_dir"
+ 
+ #> config settings
+ #list of shortcuts to use in fzf
+@@ -177,12 +177,12 @@ dep_ck () {
+ 	done
+ 	unset Dep
+ }
+-dep_ck "jq" "youtube-dl" "curl"
++dep_ck "@jq@" "@youtube-dl@" "@curl@"
+ 
+ 
+ #only check for mpv if $YTFZF_PLAYER is set to it
+ #don't check $YTFZF_PLAYER as it could be multiple commands
+-[ "$video_player" = "mpv" ] && dep_ck "mpv"
++[ "$video_player" = "@mpv@" ] && dep_ck "@mpv@"
+ 
+ ############################
+ #       Help Texts         #
+@@ -326,8 +326,8 @@ print_info () {
+ }
+ 
+ print_error () {
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
++    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "error" "$*" || printf "\033[31m$*\033[0m" >&2
++    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
+ }
+ 
+ ############################
+@@ -398,12 +398,12 @@ format_fzf () {
+ format_menu () {
+ 	if [ "$is_ext_menu" -eq 0 ]; then
+ 		#dep_ck fzf here because it is only necessary to use here
+-		dep_ck "fzf"
+-		menu_command='column -t -s "$tab_space" | fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
++		dep_ck "@fzf@"
++		menu_command='@column@ -t -s "$tab_space" | @fzf@ -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
+ 		format_fzf
+ 	else
+ 		# Dmenu doesn't render tabs so removing it
+-		menu_command='tr -d "$tab_space" | '"$external_menu"
++		menu_command='@tr@ -d "$tab_space" | '"$external_menu"
+ 		format_ext_menu
+ 	fi
+ }
+@@ -461,13 +461,13 @@ ID="ytfzf-ueberzug"
+ WIDTH=$FZF_PREVIEW_COLUMNS
+ HEIGHT=$FZF_PREVIEW_LINES
+ start_ueberzug () {
+-    [ -e $FIFO ] || { mkfifo "$FIFO" || exit 1 ; }
+-    ueberzug layer --parser json --silent < "$FIFO" &
++    [ -e $FIFO ] || { @mkfifo@ "$FIFO" || exit 1 ; }
++    @ueberzug@ layer --parser json --silent < "$FIFO" &
+     exec 3>"$FIFO"
+ }
+ stop_ueberzug () {
+     exec 3>&-
+-    rm "$FIFO" > /dev/null 2>&1
++    @rm@ "$FIFO" > /dev/null 2>&1
+ }
+ 
+ preview_img () {
+@@ -476,12 +476,12 @@ preview_img () {
+ 	shorturl=${args##*${tab_space}|}
+ 	shorturl="${shorturl%% *}"
+ 
+-	json_obj=$(printf "%s" "$videos_json" | jq '.[]|select( .videoID == "'"$shorturl"'")')
++	json_obj=$(printf "%s" "$videos_json" | @jq@ '.[]|select( .videoID == "'"$shorturl"'")')
+ 
+ 
+ 	IFS=$tab_space read -r title channel duration views date description <<-EOF
+ 	$(
+-		printf "%s" "$json_obj" | jq -r \
++		printf "%s" "$json_obj" | @jq@ -r \
+ 		'
+ 		[.title,.channel,.duration,.views,.date,.description]|@tsv
+ 		'
+@@ -530,31 +530,31 @@ preview_img () {
+ 		} > "$FIFO" ;;
+ 	    catimg)
+ 		printf "\n"
+-		catimg -w "$((thumb_width * 2))" "$IMAGE" ;;
++		@catimg@ -w "$((thumb_width * 2))" "$IMAGE" ;;
+ 	    jp2a)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
+ 	    jp2a-8)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
+ 	    jp2a-4)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
+ 	    jp2a-gray|jp2a-grey)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
+ 	    chafa)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
+ 	    chafa-gray|chafa-grey)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
+ 	    chafa-4)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
+ 	    chafa-8)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
+ 	    custom)
+ 		if ! function_exists "handle_display_img"; then
+ 		    printf "\033[031mERROR[#07]: \033[0m\033[1mhandle_display_img\033[0m is not defined" >&2
+@@ -585,20 +585,20 @@ download_thumbnails () {
+ 	if [ "$thumbnail_quality" -eq 1 ]; then
+ 		image_download () {
+ 			# higher quality images
+-			curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
++			@curl@ -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
+ 		}
+ 	else
+ 		image_download () {
+- 			curl -s "$Url"  > "$thumb_dir/$Name.png"
++			@curl@ -s "$Url"  > "$thumb_dir/$Name.png"
+ 		}
+ 	fi
+ 
+ 	print_info "Downloading Thumbnails...\n"
+ 	thumb_urls=$(printf "%s" "$*" |\
+-		jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
++		@jq@  -r '.[]|[.thumbs,.videoID]|@tsv' )
+ 
+ 	while IFS=$tab_space read -r Url Name; do
+-	    sleep 0.001
++	    @sleep@ 0.001
+ 		{
+ 			image_download
+ 		} &
+@@ -628,7 +628,7 @@ get_sp_filter () {
+ 	#another example is sort by filter + upload date filter only changes one character as well
+ 	if [ -n "$filter_id" ]; then
+ 		#gets the character in the filter_id that needs to be replaced if upload_date_filter is also given
+-		upload_date_character=$(printf "%s" "$filter_id" | awk '{print substr($1, 8, 1)}')
++		upload_date_character=$(printf "%s" "$filter_id" | @awk@ '{print substr($1, 8, 1)}')
+ 	fi
+ 
+ 	#For each of these, if upload_date_character is unset, the filter_id should be the normal filter
+@@ -650,7 +650,7 @@ get_sp_filter () {
+ 	if [ -n "$upload_date_character" ]; then
+ 		#replaces the 8th character in the filter_id with the appropriate character
+ 		#the 8th character specifies the upload_date_filter
+-		sp=$(printf "%s" "$filter_id" | sed 's/\(.\{7\}\)./\1'"$upload_date_character"'/')
++		sp=$(printf "%s" "$filter_id" | @sed@ 's/\(.\{7\}\)./\1'"$upload_date_character"'/')
+ 	#otherwise set it to the filter_id
+ 	else
+ 		sp=$filter_id
+@@ -660,15 +660,15 @@ get_sp_filter () {
+ 
+ get_yt_json () {
+ 	# scrapes the json embedded in the youtube html page
+-	printf "%s" "$*" | sed -n '/var *ytInitialData/,$p' | tr -d '\n' |\
+-        sed -E ' s_^.*var ytInitialData ?=__ ; s_;</script>.*__ ;'
++	printf "%s" "$*" | @sed@ -n '/var *ytInitialData/,$p' | @tr@ -d '\n' |\
++        @sed@ -E ' s_^.*var ytInitialData ?=__ ; s_;</script>.*__ ;'
+ }
+ 
+ get_yt_html () {
+     link=$1
+     query=$2
+     printf "%s" "$(
+-	curl "$link" -s \
++	@curl@ "$link" -s \
+ 	  -G --data-urlencode "search_query=$query" \
+ 	  -G --data-urlencode "sp=$sp" \
+ 	  -H 'Authority: www.youtube.com' \
+@@ -684,7 +684,7 @@ get_video_data () {
+ 	# outputs tab and pipe separated fields: title, channel, view count, video length, video upload date, and the video id/url
+ 	# from the videos_json
+ 	printf "%s" "$*" |\
+-	    jq -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
++	    @jq@ -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
+ }
+ 
+ scrape_channel () {
+@@ -694,7 +694,7 @@ scrape_channel () {
+ 	channel_url=$*
+ 
+ 	# Converting channel title page url to channel video url
+-	if ! printf "%s" "$channel_url" | grep -q '/videos *$'; then
++	if ! printf "%s" "$channel_url" | @grep@ -q '/videos *$'; then
+ 		channel_url=${channel_url%/featured}/videos
+ 	fi
+ 
+@@ -706,8 +706,8 @@ scrape_channel () {
+ 	fi
+ 
+ 	#gets the channel name from title of page
+-	channel_name=$(printf "%s" "$yt_html" | grep -o '<title>.*</title>' |
+-		sed \
++	channel_name=$(printf "%s" "$yt_html" | @grep@ -o '<title>.*</title>' |
++		@sed@ \
+ 		-e 's/ - YouTube//' \
+ 		-e 's/<\/\?title>//g' \
+ 		-e "s/&apos;/'/g" \
+@@ -723,7 +723,7 @@ scrape_channel () {
+ 
+ 	#gets a list of videos
+ 	videos_json=$(printf "%s" "$yt_json" |\
+-	jq '[ .contents | ..|.gridVideoRenderer? |
++	@jq@ '[ .contents | ..|.gridVideoRenderer? |
+ 	select(. !=null) |
+ 	    {
+ 	    	title: .title.runs[0].text,
+@@ -736,7 +736,7 @@ scrape_channel () {
+ 	    }
+ 	]')
+ 
+-	videos_json=$(printf "%s" "$videos_json" | jq '.[0:'$sub_link_count']')
++	videos_json=$(printf "%s" "$videos_json" | @jq@ '.[0:'$sub_link_count']')
+ 	printf "%s\n" "$videos_json" >> "$tmp_video_json_file"
+ 	#checks if it's empty in case it was defined in a config function eg: on_get_search
+ 	[ -z "$videos_data" ] && videos_data=$(get_video_data "$videos_json")
+@@ -768,11 +768,11 @@ get_trending_url_data () {
+ scrape_pt () {
+      #gets a list of videos
+      pt_json=$(
+-     curl \
++     @curl@ \
+          -s "https://sepiasearch.org/api/v1/search/videos" \
+ 	 -G --data-urlencode "search=$*") 
+      videos_json=$(printf "%s" "$pt_json" |\
+-	jq '[ .data | .[] |
++	@jq@ '[ .data | .[] |
+ 	    {
+ 		title: .name,
+ 		channel: .channel.displayName,
+@@ -829,7 +829,7 @@ scrape_yt () {
+ 	fi
+ 
+ 	#gets a list of videos
+-	videos_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	videos_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
+ 	..|.videoRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -844,7 +844,7 @@ scrape_yt () {
+ 		}
+ 	]')
+ 
+-	playlist_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	playlist_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
+ 	..|.playlistRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -904,31 +904,31 @@ get_search_query () {
+ #> To select videos from videos_data
+ user_selection () {
+ 	#remove subscription separators
+-	videos_data_clean=$(printf "%s" "$videos_data" | sed "/.*$tab_space$/d")
++	videos_data_clean=$(printf "%s" "$videos_data" | @sed@ "/.*$tab_space$/d")
+ 
+ 	#$selected_data is the video the user picked
+ 	#picks the first n videos
+ 	if [ "$select_all" -eq 1 ] ; then
+ 		selected_data=$videos_data_clean
+ 	elif [ "$auto_select" -eq 1 ] ; then
+-		selected_data=$(printf "%s\n" "$videos_data_clean" | sed "${link_count}"q )
++		selected_data=$(printf "%s\n" "$videos_data_clean" | @sed@ "${link_count}"q )
+ 	#picks n random videos
+ 	elif [ "$random_select" -eq 1 ] ; then
+-	    selected_data=$(printf "%s\n" "$videos_data_clean" | posix_shuf | head -n${link_count}) 
++	    selected_data=$(printf "%s\n" "$videos_data_clean" | posix_shuf | @head@ -n${link_count})
+ 	    #posix_shuf, pick the first $link_count videos
+ 
+ 	#show thumbnail menu
+ 	elif [ "$show_thumbnails" -eq 1 ] ; then
+-		dep_ck "ueberzug" "fzf"
++		dep_ck "@ueberzug@" "@fzf@"
+ 		export YTFZF_THUMB_DISP_METHOD="$thumb_disp_method"
+-		[ "$thumb_disp_method" = "ueberzug" ] && start_ueberzug
++		[ "$thumb_disp_method" = "@ueberzug@" ] && start_ueberzug
+ 		#thumbnails only work in fzf, use fzf
+-		menu_command="fzf -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
++		menu_command="@fzf@ -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
+ 		--nth=1,2 --expect='$shortcuts' $FZF_DEFAULT_OPTS \
+ 		--layout=reverse --preview \"sh $0 -U {}\" \
+         	--preview-window \"$PREVIEW_SIDE:50%:noborder:wrap\""
+ 		selected_data=$( title_len=200 video_menu "$videos_data" )
+-		[ "$thumb_disp_method" = "ueberzug" ] && stop_ueberzug
++		[ "$thumb_disp_method" = "@ueberzug@" ] && stop_ueberzug
+ 		# Deletes thumbnails if no video is selected
+ 		[ -z "$selected_data" ] && clean_up
+ 	#show regular menu
+@@ -951,10 +951,10 @@ handle_shortcuts () {
+     case $selected_key in
+ 	"$urls_shortcut") printf "%s\n" $selected_urls; return 1 ;;
+ 	"$title_shortcut") 
+-	    printf "%s\n" "$selected_data" | awk -F "  " '{print $1}'; return 1 ;;
++	    printf "%s\n" "$selected_data" | @awk@ -F "  " '{print $1}'; return 1 ;;
+ 	"$open_browser_shortcut")
+ 	    for url in $selected_urls; do
+-		nohup $BROWSER "$url" >/dev/null 2>&1
++		@nohup@ $BROWSER "$url" >/dev/null 2>&1
+ 	    done
+ 	    return 1 ;;
+ 	"$watch_shortcut") is_download=0; is_audio_only=0; return 0;;
+@@ -988,10 +988,10 @@ format_user_selection () {
+ 			11) selected_urls=$selected_urls$new_line'https://www.youtube.com/watch?v='$surl ;;
+ 			34) selected_urls=$selected_urls$new_line'https://www.youtube.com/playlist?list='$surl ;;
+ 			36)
+-			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | jq '.[].url' | grep -F "$surl" | tr -d '"')" ;;
++			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | @jq@ '.[].url' | @grep@ -F "$surl" | @tr@ -d '"')" ;;
+ 			*) continue ;;
+ 		esac
+-		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | grep "|$surl" )
++		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | @grep@ "|$surl" )
+ 	done<<-EOF
+ 	$selected_data
+ 	EOF
+@@ -1014,9 +1014,9 @@ print_data () {
+ get_video_format () {
+ 	# select format if flag given
+ 	[ $show_format -eq 0 ] && return
+-        formats=$(youtube-dl -F "$(printf "$selected_urls")") 
+-        line_number=$(printf "$formats" | grep -n '.*extension  resolution.*' | cut -d: -f1)
+-        quality=$(printf "$formats \n1 2 xAudio" | awk -v lineno=$line_number 'FNR > lineno {print $3}' | sort -n |  awk -F"x" '{print $2 "p"}' | uniq | sed -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | sed "s/p//g")
++        formats=$(@youtube-dl@ -F "$(printf "$selected_urls")")
++        line_number=$(printf "$formats" | @grep@ -n '.*extension  resolution.*' | @cut@ -d: -f1)
++        quality=$(printf "$formats \n1 2 xAudio" | @awk@ -v lineno=$line_number 'FNR > lineno {print $3}' | @sort@ -n |  @awk@ -F"x" '{print $2 "p"}' | @uniq@ | @sed@ -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | @sed@ "s/p//g")
+ 		[ -z "$quality"  ] && exit;
+ 		[ $quality = "Audio"  ] && video_pref= && video_player="$audio_player" || video_pref="bestvideo[height=?$quality][vcodec!=?vp9]+bestaudio/best"
+ 
+@@ -1026,9 +1026,9 @@ get_video_format () {
+ get_sub_lang () {
+     if [ $auto_caption -eq 1 ]; then
+         #Gets the auto generated subs and stores them in a file
+-        sub_list=$(youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
++        sub_list=$(@youtube-dl@ --list-subs  --write-auto-sub "$selected_urls" | @sed@ '/Available subtitles/,$d' | @awk@ '{print $1}' | @sed@ '1d;2d;3d')
+         if [ -n "$sub_list" ]; then
+-            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
++            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  @youtube-dl@  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
+         fi
+ 	unset sub_list
+     fi
+@@ -1046,10 +1046,10 @@ open_player () {
+ 	if [ $detach_player -eq 1 ]; then
+ 		if [ -z "$video_pref" ] || [ $is_audio_only -eq 1 ]; then
+ 			printf "Opening Player: %s\n" "$video_player $*"
+-			setsid -f $video_player "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
++			@setsid@ -f $video_player "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
+ 		else
+ 			printf "Opening Player: %s\n" "$video_player_format$video_pref $*"
+-			setsid -f $video_player_format"$video_pref"  "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
++			@setsid@ -f $video_player_format"$video_pref"  "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
+ 		fi
+ 		return
+ 	fi
+@@ -1064,9 +1064,9 @@ open_player () {
+ 		fi
+ 	elif [ $is_download -eq 1 ]; then
+ 		if [ -z "$video_pref" ]; then
+-			youtube-dl "$@"  "$YTFZF_SUBT_NAME"
++			@youtube-dl@ "$@"  "$YTFZF_SUBT_NAME"
+ 		else
+-			youtube-dl -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
++			@youtube-dl@ -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
+ 		fi
+ 	fi
+ }
+@@ -1087,7 +1087,7 @@ play_url () {
+ 	fi
+ 
+ 	#Delete the temp auto-gen subtitle file
+-	[ $auto_caption -eq 1 ] && rm -f "${YTFZF_SUBT_NAME#*=}"
++	[ $auto_caption -eq 1 ] && @rm@ -f "${YTFZF_SUBT_NAME#*=}"
+ 
+ 	unset player_urls
+ }
+@@ -1102,7 +1102,7 @@ session_is_running () {
+ #> removes tmp files and clutter
+ clean_up () {
+ 	if ! session_is_running ; then
+-		[ -d "$thumb_dir" ] && rm -r "$thumb_dir"
++		[ -d  "$thumb_dir" ] && @rm@ -r "$thumb_dir"
+ 		: > "$pid_file"
+ 		function_exists "on_exit" && on_exit
+ 	fi
+@@ -1124,9 +1124,9 @@ save_before_exit () {
+ check_if_url () {
+ 	# to check if given input is a url
+ 	url_regex='^https\?://.*'
+-	if printf "%s" "$1" | grep -q "$url_regex"; then
++	if printf "%s" "$1" | @grep@ -q "$url_regex"; then
+ 		is_url=1
+-		selected_urls=$(printf "%s" "$1" | tr ' ' '\n')
++		selected_urls=$(printf "%s" "$1" | @tr@ ' ' '\n')
+ 		scrape="url"
+ 	else
+ 		is_url=0
+@@ -1139,10 +1139,10 @@ get_history () {
+ 	if [ "$enable_hist" -eq 1 ]; then
+ 		[ -e "$history_file" ] || : > "$history_file"
+ 		#gets history data in reverse order (makes it most recent to least recent)
+-		hist_data=$( sed '1!G; h; $!d' "$history_file" )
++		hist_data=$( @sed@ '1!G; h; $!d' "$history_file" )
+ 		[ -z "$hist_data" ] && printf "History is empty!\n" >&2 && return 1;
+ 		#removes duplicate values from $history_data
+-		videos_data=$(printf "%s" "$hist_data" | uniq )
++		videos_data=$(printf "%s" "$hist_data" | @uniq@ )
+ 		[ "$sort_videos_data" -eq 1 ] && videos_data="$(printf "%s" "$videos_data"  | sort_video_data_fn)"
+ 	else
+ 		printf "History is not enabled. Please enable it to use this option (-H).\n" >&2;
+@@ -1177,10 +1177,10 @@ get_search_history () {
+ 	if [ "$enable_search_hist" -eq 1 ]; then
+ 		[ -e "$search_history_file" ] || : > "$search_history_file"
+ 		#gets history data in reverse order (makes it most recent to least recent)
+-		hist_data=$( sed '1!G; h; $!d' "$search_history_file" )
++		hist_data=$( @sed@ '1!G; h; $!d' "$search_history_file" )
+ 		[ -z "$hist_data" ] && printf "Search history is empty!\n" >&2 && return 1;
+ 		#removes duplicate values from $history_data
+-		search_history=$(printf "%s" "$hist_data" | uniq )
++		search_history=$(printf "%s" "$hist_data" | @uniq@ )
+ 	else
+ 		printf "Search history is not enabled. Please enable it to use this option (-q).\n" >&2;
+ 		exit 1;
+@@ -1190,7 +1190,7 @@ get_search_history () {
+ 
+ set_search_history () {
+     [ -z "$search_query" ] && return
+-    [ $enable_search_hist -eq 1 ] && printf "%s\t%s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$search_query" >> "$search_history_file" ;
++    [ $enable_search_hist -eq 1 ] && printf "%s\t%s\n" "$(@date@ '+%Y-%m-%d %H:%M:%S')" "$search_query" >> "$search_history_file" ;
+ }
+ 
+ search_history_menu () {
+@@ -1200,15 +1200,15 @@ search_history_menu () {
+     #when using an external menu, the search history will be done there
+         choice=$( printf "%s\n" "$search_history" | eval "$external_menu" )
+     else
+-        choice="$( printf "%s\n" "$search_history" | fzf --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
++        choice="$( printf "%s\n" "$search_history" | @fzf@ --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
+     fi
+ 
+     # first line is the fzf query (what the user types in fzf)
+     # second line is the fzf --expect key pressed
+     # third line is the search_history selection made
+-    query="$( printf "%s" "$choice" | sed -n '1p' )"
+-    key="$( printf "%s" "$choice" | sed -n '2p' )"
+-    selection="$( printf "%s" "$choice" | sed -n '3p' )"
++    query="$( printf "%s" "$choice" | @sed@ -n '1p' )"
++    key="$( printf "%s" "$choice" | @sed@ -n '2p' )"
++    selection="$( printf "%s" "$choice" | @sed@ -n '3p' )"
+ 
+     # if no search history selection has been made
+     # and the user typed a query, use that instead
+@@ -1225,7 +1225,7 @@ search_history_menu () {
+             search_query="$query"
+             return;;
+     esac
+-    search_query="$( printf "%s" "$selection" | awk -F'\t' '{printf "%s", $NF}' )"
++    search_query="$( printf "%s" "$selection" | @awk@ -F'\t' '{printf "%s", $NF}' )"
+ }
+ 
+ ! function_exists "send_select_video_notif" && send_select_video_notif () {
+@@ -1244,13 +1244,13 @@ search_history_menu () {
+ 
+ 	#if downloading, say Downloading not currently playing
+ 	[ $is_download -eq 1 ] && title="Downloading" || title="Currently playing"
+-	notify-send "$title" "$message" -i "$video_thumb"
++	@notify-send@ "$title" "$message" -i "$video_thumb"
+ 
+ 	unset message video_thumb title
+ }
+ 
+ send_notify () {
+-	videos_selected_count=$(printf "%s\n" "$*" | wc -l)
++	videos_selected_count=$(printf "%s\n" "$*" | @wc@ -l)
+ 	while IFS=$tab_space read -r video_title video_channel video_views video_duration video_date video_shorturl; do
+ 	    send_select_video_notif
+ 	done << EOF
+@@ -1284,14 +1284,14 @@ if ! function_exists "data_sort_key"; then
+ 	sort_by="${5#|}"
+ 	sort_by="${sort_by#Streamed}"
+ 	#print the data that should be sorted by
+-	printf "%d" "$(date -d "${sort_by}" '+%s')"
++	printf "%d" "$(@date@ -d "${sort_by}" '+%s')"
+ 	unset sort_by
+     }
+ fi
+ #the function to use for sorting
+ if ! function_exists "data_sort_fn"; then
+     data_sort_fn () {
+-	sort -nr
++	@sort@ -nr
+     }
+ fi
+ sort_video_data_fn () {
+@@ -1300,7 +1300,7 @@ sort_video_data_fn () {
+ 		IFS="$tab_space"
+ 		#run the key function to get the value to sort by
+ 		printf "%s\t%s\n" "$(data_sort_key $line)" "$line"
+-	done | data_sort_fn | cut -f2-
++	done | data_sort_fn | @cut@ -f2-
+ 	unset IFS line 
+ }
+ 
+@@ -1314,19 +1314,19 @@ scrape_subscriptions () {
+ 	while IFS= read -r url; do
+ 		scrape_channel "$url" &
+ 	done <<-EOF
+-	$( sed \
++	$( @sed@ \
+ 	-e "s/#.*//" \
+ 	-e "/^[[:space:]]*$/d" \
+ 	-e "s/[[:space:]]*//g" \
+ 	"$subscriptions_file")
+ 	EOF
+ 	wait
+-	videos_json="$(cat "$tmp_video_json_file")"
++	videos_json="$(@cat@ "$tmp_video_json_file")"
+ 	export videos_json
+ 	if [ $sort_videos_data -eq 1 ]; then 
+ 		videos_data=$(sort_video_data_fn < "$tmp_video_data_file")
+ 	else
+-		videos_data=$(cat "$tmp_video_data_file")
++		videos_data=$(@cat@ "$tmp_video_data_file")
+ 	fi
+ }
+ 
+@@ -1346,11 +1346,11 @@ create_subs () {
+     : > "$config_dir/subscriptions"
+ 
+     # check how many subscriptions there are in the file
+-    sublength=$( jq '. | length' < "$yt_sub_import_file" )
++    sublength=$( @jq@ '. | length' < "$yt_sub_import_file" )
+ 
+-    for i in $(seq $((sublength - 1))); do
+-        channelInfo=$(jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
+-	printf "%s\n" "$(printf "%s" "$channelInfo" | tr -d '[]"\n,')" >> "$subscriptions_file"
++    for i in $(@seq@ $((sublength - 1))); do
++        channelInfo=$(@jq@ --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
++	printf "%s\n" "$(printf "%s" "$channelInfo" | @tr@ -d '[]"\n,')" >> "$subscriptions_file"
+     done
+     exit
+ }
+@@ -1367,10 +1367,10 @@ verify_thumb_disp_method () {
+ 
+ #sort -R is not posix
+ posix_shuf () {
+-    awk -F '\n' '
++    @awk@ -F '\n' '
+ 	BEGIN {srand()} #set the random seed at the start
+ 	{print rand() " " $0} #prepend a random number for each line' |\
+-    sort | sed -E 's/[^ ]* //'
++    @sort@ | @sed@ -E 's/[^ ]* //'
+     #sort by the random numbers, remove the random number
+ }
+ 
+@@ -1486,8 +1486,8 @@ parse_opt () {
+ 			exit ;;
+ 		version)
+ 			printf "\033[1mytfzf:\033[0m %s\n" "$YTFZF_VERSION"
+-			printf "\033[1myoutube-dl:\033[0m %s\n" "$(youtube-dl --version)"
+-			command -v "fzf" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(fzf --version)"
++			printf "\033[1myoutube-dl:\033[0m %s\n" "$(@youtube-dl@ --version)"
++			command -v "@fzf@" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(@fzf@ --version)"
+ 			exit ;;
+ 
+ 		subt)
+@@ -1559,19 +1559,19 @@ done
+ shift $((OPTIND-1))
+ 
+ #only apply to ext_menu since they dont have a terminal to print to
+-[ $is_ext_menu -eq 1 ] && command -v notify-send 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
++[ $is_ext_menu -eq 1 ] && command -v @notify-send@ 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
+ 
+ #used for thumbnail previews in ueberzug
+ if [ $is_ext_menu -eq 0 ]; then
+-	export TTY_LINES=$(tput lines)
+- 	export TTY_COLS=$(tput cols)
++	export TTY_LINES=$(@tput@ lines)
++	export TTY_COLS=$(@tput@ cols)
+ fi
+ 
+ #if both are true, it defaults to using fzf, and if fzf isnt installed it will throw an error
+ #so print this error instead and set $show_thumbnails to 0
+ if [ $is_ext_menu -eq 1 ] && [ $show_thumbnails -eq 1 ]; then
+ 	[ $ext_menu_notifs -eq 1 ] &&\
+-	    notify-send "warning" "Currently thumbnails do not work in external menus" ||\
++	    @notify-send@ "warning" "Currently thumbnails do not work in external menus" ||\
+ 	    printf "\033[33mWARNING: Currently thumbnails do not work in external menus\033[0m\n" >&2
+ 	show_thumbnails=0
+ fi
+-- 
+2.32.0
+
diff --git a/gnu/packages/patches/ytfzf-updates.patch b/gnu/packages/patches/ytfzf-updates.patch
new file mode 100644
index 0000000000..1790b7a238
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-updates.patch
@@ -0,0 +1,44 @@
+From 75bf4f584866a013d5618ea6be19e97a8196d63e Mon Sep 17 00:00:00 2001
+From: Raghav Gururajan <rg <at> raghavgururajan.name>
+Date: Mon, 5 Jul 2021 06:47:38 -0400
+Subject: [PATCH 2/2] Disable updates within the application.
+
+Patch the code responsible for self-updating the application.
+
+Co-authored-by: jgart <jgart <at> dismail.de>
+---
+ ytfzf | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index 0a2c372..845e8e9 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -1260,22 +1260,8 @@ EOF
+ }
+ 
+ update_ytfzf () {
+-	branch="$1"
+-	updatefile="/tmp/ytfzf-update"
+-	curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
+-
+-	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then
+-		chmod 755 "$updatefile"
+-		[ "$(uname)" = "Darwin" ] && prefix="/usr/local/bin" || prefix="/usr/bin"
+-		function_exists "sudo" && doasroot="sudo" || doasroot="doas"
+-		$doasroot cp "$updatefile" "$prefix/ytfzf"
+-		unset prefix doasroot
+-	else
+-		printf "%bFailed to update ytfzf. Try again later.%b" "$c_red" "$c_reset"
+-	fi
+-
+-	rm "$updatefile"
+-	exit 0
++       printf "%bUpdates have to be installed with Guix.%b\n" "$c_red" "$c_reset"
++       exit 1
+ }
+ 
+ #gives a value to sort by (this will give the unix time the video was uploaded)
+-- 
+2.32.0
+
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 12:03:01 GMT) Full text and rfc822 format available.

Message #29 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: Raghav Gururajan <rg <at> raghavgururajan.name>, 49238 <at> debbugs.gnu.org
Cc: jgart <jgart <at> dismail.de>
Subject: Re: [bug#49238] [PATCH v3 2/2] gnu: Add ytfzf.
Date: Mon, 05 Jul 2021 14:02:20 +0200
[Message part 1 (text/plain, inline)]
Hi,

> +       (modify-phases %standard-phases
> +         (add-after 'unpack 'patch
> +           (lambda* (#:key inputs outputs #:allow-other-keys)
> +             (let* ((out (assoc-ref outputs "out"))
> +                    (binutils (assoc-ref inputs "binutils"))

The 'binutils' input doesn't seem to be used anywhere.


> +         if [ -n "$sub_list" ]; then
> +-            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
> ++            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  @youtube-dl@  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."

For a previous version of this patch series,
I noted that writing /tmp/ytfzf is quite possibly
insecure, and also incorrect on multi-user systems.

I don't see this addressed anywhere.

Greetings,
Maxime.
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 12:04:01 GMT) Full text and rfc822 format available.

Message #32 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: Maxime Devos <maximedevos <at> telenet.be>
Cc: 49238 <at> debbugs.gnu.org, jgart <at> dismail.de
Subject: Re: [bug#49238] [PATCH v1 2/2] gnu: Add ytfzf.
Date: Mon, 5 Jul 2021 08:03:53 -0400
[Message part 1 (text/plain, inline)]
Hi Maxime!

> That's a neat trick to avoid fragile (substitute* ...).
> However, as I understand it, the origin is meant to be
> usable as source code (think install dependencies && guix build && tar xzf stuff.tgz
> && ./configure && make && try it out), such that
> "guix build --source=transitive stuff" would give all the
> source code for building stuff (in the sense of ‘Corresponding Source’
> of the GPL), and "guix-mpv", 'guix-jq" ... don't exist anywhere.
> 
> I don't know if that has been spelled out somewhere though.
> 
> I'd suggest adding "patch" to 'native-inputs', adding the patch
> to 'inputs' or 'native-inputs' (doesn't really matter which) and
> doing (invoke "patch" OPTIONS "blabla.patch") before the substitute*.
> 
> Actually, myself I'm not convinced because you could consider
> the package definition itself to be part of the ‘corresponding source’.

I get the idea, but I don't think we can call .patch files inside 
phases, the patches directory is not exposed/available inside 
build-environment.

> I'm wondering if (string-append (assoc-ref inputs "catimg") "/bin/catimg")
> would be better, as 'string-append' is less complex than 'format'
> and "format" doesn't seem to provide any additional value here.

Cool! I have made this change in v4.

> Now about the patch:
> 
> Maybe tell people to report issues at bug-guix <at> gnu.org or #guix? Dunno

Changed in v4.

> Don't forget to patch 'column'.
> 
> Don't forget to patch "mkfifo".
> 
> Don't forget patching 'sleep'. It is not shell a built-in
> (try "type sleep" and "type [" in a terminal").
> 
> Don't forget patching 'grep' and 'tr'.
> 
> Don't forget 'grep -> guix-grep' and 'cut -> guix-cut'
> 
> Don't forget 'awk -> guix-awk' and 'sort -> guix-sort' and 'uniq -> 'guix-uniq'
> 
> Don't forget 'sed -> guix-sed' and 'awk -> guix-awk'

Thanks, I have patched these in v4.

> FWIW, writing to "/tmp/ytfzf" seems to be a potential security problem
> and bad behaviour on multiple-user systems.
> 
> What would happen if /tmp/ytfzf is a symlink to /etc/passwd an ytfzf is run
> as root (yes, running as root is not recommended)? Would that brick the system?
> What if /tmp/ytfzf is a symlink to ~/.profile? Would that brick the login?
> 
> What if multiple users run ytfzf concurrently? Would they overwrite eaech
> other subtitles?  Would a different user be able to see what the other
> is downloading?
> 
> A relatively easy fix would be to write to, say, $HOME/.cache/ytzf-subs
> instead (not sure what the proper directory would be), which is completely
> under the user's control.

Good catch. I have changed this in v4.

Let me know if v4 looks good.

Regards,
RG.

[OpenPGP_signature (application/pgp-signature, attachment)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 12:14:01 GMT) Full text and rfc822 format available.

Message #35 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: Raghav Gururajan <rg <at> raghavgururajan.name>
Cc: 49238 <at> debbugs.gnu.org, jgart <at> dismail.de
Subject: Re: [bug#49238] [PATCH v1 2/2] gnu: Add ytfzf.
Date: Mon, 05 Jul 2021 14:13:32 +0200
[Message part 1 (text/plain, inline)]
Raghav Gururajan schreef op ma 05-07-2021 om 08:03 [-0400]:
> [...]
> > 
> > I'd suggest adding "patch" to 'native-inputs', adding the patch
> > to 'inputs' or 'native-inputs' (doesn't really matter which) and
> > doing (invoke "patch" OPTIONS "blabla.patch") before the substitute*.
> > 
> > [...]
>
> I get the idea, but I don't think we can call .patch files inside 
> phases, the patches directory is not exposed/available inside 
> build-environment.

If the relevant patch files are added to 'inputs' or 'native-inputs',
then they are available in the build environment.  As an example,
see the "libpng-apng" package.  It adds the patch to 'inputs'
(named "apng") and invokes "patch" during the 'patch-apng' phase.

The "apng" input uses an 'origin' reference, but you could use
(local-file ...) there as well.  Or beter: use 'search-patch'
instead.

Greetings,
Maxime.
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 12:20:02 GMT) Full text and rfc822 format available.

Message #38 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: Maxime Devos <maximedevos <at> telenet.be>
Cc: 49238 <at> debbugs.gnu.org, jgart <jgart <at> dismail.de>
Subject: Re: [bug#49238] [PATCH v3 2/2] gnu: Add ytfzf.
Date: Mon, 5 Jul 2021 08:19:09 -0400
[Message part 1 (text/plain, inline)]
Hi Maxime!

> The 'binutils' input doesn't seem to be used anywhere.
> 
> I don't see this addressed anywhere.

My v4 patch-set didn't come through it seems.

Regards,
RG.

[OpenPGP_signature (application/pgp-signature, attachment)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 12:21:02 GMT) Full text and rfc822 format available.

Message #41 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: Maxime Devos <maximedevos <at> telenet.be>
Cc: 49238 <at> debbugs.gnu.org, jgart <at> dismail.de
Subject: Re: [bug#49238] [PATCH v1 2/2] gnu: Add ytfzf.
Date: Mon, 5 Jul 2021 08:20:56 -0400
[Message part 1 (text/plain, inline)]
Hi Maixme!

>> I get the idea, but I don't think we can call .patch files inside
>> phases, the patches directory is not exposed/available inside
>> build-environment.
> 
> If the relevant patch files are added to 'inputs' or 'native-inputs',
> then they are available in the build environment.  As an example,
> see the "libpng-apng" package.  It adds the patch to 'inputs'
> (named "apng") and invokes "patch" during the 'patch-apng' phase.
> 
> The "apng" input uses an 'origin' reference, but you could use
> (local-file ...) there as well.  Or beter: use 'search-patch'
> instead.

Ah thanks so much for the pointer. Since my v4 patch-set didn't come 
through, I'll make this change and send v5.

Regards,
RG.

[OpenPGP_signature (application/pgp-signature, attachment)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 15:11:02 GMT) Full text and rfc822 format available.

Message #44 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, maximedevos <at> telenet.be,
 jgart <jgart <at> dismail.de>
Subject: [PATCH v5 1/2] gnu: Add python-ueberzug.
Date: Mon,  5 Jul 2021 11:10:01 -0400
* gnu/packages/python-xyz.scm (python-ueberzug): New variable.

Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/packages/python-xyz.scm | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index b74b3b808f..aa2406287d 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -101,6 +101,7 @@
 ;;; Copyright © 2021 LibreMiami <packaging-guix <at> libremiami.org>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;; Copyright © 2021 Danial Behzadi <dani.behzi <at> ubuntu.com>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -221,6 +222,41 @@
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26))
 
+(define-public python-ueberzug
+  (package
+    (name "python-ueberzug")
+    (version "18.1.9")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "ueberzug" version))
+       (sha256
+        (base32
+         "1hxd45dnwa9yv908acarr98n2drmar66wzq9z2qd3irj24srzr3w"))))
+    (build-system python-build-system)
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)))
+    (propagated-inputs
+     `(("python-attrs" ,python-attrs)
+       ("python-docopt" ,python-docopt)
+       ("python-pillow" ,python-pillow)
+       ("python-xlib" ,python-xlib)))
+    (home-page "https://github.com/seebye/ueberzug")
+    (synopsis "Command line util to display images in combination with X11")
+    (description "Überzug is a command line util which allows to draw images on
+terminals by using child windows.  The advantages of using Überzug are:
+@itemize
+@item No race conditions as a new window is created to display images.
+@item Expose events will be processed, so images will be redrawn on switch
+workspaces.
+@item Tmux support (excluding multi pane windows).
+@item Terminals without the WINDOWID environment variable are supported.
+@item Chars are used as position - and size unit.
+@item No memory leak (/ unlimited cache).
+@end itemize")
+    (license license:gpl3+)))
+
 (define-public python-fire
   (package
     (name "python-fire")
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 15:11:02 GMT) Full text and rfc822 format available.

Message #47 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238 <at> debbugs.gnu.org
Cc: Raghav Gururajan <rg <at> raghavgururajan.name>, maximedevos <at> telenet.be,
 jgart <jgart <at> dismail.de>
Subject: [PATCH v5 2/2] gnu: Add ytfzf.
Date: Mon,  5 Jul 2021 11:10:02 -0400
* gnu/packages/image-viewers.scm (ytfzf): New variable.

Co-authored-by: jgart <jgart <at> dismail.de>
---
 gnu/local.mk                              |   2 +
 gnu/packages/image-viewers.scm            | 173 ++++++
 gnu/packages/patches/ytfzf-programs.patch | 650 ++++++++++++++++++++++
 gnu/packages/patches/ytfzf-updates.patch  |  44 ++
 4 files changed, 869 insertions(+)
 create mode 100644 gnu/packages/patches/ytfzf-programs.patch
 create mode 100644 gnu/packages/patches/ytfzf-updates.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index beaf99bf71..66687b420c 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1858,6 +1858,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/xsane-support-ipv6.patch			\
   %D%/packages/patches/xsane-tighten-default-umask.patch	\
   %D%/packages/patches/yggdrasil-extra-config.patch	\
+  %D%/packages/patches/ytfzf-programs.patch        \
+  %D%/packages/patches/ytfzf-updates.patch        \
   %D%/packages/patches/ytnef-CVE-2021-3403.patch	\
   %D%/packages/patches/ytnef-CVE-2021-3404.patch	\
   %D%/packages/patches/zstd-CVE-2021-24031_CVE-2021-24032.patch	\
diff --git a/gnu/packages/image-viewers.scm b/gnu/packages/image-viewers.scm
index f01b6a614a..9850aabad6 100644
--- a/gnu/packages/image-viewers.scm
+++ b/gnu/packages/image-viewers.scm
@@ -18,6 +18,8 @@
 ;;; Copyright © 2021 Rovanion Luckey <rovanion.luckey <at> gmail.com>
 ;;; Copyright © 2021 Xinglu Chen <public <at> yoctocell.xyz>
 ;;; Copyright © 2021 Stefan Reichör <stefan <at> xsteve.at>
+;;; Copyright © 2021 Raghav Gururajan <rg <at> raghavgururajan.name>
+;;; Copyright © 2021 jgart <jgart <at> dismail.de>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -46,6 +48,7 @@
   #:use-module (guix build-system python)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages algebra)
+  #:use-module (gnu packages base)
   #:use-module (gnu packages boost)
   #:use-module (gnu packages check)
   #:use-module (gnu packages compression)
@@ -53,6 +56,7 @@
   #:use-module (gnu packages documentation)
   #:use-module (gnu packages fontutils)
   #:use-module (gnu packages freedesktop)
+  #:use-module (gnu packages gawk)
   #:use-module (gnu packages gettext)
   #:use-module (gnu packages ghostscript)
   #:use-module (gnu packages gl)
@@ -63,7 +67,9 @@
   #:use-module (gnu packages image)
   #:use-module (gnu packages image-processing)
   #:use-module (gnu packages imagemagick)
+  #:use-module (gnu packages linux)
   #:use-module (gnu packages maths)
+  #:use-module (gnu packages ncurses)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages perl-check)
   #:use-module (gnu packages photo)
@@ -71,10 +77,177 @@
   #:use-module (gnu packages python)
   #:use-module (gnu packages python-xyz)
   #:use-module (gnu packages qt)
+  #:use-module (gnu packages suckless)
+  #:use-module (gnu packages terminals)
+  #:use-module (gnu packages video)
+  #:use-module (gnu packages web)
   #:use-module (gnu packages xdisorg)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages))
 
+(define-public ytfzf
+  (package
+    (name "ytfzf")
+    (version "1.2.0")
+    (home-page "https://github.com/pystardust/ytfzf")
+    (source
+     (origin
+       (method git-fetch)
+       (uri
+        (git-reference
+         (url home-page)
+         (commit (string-append "v" version))))
+       (file-name (git-file-name name version))
+       (sha256
+        (base32 "00d416qb4109pm77ikhnmds8qng90ni2jan9kdnxz7b6sh5f61nz"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f                      ;no test suite
+       #:modules
+       ((guix build gnu-build-system)
+        (guix build utils)
+        (srfi srfi-26))
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'apply-patches
+           (lambda* (#:key inputs #:allow-other-keys)
+             ;; Pre-requisite for 'patch-script' phase.
+             (invoke "patch" "--input"
+                     (assoc-ref inputs "ytfzf-programs"))
+             ;; Disables self-update.
+             (invoke "patch" "--input"
+                     (assoc-ref inputs "ytfzf-updates"))))
+         (add-after 'apply-patches 'patch-script
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (catimg (assoc-ref inputs "catimg"))
+                    (chafa (assoc-ref inputs "chafa"))
+                    (coreutils (assoc-ref inputs "coreutils"))
+                    (curl (assoc-ref inputs "curl"))
+                    (dmenu (assoc-ref inputs "dmenu"))
+                    (fzf (assoc-ref inputs "fzf"))
+                    (gawk (assoc-ref inputs "gawk"))
+                    (grep (assoc-ref inputs "grep"))
+                    (jp2a (assoc-ref inputs "jp2a"))
+                    (jq (assoc-ref inputs "jq"))
+                    (libnotify (assoc-ref inputs "libnotify"))
+                    (mpv (assoc-ref inputs "mpv"))
+                    (ncurses (assoc-ref inputs "ncurses"))
+                    (python-ueberzug (assoc-ref inputs "python-ueberzug"))
+                    (sed (assoc-ref inputs "sed"))
+                    (util-linux (assoc-ref inputs "util-linux"))
+                    (youtube-dl (assoc-ref inputs "youtube-dl")))
+               ;; Use correct $PREFIX path.
+               (substitute* "Makefile"
+                 (("/usr/bin")
+                  (string-append out "/bin")))
+               ;; Use absolute path for referenced programs.
+               (substitute* "ytfzf"
+                 (("@awk@")
+                  (string-append gawk "/bin/awk"))
+                 (("@cat@")
+                  (string-append coreutils "/bin/cat"))
+                 (("@catimg@")
+                  (string-append catimg "/bin/catimg"))
+                 (("@chafa@")
+                  (string-append chafa "/bin/chafa"))
+                 (("@chmod@")
+                  (string-append coreutils "/bin/chmod"))
+                 (("@column@")
+                  (string-append util-linux "/bin/column"))
+                 (("@cp@")
+                  (string-append coreutils "/bin/cp"))
+                 (("@cut@")
+                  (string-append coreutils "/bin/cut"))
+                 (("@curl@")
+                  (string-append curl "/bin/curl"))
+                 (("@date@")
+                  (string-append coreutils "/bin/date"))
+                 (("@dmenu@")
+                  (string-append dmenu "/bin/dmenu"))
+                 (("@fzf@")
+                  (string-append fzf "/bin/fzf"))
+                 (("@grep@")
+                  (string-append grep "/bin/grep"))
+                 (("@head@")
+                  (string-append coreutils "/bin/head"))
+                 (("@jp2a@")
+                  (string-append jp2a "/bin/jp2a"))
+                 (("@jq@")
+                  (string-append jq "/bin/jq"))
+                 (("@mkdir@")
+                  (string-append coreutils "/bin/mkdir"))
+                 (("@mkfifo@")
+                  (string-append coreutils "/bin/mkfifo"))
+                 (("@mpv@")
+                  (string-append mpv "/bin/mpv"))
+                 (("@nohup@")
+                  (string-append coreutils "/bin/nohup"))
+                 (("@notify-send@")
+                  (string-append libnotify "/bin/notify-send"))
+                 (("@rm@")
+                  (string-append coreutils "/bin/rm"))
+                 (("@sed@")
+                  (string-append sed "/bin/sed"))
+                 (("@seq@")
+                  (string-append coreutils "/bin/seq"))
+                 (("@setsid@")
+                  (string-append util-linux "/bin/setsid"))
+                 (("@sleep@")
+                  (string-append coreutils "/bin/sleep"))
+                 (("@sort@")
+                  (string-append coreutils "/bin/sort"))
+                 (("@tput@")
+                  (string-append ncurses "/bin/tput"))
+                 (("@tr@")
+                  (string-append coreutils "/bin/tr"))
+                 (("@ueberzug@")
+                  (string-append python-ueberzug "/bin/ueberzug"))
+                 (("@uname@")
+                  (string-append coreutils "/bin/uname"))
+                 (("@uniq@")
+                  (string-append coreutils "/bin/uniq"))
+                 (("@wc@")
+                  (string-append coreutils "/bin/wc"))
+                 (("@youtube-dl@")
+                  (string-append youtube-dl "/bin/youtube-dl"))))
+             (substitute* "ytfzf"
+               ;; Generate temporary files in the user-specific path,
+               ;; to avoid issues in multi-user systems.
+               (("/tmp/ytfzf")
+                "$HOME/.cache/ytfzf")
+               ;; Report errors to Guix.
+               (("report at: https://github.com/pystardust/ytfzf")
+                "report at: https://issues.guix.gnu.org"))))
+         (delete 'configure))))         ;no configure script
+    (native-inputs
+     `(("ytfzf-programs"
+        ,(search-patch "ytfzf-programs.patch"))
+       ("ytfzf-updates"
+        ,(search-patch "ytfzf-updates.patch"))))
+    (inputs
+     `(("catimg" ,catimg)
+       ("chafa" ,chafa)
+       ("coreutils" ,coreutils)
+       ("curl" ,curl)
+       ("dmenu" ,dmenu)
+       ("fzf" ,fzf)
+       ("gawk" ,gawk)
+       ("grep" ,grep)
+       ("jp2a" ,jp2a)
+       ("jq" ,jq)
+       ("libnotify" ,libnotify)
+       ("mpv" ,mpv)
+       ("ncurses" ,ncurses)
+       ("python-ueberzug" ,python-ueberzug)
+       ("sed" ,sed)
+       ("util-linux" ,util-linux)
+       ("youtube-dl" ,youtube-dl)))
+    (synopsis "Watch PeerTube or YouTube videos from the terminal")
+    (description "@code{ytfzf} is a POSIX script that helps you find PeerTube or
+YouTube videos without requiring API and opens/downloads them using mpv/ytdl.")
+    (license license:gpl3+)))
+
 (define-public feh
   (package
     (name "feh")
diff --git a/gnu/packages/patches/ytfzf-programs.patch b/gnu/packages/patches/ytfzf-programs.patch
new file mode 100644
index 0000000000..fc7684d3ef
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-programs.patch
@@ -0,0 +1,650 @@
+From 291a0cd6e24026da0cfd2007e48c00f0824bd0d2 Mon Sep 17 00:00:00 2001
+From: Raghav Gururajan <rg <at> raghavgururajan.name>
+Date: Mon, 5 Jul 2021 06:45:49 -0400
+Subject: [PATCH 1/2] Modify the strings of referenced programs.
+
+Pattern the strings of referenced programs, so that they can be easily
+substituted with absolute paths using a custom-phase.
+
+Co-authored-by: jgart <jgart <at> dismail.de>
+---
+ ytfzf | 202 +++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 101 insertions(+), 101 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index f4d2e0d..0a2c372 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -49,19 +49,19 @@ cache_dir=${YTFZF_CACHE-${cache_dir-$HOME/.cache/ytfzf}}
+ #video type preference (mp4/1080p, mp4/720p, etc..)
+ video_pref=${YTFZF_PREF-${video_pref-}}
+ #the menu to use instead of fzf when -D is specified
+-external_menu=${YTFZF_EXTMENU-${external_menu-dmenu -i -l 30 -p Search:}}
++external_menu=${YTFZF_EXTMENU-${external_menu-@dmenu@ -i -l 30 -p Search:}}
+ #number of columns (characters on a line) the external menu can have
+ #necessary for formatting text for external menus
+ external_menu_len=${YTFZF_EXTMENU_LEN-${external_menu_len-220}}
+ #player settings (players need to support streaming with youtube-dl)
+ #player to use for watching the video
+-video_player=${YTFZF_PLAYER-${video_player-mpv}}
++video_player=${YTFZF_PLAYER-${video_player-@mpv@}}
+ #if YTFZF_PREF is specified, use this player instead
+-video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-mpv --ytdl-format=}}
++video_player_format=${YTFZF_PLAYER_FORMAT-${video_player_format-@mpv@ --ytdl-format=}}
+ #player to use for audio only
+-audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-mpv --no-video}}
++audio_player=${YTFZF_AUDIO_PLAYER-${audio_player-@mpv@ --no-video}}
+ #the command to use for displaying thumbnails
+-thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-ueberzug}}
++thumb_disp_method=${YTFZF_THUMB_DISP_METHOD-${thumb_disp_method-@ueberzug@}}
+ #Storing the argument and location for autogenerated subtitles
+ [ -z "$YTFZF_SUBT_NAME" ] && YTFZF_SUBT_NAME=""
+ #Stores the language for the auto genereated subtitles
+@@ -85,8 +85,8 @@ subscriptions_file=${subscriptions_file-$config_dir/subscriptions}
+ #> stores the pid of running ytfzf sessions
+ pid_file="$cache_dir/.pid"
+ #> make folders that don't exist
+-[ -d "$cache_dir" ] || mkdir -p "$cache_dir"
+-[ -d "$thumb_dir" ] || mkdir -p "$thumb_dir"
++[ -d "$cache_dir" ] || @mkdir@ -p "$cache_dir"
++[ -d "$thumb_dir" ] || @mkdir@ -p "$thumb_dir"
+ 
+ #> config settings
+ #list of shortcuts to use in fzf
+@@ -177,12 +177,12 @@ dep_ck () {
+ 	done
+ 	unset Dep
+ }
+-dep_ck "jq" "youtube-dl" "curl"
++dep_ck "@jq@" "@youtube-dl@" "@curl@"
+ 
+ 
+ #only check for mpv if $YTFZF_PLAYER is set to it
+ #don't check $YTFZF_PLAYER as it could be multiple commands
+-[ "$video_player" = "mpv" ] && dep_ck "mpv"
++[ "$video_player" = "@mpv@" ] && dep_ck "@mpv@"
+ 
+ ############################
+ #       Help Texts         #
+@@ -326,8 +326,8 @@ print_info () {
+ }
+ 
+ print_error () {
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "error" "$*" || printf "\033[31m$*\033[0m" >&2
+-    [ $ext_menu_notifs -eq 1 ] && notify-send "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
++    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "error" "$*" || printf "\033[31m$*\033[0m" >&2
++    [ $ext_menu_notifs -eq 1 ] && @notify-send@ "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" || printf "Check for new versions and report at: https://github.com/pystardust/ytfzf\n" >&2
+ }
+ 
+ ############################
+@@ -398,12 +398,12 @@ format_fzf () {
+ format_menu () {
+ 	if [ "$is_ext_menu" -eq 0 ]; then
+ 		#dep_ck fzf here because it is only necessary to use here
+-		dep_ck "fzf"
+-		menu_command='column -t -s "$tab_space" | fzf -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
++		dep_ck "@fzf@"
++		menu_command='@column@ -t -s "$tab_space" | @fzf@ -m --bind change:top --tabstop=1 --layout=reverse --delimiter="$tab_space" --nth=1,2 --expect="$shortcuts" $FZF_DEFAULT_OPTS'
+ 		format_fzf
+ 	else
+ 		# Dmenu doesn't render tabs so removing it
+-		menu_command='tr -d "$tab_space" | '"$external_menu"
++		menu_command='@tr@ -d "$tab_space" | '"$external_menu"
+ 		format_ext_menu
+ 	fi
+ }
+@@ -461,13 +461,13 @@ ID="ytfzf-ueberzug"
+ WIDTH=$FZF_PREVIEW_COLUMNS
+ HEIGHT=$FZF_PREVIEW_LINES
+ start_ueberzug () {
+-    [ -e $FIFO ] || { mkfifo "$FIFO" || exit 1 ; }
+-    ueberzug layer --parser json --silent < "$FIFO" &
++    [ -e $FIFO ] || { @mkfifo@ "$FIFO" || exit 1 ; }
++    @ueberzug@ layer --parser json --silent < "$FIFO" &
+     exec 3>"$FIFO"
+ }
+ stop_ueberzug () {
+     exec 3>&-
+-    rm "$FIFO" > /dev/null 2>&1
++    @rm@ "$FIFO" > /dev/null 2>&1
+ }
+ 
+ preview_img () {
+@@ -476,12 +476,12 @@ preview_img () {
+ 	shorturl=${args##*${tab_space}|}
+ 	shorturl="${shorturl%% *}"
+ 
+-	json_obj=$(printf "%s" "$videos_json" | jq '.[]|select( .videoID == "'"$shorturl"'")')
++	json_obj=$(printf "%s" "$videos_json" | @jq@ '.[]|select( .videoID == "'"$shorturl"'")')
+ 
+ 
+ 	IFS=$tab_space read -r title channel duration views date description <<-EOF
+ 	$(
+-		printf "%s" "$json_obj" | jq -r \
++		printf "%s" "$json_obj" | @jq@ -r \
+ 		'
+ 		[.title,.channel,.duration,.views,.date,.description]|@tsv
+ 		'
+@@ -530,31 +530,31 @@ preview_img () {
+ 		} > "$FIFO" ;;
+ 	    catimg)
+ 		printf "\n"
+-		catimg -w "$((thumb_width * 2))" "$IMAGE" ;;
++		@catimg@ -w "$((thumb_width * 2))" "$IMAGE" ;;
+ 	    jp2a)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=24 "$IMAGE" ;;
+ 	    jp2a-8)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=8 "$IMAGE" ;;
+ 	    jp2a-4)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" --colors  --color-depth=4 "$IMAGE" ;;
+ 	    jp2a-gray|jp2a-grey)
+ 		printf "\n"
+-		jp2a --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
++		@jp2a@ --size="${thumb_width}x$((thumb_height / 2))" "$IMAGE" ;;
+ 	    chafa)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" "$IMAGE" ;;
+ 	    chafa-gray|chafa-grey)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=2 "$IMAGE" ;;
+ 	    chafa-4)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=16 "$IMAGE" ;;
+ 	    chafa-8)
+ 		printf "\n"
+-		chafa --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
++		@chafa@ --size="${thumb_width}x${thumb_height}" --colors=256 "$IMAGE" ;;
+ 	    custom)
+ 		if ! function_exists "handle_display_img"; then
+ 		    printf "\033[031mERROR[#07]: \033[0m\033[1mhandle_display_img\033[0m is not defined" >&2
+@@ -585,20 +585,20 @@ download_thumbnails () {
+ 	if [ "$thumbnail_quality" -eq 1 ]; then
+ 		image_download () {
+ 			# higher quality images
+-			curl -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
++			@curl@ -s "$Url" -G --data-urlencode "sqp=" > "$thumb_dir/$Name.png"
+ 		}
+ 	else
+ 		image_download () {
+- 			curl -s "$Url"  > "$thumb_dir/$Name.png"
++			@curl@ -s "$Url"  > "$thumb_dir/$Name.png"
+ 		}
+ 	fi
+ 
+ 	print_info "Downloading Thumbnails...\n"
+ 	thumb_urls=$(printf "%s" "$*" |\
+-		jq  -r '.[]|[.thumbs,.videoID]|@tsv' )
++		@jq@  -r '.[]|[.thumbs,.videoID]|@tsv' )
+ 
+ 	while IFS=$tab_space read -r Url Name; do
+-	    sleep 0.001
++	    @sleep@ 0.001
+ 		{
+ 			image_download
+ 		} &
+@@ -628,7 +628,7 @@ get_sp_filter () {
+ 	#another example is sort by filter + upload date filter only changes one character as well
+ 	if [ -n "$filter_id" ]; then
+ 		#gets the character in the filter_id that needs to be replaced if upload_date_filter is also given
+-		upload_date_character=$(printf "%s" "$filter_id" | awk '{print substr($1, 8, 1)}')
++		upload_date_character=$(printf "%s" "$filter_id" | @awk@ '{print substr($1, 8, 1)}')
+ 	fi
+ 
+ 	#For each of these, if upload_date_character is unset, the filter_id should be the normal filter
+@@ -650,7 +650,7 @@ get_sp_filter () {
+ 	if [ -n "$upload_date_character" ]; then
+ 		#replaces the 8th character in the filter_id with the appropriate character
+ 		#the 8th character specifies the upload_date_filter
+-		sp=$(printf "%s" "$filter_id" | sed 's/\(.\{7\}\)./\1'"$upload_date_character"'/')
++		sp=$(printf "%s" "$filter_id" | @sed@ 's/\(.\{7\}\)./\1'"$upload_date_character"'/')
+ 	#otherwise set it to the filter_id
+ 	else
+ 		sp=$filter_id
+@@ -660,15 +660,15 @@ get_sp_filter () {
+ 
+ get_yt_json () {
+ 	# scrapes the json embedded in the youtube html page
+-	printf "%s" "$*" | sed -n '/var *ytInitialData/,$p' | tr -d '\n' |\
+-        sed -E ' s_^.*var ytInitialData ?=__ ; s_;</script>.*__ ;'
++	printf "%s" "$*" | @sed@ -n '/var *ytInitialData/,$p' | @tr@ -d '\n' |\
++        @sed@ -E ' s_^.*var ytInitialData ?=__ ; s_;</script>.*__ ;'
+ }
+ 
+ get_yt_html () {
+     link=$1
+     query=$2
+     printf "%s" "$(
+-	curl "$link" -s \
++	@curl@ "$link" -s \
+ 	  -G --data-urlencode "search_query=$query" \
+ 	  -G --data-urlencode "sp=$sp" \
+ 	  -H 'Authority: www.youtube.com' \
+@@ -684,7 +684,7 @@ get_video_data () {
+ 	# outputs tab and pipe separated fields: title, channel, view count, video length, video upload date, and the video id/url
+ 	# from the videos_json
+ 	printf "%s" "$*" |\
+-	    jq -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
++	    @jq@ -r '.[]| "\(.title)'"$tab_space"'|\(.channel)'"$tab_space"'|\(.views)'"$tab_space"'|\(.duration)'"$tab_space"'|\(.date)'"$tab_space"'|\(.videoID)"'
+ }
+ 
+ scrape_channel () {
+@@ -694,7 +694,7 @@ scrape_channel () {
+ 	channel_url=$*
+ 
+ 	# Converting channel title page url to channel video url
+-	if ! printf "%s" "$channel_url" | grep -q '/videos *$'; then
++	if ! printf "%s" "$channel_url" | @grep@ -q '/videos *$'; then
+ 		channel_url=${channel_url%/featured}/videos
+ 	fi
+ 
+@@ -706,8 +706,8 @@ scrape_channel () {
+ 	fi
+ 
+ 	#gets the channel name from title of page
+-	channel_name=$(printf "%s" "$yt_html" | grep -o '<title>.*</title>' |
+-		sed \
++	channel_name=$(printf "%s" "$yt_html" | @grep@ -o '<title>.*</title>' |
++		@sed@ \
+ 		-e 's/ - YouTube//' \
+ 		-e 's/<\/\?title>//g' \
+ 		-e "s/&apos;/'/g" \
+@@ -723,7 +723,7 @@ scrape_channel () {
+ 
+ 	#gets a list of videos
+ 	videos_json=$(printf "%s" "$yt_json" |\
+-	jq '[ .contents | ..|.gridVideoRenderer? |
++	@jq@ '[ .contents | ..|.gridVideoRenderer? |
+ 	select(. !=null) |
+ 	    {
+ 	    	title: .title.runs[0].text,
+@@ -736,7 +736,7 @@ scrape_channel () {
+ 	    }
+ 	]')
+ 
+-	videos_json=$(printf "%s" "$videos_json" | jq '.[0:'$sub_link_count']')
++	videos_json=$(printf "%s" "$videos_json" | @jq@ '.[0:'$sub_link_count']')
+ 	printf "%s\n" "$videos_json" >> "$tmp_video_json_file"
+ 	#checks if it's empty in case it was defined in a config function eg: on_get_search
+ 	[ -z "$videos_data" ] && videos_data=$(get_video_data "$videos_json")
+@@ -768,11 +768,11 @@ get_trending_url_data () {
+ scrape_pt () {
+      #gets a list of videos
+      pt_json=$(
+-     curl \
++     @curl@ \
+          -s "https://sepiasearch.org/api/v1/search/videos" \
+ 	 -G --data-urlencode "search=$*") 
+      videos_json=$(printf "%s" "$pt_json" |\
+-	jq '[ .data | .[] |
++	@jq@ '[ .data | .[] |
+ 	    {
+ 		title: .name,
+ 		channel: .channel.displayName,
+@@ -829,7 +829,7 @@ scrape_yt () {
+ 	fi
+ 
+ 	#gets a list of videos
+-	videos_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	videos_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
+ 	..|.videoRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -844,7 +844,7 @@ scrape_yt () {
+ 		}
+ 	]')
+ 
+-	playlist_json=$(printf "%s" "$yt_json" | jq '[ .contents|
++	playlist_json=$(printf "%s" "$yt_json" | @jq@ '[ .contents|
+ 	..|.playlistRenderer? |
+ 	select(. !=null) |
+ 		{
+@@ -904,31 +904,31 @@ get_search_query () {
+ #> To select videos from videos_data
+ user_selection () {
+ 	#remove subscription separators
+-	videos_data_clean=$(printf "%s" "$videos_data" | sed "/.*$tab_space$/d")
++	videos_data_clean=$(printf "%s" "$videos_data" | @sed@ "/.*$tab_space$/d")
+ 
+ 	#$selected_data is the video the user picked
+ 	#picks the first n videos
+ 	if [ "$select_all" -eq 1 ] ; then
+ 		selected_data=$videos_data_clean
+ 	elif [ "$auto_select" -eq 1 ] ; then
+-		selected_data=$(printf "%s\n" "$videos_data_clean" | sed "${link_count}"q )
++		selected_data=$(printf "%s\n" "$videos_data_clean" | @sed@ "${link_count}"q )
+ 	#picks n random videos
+ 	elif [ "$random_select" -eq 1 ] ; then
+-	    selected_data=$(printf "%s\n" "$videos_data_clean" | posix_shuf | head -n${link_count}) 
++	    selected_data=$(printf "%s\n" "$videos_data_clean" | posix_shuf | @head@ -n${link_count})
+ 	    #posix_shuf, pick the first $link_count videos
+ 
+ 	#show thumbnail menu
+ 	elif [ "$show_thumbnails" -eq 1 ] ; then
+-		dep_ck "ueberzug" "fzf"
++		dep_ck "@ueberzug@" "@fzf@"
+ 		export YTFZF_THUMB_DISP_METHOD="$thumb_disp_method"
+-		[ "$thumb_disp_method" = "ueberzug" ] && start_ueberzug
++		[ "$thumb_disp_method" = "@ueberzug@" ] && start_ueberzug
+ 		#thumbnails only work in fzf, use fzf
+-		menu_command="fzf -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
++		menu_command="@fzf@ -m --tabstop=1 --bind change:top --delimiter=\"$tab_space\" \
+ 		--nth=1,2 --expect='$shortcuts' $FZF_DEFAULT_OPTS \
+ 		--layout=reverse --preview \"sh $0 -U {}\" \
+         	--preview-window \"$PREVIEW_SIDE:50%:noborder:wrap\""
+ 		selected_data=$( title_len=200 video_menu "$videos_data" )
+-		[ "$thumb_disp_method" = "ueberzug" ] && stop_ueberzug
++		[ "$thumb_disp_method" = "@ueberzug@" ] && stop_ueberzug
+ 		# Deletes thumbnails if no video is selected
+ 		[ -z "$selected_data" ] && clean_up
+ 	#show regular menu
+@@ -951,10 +951,10 @@ handle_shortcuts () {
+     case $selected_key in
+ 	"$urls_shortcut") printf "%s\n" $selected_urls; return 1 ;;
+ 	"$title_shortcut") 
+-	    printf "%s\n" "$selected_data" | awk -F "  " '{print $1}'; return 1 ;;
++	    printf "%s\n" "$selected_data" | @awk@ -F "  " '{print $1}'; return 1 ;;
+ 	"$open_browser_shortcut")
+ 	    for url in $selected_urls; do
+-		nohup $BROWSER "$url" >/dev/null 2>&1
++		@nohup@ $BROWSER "$url" >/dev/null 2>&1
+ 	    done
+ 	    return 1 ;;
+ 	"$watch_shortcut") is_download=0; is_audio_only=0; return 0;;
+@@ -988,10 +988,10 @@ format_user_selection () {
+ 			11) selected_urls=$selected_urls$new_line'https://www.youtube.com/watch?v='$surl ;;
+ 			34) selected_urls=$selected_urls$new_line'https://www.youtube.com/playlist?list='$surl ;;
+ 			36)
+-			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | jq '.[].url' | grep -F "$surl" | tr -d '"')" ;;
++			    selected_urls=$selected_urls$new_line"$(printf "%s" "$videos_json" | @jq@ '.[].url' | @grep@ -F "$surl" | @tr@ -d '"')" ;;
+ 			*) continue ;;
+ 		esac
+-		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | grep "|$surl" )
++		refined_selected_data=$refined_selected_data$new_line$(printf '%s' "$videos_data" | @grep@ "|$surl" )
+ 	done<<-EOF
+ 	$selected_data
+ 	EOF
+@@ -1014,9 +1014,9 @@ print_data () {
+ get_video_format () {
+ 	# select format if flag given
+ 	[ $show_format -eq 0 ] && return
+-        formats=$(youtube-dl -F "$(printf "$selected_urls")") 
+-        line_number=$(printf "$formats" | grep -n '.*extension  resolution.*' | cut -d: -f1)
+-        quality=$(printf "$formats \n1 2 xAudio" | awk -v lineno=$line_number 'FNR > lineno {print $3}' | sort -n |  awk -F"x" '{print $2 "p"}' | uniq | sed -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | sed "s/p//g")
++        formats=$(@youtube-dl@ -F "$(printf "$selected_urls")")
++        line_number=$(printf "$formats" | @grep@ -n '.*extension  resolution.*' | @cut@ -d: -f1)
++        quality=$(printf "$formats \n1 2 xAudio" | @awk@ -v lineno=$line_number 'FNR > lineno {print $3}' | @sort@ -n |  @awk@ -F"x" '{print $2 "p"}' | @uniq@ | @sed@ -e "s/Audiop/Audio/" -e "/^p$/d" | eval "$menu_command" | @sed@ "s/p//g")
+ 		[ -z "$quality"  ] && exit;
+ 		[ $quality = "Audio"  ] && video_pref= && video_player="$audio_player" || video_pref="bestvideo[height=?$quality][vcodec!=?vp9]+bestaudio/best"
+ 
+@@ -1026,9 +1026,9 @@ get_video_format () {
+ get_sub_lang () {
+     if [ $auto_caption -eq 1 ]; then
+         #Gets the auto generated subs and stores them in a file
+-        sub_list=$(youtube-dl --list-subs  --write-auto-sub "$selected_urls" | sed '/Available subtitles/,$d' | awk '{print $1}' | sed '1d;2d;3d')
++        sub_list=$(@youtube-dl@ --list-subs  --write-auto-sub "$selected_urls" | @sed@ '/Available subtitles/,$d' | @awk@ '{print $1}' | @sed@ '1d;2d;3d')
+         if [ -n "$sub_list" ]; then
+-            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  youtube-dl  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
++            [ -n "$selected_sub" ] ||  selected_sub=$(printf "$sub_list" | eval "$menu_command") &&  @youtube-dl@  --sub-lang $selected_sub  --write-auto-sub --skip-download "$selected_urls" -o /tmp/ytfzf && YTFZF_SUBT_NAME="--sub-file=/tmp/ytfzf.$selected_sub.vtt" || printf "Auto generated subs not available."
+         fi
+ 	unset sub_list
+     fi
+@@ -1046,10 +1046,10 @@ open_player () {
+ 	if [ $detach_player -eq 1 ]; then
+ 		if [ -z "$video_pref" ] || [ $is_audio_only -eq 1 ]; then
+ 			printf "Opening Player: %s\n" "$video_player $*"
+-			setsid -f $video_player "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
++			@setsid@ -f $video_player "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
+ 		else
+ 			printf "Opening Player: %s\n" "$video_player_format$video_pref $*"
+-			setsid -f $video_player_format"$video_pref"  "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
++			@setsid@ -f $video_player_format"$video_pref"  "$@"  $YTFZF_SUBT_NAME >/dev/null 2>&1
+ 		fi
+ 		return
+ 	fi
+@@ -1064,9 +1064,9 @@ open_player () {
+ 		fi
+ 	elif [ $is_download -eq 1 ]; then
+ 		if [ -z "$video_pref" ]; then
+-			youtube-dl "$@"  "$YTFZF_SUBT_NAME"
++			@youtube-dl@ "$@"  "$YTFZF_SUBT_NAME"
+ 		else
+-			youtube-dl -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
++			@youtube-dl@ -f "$video_pref"  "$@"  $YTFZF_SUBT_NAME || video_pref= open_player "$@"
+ 		fi
+ 	fi
+ }
+@@ -1087,7 +1087,7 @@ play_url () {
+ 	fi
+ 
+ 	#Delete the temp auto-gen subtitle file
+-	[ $auto_caption -eq 1 ] && rm -f "${YTFZF_SUBT_NAME#*=}"
++	[ $auto_caption -eq 1 ] && @rm@ -f "${YTFZF_SUBT_NAME#*=}"
+ 
+ 	unset player_urls
+ }
+@@ -1102,7 +1102,7 @@ session_is_running () {
+ #> removes tmp files and clutter
+ clean_up () {
+ 	if ! session_is_running ; then
+-		[ -d "$thumb_dir" ] && rm -r "$thumb_dir"
++		[ -d  "$thumb_dir" ] && @rm@ -r "$thumb_dir"
+ 		: > "$pid_file"
+ 		function_exists "on_exit" && on_exit
+ 	fi
+@@ -1124,9 +1124,9 @@ save_before_exit () {
+ check_if_url () {
+ 	# to check if given input is a url
+ 	url_regex='^https\?://.*'
+-	if printf "%s" "$1" | grep -q "$url_regex"; then
++	if printf "%s" "$1" | @grep@ -q "$url_regex"; then
+ 		is_url=1
+-		selected_urls=$(printf "%s" "$1" | tr ' ' '\n')
++		selected_urls=$(printf "%s" "$1" | @tr@ ' ' '\n')
+ 		scrape="url"
+ 	else
+ 		is_url=0
+@@ -1139,10 +1139,10 @@ get_history () {
+ 	if [ "$enable_hist" -eq 1 ]; then
+ 		[ -e "$history_file" ] || : > "$history_file"
+ 		#gets history data in reverse order (makes it most recent to least recent)
+-		hist_data=$( sed '1!G; h; $!d' "$history_file" )
++		hist_data=$( @sed@ '1!G; h; $!d' "$history_file" )
+ 		[ -z "$hist_data" ] && printf "History is empty!\n" >&2 && return 1;
+ 		#removes duplicate values from $history_data
+-		videos_data=$(printf "%s" "$hist_data" | uniq )
++		videos_data=$(printf "%s" "$hist_data" | @uniq@ )
+ 		[ "$sort_videos_data" -eq 1 ] && videos_data="$(printf "%s" "$videos_data"  | sort_video_data_fn)"
+ 	else
+ 		printf "History is not enabled. Please enable it to use this option (-H).\n" >&2;
+@@ -1177,10 +1177,10 @@ get_search_history () {
+ 	if [ "$enable_search_hist" -eq 1 ]; then
+ 		[ -e "$search_history_file" ] || : > "$search_history_file"
+ 		#gets history data in reverse order (makes it most recent to least recent)
+-		hist_data=$( sed '1!G; h; $!d' "$search_history_file" )
++		hist_data=$( @sed@ '1!G; h; $!d' "$search_history_file" )
+ 		[ -z "$hist_data" ] && printf "Search history is empty!\n" >&2 && return 1;
+ 		#removes duplicate values from $history_data
+-		search_history=$(printf "%s" "$hist_data" | uniq )
++		search_history=$(printf "%s" "$hist_data" | @uniq@ )
+ 	else
+ 		printf "Search history is not enabled. Please enable it to use this option (-q).\n" >&2;
+ 		exit 1;
+@@ -1190,7 +1190,7 @@ get_search_history () {
+ 
+ set_search_history () {
+     [ -z "$search_query" ] && return
+-    [ $enable_search_hist -eq 1 ] && printf "%s\t%s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$search_query" >> "$search_history_file" ;
++    [ $enable_search_hist -eq 1 ] && printf "%s\t%s\n" "$(@date@ '+%Y-%m-%d %H:%M:%S')" "$search_query" >> "$search_history_file" ;
+ }
+ 
+ search_history_menu () {
+@@ -1200,15 +1200,15 @@ search_history_menu () {
+     #when using an external menu, the search history will be done there
+         choice=$( printf "%s\n" "$search_history" | eval "$external_menu" )
+     else
+-        choice="$( printf "%s\n" "$search_history" | fzf --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
++        choice="$( printf "%s\n" "$search_history" | @fzf@ --prompt="$search_history_prompt" --print-query --no-multi -d '\t' --with-nth=2.. --expect='alt-enter' --bind='tab:replace-query' )"
+     fi
+ 
+     # first line is the fzf query (what the user types in fzf)
+     # second line is the fzf --expect key pressed
+     # third line is the search_history selection made
+-    query="$( printf "%s" "$choice" | sed -n '1p' )"
+-    key="$( printf "%s" "$choice" | sed -n '2p' )"
+-    selection="$( printf "%s" "$choice" | sed -n '3p' )"
++    query="$( printf "%s" "$choice" | @sed@ -n '1p' )"
++    key="$( printf "%s" "$choice" | @sed@ -n '2p' )"
++    selection="$( printf "%s" "$choice" | @sed@ -n '3p' )"
+ 
+     # if no search history selection has been made
+     # and the user typed a query, use that instead
+@@ -1225,7 +1225,7 @@ search_history_menu () {
+             search_query="$query"
+             return;;
+     esac
+-    search_query="$( printf "%s" "$selection" | awk -F'\t' '{printf "%s", $NF}' )"
++    search_query="$( printf "%s" "$selection" | @awk@ -F'\t' '{printf "%s", $NF}' )"
+ }
+ 
+ ! function_exists "send_select_video_notif" && send_select_video_notif () {
+@@ -1244,13 +1244,13 @@ search_history_menu () {
+ 
+ 	#if downloading, say Downloading not currently playing
+ 	[ $is_download -eq 1 ] && title="Downloading" || title="Currently playing"
+-	notify-send "$title" "$message" -i "$video_thumb"
++	@notify-send@ "$title" "$message" -i "$video_thumb"
+ 
+ 	unset message video_thumb title
+ }
+ 
+ send_notify () {
+-	videos_selected_count=$(printf "%s\n" "$*" | wc -l)
++	videos_selected_count=$(printf "%s\n" "$*" | @wc@ -l)
+ 	while IFS=$tab_space read -r video_title video_channel video_views video_duration video_date video_shorturl; do
+ 	    send_select_video_notif
+ 	done << EOF
+@@ -1284,14 +1284,14 @@ if ! function_exists "data_sort_key"; then
+ 	sort_by="${5#|}"
+ 	sort_by="${sort_by#Streamed}"
+ 	#print the data that should be sorted by
+-	printf "%d" "$(date -d "${sort_by}" '+%s')"
++	printf "%d" "$(@date@ -d "${sort_by}" '+%s')"
+ 	unset sort_by
+     }
+ fi
+ #the function to use for sorting
+ if ! function_exists "data_sort_fn"; then
+     data_sort_fn () {
+-	sort -nr
++	@sort@ -nr
+     }
+ fi
+ sort_video_data_fn () {
+@@ -1300,7 +1300,7 @@ sort_video_data_fn () {
+ 		IFS="$tab_space"
+ 		#run the key function to get the value to sort by
+ 		printf "%s\t%s\n" "$(data_sort_key $line)" "$line"
+-	done | data_sort_fn | cut -f2-
++	done | data_sort_fn | @cut@ -f2-
+ 	unset IFS line 
+ }
+ 
+@@ -1314,19 +1314,19 @@ scrape_subscriptions () {
+ 	while IFS= read -r url; do
+ 		scrape_channel "$url" &
+ 	done <<-EOF
+-	$( sed \
++	$( @sed@ \
+ 	-e "s/#.*//" \
+ 	-e "/^[[:space:]]*$/d" \
+ 	-e "s/[[:space:]]*//g" \
+ 	"$subscriptions_file")
+ 	EOF
+ 	wait
+-	videos_json="$(cat "$tmp_video_json_file")"
++	videos_json="$(@cat@ "$tmp_video_json_file")"
+ 	export videos_json
+ 	if [ $sort_videos_data -eq 1 ]; then 
+ 		videos_data=$(sort_video_data_fn < "$tmp_video_data_file")
+ 	else
+-		videos_data=$(cat "$tmp_video_data_file")
++		videos_data=$(@cat@ "$tmp_video_data_file")
+ 	fi
+ }
+ 
+@@ -1346,11 +1346,11 @@ create_subs () {
+     : > "$config_dir/subscriptions"
+ 
+     # check how many subscriptions there are in the file
+-    sublength=$( jq '. | length' < "$yt_sub_import_file" )
++    sublength=$( @jq@ '. | length' < "$yt_sub_import_file" )
+ 
+-    for i in $(seq $((sublength - 1))); do
+-        channelInfo=$(jq --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
+-	printf "%s\n" "$(printf "%s" "$channelInfo" | tr -d '[]"\n,')" >> "$subscriptions_file"
++    for i in $(@seq@ $((sublength - 1))); do
++        channelInfo=$(@jq@ --argjson index ${i} '[ "https://www.youtube.com/channel/" + .[$index].snippet.resourceId.channelId + "/videos", "#" + .[$index].snippet.title ]' < "$yt_sub_import_file")
++	printf "%s\n" "$(printf "%s" "$channelInfo" | @tr@ -d '[]"\n,')" >> "$subscriptions_file"
+     done
+     exit
+ }
+@@ -1367,10 +1367,10 @@ verify_thumb_disp_method () {
+ 
+ #sort -R is not posix
+ posix_shuf () {
+-    awk -F '\n' '
++    @awk@ -F '\n' '
+ 	BEGIN {srand()} #set the random seed at the start
+ 	{print rand() " " $0} #prepend a random number for each line' |\
+-    sort | sed -E 's/[^ ]* //'
++    @sort@ | @sed@ -E 's/[^ ]* //'
+     #sort by the random numbers, remove the random number
+ }
+ 
+@@ -1486,8 +1486,8 @@ parse_opt () {
+ 			exit ;;
+ 		version)
+ 			printf "\033[1mytfzf:\033[0m %s\n" "$YTFZF_VERSION"
+-			printf "\033[1myoutube-dl:\033[0m %s\n" "$(youtube-dl --version)"
+-			command -v "fzf" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(fzf --version)"
++			printf "\033[1myoutube-dl:\033[0m %s\n" "$(@youtube-dl@ --version)"
++			command -v "@fzf@" 1>/dev/null && printf "\033[1mfzf:\033[0m %s\n" "$(@fzf@ --version)"
+ 			exit ;;
+ 
+ 		subt)
+@@ -1559,19 +1559,19 @@ done
+ shift $((OPTIND-1))
+ 
+ #only apply to ext_menu since they dont have a terminal to print to
+-[ $is_ext_menu -eq 1 ] && command -v notify-send 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
++[ $is_ext_menu -eq 1 ] && command -v @notify-send@ 1>/dev/null 2>&1 && ext_menu_notifs=1 || ext_menu_notifs=0
+ 
+ #used for thumbnail previews in ueberzug
+ if [ $is_ext_menu -eq 0 ]; then
+-	export TTY_LINES=$(tput lines)
+- 	export TTY_COLS=$(tput cols)
++	export TTY_LINES=$(@tput@ lines)
++	export TTY_COLS=$(@tput@ cols)
+ fi
+ 
+ #if both are true, it defaults to using fzf, and if fzf isnt installed it will throw an error
+ #so print this error instead and set $show_thumbnails to 0
+ if [ $is_ext_menu -eq 1 ] && [ $show_thumbnails -eq 1 ]; then
+ 	[ $ext_menu_notifs -eq 1 ] &&\
+-	    notify-send "warning" "Currently thumbnails do not work in external menus" ||\
++	    @notify-send@ "warning" "Currently thumbnails do not work in external menus" ||\
+ 	    printf "\033[33mWARNING: Currently thumbnails do not work in external menus\033[0m\n" >&2
+ 	show_thumbnails=0
+ fi
+-- 
+2.32.0
+
diff --git a/gnu/packages/patches/ytfzf-updates.patch b/gnu/packages/patches/ytfzf-updates.patch
new file mode 100644
index 0000000000..1790b7a238
--- /dev/null
+++ b/gnu/packages/patches/ytfzf-updates.patch
@@ -0,0 +1,44 @@
+From 75bf4f584866a013d5618ea6be19e97a8196d63e Mon Sep 17 00:00:00 2001
+From: Raghav Gururajan <rg <at> raghavgururajan.name>
+Date: Mon, 5 Jul 2021 06:47:38 -0400
+Subject: [PATCH 2/2] Disable updates within the application.
+
+Patch the code responsible for self-updating the application.
+
+Co-authored-by: jgart <jgart <at> dismail.de>
+---
+ ytfzf | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+diff --git a/ytfzf b/ytfzf
+index 0a2c372..845e8e9 100755
+--- a/ytfzf
++++ b/ytfzf
+@@ -1260,22 +1260,8 @@ EOF
+ }
+ 
+ update_ytfzf () {
+-	branch="$1"
+-	updatefile="/tmp/ytfzf-update"
+-	curl -L "https://raw.githubusercontent.com/pystardust/ytfzf/$branch/ytfzf" -o "$updatefile"
+-
+-	if sed -n '1p' < "$updatefile" | grep -q '#!/bin/sh'; then
+-		chmod 755 "$updatefile"
+-		[ "$(uname)" = "Darwin" ] && prefix="/usr/local/bin" || prefix="/usr/bin"
+-		function_exists "sudo" && doasroot="sudo" || doasroot="doas"
+-		$doasroot cp "$updatefile" "$prefix/ytfzf"
+-		unset prefix doasroot
+-	else
+-		printf "%bFailed to update ytfzf. Try again later.%b" "$c_red" "$c_reset"
+-	fi
+-
+-	rm "$updatefile"
+-	exit 0
++       printf "%bUpdates have to be installed with Guix.%b\n" "$c_red" "$c_reset"
++       exit 1
+ }
+ 
+ #gives a value to sort by (this will give the unix time the video was uploaded)
+-- 
+2.32.0
+
-- 
2.32.0





Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Mon, 05 Jul 2021 15:43:01 GMT) Full text and rfc822 format available.

Message #50 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: Raghav Gururajan <rg <at> raghavgururajan.name>, 49238 <at> debbugs.gnu.org
Cc: jgart <jgart <at> dismail.de>
Subject: Re: [PATCH v5 2/2] gnu: Add ytfzf.
Date: Mon, 05 Jul 2021 17:42:15 +0200
[Message part 1 (text/plain, inline)]
Hi,

This patch looks good to me, but I haven't actually tested it.
Also, it may be a good idea to inform upstream on the /tmp/ytfzf
issue, such that non-Guix users can benefit as well.

Greetings,
Maxime.
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#49238; Package guix-patches. (Tue, 06 Jul 2021 05:26:02 GMT) Full text and rfc822 format available.

Message #53 received at 49238 <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: Maxime Devos <maximedevos <at> telenet.be>
Cc: 49238 <at> debbugs.gnu.org, jgart <jgart <at> dismail.de>
Subject: Re: [PATCH v5 2/2] gnu: Add ytfzf.
Date: Tue, 6 Jul 2021 01:25:14 -0400
[Message part 1 (text/plain, inline)]
Hi Maxime!

> This patch looks good to me, but I haven't actually tested it.

Cool! I'll test and push as v6.

> Also, it may be a good idea to inform upstream on the /tmp/ytfzf
> issue, such that non-Guix users can benefit as well.

Sure thing.

Regards,
RG.

[OpenPGP_signature (application/pgp-signature, attachment)]

Reply sent to Raghav Gururajan <rg <at> raghavgururajan.name>:
You have taken responsibility. (Tue, 06 Jul 2021 05:38:02 GMT) Full text and rfc822 format available.

Notification sent to Raghav Gururajan <rg <at> raghavgururajan.name>:
bug acknowledged by developer. (Tue, 06 Jul 2021 05:38:02 GMT) Full text and rfc822 format available.

Message #58 received at 49238-done <at> debbugs.gnu.org (full text, mbox):

From: Raghav Gururajan <rg <at> raghavgururajan.name>
To: 49238-done <at> debbugs.gnu.org
Cc: jgart <jgart <at> dismail.de>
Date: Tue, 6 Jul 2021 01:37:39 -0400
[Message part 1 (text/plain, inline)]
Pushed as 586136d127..aa6e6fb2e9 to master.

[OpenPGP_signature (application/pgp-signature, attachment)]

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 03 Aug 2021 11:24:07 GMT) Full text and rfc822 format available.

This bug report was last modified 2 years and 259 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.