-
Notifications
You must be signed in to change notification settings - Fork 3
/
aliases.sh
387 lines (344 loc) · 12.6 KB
/
aliases.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
#!/bin/bash
# WARNING: Shared aliases between bash/zsh, so needs to be compatible.
# Throws every tunable at the job to beg it to compete for no resources.
#
# systemd-run is used to put it in a scope (and thus cgroup) with the cpu/io weight set to minimum. The cgroup settings
# only have an effect if you have cgroup control delegated to your user slice in systemd and are using cgroups v2,
# however.
#
# nice is an older/simpler way to set CPU weight, which I believe is just factored in to the cgroup's weight in the
# CFS/cgroups world. Including it is a nice fallback if cgroups aren't setup per above. It also causes some system
# monitors to highlight the task as low priority, like htop, that don't currently know about cgroups.
#
# Finally, we set the scheduling priority of the task to 'idle'. This kind of makes its weight a moot point.
#
# If kernel compiles still caused dropped frames running under this, I'm starting a crusade.
lowprio() {
cmd systemd-run --user --scope \
--property=CPUWeight=1 \
--property=IOWeight=1 \
nice -n20 chrt -i 0 "$@"
}
# Run a command detached from the shell, with no connection to the tty or return code, etc..
# Can return failure if the given arguments don't map to a runnable command, and will still print the relevant error.
#
# Commands that parse to a valid file/function/etc, but cannot be launched -- e.g. due to permissions errors -- will
# still silently succeed. This is a limitation of bash/zsh as far as I can tell: that class of failure is simply the
# same as the application failing early.
#
# Ex: A `chmod ugo=x` shell script will be parsed as valid by `command -v`, but hit a permissions error prior to bash
# creating a child process to run it. From the shell's perspective, that command simply failed quickly, and any
# complaining the shell itself writes to stderr is part of the command's output.
#
# Update: The s() alias below is a better way to do this in a systemd system.
x() {
# Warn if you're accidentally launching something in a cgroup (since that is not detached) using the neph cgroup
# functions.
[[ -z $NEPH_CGROUP ]] || ewarn "WARNING: In cgroup"
# If `command -v` doesn't think this parses as something runnable, just run it bare so the shell-level
# error/error-code occurs. This means that `x some_typo --args` doesn't silently succeed, but errors exactly as
# `some_typo --args` would.
if command -v "${1-}" &>/dev/null; then
( "$@" &>/dev/null & )
else
"$@"
fi
}
# spawns a command with systemd-run, like x() but good for spawning something in the desktop session with proper
# cgrouping and such like top-level apps enjoy.
s()
{
# --user - as this user, not system-level command
# --same-dir - keep this working directory
# --collect - don't leave failed units around for inspection
cmd systemd-run --user --same-dir --collect -- "$@"
}
# spawns a detached command with systemd-run, but *without* preserving working directory.
# This is just s() without `--same-dir`
#
# This is useful for spawning long-running things that don't care about working directory, without accidentally keeping
# a reference to random temp directories or external mounts etc related to that process.
S() {
cmd systemd-run --user --collect -- "$@"
}
# Set window title and tmux tab name
# Note that PS1/PROMPT_COMMANDs often reset window titles
t() {
# https://tldp.org/HOWTO/Xterm-Title-3.html
# ESC]0;stringBEL -- Set icon name and window title to string
# ESC]1;stringBEL -- Set icon name to string
# ESC]2;stringBEL -- Set window title to string
#
# where ESC is the escape character (\033), and BEL is the bell character (\007).
[[ -t 1 ]] && printf "\033]0;%s\007" "$*"
# Opportunistically set tmux window name too.
tmux renamew "$*" &>/dev/null || true
}
brs() { s dolphin -- "$@"; }
# enhanced reset
# - rmcup exits alternate screen mode that utilities leave on. In theory typing this in some nested bash-in-ncurses app
# might break it, but things like tmux emulate the nested terminal, so you're not breaking the outer tmux session.
# Fixes panes in tmux randomly not scrolling correctly anymore (since all shell interaction is on the alternate
# screen and not contributing to scrollback)
ereset() {
cmd reset
cmd tput rmcup
}
# zdir <archive> [dirname]
#
# Unarchive something into a directory named after the zip file (without extention, using `autounzip` utility from
# nephscripts) in the current directory and then cd into it.
#
# Optionally specify the output dir name.
zdir() {
[[ -n ${1-} && $# -le 2 && ( -n ${2-} || $# -lt 2 ) ]] || { eerr 'Usage: zdir <archive> [dirname]'; return 1; }
local archive=$1
local outdir=${2-}
archive=$(readlink -f "$archive")
if [[ -z $outdir ]]; then
outdir=$(basename -- "$archive")
outdir=${outdir%.*}
fi
[[ -n $outdir ]] || { eerr "Couldn't determine output name for archive \"$archive\""; return 1; }
einfo "Output dir $outdir"
cmd autounzip -- "$archive" "$outdir"
cmd cd -- "$outdir"
}
# marchive <archive> [<archive> ...]
#
# Moves the archive to $PWD and then runs autounzip on it.
#
# Very specific, for pulling things out of ~/Downloads and archiving them elsewhere mostly.
marchive() {
local usage="Usage: marchive <archive> [<archive> ...]"
[[ $# -ge 1 ]] || { eerr "$usage"; return 1; }
local archive
for archive in "$@"; do
[[ -n $archive && -f $archive ]] || { eerr "$usage"; return 1; }
local base
base=$(basename -- "$archive")
[[ -n $base && ! -e $base ]] || { eerr "Usage: Bad target to move archive to: \"$base\""; return 1; }
cmd mv -v -- "$archive" "$base"
cmd autounzip "$base"
done
}
# Try to setup a fully clean environment, looking at user's session and etc. Preserves $TERM if set, but that's it.
#
# Looks at systemd session variables, but isn't going to restore things like SSH specific or DE specific things that've
# been inherited.
#
# Arguments are a list of variables to preserve
ncleanenv() {
# Roughly init_environ does in /bin/login. Closest to being a standard for what fresh environments should look like.
# Doesn't query PAM though. I wish /bin/login had a no-auth mode that just re-evaluated the environment.
local user && user=$(/bin/id -un)
local uid && uid=$(/bin/id -u)
local ent && ent=$(/bin/getent passwd "$user")
local home && home=$(cut -d ':' -f 6 <<< "$ent")
local shell && shell=$(cut -d ':' -f 7 <<< "$ent")
local vars=()
vars+=(USER="$user")
vars+=(HOME="$home")
vars+=(LOGNAME="$user")
vars+=(SHELL="$shell")
# Check what we have exported against the preserve list (and $TERM)
local envvar var preserve
while IFS= read -r -d $'\0' envvar; do
var=${envvar%%=*}
for preserve in TERM "$@"; do
if [[ $var = "$preserve" ]]; then
vars+=("$envvar")
fi
done
done < <(/bin/env -0)
# Okay now systemd
# If we can talk to it. Since this is supposed to be a clean environment, don't re-use existing bus address.
local bus=/run/user/$uid/bus
if [[ -n $uid && -e $bus ]]; then
local senv
if senv=$(DBUS_SESSION_BUS_ADDRESS=unix:path=$bus systemctl --user show-environment 2>/dev/null); then
local senvvar
while IFS= read -r -d $'\n' senvvar; do
local var=${senvvar%%=*}
local val=${senvvar#*=}
eval "val=$val" # val quoted by systemd, so we want to expand and eval it
vars+=("$var=$val")
done <<< "$senv"
fi
fi
for var in "${vars[@]}"; do
estat "$var"
done
local execshell && execshell=$(/bin/readlink -f /proc/$$/exe)
cmd exec env -i "${vars[@]}" "$execshell"
}
nenv() {
local env
# If we don't even have a session bus try to find the default one for our user
if [[ -z $(sh -c 'printf %s "${DBUS_SESSION_BUS_ADDRESS-}"') ]]; then
local uid && uid=$(id -u)
local bus=/run/user/$uid/bus
[[ -n $uid && -e $bus ]] && export DBUS_SESSION_BUS_ADDRESS=unix:path=$bus
fi
if env=$(systemctl --user show-environment 2>/dev/null); then
# systemctl outputs this in bash/zsh-compatible escaped format with one variable per line. Prepend 'export' to each
# line. Careful of bash/zsh differences here
env=${env//$'\n'/$'\n'export }
env=${env:+export $env}
eval "$env"
einfo "New env: DISPLAY=${DISPLAY:-<empty/unset>} WAYLAND_DISPLAY=${WAYLAND_DISPLAY:-<empty/unset>}"
# Now reload zsh since we just stomped PATH etc
reload
fi
}
uricopy() {
local file=$(realpath -e -- "$1")
local uri
uri="file://$file"
einfo "copying $uri"
printf %s "$uri" | wl-copy -t text/uri-list
}
# Re-execute or switch shell (to load new configs or whatever clearly)
reload() {
# $SHELL is the user's login shell, not what is currently running interactively.
local shell && shell=$(readlink -f /proc/$$/exe);
local args
# If we're a "login" shell use -l to re-exec too
[[ $- = *l* ]] && args="-l"
cmd exec -- "$shell" $args
}
rezsh() { cmd exec zsh; }
rebash() { cmd exec bash; }
pic() { s qimgv "$@"; }
rand32() { shuf -i 0-$(( 2**32 - 1 )) -n 1; }
gdiff() { cmd git diff --no-index "$@"; }
pd() { git diff --no-index --color=always "$@" | diff-so-fancy | less --tabs=4 -RFX; }
rv() { cmd rsync -avy --progress "$@"; }
rvp() { cmd rsync -avy --partial --inplace --progress "$@"; }
# Shorthand rdp
rdp()
{
cmd xfreerdp /dynamic-resolution /scale-desktop:140 /scale:140 /scale-device:140 /clipboard /w:1920 /h:1200 /v:"$1" "${@:2}"
}
winepids()
{
local pids=($(egrep -lzEi '^WINELOADERNOEXEC=' /proc/*/environ 2>/dev/null \
| sed -r 's/^\/proc\/([0-9]+)\/environ$/\1/'))
echo "${pids[@]}"
}
iswine()
{
local winepids=($(winepids))
if [[ ${#winepids[@]} -gt 0 ]]; then
cmd ps -fp "${winepids[@]}"
else
ewarn No wine processes found
fi
}
killwine()
{
local winepids=($(winepids))
if [[ ${#winepids[@]} -gt 0 ]]; then
cmd kill "${1--9}" "${winepids[@]}"
else
ewarn No wine processes found
fi
}
ct()
{
dir=$(mktemp -d -t nephtmp.XXXXXXX)
export NEPH_TEMP_DIR="$dir"
cd "$dir"
}
clt()
{
# (This matches how mktemp picks)
local tmpdir=${TMPDIR:-/tmp}
for x in "$tmpdir"/nephtmp.*; do
if [[ ! -d $x || -L $x ]]; then
ewarn "$x: Not a simple directory, ignoring"
continue
fi
if findmnt -m "$x" &>/dev/null; then
ewarn "$x: Appears to be a mount point, ignoring"
continue
fi
local pids
# +D Scan directory hierarchy for open files
# -x f Also cross into mountpoints within
# -Fp Output pid
#
# TODO If there's any mounts in here we should probably not clean it up. --one-file-system will avoid accidentally
# nuking them, but we'll fail to finish cleaning the directory anyway.
#
# FIXME If something is mounted directly on the nephtmp.xxx folder, we're going to nuke it inappropriately I think.
# findmnt -T "$x" should be null, don't touch mountpoints
# findmnt -T "$x" -R Should find everything mounted under the same mount (probably /tmp) -- grep for our prefix?
# Make sure we're not a symlink?
pids=($(lsof -x f -Fp +D "$x" | tr -d p))
if [[ -z $pids ]]; then
estat "Removing $x"
cmd rm -rf --one-file-system -- "$x"
# If this is our cached directory nuke it
[[ $x != ${NEPH_TEMP_DIR-} ]] || unset NEPH_TEMP_DIR
else
estat "Skipping $x, in use:"
ps -p "${pids[@]}" | einfo_pipe
fi
done
}
rt()
{
if [[ -n $NEPH_TEMP_DIR && -d $NEPH_TEMP_DIR ]]; then
cd -- "$NEPH_TEMP_DIR"
else
unset NEPH_TEMP_DIR
estat "No temp dir in context"
fi
}
service() {
if which systemctl &>/dev/null; then
cmd sudo systemctl -- "$2" "$1"
elif [[ -d /etc/rc.d ]]; then
cmd sudo /etc/rc.d/"$1" "$2";
else
eerr "Don't know how to modify services on this system"
return 1
fi
}
lx() { ls++ --potsf "$@"; }
lxx() { ls++ --potsf -tr "$@"; }
v() {
local json
if ! json=$(cmd yt-dlp --no-simulate -J "$@"); then
eerr "yt-dlp failed, see above"
return 1
fi
local filename
filename=$(jq -r '.requested_downloads[0]._filename | select(type == "string")' <<< "$json")
if [[ -z $filename ]]; then
jq <<< "$json"
eerr "yt-dlp didn't return a URL, see JSON dump above"
return 1
fi
filename="file://$PWD/$filename"
cmd systemd-run --user --collect -- bash -c "exec wl-copy --foreground -t 'text/uri-list' <<< $(sh_quote $filename)"
}
# Print a timestamp or timestamp for a date
tt() {
local date
if [[ $# -eq 0 ]]; then
date="now"
elif [[ $# -eq 1 && $1 =~ ^[0-9]+$ ]]; then
date="@$1"
else
# Treat as date
date="$*"
fi
einfo "Parsed"
date --date="$date" || return
einfo "Timestamp"
date --date="$date" +%s
}
# Include local aliases
[[ ! -f $HOME/.aliases.local.sh ]] || source "$HOME"/.aliases.local.sh