From eb494c9f7f979067d79bb74a792bf790d2692599 Mon Sep 17 00:00:00 2001 From: TrudeEH Date: Wed, 26 Jun 2024 22:28:27 +0100 Subject: [PATCH] Bookmarks script rewrite; Web shortcut now launches the script instead, and +SHIFT, the browser --- TODO.md | 9 - dotfiles/.local/bin/dm-bm | 14 - dotfiles/.local/bin/dm-fm | 324 -------------------- dotfiles/.local/bin/dm-web | 81 ++--- dotfiles/.local/bin/dmenu-bookmark-sources | 7 - dotfiles/.local/bin/dmenu-websearch-sources | 8 - programs/dwm/config.h | 3 +- programs/dwm/dwm | Bin 82720 -> 82800 bytes 8 files changed, 23 insertions(+), 423 deletions(-) delete mode 100755 dotfiles/.local/bin/dm-bm delete mode 100755 dotfiles/.local/bin/dm-fm delete mode 100644 dotfiles/.local/bin/dmenu-bookmark-sources delete mode 100644 dotfiles/.local/bin/dmenu-websearch-sources diff --git a/TODO.md b/TODO.md index 087db762..b6dbda7f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,11 +1,2 @@ # TODO -## SCRIPT -- Dmenu bookmarks + search - - Add bookmarks/Remove - - Detect follow up input for engines - - Launch default browser with search/bookmark - -## DWM -- Web Browser shortcut -> META+SHIFT+W -- Bookmarks + Search dmenu script -> META+W diff --git a/dotfiles/.local/bin/dm-bm b/dotfiles/.local/bin/dm-bm deleted file mode 100755 index 15b6fc55..00000000 --- a/dotfiles/.local/bin/dm-bm +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -bookmarks_file="$HOME/.local/bin/dmenu-bookmark-sources" -bookmark_entries=$(awk -F'"' '{print $2 "\t" $4}' "$bookmarks_file") - -choice=$(echo "$bookmark_entries" | cut -f1 | dmenu -i -p "Select bookmark:") - -if [[ -n "$choice" ]]; then - # Find the matching URL - url=$(echo "$bookmark_entries" | awk -v choice="$choice" '$1 == choice {print $2}') - echo $url - xdg-open $url -fi - diff --git a/dotfiles/.local/bin/dm-fm b/dotfiles/.local/bin/dm-fm deleted file mode 100755 index 82d2f229..00000000 --- a/dotfiles/.local/bin/dm-fm +++ /dev/null @@ -1,324 +0,0 @@ -#!/bin/sh - -PROGRAM_NAME=$(basename $0) # This will be used in a few messages - -main() { - parse_opts "$@" - [ -z "$mode" ] && mode=open # The default mode - - if [ -n "$copy" -a "$copy" != false -a "$cat" = true ]; then - prompt_copy_contents "$@" - elif [ "$open" = true ]; then - prompt_open "$@" - elif [ "$cat" = true ]; then - prompt_print_contents "$@" - elif [ "$print" = true ]; then - prompt_print "$@" - elif [ -n "$copy" -a "$copy" != false ]; then - prompt_copy "$@" - else - prompt_$mode "$@" - fi -} - -prompt_base() { - [ -z "$length" ] && length=10 - - if [ "$case_sensitivity" = sensitive ]; then - backtrack() { sed 's|\(.*/'$sel'[^/]*\).*|\1|'; } - s=+i - else - backtrack() { perl -pe 's|(.*/'$sel'[^/]*).*|$1|i'; } - i=-i - fi - - [ -z "$menu" ] && menu="dmenu" - if [ "$menu" = dmenu ]; then menu() { $menu $i -l $length -p "$@"; } - elif [ "$menu" = fzf ]; then menu() { $menu $s $i --header="$@"; } - else menu() { $menu; }; fi - - if [ "$path" = "full" ]; then prompt() { p="$target"; } - else prompt() { p="$(printf '%s' "$target" | sed 's|^'"$HOME"'|~|')"; }; fi - - # Only GNU `ls` supports `--group-directories-first` - if [ "$(ls --version | head -1 | cut -d " " -f 2-3)" = "(GNU coreutils)" ] - then - list() { ls --group-directories-first "$@"; } - else - list() { - (ls -l "$@" | grep "^d" - ls -l "$@" | grep -vE "^d|^total") | tr -s " " | cut -d " " -f 9- - } - fi - - # Commonly used functions in DFM - truepath() { sh -c "realpath -s "$sel""; } - slash() { printf '%s' "$target/$sel" | rev | cut -b 1-2; } - check() { file -E "$@" | grep "(No such file or directory)$"; } - fullcmd() { - printf '%s\n' "$PWD" > "$cache_file" - printf '%s' "$target" | sed -e "s/'/'\\\\''/g;s/\(.*\)/'\1'/" | cmd - } - - while true; do - p="$prompt" # Reset the prompt to have it update - [ -z "$p" ] && prompt # Make the prompt if it does not exist - - # This is where the file manager actually first opens. - sel="$(printf '%s' "$(list "$target"; list -A "$target" | grep '^\.')" | - menu "$p")" - - # Exit if the user presses Escape, Control-C, etc. - exit_code=$? - if [ "$exit_code" -ne 0 ]; then - printf '%s\n' "$target" > "$cache_file" - exit $exit_code - fi - - if [ $(printf '%s' "$sel" | wc -l) -eq 0 ]; then - # If the input box is empty, go to the parent directory - if [ "$sel" = "" ]; then - newt="$(realpath -s "$target/..")" - # Relative directories - elif [ -e "$target/$sel" -a "$(slash)" != // ]; then - newt="$(realpath -s "$target/$sel")" - elif [ ! -e "$target/$sel" -a $(printf '%s' "$target" | - grep $i "$(sh -c "printf '%s' "$sel"")" | wc -l) -eq 1 ] - then - # Go to a lower directory using the input box - if [ ! -e "$(truepath)" ]; then - newt="$(printf '%s' "$target" | backtrack)" - # Go to certain directories like `~` `$HOME`, etc. - else - newt="$(truepath)" - fi - # Go to a directory when the input box begins with `/` - elif [ -e "$(truepath)" ] && - [ ! -e "$target/$sel" -o "$(slash)" = "//" ] - then - newt="$(truepath)" - else - # This applies to wildcards - newt="$(realpath -s "$target/$sel")" - fi - else - newt="$sel" - fi - - # If the current working directory is not empty - if [ $(ls | wc -l) -ge 1 ]; then - target="$newt" - if [ ! -d "$target" ]; then - # Check if the user used a wildcard - if [ $(printf '%s' "$target" | grep "*" | wc -l) -ge 1 -a\ - $(check "$target" | wc -l) -eq 1 ] - then - IFS= # Needed to make wildcards work - ls "$PWD"/$sel 1> /dev/null 2>& 1 - # Target is a file or directory - if [ $? -ne 0 ]; then - target="$PWD" - # Target is a wildcard - else - target=$(ls -d "$PWD"/$sel) fullcmd - exit 0 - fi - # No such file or directory - elif [ $(printf '%s' "$target" | wc -l) -eq 0 -a\ - $(check "$target" | wc -l) -eq 1 ] - then - target="$PWD" - # More than one selection - elif [ $(printf '%s' "$target" | wc -l) -gt 0 ]; then - target=$(printf '%s' "$target" | sed 's|^|'"$PWD"/'|') - fullcmd - exit - # Exactly one selection - else - fullcmd - exit - fi - # Target is a directory - else - PWD="$target" - fi - fi - done -} - -prompt_print() { - cmd () { xargs ls -d; } - prompt_base "$@" -} - -prompt_print_contents() { - cmd() { xargs cat; } - prompt_base "$@" -} - -prompt_open() { - if [ -x "$(command -v sesame)" ]; then cmd() { xargs sesame; } - else cmd() { xargs xdg-open; }; fi - prompt_base "$@" -} - -prompt_copy() { - cmd() { tr '\n' ' ' | xclip -r -i -selection $copy; } - prompt_base "$@" -} - -prompt_copy_contents() { - if [ "$(file -b "$target" | cut -d " " -f2)" = "image" ]; then - cmd() { xargs xclip -i -selection $copy -t image/png; } - else - cmd() { xargs xclip -r -i -selection $copy; } - fi - prompt_base "$@" -} - -help() { - printf "Usage:\t$0 [options] [target] [prompt] - -Options: - -Modes: --p|--print │ Print the output of the selection --o|--open │ Open the appropriate program for the selection (default) - - --cat │ Concatenate the selections before using a mode --c|--copy=[CLIPBOARD] │ Copy the output of the selection - --no-copy │ Do not copy (always overrides \`--copy\`) - │ --r|--restore │ Start from the previous path restored from the last run --s|--sensitive │ Use case-sensitive matching --i|--insensitive │ Use case-insensitive matching (default) --m|--menu=MENU │ Choose which menu program to use (default: dmenu) --l|--length=LENGTH │ Specify the length of dmenu (default: 10) - │ --f|--full │ Use the full path for the prompt --a|--abbreviated │ Use the abbreviated path for the prompt (default) - │ --h|--help │ Print this help message and exit -"; } - -parse_opts() { - : "${config_dir:=${XDG_CONFIG_HOME:-$HOME/.config}/$PROGRAM_NAME}" - : "${config_file:=$config_dir/$PROGRAM_NAME.conf}" - [ -f "$config_file" ] && . "$config_file" - - : "${cache_dir:=${XDG_CACHE_DIR:-$HOME/.cache}/$PROGRAM_NAME}" - : "${cache_file:=$cache_dir/path}" - # Create the cache file if it doesn't exist - if [ ! -f "$cache_file" ]; then - mkdir -p "$(dirname "$cache_file")" && - touch "$cache_file" - fi - - needs_arg() { - if [ -z "$OPTARG" ]; then - printf '%s\n' "No arg for --$OPT option" >&2 - exit 2 - fi - } - - while getopts hpcosim:l:far-: OPT; do - # Support long options: https://stackoverflow.com/a/28466267/519360 - if [ "$OPT" = "-" ]; then - OPT="${OPTARG%%=*}" - OPTARG="${OPTARG#$OPT}" - OPTARG="${OPTARG#=}" - fi - case "$OPT" in - h|help) - help - exit 0 - ;; - p|print) - print=true - ;; - c|copy) - shift - [ $(printf '%s' "$OPT" | wc -c) -eq 1 ] && OPTARG="$1" - case "$OPTARG" in - primary|secondary|clipboard|buffer-cut) - copy="$OPTARG" - ;; - *) - copy=clipboard - ;; - esac - [ -n "$1" -a "$OPTARG" = "$1" -a "$copy" = "$OPTARG" ] && shift - ;; - no-copy) - copy=false - ;; - cat) - cat=true - ;; - o|open) - open=true - ;; - s|sensitive) - case_sensitivity="sensitive" - ;; - i|insensitive) - case_sensitivity="insensitive" - ;; - m|menu) - needs_arg - menu="$OPTARG" - ;; - l|length) - needs_arg - length=$OPTARG - ;; - f|full) - path="full" - ;; - a|abbreviated) - path="abbreviated" - ;; - r|restore) - restore=true - ;; - ??*) - printf '%s\n' "Illegal option --$OPT" >&2 - exit 2 - ;; - ?) # Error reported via `getopts` - exit 2 - ;; - esac - done - shift $((OPTIND-1)) # Remove option arguments from the argument list - - if [ -n "$1" ]; then - target="$1" - elif [ -z "$target" ]; then - if [ "$restore" = true -a -s "$cache_file" ]; then - target="$(cat "$cache_file")" - else - target="$PWD" - fi - fi - - if [ -d "$target" ]; then - target="$(realpath -s "$target")" - PWD="$target" - else - # Zero out cache file. - [ "$restore" = true -a -s "$cache_file" ] && > "$cache_file" - printf '%s\n' "$PROGRAM_NAME: \`$target\` is not a directory." >&2 - exit 2 - fi - - [ -n "$2" ] && prompt="$2" - # If the prompt is the same as the target, uset the prompt so that it can - # update. This is useful if you set a prompt in your configuration file but - # want to use the default prompt - if [ -n "$prompt" ] && [ "$(realpath -s "$prompt")" = "$target" ]; then - unset prompt - fi -} - -main "$@" diff --git a/dotfiles/.local/bin/dm-web b/dotfiles/.local/bin/dm-web index 5b25e916..8971df4a 100755 --- a/dotfiles/.local/bin/dm-web +++ b/dotfiles/.local/bin/dm-web @@ -1,66 +1,27 @@ -#!/usr/bin/env bash +#!/bin/bash -sources_file="$HOME/.local/bin/dmenu-websearch-sources" +engine="https://www.google.com/search?q=" -prompt="-p Search:" +declare -A bookmarks=( + ["YouTube"]="https://www.youtube.com/" + ["GitHub"]="https://github.com/TrudeEH/dotfiles" + ["TrudeWeb"]="https://trudeeh.github.io/web/" + ["Gemini"]="https://gemini.google.com/app" + ["Element"]="https://app.element.io/#/home" + ["Gmail"]="https://mail.google.com/mail/u/0/#inbox" + ["Google Messages"]="https://messages.google.com/web/conversations" + ["WOL"]="https://wol.jw.org/pt-PT/" +) -se_data="$( - awk -F'"' ' - BEGIN { - labels="" - } - { - # Selector line - gsub(/[[:space:]]/,"",$1) - sel=$1 - - # Description line - dsc=$2 - - # URL line - gsub(/[[:space:]]/,"",$3) - url=$3 - - # URL array (selector is the key) - surl[sel]=url - - # Descriptions array (selector is the key) - sdsc[sel]=dsc - - if (labels != "") { - labels=sprintf ("%s\n%s - %s", labels, sel, dsc) - } else { - labels=sprintf ("%s - %s", sel, dsc) - } - } - END { - for(k in surl) { - print "declare -A " k - print k "[url]=\"" surl[k] "\"" - print k "[dsc]=\"" sdsc[k] "\"" - } - print "dmenu_labels=\"" labels "\"" - } - ' "$sources_file" -)"; +choice=$(printf "%s\n" "${!bookmarks[@]}" | dmenu -i -p "Search:") -# Eval awk output as real variables... -eval "$se_data" - -# Output label string to rofi... -search="$(dmenu $prompt <<< $dmenu_labels)" - -if [[ ! -z "$search" ]]; then - - # Retrieve data... - sel="$( awk '{ print tolower($1) }' <<< $search )" - txt="$( cut -d" " -f2- <<< $search )" - - eval "sen_dsc=\"\${$sel[dsc]}\"" - eval "sen_url=\"\${$sel[url]}\"" - - xdg-open "$sen_url$txt" &>/dev/null & +if [[ -n "$choice" ]]; then + # Find the matching URL + url=${bookmarks[$choice]} + if [[ -n "$url" ]]; then + xdg-open $url + else + xdg-open $engine$choice + fi fi - -exit 0 diff --git a/dotfiles/.local/bin/dmenu-bookmark-sources b/dotfiles/.local/bin/dmenu-bookmark-sources deleted file mode 100644 index bbb2d85f..00000000 --- a/dotfiles/.local/bin/dmenu-bookmark-sources +++ /dev/null @@ -1,7 +0,0 @@ -"YouTube" "https://www.youtube.com/" -"GitHub" "https://github.com/TrudeEH/dotfiles" -"TrudeWeb" "https://trudeeh.github.io/web/" -"Gemini" "https://gemini.google.com/app" -"Element" "https://app.element.io/#/home" -"Gmail" "https://mail.google.com/mail/u/0/#inbox" -"Google Messages" "https://messages.google.com/web/conversations" diff --git a/dotfiles/.local/bin/dmenu-websearch-sources b/dotfiles/.local/bin/dmenu-websearch-sources deleted file mode 100644 index e78efe34..00000000 --- a/dotfiles/.local/bin/dmenu-websearch-sources +++ /dev/null @@ -1,8 +0,0 @@ -gg "Google Search" https://www.google.com/search?q= -dd "DuckDuckGo" https://duckduckgo.com/?q= -we "Wikipedia (en)" https://en.wikipedia.org/wiki/ -wp "Wikipedia (pt)" https://pt.wikipedia.org/wiki/ -so "Stack Overflow" https://stackoverflow.com/search?q= -gt "Google Translate" https://translate.google.com.br/?text= -yt "YouTube" https://www.youtube.com/results?search_query= - diff --git a/programs/dwm/config.h b/programs/dwm/config.h index 6bcd6310..6f2ac88a 100644 --- a/programs/dwm/config.h +++ b/programs/dwm/config.h @@ -76,7 +76,8 @@ static const Key keys[] = { { MODKEY, XK_Return, spawn, {.v = termcmd } }, { MODKEY|ShiftMask, XK_l, spawn, {.v = slockcmd } }, { MODKEY|ShiftMask, XK_s, spawn, {.v = screenshotcmd } }, - { MODKEY, XK_w, spawn, {.v = webcmd } }, + { MODKEY, XK_w, spawn, SHCMD("dm-web") }, + { MODKEY|ShiftMask, XK_w, spawn, {.v = webcmd } }, { MODKEY, XK_b, togglebar, {0} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, diff --git a/programs/dwm/dwm b/programs/dwm/dwm index 65466cb0f7f08955029c08071795c3301acdc87a..a8fccaa1b9e2e81993192c8323e4d33fe11927da 100755 GIT binary patch delta 16950 zcmc&+dt8)N{yt{_0Y#nR;xM8PBPMuBz)P6AI$$O4YT>0auVY$LSwd=JQZt&hw3#s; z>Ls%rlJ#DKU|^XIo9kM+g|4+$>@Uo=Ty;0^f|uUkbKY|f!n^C=y`Rs#&wHNdd%ov; zuJ08BFNB?WA*?vw=F1|+<`zKC`1@?i+_zVx6cR!Wg74emmvT<%Ddz;QusBBW9%iGz zx7BYFsTO2g=q%UG@*eFdtdFujmf^AEr~g35L?rB=@$AVLSDbxmon>g&Z&`uGM+4fi zb~LW4Q^?jRM^Sr=$Rqdb!wInx2PtBQI@=w!VQtlyT2yNNZ}l0e*0OY~ofcJ%wK^lc zs$LY{w1rkK>BY-K{O&0w((l%+|y1RgpBB)afe1OKl?@Tq0ZVCcN9k*S{|8J^!0$n|jz< zS|ebx39>^y>|<3VjV9Iel5E4vZ6j1QN;L67mhQaa&0|uPH=l`D-U22*$o#FmHJViA zjWpdPHWMFYXIpvmm{jG>XX0C8Gx0$-A@N2{8%?V6Mw)LDn~4vy%2wVyCRKU!nfR92 zOni{pT&-d=smdFQdp;XR=YNT#<<{kn3&0#K*rW`~;b+r#-XLq{gn5Gw52| z8mab4H1Y6~WS^kg$751e`}jRZ-o(cj z3ckt2uUaj5a=mRG6D4mI{KS@19+6F-XwI-oI7%_`zL|m_YT}DnelNS@piig;CUrY2 z>t*j+`lwJF^|ryeN3z4c26UYxPvb*F#g&&jyFR{&b-iW4*teuS#U#HVd5?)-E%{s% z{~Gh(V)rVwz@#c~zMJqxH{pv-yz*aa;$IU{vE<&iu}yyz?XlTpLpBP&!o-J2K4{{b z*z(?XugX<#QrpX1jV4}|e!|2nKW9w*6zNA@J*n=Ie)^IKIV+W*99d2L7M7W8cU+e4 zQcSAO@{{e}DA{>#lX|P*5(5t5%`;zvt9*Tjz(yqBmYMpb5#%-}O+P?an) z@l&OJv58j~)ukr>9XS>P2H)$(HR%lLXtODUXH(UKDTkwCvqDJ8^<{ONgCVoN62pd& zD)*3`5#BET3|-d}W5|$1Le7wD9sD`*q~tb!OnejT4u|-^`$gA$(PUR6A;skM7@VEl z&4z81-M4qBo)A(`irf3=AW!pg>c6sq z`h6^a7jzCr2CA^F_Ox??HKs<{CCgd$ zlluu8+1SN@3>9!SvYA=Qtx~JAM$_-v;jCoruVf|C@T!E-lPolZEx2=#D+KN0ZXS6J zg|*|Ah}{~F<1@N$NBh;2lF+J;?{rccT6O%c%N82Wz8$-le$3YXwpT=$KZ=r)#E;qj z-+o7fRU3adpVBZEGk&5a#Lni8AA`h>@y@t*{?k`=ttVQrF(hHD3r<}n?bz}03vKQE zYoIiu-Q3sF#Ub{pd3R5>&=c%WIrA)TC+j!i1$u_wr7?niHfarQs+u|Ze#*Vo+}nf0-|w9XsLHtS z8w)p$d0+sC(GR>$o7j&J+|LuErv60RS0zvTo?0@Utiz1^I5}s=Fb?Zy42(vH@wWO8 z+GsyQ*blGAh0*YtJ-N}WnU^@+KWi(85YOElCV5`taLUtz$JSx?k34l=z_$EqqGK4N=TOQfR zxdo3t+6i-D;e$#3rqR^D3)D}KKF!;1&SMW-NH+WIF{45W^B?5q-ubrys%qx%r98Rh ziGdupJu$2kijIwNH)B%m;vt@YVl`KuTTl>MLEueaV8r_SJR|Zi@&?k=%#zQre=UC$ zZD3#J55jT#C;RbS8BgBU4wHf5aN(0rbU!`1nZ%u-;yN7URf5hG0ZgkS6xa zljCT6_Pd3>dCr9kH*!c=w3lvY-z*wrAx_qL@j%OH^!nnF9G+YJ1c&pBpX7$~o*ISB zo1V(RvhdwgS)58*V)Xs2CAab5mSk}5izOrJN!F>r?m8LL96%Kbh61(t4wHuV{*NQY zk`s&wCf@(t6$>6V{fc$tbVy z(u|(SQ-G#zM!qhXRk0WeB*xtw8%cJ}hKBWoJ-77kTX3kqM0P8;p+C2Ed%;MvOG^iF zw@)=4Cp<{o_@Lt)g7?RX#Z);oRJ;;C?iRIL6E1A3;HggIy(2j2u_U?#a1DG$K{aBYzvd;@sdHd;w52N6RpBaVy#%GeS z|J2z3$Jj?dJB=GHcy_BXj=lRri>r}7?j33Lhwmvq3Hcnj=d!N-8LI~`ahuN=df)l( z;zPv;rr&a7&V9Vx=*I9BeR=LdD@OLNkKB#1Qta#>x;uzd()DE@Zo$=FJ^HZzdI<5m z=6Cm#Zc$8IkwiPP4^||5JNf7RTi2YSB)##vKAGD#V&!oab@E>XkNzLR^OAL){I4T@ z8cRcq&EU@d)8HCm6XeS?`i!K#QZu;zY#n3Uu&qIjw6v-AIwHx3Ujjm=tOCcWg&W_z1E8o_oIM z_jZTPe+8DFcS*Acquau3kIJ~F+n5(>tp7h;eb1x@Y;1>-_j|7XXi|Gcv+tlr`@iDq zVUt=B%{mv^9Wnk-x%!PsT^YkhL5=nAQ#n+a0?fdgf?{a1RDmx}w&8lg(4*r@`7>H=%izkIi(#wZ&PP_E-q%N2ZJrgmi zF<&w%*+uubo4Jo!s~_b)K3m;`!>QH7y2wfOk%gQJ{-RGNY3}9{NW)(-*1sjM7$f5^ zucX^+u-G*}7P>`GCCwAhW57~UeF2u8i;XEZytper*W6#cwmr@yxN@0@vkALeY%Iu0 z{!e*%Kl|_FFlLQ05|^#vXAxGl#yA;VU1OO1g&Dv~j5A^Ct8eiDXMc+I4%cKoPM{t4 zyPID{w&SnObms1+kE#Fi_pJ9?JILSHJ-@;1QIgE(c zJ=qmm)H%rfmPLiETk-T(=Fb-*K~b;7o5h{>iUrotSN8k`Uzkf@ER}=XvLHIAaF2n zA21te#g*`MU=Gj+jCxbotAT~U2H?TBbUi+dkZZsZz!B?p-2jC2Vem(uu0eV0FMIefg?8S`UPMqFfkkj0<(eFfYX7wTXa1S z7yzyW9s!mDr)<^r?Z6UXFx-obI5@%$fG2<#fDsXd9N4DoLxFc}N94eDKp*flumTwR zuC5;iZm!hzs7OK*IhG zKo9Upt*#dV`|m-E06jp`fe_z^=mKETUf2PnK0=Lvdw>UllY?jxU=uI}&+kj?UR=wLlNhYsDL)S{(EOuKWuk2Ob5k1X>U1`etCSPjtNzSPqQpM99!j z5eTpXm<>DvoDQ7(8S(+64k9106xaaF`zuXMll!pu*AU%K!6Xkl~>CI3fq00agHWen19bw|`>v#~}TquDgMIfCa#DKVc97 zqfQ`T;3{B5Ebt@(1~vlofH|ko^uW2NQ9qVQ}+a!9GW~s4p>s9zI0yj=jhIIhP+u1wYlIQ_;Xxku~!@{;F(^7Wp_Tjj) zePnwQtz|D`e}q+HpTfS}p4!KUWduXZ*tp*)JhUok#c}_M;PTk5@7#mitY_XyqKT~R zon$(fee%xexCX2OLq&EYhFHENG1t3E)XnaEw;#=8`R^w8Da4x4x~>6Om4cfubMlg_ z!JT1s@5cNl_HEf(V7bx&WiYsvt*p<0D+i}qi`#|rWsKQ&#KfI}f|+h?-LUTuy)uKAvwJI@w4N=lOpY769Ya-=OgNTf$-_&Y%4B*6`?_)x z&1SdmOrlfRgq?%HJioIanzM3e2A$9T1?B|nUX={>&Z0rfWLRDlj%72Wpxtuux2nLSo*Ghw3yAyOQX1*1T&Ft!B5r*AE^az`m3{|K4c2l6`{XPb_bgz@1sB-P~ z4)UtE?P_o zvMRu)NAOWX)LRJk;8W?*CS5&XReFp`SC4Jo(jZTw@Q?FzntbA_3_9w4GJLMb01D*sDb>wG;3$N-dsHU`iWO%5KE4$9fF^G=s~(@Z7nmiU;& zL`E;!BOj3|AIrSpq&_zLf-_USRsQS2aUXKoEp1csG;)Jzw-F7^sIFC35C)hH|g>%RZB#PCS4|5B9c1uUbL}_i&n%`chQMuz;(es zw!bu1@04|HoN`NkfJCLMc2u=h`RiHcCBA6R#=e3r$3Do)E;%#Rn<|y>PU$aQqIzSc zbhqRON~~b?GWX@We8ZPTYRZ?gRlbz2d<|;xwcPMk*2)*o6~?A~DO=@B>27IfocD2z zxSEW(nr_6U&QZ#jvQ@s6u6zxVKG9x=ud-IYj7bh%`BJvZm(rE5+gg0lW+SfV8*wE{ zP5Dx`%9qmJ(k??H;xc@dweqEGlrLqgd?{U_x|%?HT`}Uiaw9Gu5u5U*Y?UviyQSUj z5)qf-tL%!?rN$SL14#K&wjNe?#cq2@=2Y*AiN7qyuvAk{>1r6_dc@e2uBM#g)ex&@ zv#&Zc)mo?4LOy8R_$hDd6|mtFJEbcx7g*g@rzLhRJ4Cx^Ry_H}6r$IR=E8nDj$=A< zf2wp3b6tyJjWlYQdapFR+k zR=OFLuI$x^3i4IEm#FU`RDmV~qP}>zncngxgETPb-?CBV6sSH`&NGP;2wB$}jX`P@8>LtIEK z8LE|q(PQe7WT1We54DgW%KT-Ss$W?~wNLuDdT;Ck2-j)a`mM(tPVJd7oB?c*h>( zeS)o602wCb=`#hHpR;exG9n^*IZGk{dl-n`O4?Qf|;@Lmr#E zNbpCcTqtGtVnN70BSp%q`D&18RB%=?lbDr=J?r^*4z z7iq4}aJO%nuvaa4T*~TGOU0j*{Cqis-Le>d%fMTHySALWE0&iLwNiFTIol@)HPQx3 z{-ET$!9CwHC4WLY#@!8;_EAD5yb`=Lx8zkD&6LsQJueK$$&Q~U?e}PzR`is*@AF7^ zk4ZVG<#SoxeH@hX3sOFrE2JWnN5A4n({!2Xe=8?pkc>day^NEs2!q^^EJYTJ_iiXFc zM^Z$BBpN1!Y=tq;oUNtDqIx+}&Xw{Ktqio57mMoEOAT&~EnYU<5zP-9$5AQAOL>(n z{)|=!xoeY@RW09?GHI`!i>04?qr!L~@hwk36Q!FN$*aezDUx?dUOkSrO1`h;)uRiy zwEj8+Lc zy*{fgJrTb6@@n3d6H94=#{5ujCdTRRz4nCH)a2# zVgKKJh4f#{%d|UEOzpA9$i^>4>mc{3{ht?`H=~nWnbx@ z5QmYWMKB(0aj~!DaUt)(G>PBdlEXN-O}pJeoqhJLZ%d0}Y{a*>Ek8zE4s%D)ME}Mp z#D;r{-42?Z{yQZ38%Fh~naamZ!|beHAwTd}{36ZP6+=?pS1Nk1mf01n-!rT%)J|9P zy%y+7nYaK(VI2%IKtc)}Rt!0Th97f)x4*rv;B_0*2RIZYRkWkC82 zX*}*uVU;7-mpt(N?{(F(BYlu(MedgctP`+RK#c+Ef0ix}-X$`*W!}#vA1~vIl6-^6 z{eysW0z$Pq7lMru(8GZAezpdIs0{FY+*XejF8N}{H@C<=QNUaQO9Z@Vfa7(U zb+a6Ob45fKS}c0vcKj_ez4}c1@*sEzA_cr>#fc_#i(g3Z# zH*Kdq)tg4A&%zsjUgId!SbjqBa($F{MdTUbr&vHhz!m}T8=w^@V=4PqP^Sdw0y>Ko zFG+Ky(1bX?FqmiMFkz7`V3Glj*_~yKa&V}1AWv8=7r+E`5sOKgNbM4ESilbkIDVG? z)amY^Xg6|RShds2`k>*W1@tf=y{}copsvwlHR delta 16676 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