Lucien Cartier-Tilet
be955e6673
All checks were successful
deploy / build (push) Successful in 4m12s
982 lines
32 KiB
Org Mode
982 lines
32 KiB
Org Mode
#+TITLE: Custom Scripts
|
||
#+setupfile: headers
|
||
#+PROPERTY: header-args :exports code
|
||
#+PROPERTY: header-args:emacs-lisp :exports none :tangle no
|
||
|
||
* Custom Scripts
|
||
This file will present all the executable scripts I wrote. It is also their
|
||
original source code, all the following code snippets are exported and tangled
|
||
from this file to the actual executables.
|
||
|
||
** Autostart
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env bash" :mkdirp yes :tangle ~/.local/bin/autostart
|
||
:END:
|
||
Because I sometimes switch from window manager to window manager, creating a
|
||
script that handles by itself autostarting things for me is way easier than
|
||
rewriting every time the autostart part of my configuration. As you can every
|
||
instance will be launched asynchronously, and only if there is no other instance
|
||
of said command running.
|
||
#+NAME: autostart-table
|
||
| Command | Arguments | Run once? |
|
||
|----------------------+------------------------------------------+-----------|
|
||
| ~pactl~ | ~load-module module-switch-on-connect~ | |
|
||
| ~mpc~ | ~stop~ | no |
|
||
| ~xrdb~ | ~-merge "$XDG_CONFIG_HOME"/X11/Xresources~ | no |
|
||
| ~picom~ | | yes |
|
||
| ~numlockx~ | ~on~ | yes |
|
||
| ~xfce-polkit~ | | yes |
|
||
| ~nm-applet~ | | yes |
|
||
| ~xwallpaper~ | ~--zoom "$(cat "$HOME"/.cache/wallpaper)"~ | no |
|
||
| ~xss-lock~ | ~plock~ | yes |
|
||
| ~/usr/lib/kdeconnectd~ | | yes |
|
||
| ~dunst~ | | yes |
|
||
|
||
#+NAME: autostart-gen
|
||
#+header: :wrap "src bash :exports code"
|
||
#+BEGIN_SRC emacs-lisp :var table=autostart-table :cache yes
|
||
(mapconcat (lambda (start-command)
|
||
(let* ((clean-string (lambda (str) (replace-regexp-in-string "~" "" str)))
|
||
(command (funcall clean-string (nth 0 start-command)))
|
||
(arguments (funcall clean-string (nth 1 start-command)))
|
||
(oncep (string= "yes" (nth 2 start-command)))
|
||
(full-command (replace-regexp-in-string
|
||
" +"
|
||
" "
|
||
(format "%s %s &" command arguments))))
|
||
|
||
(concat (format "which %s && %s"
|
||
command
|
||
(if (not oncep)
|
||
full-command
|
||
(format (concat "if pgrep -x %s ; then\n"
|
||
" echo %s already running\n"
|
||
"else\n"
|
||
" %s\n"
|
||
" disown\n"
|
||
"fi")
|
||
command
|
||
command
|
||
full-command))))))
|
||
table
|
||
"\n")
|
||
#+END_SRC
|
||
|
||
#+RESULTS[8c42a43989020c61050b2930ae60c81248c2dd44]: autostart-gen
|
||
#+begin_src bash :exports code
|
||
which pactl && pactl load-module module-switch-on-connect &
|
||
which mpc && mpc stop &
|
||
which xrdb && xrdb -merge "$XDG_CONFIG_HOME"/X11/Xresources &
|
||
which picom && if pgrep -x picom ; then
|
||
echo picom already running
|
||
else
|
||
picom &
|
||
disown
|
||
fi
|
||
which numlockx && if pgrep -x numlockx ; then
|
||
echo numlockx already running
|
||
else
|
||
numlockx on &
|
||
disown
|
||
fi
|
||
which xfce-polkit && if pgrep -x xfce-polkit ; then
|
||
echo xfce-polkit already running
|
||
else
|
||
xfce-polkit &
|
||
disown
|
||
fi
|
||
which nm-applet && if pgrep -x nm-applet ; then
|
||
echo nm-applet already running
|
||
else
|
||
nm-applet &
|
||
disown
|
||
fi
|
||
which xwallpaper && xwallpaper --zoom "$(cat "$HOME"/.cache/wallpaper)" &
|
||
which xss-lock && if pgrep -x xss-lock ; then
|
||
echo xss-lock already running
|
||
else
|
||
xss-lock plock &
|
||
disown
|
||
fi
|
||
which /usr/lib/kdeconnectd && if pgrep -x /usr/lib/kdeconnectd ; then
|
||
echo /usr/lib/kdeconnectd already running
|
||
else
|
||
/usr/lib/kdeconnectd &
|
||
disown
|
||
fi
|
||
which dunst && if pgrep -x dunst ; then
|
||
echo dunst already running
|
||
else
|
||
dunst &
|
||
disown
|
||
fi
|
||
#+end_src
|
||
|
||
I also have an external sound card, a Scarlet 2i2 G3, that I would
|
||
like to use as my default audio output. However, it might not be
|
||
always connected, hence the following code:
|
||
#+NAME: default-soundcard
|
||
#+BEGIN_SRC bash
|
||
SOUNDCARD=$(pactl list short sinks | grep "Focusrite")
|
||
if [[ -n $SOUNDCARD ]]; then
|
||
pactl set-default-sink "$(echo "$SOUNDCARD" | awk '{print $2}')"
|
||
fi
|
||
#+END_SRC
|
||
|
||
** cli utilities
|
||
*** Backup
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/backup
|
||
:END:
|
||
~backup~ is a very simple, one-liner script that will create a local
|
||
copy of a file and add the date at which it was copied in the
|
||
filename. You can see its source code here:
|
||
#+BEGIN_SRC sh
|
||
cp -r "$1" "$1.bak.$(date +%Y%m%d%H%M%S)"
|
||
#+END_SRC
|
||
|
||
*** CPU Scaling
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env bash" :mkdirp yes :tangle ~/.local/bin/cpu-scaling
|
||
:END:
|
||
As I am using a laptop, maximum performance isn’t always what I want.
|
||
Sometimes, it’s just better to have not so great but less
|
||
battery-demanding performance. It is possible to achieve this by
|
||
modifying the CPU governor with ~cpupower~. The [[https://wiki.archlinux.org/title/CPU_frequency_scaling#Scaling_governors][Arch Wiki]] has, as usual,
|
||
some superb documentation on this.
|
||
|
||
The following script asks the user through ~rofi~ which governor to
|
||
apply, and it relies on [[file:./scripts.md#askpass][askpass]] to retrieve the user’s password.
|
||
#+begin_src bash
|
||
governors=("performance" "powersave" "userspace" "ondemand" "conservative" "schedutil")
|
||
governor=$(printf "%s\n" "${governors[@]}" | rofi -dmenu)
|
||
sudo -A cpupower frequency-set -g "$governor"
|
||
#+end_src
|
||
|
||
*** docker-running
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :tangle ~/.local/bin/docker-running
|
||
:END:
|
||
As with =mu-unread= below, =docker-running= is a small and simple utility
|
||
for my StumpWM configuration which indicates how many Docker
|
||
containers are currently running.
|
||
|
||
#+begin_src sh
|
||
NB_CONTAINERS=$(docker ps -q | wc -l | tr -d '\n')
|
||
printf "^f3^f0 %d" $NB_CONTAINERS
|
||
#+end_src
|
||
|
||
*** Kamoji Generator
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :tangle ~/.local/bin/kamoji
|
||
:END:
|
||
This script comes straight from [[https://charm.sh/blog/kamoji-generator/][this blog post]] and generates kamoji. I
|
||
modified it a bit in order to work with either =xclipboard= or =wl-copy=
|
||
depending on whether I am in an X.org session or a Wayland session.
|
||
|
||
Note that it requires the =OPENAI_API_KEY= environment variable to be
|
||
set with a valid OpenAI key.
|
||
#+begin_src bash
|
||
# If the user passes '-h', '--help', or 'help' print out a little bit
|
||
# of help. text.
|
||
case "$1" in
|
||
"-h" | "--help" | "help")
|
||
printf 'Generate kaomojis on request.\n\n'
|
||
printf 'Usage: %s [kind]\n' "$(basename "$0")"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
# The user can pass an argument like "bear" or "angry" to specify the
|
||
# general kind of Kaomoji produced.
|
||
sentiment=""
|
||
if [[ $1 != "" ]]; then
|
||
sentiment=" $1"
|
||
fi
|
||
|
||
# Ask mods to generate Kaomojis. Save the output in a variable.
|
||
kaomoji="$(mods "generate 10${sentiment} kaomojis. Number them and put each one on its own line.")"
|
||
if [[ $kaomoji == "" ]]; then
|
||
exit 1
|
||
fi
|
||
|
||
# Pipe mods output to gum, so the user can choose the perfect kaomoji.
|
||
# Save that choice in a variable. Also note that we're using cut to
|
||
# drop the item number in front of the Kaomoji.
|
||
choice="$(echo "$kaomoji" | gum choose | cut -d ' ' -f 2)"
|
||
if [[ $choice == "" ]]; then
|
||
exit 1
|
||
fi
|
||
|
||
# If the current session is Wayland, copy with wl-copy, otherwise copy
|
||
# with xclipboard
|
||
if [ "$XDG_SESSION_TYPE" = "wayland" ]
|
||
then printf '%s' "$choice" | wl-copy # Wayland
|
||
else printf '%s' "$choice" | xclip -sel clip # X11
|
||
fi
|
||
|
||
# We're done!
|
||
printf 'Copied %s to the clipboard\n' "$choice"
|
||
#+end_src
|
||
|
||
*** mu-unread
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :tangle ~/.local/bin/mu-unread
|
||
:END:
|
||
~mu-unread~ is a very simple utility that simply returns the amount of
|
||
unread emails I have through the use of ~mu~.
|
||
|
||
As you can see, the output string contains two font switchers for
|
||
StumpWM so I can switch from the main font to Siji for the character
|
||
contained between them: U+E072 (an email icon).
|
||
#+begin_src sh
|
||
UNREAD=$(mu find "flag:unread AND (maildir:/Inbox OR maildir:/Junk)" | wc -l)
|
||
printf "^f2^f0%s" "$UNREAD"
|
||
#+end_src
|
||
|
||
*** screenshot
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/screenshot
|
||
:END:
|
||
This is a utility only useful with Wayland for now, using =grim=, =slurp=
|
||
(in order to select which area of the screen I wish to capture) and
|
||
=wl-copy= (from =wl-clipboard=). It saves the screenshot in my
|
||
=$HOME/Pictures/Screenshots= directory with a name formatted as
|
||
=Screenshot_20230425_134550.png= if the screenshot was taken on the 25th
|
||
of April 2023 at 1:45:50PM. If the file already exists, the script
|
||
will suffix the name with an underscore followed by an incremental
|
||
number like =Screenshot_20230425_134550_1.png= or
|
||
=Screenshot_20230425_134550_2.png=.
|
||
|
||
If the argument =select= is passed to =screenshot=, as in =screenshot
|
||
select=, then use =slurp= to select the area to capture.
|
||
#+begin_src sh
|
||
OUTFILE_BASE="$HOME/Pictures/Screenshots/Screenshot_$(date +%Y%m%d)_$(date +%H%M%S)"
|
||
OUTFILE="$OUTFILE_BASE.png"
|
||
SUFFIX=0
|
||
|
||
while getopts ':cd:egs' OPTION; do
|
||
case "$OPTION" in
|
||
c )
|
||
COPY="yes"
|
||
;;
|
||
d )
|
||
DELAY="$OPTARG"
|
||
;;
|
||
e )
|
||
EDIT="yes"
|
||
;;
|
||
g )
|
||
GIMP="yes"
|
||
;;
|
||
s )
|
||
SELECT="yes"
|
||
;;
|
||
? )
|
||
echo "Usage: $(basename "$0") [-c] [-d DELAY] [-e] [-g] [-s]"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
if [ "$SELECT" = "yes" ]
|
||
then AREA="$(slurp)"
|
||
fi
|
||
|
||
if [ -n "$DELAY" ]
|
||
then sleep "$DELAY"
|
||
fi
|
||
|
||
if [ "$SELECT" = "yes" ]
|
||
then grim -g "$AREA" "$OUTFILE"
|
||
else grim "$OUTFILE"
|
||
fi
|
||
|
||
if [ "$EDIT" = "yes" ]
|
||
then swappy -f "$OUTFILE" -o "$OUTFILE"
|
||
fi
|
||
|
||
if [ "$GIMP" = "yes" ]
|
||
then gimp "$OUTFILE"
|
||
fi
|
||
|
||
if [ "$COPY" = "yes" ]
|
||
then wl-copy < "$OUTFILE"
|
||
fi
|
||
|
||
# wl-copy < "$OUTFILE"
|
||
#+end_src
|
||
|
||
*** sshbind
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/sshbind
|
||
:END:
|
||
Something that I did not know for quite some time, but that is
|
||
actually crazy useful about SSH is its ability to bind locally the
|
||
port of a remote machine, and vice versa. The syntax is actually very
|
||
simple, but I prefer a more intuitive way of writing it. Its usage is
|
||
~sshbind PORT FROMHOST TOHOST~.
|
||
#+BEGIN_SRC sh
|
||
ssh -L "$1:$3:$1" "$2" -N
|
||
#+END_SRC
|
||
|
||
*** Nsxiv key handler
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :mkdirp yes :tangle no :noweb yes
|
||
:END:
|
||
One thing I like with ~nsxiv~ is you can trigger different behaviours
|
||
based on keypresses. For instance, with my current nsxiv
|
||
configuration, if I press the space key followed by a character, it
|
||
can delete to the trashcan, delete definitively, or open the current
|
||
image in GIMP. All of that is done through one script file stored in
|
||
~$HOME/.config/nsxiv/exec/key-handler~. The fact it reacts to first
|
||
thespace bar instead of /Ctrl-x/ is because I use a custom version of
|
||
nsxiv I first modified to fit the bépo layout, and then I decided to
|
||
change the prefix to fit how I use Emacs and StumpWM. You can read the
|
||
PKGBUILD and my nsxiv patch [[https://labs.phundrak.com/phundrak/dotfiles/src/branch/master/Documents/code/PKGBUILDs/sxiv][in my dotfiles repo]].
|
||
|
||
#+header: :shebang "#!/usr/bin/env fish" :tangle ~/.config/nsxiv/exec/key-handler
|
||
#+begin_src fish
|
||
<<nsxiv-read-files>>
|
||
|
||
<<nsxiv-switch-statement>>
|
||
#+end_src
|
||
|
||
Here is a step by step explanation of the source code. First, we want
|
||
to store in the variable ~FILES~ all the files marked in nsxiv. This is
|
||
done with a ~while~ loop and the ~read~ command.
|
||
#+name: nsxiv-read-files
|
||
#+begin_src fish
|
||
while read file
|
||
set -g FILES "$file" $FILES
|
||
end
|
||
#+end_src
|
||
|
||
We can then read from the first member of ~argv~ which key the user
|
||
pressed. Depending on it, we can choose what to execute.
|
||
#+name: nsxiv-switch-statement
|
||
#+begin_src fish
|
||
switch "$argv[1]"
|
||
<<nsxiv-trash>>
|
||
<<nsxiv-rm>>
|
||
<<nsxiv-gimp>>
|
||
<<nsxiv-jpeg>>
|
||
<<nsxiv-rotate-clockwise>>
|
||
<<nsxiv-rotate-counter-clockwise>>
|
||
<<nsxiv-yank>>
|
||
end
|
||
#+end_src
|
||
|
||
The first option with the letter ~d~ is to move the file to the trash
|
||
can. For this, we use the ~trash~ command from ~trash-cli~.
|
||
#+name: nsxiv-trash
|
||
#+begin_src fish
|
||
case "d"
|
||
trash $FILES
|
||
#+end_src
|
||
|
||
In case we want to definitively delete a file without using the trash
|
||
can, we can use ~rm~ instead when we press the ~D~ key.
|
||
#+name: nsxiv-rm
|
||
#+begin_src fish
|
||
case "D"
|
||
rm $FILES
|
||
#+end_src
|
||
|
||
It’s not rare I want to modify an image I have open in nsxiv,
|
||
especially since screenshots are automatically open in this image
|
||
viewer aften they are taken. In that case, a simple command will do.
|
||
#+name: nsxiv-gimp
|
||
#+begin_src fish
|
||
case "g"
|
||
gimp $FILES
|
||
#+end_src
|
||
|
||
Often, I use nsxiv to convert an image to a JPEG file, because my
|
||
internet connection is not that great and JPEG screenshots are faster
|
||
to upload than PNG screenshots. So what I do is for each file
|
||
selected, I take the base name of the file (i.e. remove its
|
||
extension), and then I use the ~convert~ command from ~imagemagik~ to
|
||
convert it from its original format to a JPG format --- ~imagemagik~
|
||
detects the formats based on the extension.
|
||
#+name: nsxiv-jpeg
|
||
#+begin_src fish
|
||
case "j"
|
||
for f in $FILES
|
||
set basename (echo "$f" | sed 's/\.[^.]*$//')
|
||
convert "$f" "$basename.jpg"
|
||
end
|
||
#+end_src
|
||
|
||
I have two commands to rotate my files, and both only differ by the
|
||
angle of rotation. Once again I rely on ~convert~ in both cases. To
|
||
rotate clockwise, this is the code needed.
|
||
#+name: nsxiv-rotate-clockwise
|
||
#+begin_src fish
|
||
case "r"
|
||
for f in $FILES
|
||
convert -rotate 90 "$f" "$f"
|
||
end
|
||
#+end_src
|
||
|
||
On the other hand, to rotate counter-clockwise, we need this code:
|
||
#+name: nsxiv-rotate-counter-clockwise
|
||
#+begin_src fish
|
||
case "R"
|
||
for f in $FILES
|
||
convert -rotate 270 "$f" "$f"
|
||
end
|
||
#+end_src
|
||
|
||
Lastly, when I want to copy a file, I just hit the ~y~ key for “yank”
|
||
(that’s a term from Emacs). For that, I rely on ~file~ to tell me the
|
||
mimetype of the image, then I can pass it to ~xclip~ along with the
|
||
filename to copy it to the clipboard. In this case, we only copy the
|
||
first of the selected files since the clipboard cannot hold several
|
||
files at once.
|
||
#+name: nsxiv-yank
|
||
#+begin_src fish
|
||
case "y"
|
||
set FILE "$FILES[1]"
|
||
set TYPE (file -i "$FILE" | sed -r 's|.*(image/[a-z]+);.*|\1|')
|
||
xclip -sel clip -t "$TYPE" -i "$FILE"
|
||
#+end_src
|
||
|
||
*** Secure key generator
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :tangle ~/.local/bin/skg
|
||
:END:
|
||
#+begin_src bash
|
||
tr -cd '[:alnum:]' < /dev/urandom | fold -w 64 | head -n 1 | tr -d '\n'
|
||
#+end_src
|
||
|
||
*** Starwars
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/starwars
|
||
:END:
|
||
This is a one-liner that allows you to watch Star Wars episode 4 in ASCII art in
|
||
your terminal. Here is the code:
|
||
#+BEGIN_SRC sh
|
||
telnet towel.blinkenlights.nl
|
||
#+END_SRC
|
||
|
||
** Emacs stuff
|
||
*** Dired
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/bin/bash" :mkdirp yes :tangle ~/.local/bin/dired
|
||
:END:
|
||
This script allows me to open anything in dired from the command line.
|
||
#+BEGIN_SRC bash
|
||
emacsclient -c -a emacs -e "(dired \"$*\")"
|
||
#+END_SRC
|
||
|
||
*** Ediff
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/bin/bash" :mkdirp yes :tangle ~/.local/bin/ediff
|
||
:END:
|
||
I want Ediff as my merge tool, not just with Git but with other
|
||
programs tooa, such as =pacdiff=.
|
||
#+begin_src bash
|
||
emacsclient -c -a emacs -e "(ediff-files \"$1\" \"$2\")"
|
||
#+end_src
|
||
|
||
*** Emacsmail
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/bin/bash" :mkdirp yes :tangle ~/.local/bin/emacsmail
|
||
:END:
|
||
This short script is used in my =~/.local/share/applications/mu4e.desktop= file
|
||
in order to send to Emacs any ~mailto:~ requests made in my system.
|
||
#+BEGIN_SRC bash
|
||
emacsclient -c -n -a emacs -e "(browse-url-mail \"$*\")"
|
||
#+END_SRC
|
||
|
||
*** Restart Emacs
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/bin/bash" :mkdirp yes :tangle ~/.local/bin/restart-emacs
|
||
:END:
|
||
Believe me or not, it happens I restart Emacs. I generally start Emacs
|
||
manually with =emacs --daemon= because of an issue rendering =lsp-mode=
|
||
useless when started by the user systemd service.
|
||
#+begin_src bash
|
||
PID_EMACS=$(pidof emacs)
|
||
killall emacs
|
||
echo "Waiting for Emacs to be killed... (pid: $PID_EMACS)"
|
||
if timeout 30 tail --pid=$PID_EMACS -f /dev/null ; then
|
||
emacs --daemon
|
||
else
|
||
echo "Failed to kill Emacs after 30s"
|
||
fi
|
||
#+end_src
|
||
|
||
** Media
|
||
*** mp42webm
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/mp42webm
|
||
:END:
|
||
This function allows me to convert easily a MP4 video to the webm
|
||
format. Nothing too fancy here.
|
||
#+BEGIN_SRC sh
|
||
ffmpeg -i "$1" -c:v libvpx -crf 10 -b:v 1M -c:a libvorbis "$1".webm
|
||
#+END_SRC
|
||
|
||
*** youtube-dl wrappers
|
||
**** ytplay
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env bash" :mkdirp yes :tangle ~/.local/bin/ytplay
|
||
:END:
|
||
~ytplay~ is a simple script I’ve written that allows me to play in MPV
|
||
any YouTube video at the desired resolution. The script relies on
|
||
~dmenu~ (or ~rofi~ in dmenu-mode), ~youtube-dl~ and of course ~mpv~ itself.
|
||
#+BEGIN_SRC bash
|
||
URL=$(rofi -dmenu -i -p "Video URL")
|
||
if [ -z "$URL" ]; then
|
||
echo "You need to provide a URL"
|
||
exit 1
|
||
fi
|
||
RESOLUTION_CHOICE=$(yt-dlp --list-formats "$URL" | \
|
||
grep -E "webm.*[0-9]+x[0-9]" | \
|
||
awk '{print $3 " " $1}' | \
|
||
sort -gu | \
|
||
rofi -dmenu -i -p "Resolution")
|
||
mapfile -t RESOLUTION <<< "$RESOLUTION_CHOICE"
|
||
RESOLUTION_CODE=${RESOLUTION[0]}
|
||
mpv --ytdl-format="${RESOLUTION_CODE}+bestaudio/best" "$URL"
|
||
#+END_SRC
|
||
|
||
I’ll even add a ~.desktop~ entry for this script:
|
||
#+BEGIN_SRC conf-desktop :tangle ~/.local/share/applications/ytplay.desktop :mkdirp yes
|
||
[Desktop Entry]
|
||
Type=Application
|
||
Version=1.0
|
||
Name=ytplay (YouTube in mpv)
|
||
Comment=Play YouTube videos in mpv
|
||
Exec=/home/phundrak/.local/bin/ytplay
|
||
Path=/home/phundrak/.local/bin
|
||
Terminal=false
|
||
Categories=Media
|
||
#+END_SRC
|
||
|
||
** Misc
|
||
*** Broadway
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/broadway
|
||
:END:
|
||
This simple script launches broadwayd, a utility that renders GTK
|
||
applications as web apps, and a program displayed to broadway
|
||
directly.
|
||
#+begin_src sh
|
||
export display_screen=:5
|
||
broadwayd $display_screen &
|
||
GDK_BACKEND=broadway BROADWAY_DISPLAY=$display_screen "$@"
|
||
#+end_src
|
||
|
||
But let’s cut the middleman for most of my uses of Broadway.
|
||
#+begin_src sh :tangle ~/.local/bin/emacs-web
|
||
export display_screen=:5
|
||
broadwayd $display_screen &
|
||
GDK_BACKEND=broadway BROADWAY_DISPLAY=$display_screen emacs
|
||
#+end_src
|
||
|
||
** Plock
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/plock
|
||
:END:
|
||
~plock~ is a simple script that locks the screen with ~i3lock~ while setting as
|
||
the background image of the locked screen a corrupted screenshot of the screen
|
||
before it was locked.
|
||
#+BEGIN_SRC sh
|
||
TMPBG="/tmp/screen.png"
|
||
if [ "$XDG_SESSION_TYPE" = "wayland" ]
|
||
then
|
||
SCREENER=grim
|
||
LOCKER="swaylock -feF"
|
||
else
|
||
SCREENER=scrot
|
||
LOCKER="i3lock -ef"
|
||
fi
|
||
|
||
$SCREENER "$TMPBG"
|
||
corrupter -add 0 "$TMPBG" "$TMPBG"
|
||
$LOCKER -ti "$TMPBG"
|
||
rm $TMPBG
|
||
#+END_SRC
|
||
|
||
** Polybar-launch (Deprecated) :noexport:
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env bash" :mkdirp yes :tangle ~/.local/bin/polybar-launch
|
||
:END:
|
||
This scripts allows the user to kill polybar and relaunch it, or to simply
|
||
launch it if polybar isn’t launched yet. First thing to do is kill all polybar
|
||
processes.
|
||
#+BEGIN_SRC bash
|
||
killall -q polybar
|
||
#+END_SRC
|
||
|
||
Now we have to wait untill all polybar processes have been shut down.
|
||
#+BEGIN_SRC bash
|
||
while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
|
||
#+END_SRC
|
||
|
||
Now that our system isn’t running polybar anymore, we’ll launch it again on all
|
||
of our screens. By the way, I have two bars, so I’ll have to lauch them both.
|
||
#+BEGIN_SRC bash
|
||
if type "xrandr"; then
|
||
for m in $(xrandr --query | grep " connected" | cut -d" " -f1); do
|
||
MONITOR=$m polybar --reload top &
|
||
MONITOR=$m polybar --reload bottom &
|
||
done
|
||
else
|
||
polybar --reload top &
|
||
polybar --reload bottom &
|
||
fi
|
||
#+END_SRC
|
||
|
||
And we’re done! Let’s just launch a notification polybar has been relaunched.
|
||
#+BEGIN_SRC bash
|
||
notify-send "Polybar restarted!" -a "polybar-launch"
|
||
#+END_SRC
|
||
|
||
** Rofi utilities
|
||
*** askpass
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/askpass
|
||
:END:
|
||
Askpass is a simple script that invokes ~rofi~ as a way to get from a GUI the
|
||
user’s sudo password. It is inspired by [[https://github.com/ODEX-TOS/tools/blob/master/rofi/askpass][this original tool]], rewritten in bash
|
||
and with [[https://wiki.archlinux.org/index.php/Rofi][rofi]] support instead of [[https://wiki.archlinux.org/index.php/Dmenu][dmenu]]. As you can see, this is a oneliner if we
|
||
ignore the initial shebang. This executable is pointed at by the
|
||
#+BEGIN_SRC sh
|
||
rofi -dmenu -password -no-fixed-num-lines -p $(printf "$*" | sed 's/://')
|
||
#+END_SRC
|
||
|
||
*** awiki
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/awiki
|
||
:END:
|
||
~awiki~ is a simple script used with ~rofi~ that relies on the ~arch-wiki-docs~
|
||
package in order to provide the user a way to quickly find and display any
|
||
English page from the Arch Wiki in a browser. The advantage of using this over
|
||
the ~wiki-search~ utility from the ~arch-wiki-lite~ package is you get instant
|
||
suggestion in rofi using fuzzy-search. The downside is rofi will only help you
|
||
find pages by their title, and it will not help you find keywords in the content
|
||
of said pages.
|
||
|
||
The first step is to create the list of all the pages that are currently stored
|
||
on disk. ~arch-wiki-docs~ stores them in ~/usr/share/doc/arch-wiki/html/en~. A
|
||
simple ~ls~ piped in three ~sed~ will give us a list of page titles. We then
|
||
pipe that into rofi in dmenu mode in order to choose the page we want to
|
||
display. By the way, setting the location of the HTML files will come in handy
|
||
later.
|
||
#+BEGIN_SRC sh
|
||
WLOCATION=/usr/share/doc/arch-wiki/html/en/
|
||
WPAGE=$(/bin/ls "$WLOCATION" | \
|
||
sed -e 's/_/ /g' -e 's/\.html$//' -e 's|.*/\(.*\)|\1|' | \
|
||
rofi -dmenu -p "Arch Wiki" -i)
|
||
WPAGE=$(echo $WPAGE | sed -r 's/\s+/_/g')
|
||
#+END_SRC
|
||
|
||
Now, all I need to do is to send this list into rofi and tell it to open the
|
||
result with our favorite browser with ~xdg-open~.
|
||
#+BEGIN_SRC sh
|
||
xdg-open "$WLOCATION$WPAGE.html"
|
||
#+END_SRC
|
||
|
||
*** dmenu
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/dmenu
|
||
:END:
|
||
I wrote this very simple script in order to replace =dmenu= with rofi’s
|
||
emulation of dmenu, since I prefer rofi’s appearance. It basically calls rofi’s
|
||
dmenu emulation with the arguments initially passed to dmenu.
|
||
#+BEGIN_SRC sh
|
||
rofi -dmenu "$*"
|
||
#+END_SRC
|
||
|
||
*** Emoji picker
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env bash" :mkdirp yes :tangle ~/.local/bin/rofi-emoji
|
||
:END:
|
||
The emoji picker is a simple bash script that uses rofi and
|
||
[[file:~/.config/emoji.txt][~/.config/emoji.txt]] to provide a small, local search for emojis. It is
|
||
relatively easy to build this file from the Unicode’s [[https://unicode.org/Public/emoji/15.0/emoji-test.txt][test file]]. Once
|
||
the emoji is selected, it is copied to the clipboard using =xclipboard=
|
||
when in a Xorg session or =wl-copy= from =wl-clipboard= when in a Wayland
|
||
session.
|
||
#+BEGIN_SRC bash
|
||
SELECTED_EMOJI=$(grep -v "#" ~/.config/emoji.txt | rofi -dmenu -p "Select emoji" -i | awk '{print $1}' | tr -d '\n')
|
||
if [ "$XDG_SESSION_TYPE" = "wayland" ]
|
||
then printf "%s" "$SELECTED_EMOJI" | wl-copy
|
||
else printf "%s" "$SELECTED_EMOJI" | xclip -sel clip
|
||
fi
|
||
#+END_SRC
|
||
|
||
Also, let’s send a notification telling the user the emoji has been copied!
|
||
#+BEGIN_SRC bash
|
||
if [ "$XDG_SESSION_TYPE" = "wayland" ]
|
||
then EMOJI=$(wl-paste)
|
||
else EMOJI=$(xclip -o)
|
||
fi
|
||
|
||
test -z "$EMOJI" && notify-send "No emoji copied" -u low && exit
|
||
EMOJI="$EMOJI copied to clipboard"
|
||
notify-send -u low "$EMOJI"
|
||
#+END_SRC
|
||
|
||
It is inspired from [[https://www.youtube.com/watch?v=UCEXY46t3OA][this video]] from [[https://lukesmith.xyz/][Luke Smith]].
|
||
|
||
*** rofi-ytdl
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env bash" :mkdirp yes :tangle ~/.local/bin/rofi-ytdl
|
||
:END:
|
||
This is just a simple wrapper around [[file:./scripts.md#ytdl-a-youtube-dl-wrapper][ytdl]] so I can easily download a
|
||
video from rofi, which we’ll use first to retrieve the URL of the
|
||
video we want to download, be it from YouTube or other website
|
||
supported by ~youtube-dl~.
|
||
#+BEGIN_SRC bash
|
||
URL=$(echo "Video to download:" | rofi -dmenu -i -p "Video to download:")
|
||
#+END_SRC
|
||
|
||
Now, if the variable ~URL~ is not empty (i.e. the user specified a link and did
|
||
not abort the operation), we’ll proceed to the download. Before it begins, we’ll
|
||
send a notification saying the download is about to begin. When the ~ytdl~
|
||
process ends, we’ll also send a notification notifying the user on the success
|
||
or failure of the download.
|
||
#+BEGIN_SRC bash
|
||
if [ -n "$URL" ]; then
|
||
notify-send -u normal "YTDL" "Starting downloading\n$URL"
|
||
if [[ $(ytdl "$URL") ]]
|
||
then
|
||
notify-send -u normal "YTDL" "Finished downloading!"
|
||
else
|
||
notify-send -u critical "YTDL" "Failed downloading\n$URL"
|
||
fi
|
||
fi
|
||
#+END_SRC
|
||
|
||
** Wallpaper utilities
|
||
*** pape-update
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/pape-update
|
||
:END:
|
||
This little tool sets a random wallpaper using xwallpaper.
|
||
#+BEGIN_SRC sh
|
||
PAPESDIR=$HOME/Pictures/Wallpapers
|
||
PAPE=$(find "$PAPESDIR" -type f | sort -R | tail -1)
|
||
set-pape "$PAPE"
|
||
#+END_SRC
|
||
|
||
*** Select wallpaper
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/select-pape
|
||
:END:
|
||
This script is based on what ~nsxiv~ can do as an image viewer as well as
|
||
xwallpaper.
|
||
#+BEGIN_SRC sh
|
||
PAPE=$(nsxiv -orbft ~/Pictures/Wallpapers/*)
|
||
set-pape "$PAPE"
|
||
#+END_SRC
|
||
|
||
*** Set a wallpaper
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env bash" :mkdirp yes :tangle ~/.local/bin/set-pape
|
||
:END:
|
||
This utility is not meant to be called by the user directly, but rather by
|
||
scripts that may be written by the user. Its role is simple: check if the
|
||
provided wallpaper exists and if it is an image. If both requirements are met,
|
||
the path to this image is then stored in ~$XDG_CACHE_HOME/wallpaper~, or if this
|
||
variable is empty in ~$HOME/.cache/wallpaper~.
|
||
#+BEGIN_SRC sh
|
||
CACHEFILE=$([ -n "$XDG_CACHE_HOME" ] && echo "$XDG_CACHE_HOME/wallpaper" || echo "$HOME/.cache/wallpaper")
|
||
[[ -f $1 ]] && \
|
||
grep image <(file -b --mime-type "$1") && \
|
||
echo "$1" > "$CACHEFILE" \
|
||
&& xwallpaper --zoom "$1"
|
||
#+END_SRC
|
||
|
||
** Wayland
|
||
*** Wayland Environment Variables Setup
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/way-env-setup
|
||
:END:
|
||
#+begin_src sh
|
||
#export GDK_BACKEND=wayland # May cause problems with some xorg applications
|
||
export TDESKTOP_DISABLE_GTK_INTEGRATION=1
|
||
export CLUTTER_BACKEND=wayland
|
||
export BEMENU_BACKEND=wayland
|
||
|
||
# Firefox
|
||
export MOZ_ENABLE_WAYLAND=1
|
||
|
||
#
|
||
# Qt environment
|
||
#
|
||
export QT_QPA_PLATFORM=wayland-egl #error with apps xcb
|
||
export QT_WAYLAND_FORCE_DPI=physical
|
||
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
|
||
|
||
#
|
||
# Elementary environment
|
||
#
|
||
export ELM_DISPLAY=wl
|
||
export ECORE_EVAS_ENGINE=wayland_egl
|
||
export ELM_ENGINE=wayland_egl
|
||
export ELM_ACCEL=opengl
|
||
# export ELM_SCALE=1
|
||
|
||
#
|
||
# SDL environment
|
||
#
|
||
export SDL_VIDEODRIVER=wayland
|
||
|
||
#
|
||
# Java environment
|
||
#
|
||
export _JAVA_AWT_WM_NONREPARENTING=1
|
||
|
||
export NO_AT_BRIDGE=1
|
||
export WINIT_UNIX_BACKEND=wayland
|
||
export DBUS_SESSION_BUS_ADDRESS
|
||
export DBUS_SESSION_BUS_PID
|
||
#+end_src
|
||
|
||
*** Qtile
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/launch-qtile
|
||
:END:
|
||
#+begin_src sh
|
||
export SDL_VIDEODRIVER=wayland
|
||
export XDG_SESSION_TYPE=wayland
|
||
export XDG_SESSION_DESKTOP=wlroots
|
||
export XDG_CURRENT_TYPE=wlroots
|
||
export XDG_CURRENT_DESKTOP=wlroots
|
||
. /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
|
||
. way-env-setup
|
||
systemctl --user import-environment DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
|
||
exec qtile start -b wayland
|
||
#+end_src
|
||
|
||
*** Newm
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/launch-newm
|
||
:END:
|
||
#+begin_src sh
|
||
export SDL_VIDEODRIVER=wayland
|
||
export XDG_SESSION_TYPE=wayland
|
||
export XDG_SESSION_DESKTOP=wlroots
|
||
export XDG_CURRENT_TYPE=wlroots
|
||
export XDG_CURRENT_DESKTOP=wlroots
|
||
. /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
|
||
. way-env-setup
|
||
systemctl --user import-environment DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
|
||
exec start-newm
|
||
#+end_src
|
||
|
||
*** Sway
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/swaybar-cmd
|
||
:END:
|
||
#+begin_src sh :tangle ~/.local/bin/launch-sway
|
||
export SDL_VIDEODRIVER=wayland
|
||
# export XDG_SESSION_TYPE=wayland
|
||
# export XDG_SESSION_DESKTOP=wlroots
|
||
# export XDG_CURRENT_TYPE=wlroots
|
||
export XDG_CURRENT_DESKTOP=sway
|
||
. /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
|
||
. way-env-setup
|
||
systemctl --user import-environment DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
|
||
exec sway --unsupported-gpu
|
||
#+end_src
|
||
|
||
Below is the script I use to display information in sway’s bar. It is
|
||
divided by functions that are then called all together. First, getting
|
||
the date is quite straightforward.
|
||
#+begin_src sh
|
||
sb_date() {
|
||
echo "$(date +'%Y-%m-%d %H:%M:%S') | "
|
||
}
|
||
#+end_src
|
||
|
||
Then we can get what piece of audio is playing. Note however that
|
||
something will be displayed only if something is playing.
|
||
#+begin_src sh
|
||
sb_playerctl() {
|
||
PLAYING=""
|
||
if [ "$(playerctl status)" = "Playing" ]; then
|
||
PLAYING_ARTIST="$(playerctl metadata xesam:artist)"
|
||
PLAYING_TITLE="$(playerctl metadata xesam:title)"
|
||
PLAYING=" $PLAYING_ARTIST - $PLAYING_TITLE | "
|
||
fi
|
||
echo "$PLAYING"
|
||
}
|
||
#+end_src
|
||
|
||
The battery is relatively straightforward too. I should however find
|
||
how to get estimates of battery time. I’m sure I can come up with
|
||
something, but for now I’m just too lazy.
|
||
#+begin_src sh
|
||
sb_battery() {
|
||
CAPACITY="$(cat /sys/class/power_supply/BAT0/capacity)%"
|
||
STATE="$(cat /sys/class/power_supply/BAT0/status)"
|
||
echo "$CAPACITY ($STATE)"
|
||
}
|
||
#+end_src
|
||
|
||
Now comes an indicator for Docker containers which will be displayed
|
||
only if at least one is running.
|
||
#+begin_src sh
|
||
sb_docker() {
|
||
DOCKER_RUNNING="$(docker ps -q | wc -l)"
|
||
# echo "Docker: $DOCKER_RUNNING"
|
||
if [ "$DOCKER_RUNNING" = "0" ]
|
||
then echo ""
|
||
else echo "Docker: $DOCKER_RUNNING | "
|
||
fi
|
||
}
|
||
#+end_src
|
||
|
||
Finally, let’s display everything.
|
||
#+begin_src sh
|
||
echo "$(sb_docker)$(sb_playerctl)$(sb_date)$(sb_battery) "
|
||
#+end_src
|
||
|
||
** Weather
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes :tangle ~/.local/bin/we
|
||
:END:
|
||
A quick and useful script I often use is a ~curl~ request to [[http://v2.wttr.in/][v2.wttr.in]] to get a
|
||
weather forecast in the terminal. By default, I want the request to be about the
|
||
city I live in, but it is also possible for the script to accept as its
|
||
arguments a search inquiry.
|
||
#+BEGIN_SRC sh
|
||
if [ $# -gt 0 ]; then
|
||
SEARCH=$(printf "%s+" "$@")
|
||
SEARCH=${SEARCH%+}
|
||
curl "http://v2.wttr.in/~$SEARCH"
|
||
else
|
||
curl "http://v2.wttr.in/Aubervilliers"
|
||
fi
|
||
#+END_SRC
|
||
|
||
** Wrappers
|
||
:PROPERTIES:
|
||
:HEADER-ARGS: :shebang "#!/usr/bin/env sh" :mkdirp yes
|
||
:END:
|
||
In order to avoid clutter in my =$HOME= directory, I have some wrappers
|
||
around some commands that simply add some options by default.
|
||
|
||
#+begin_src sh :tangle ~/.local/bin/adb
|
||
HOME="$XDG_DATA_HOME"/android /usr/bin/adb "$@"
|
||
#+end_src
|
||
|
||
#+begin_src sh :tangle ~/.local/bin/mbsync
|
||
/usr/bin/mbsync -c "$XDG_CONFIG_HOME"/isync/mbsyncrc "$@"
|
||
#+end_src
|
||
|
||
#+begin_src sh :tangle ~/.local/bin/wget
|
||
/usr/bin/wget --hsts-file="$XDG_DATA_HOME"/wget-hsts "$@"
|
||
#+end_src
|
||
|
||
#+begin_src sh :tangle ~/.local/bin/yarn
|
||
/usr/bin/yarn --use-yarnrc "$XDG_CONFIG_HOME"/yarn/config "$@"
|
||
#+end_src
|