aboutsummaryrefslogtreecommitdiff
path: root/includes
blob: b080e515ca1339cbded8c6785e36ba34af95ff3b (plain)
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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
# vi:syntax=bash

# Heavily inspired from https://github.com/sorin-ionescu/prezto/blob/master/modules/git/alias.zsh
# Git aliases
# Log
zstyle -s ':prezto:module:git:log:medium' format '_git_log_medium_format' \
  || _git_log_medium_format='%C(bold)Commit:%C(reset) %C(green)%H%C(red)%d%n%C(bold)Author:%C(reset) %C(cyan)%an <%ae>%n%C(bold)Date:%C(reset)   %C(blue)%ai (%ar)%C(reset)%n%w(80,1,2)%+B'
zstyle -s ':prezto:module:git:log:oneline' format '_git_log_oneline_format' \
    || _git_log_oneline_format='%C(green)%h%C(reset) %><(55,trunc)%s%C(red)%d%C(reset) %C(blue)[%an]%C(reset) %C(yellow)%ad%C(reset)%n'
zstyle -s ':prezto:module:git:log:brief' format '_git_log_brief_format' \
  || _git_log_brief_format='%C(green)%h%C(reset) %s%n%C(blue)(%ar by %an)%C(red)%d%C(reset)%n'

# Status
zstyle -s ':prezto:module:git:status:ignore' submodules '_git_status_ignore_submodules' \
  || _git_status_ignore_submodules='none'

# Aliases

# Branch (b)
alias gb='git branch'
alias gba='git rev-parse --abbrev-ref HEAD'
alias gbc='git checkout -b'
alias gbx='git branch -d'
alias gbX='git branch -D'
# Show the differences of the current head since it diverged from master
function gbd (){
    git diff $(git merge-base master HEAD)...HEAD
}
function gbds (){
    git diff --stat $(git merge-base master HEAD)...HEAD
}
alias gdiff='git diff --no-index'

# Commit (c)
alias gc='git commit --verbose'
alias gcam='git commit --verbose --amend'
alias ga='git add'
alias gcu='git add -u; git commit --verbose'
alias gca='git add -A; git commit --verbose'
alias gco='git checkout'
gcoo() {
    if [[ "$#" -eq 0 ]]; then
        local FILES=(${(f)"$(git diff --name-only| fzf --multi --reverse)"})
        for FILE in ${FILES[@]}; do
            git checkout "$FILE"
        done
    else
        git checkout "$@"
    fi
}
gsq() {
    if [[ "$#" -ne 1 ]]; then
        echo "requires an int arg representing number of commits"
    fi
    MSG=$(git log --format=%B HEAD~"${1}"..HEAD)
    git reset --soft HEAD~"${1}"
    git commit --verbose --edit -m"${MSG}"
}
gfo() {
    git commit -m 'temp'
    MSG=$(git log --format=%B HEAD~2..HEAD~1)
    git reset --soft HEAD~"2"
    git commit --verbose --edit -m"${MSG}"
}
alias gcp='git cherry-pick --ff'
alias gcm='git commit --amend'

# Fetch (f)
alias gf='git fetch'
alias gfc='git clone'

# Log (l)
alias gl='git log --topo-order --pretty=format:${_git_log_medium_format}'
alias glp='git log --topo-order --pretty=format:${_git_log_medium_format} -p'
alias gls='git log --topo-order --stat --pretty=format:${_git_log_medium_format}'
alias gld='git log --topo-order --stat --patch --full-diff --pretty=format:${_git_log_medium_format}'
alias glo='git log --topo-order --date=local --pretty=format:${_git_log_oneline_format}'
# sed will remove multiple adjacent whitespaces
alias glg='git log --topo-order --all --graph --date=local --pretty=format:${_git_log_oneline_format}'
alias glb='git log --topo-order --pretty=format:${_git_log_brief_format}'
alias glc='git shortlog --summary --numbered'

# Rebase (r)
alias gr='git rebase'
alias gra='git rebase --abort'
alias grc='git rebase --continue'
alias gri='git rebase --interactive'
alias grs='git rebase --skip'

# Merge (m)
alias gm='git merge'

# Push (p)
alias gp='git push'
alias gpl='git fetch origin master && git rebase origin/master'

# Stash (s)
alias gs='git stash'
alias gsa='git stash apply'
alias gsx='git stash drop'
alias gsX='git-stash-clear-interactive'
alias gsl='git stash list'
alias gss='git stash save --include-untracked'

# Working Copy (w)
alias gws='git status --ignore-submodules=${_git_status_ignore_submodules} --short'
alias gwS='git status --ignore-submodules=${_git_status_ignore_submodules}'
alias gwd='git diff --no-ext-diff'
alias gwsd='git diff --cached'
alias gwD='git diff --no-ext-diff --word-diff'
alias gwr='git reset'
alias gwR='git reset --hard'
alias gwc='git clean -f'
gwu() {
    local FILES=(${(f)"$(git ls-files --others --exclude-standard| fzf --multi --reverse)"})
    for FILE in ${FILES[@]}; do
        rm "$FILE"
    done
}
alias gcp='git cherry-pick --ff'


# Personal Aliases
alias s='ssh'
alias n='nvim'
alias ks='kitty +kitten ssh'
alias sco='nvim ~/.ssh/config'
alias nvimf='nvim $(fzf)'
alias cdf='cd $(find . -type d | fzf)'
alias ..='cd ../'
alias ...='cd ../../'
alias ....='cd ../../../'
alias t='tmux'
alias ta='tmux attach'
alias tre='~/.tmux/window_renum.sh'
alias ncdu='ncdu --color dark -x'
alias rcp='rsync --verbose --progress --human-readable -zz --archive --hard-links --one-file-system'
alias rmv='rsync --verbose --progress --human-readable -zz --archive --hard-links --one-file-system --remove-source-files'
alias rmvu='rsync --verbose --progress --human-readable -zz --archive --hard-links --one-file-system --remove-source-files --update'
alias rsynchronize='rsync --verbose --progress --human-readable --compress --archive --hard-links --one-file-system --remove-source-files --update --delete'


###########
# Functions
###########

# Color shortcuts
G="\e[32m"
R="\e[31m"
C="\e[36m"
NC="\e[39m"

# Docker functions
alias dl="docker logs"
alias dlf="docker logs --follow"
dpa() { docker ps -a } # List all containers
di() { docker images } # Show images
drm() { docker rm $(docker ps -a -q) 2> /dev/null; } # Remove dead containers
drv() { docker volume rm $(docker volume ls -qf dangling=true) } # remove dangling volumes
dri() { docker rmi -f $(docker images -q) } # Remove unused images
dstop() { docker stop $(docker ps -a -q); } # Stop all containers
dip() { docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$1" }
dfp() { # Function to get forwarded port of docker container
  if [ -z "$2" ]; then
    docker inspect --format='{{(index (index .NetworkSettings.Ports "8000/tcp") 0).HostPort}}' $1
  else
    docker inspect --format='{{(index (index .NetworkSettings.Ports "'$2'/tcp") 0).HostPort}}' $1
  fi
}
dfpo() { # Open chrome to a forwarded container port
  if [ "$#" -ne 1 ]; then
      echo 'Usage: dfpo $port'
  else
      /usr/bin/open -a '/Applications/Google Chrome.app' 'http://localhost:'"$1"
  fi
}
dex() { # Enter a container
  if [ -z "$2"]; then
    docker exec -it "$1" /bin/bash
  else
    docker exec -it "$1" "$2"
  fi
}


# Tmux functions
t4() {
    tmux split-window
    tmux split-window
    tmux split-window
    tmux select-layout tiled
}
tat() { # Creating a second window on a session
  if [ ! -z "$1" ]; then
    tmux new -t "$1" -s "$1"1
  fi
}
tla() {
    if [[ -z "$1" ]]; then
        return
    fi
    # Search in all folders under 'Work'
    local PROJS=($(find "$HOME"/Work/* -mindepth 1 -maxdepth 1 -type d))
    local PROJ_NAME=''
    local PROJ_DIR=''
    # Find if we have a match
    for dir in "${PROJS[@]}"; do
        if [[ $(basename "$dir") == "$1" ]]; then
            PROJ_NAME=$(basename "$dir")
            PROJ_DIR="$dir/code"
        fi
    done
    if [[ -z "$PROJ_NAME" ]]; then
        echo 'Project not found'
        return
    fi
    PROJECT="$PROJ_NAME" DIR="$PROJ_DIR" tmuxp load ~/.tmux/templates/alternative.yaml
}

# Nixos
alias nrs="sudo -i nixos-rebuild switch"
alias nco="sudo nixos-container"
alias ns="nix-shell -p"

# Git
gup() { # Loop through args, branches, and update them
    orig_head="$(git name-rev --name-only HEAD)"
    for var in "$@"
    do
        git checkout "$var"
        git pull origin "$var"
        git merge origin/"$var"
    done
    git checkout "$orig_head"
}

gupr() {
    git checkout "$1"
    git fetch origin master
    git rebase origin/master
}

gpf() {
    current_branch="$(git name-rev --name-only HEAD)"
    git push origin "$current_branch" --force
}

gpu() {
    current_branch="$(git name-rev --name-only HEAD)"
    git fetch origin "$current_branch"
    git reset --hard origin/"$current_branch"
}


# GPG
gpgen() { # Function for compressing and encrypting a file
  tar -zc $1 | gpg --encrypt --sign --armor --recipient cody@hiar.ca > $2
}
gpgde() { # Function for uncompressing and decrypting a file
  gpg -d $1 | tar -zx
}


# SSH
sl() { # Handy ssh forwarding commands, pull a port down
    if [ $# -eq 0 ]; then
        echo 'Usage: sl $host $port $bindingaddress(optional)'
    else
        while true
        do
            if [ -z "$3"]; then
                ssh -nNT -L "$2":localhost:"$2" "$1"
            else
                ssh -nNT -L "$2":"$3":"$2" "$1"
            fi
            sleep 10
        done &
    fi
}
sr() { # Handy ssh forwarding commands, push a port up
    if [ $# -eq 0 ]; then
        echo 'Usage: sl $host $port $bindingaddress(optional)'
    else
        while true
        do
            if [ -z "$3"]; then
                ssh -nNT -R "$2":localhost:"$2" "$1"
            else
                ssh -nNT -R "$2":"$3":"$2" "$1"
            fi
        done &
    fi
}


pgdumpr() { # Dump remote postgres database.
    ssh -t "$1" "sudo -u postgres bash -c \"pg_dump --no-acl --no-owner -d "$2" > /tmp/"$2"-$(date +%F).sql\""
    scp "$1":/tmp/"$2"-$(date +%F).sql .
}
pgimport() { # SCP file remotely and import it.
    scp "$2" "$1":/tmp
    SHORTNAME=$(echo "$2" | cut -d'-' -f1)
    ssh -t "$1" "sudo -u postgres bash -c \"psql -d "$SHORTNAME" < /tmp/"$2"\""
}
pgls() { # List commands on a server
    HOST="$1"
    ssh -tt "$HOST" 'sudo -u postgres bash -c "psql --list"'
}
mysqldumpr() { # Dump remote mysql database
    ssh -t "$1" "mysqldump "$2" > /tmp/"$2"-$(date +%F).sql" && scp "$1":/tmp/"$2"-$(date +%F).sql .
}
fwkill() { # Kill all of the forwarded ports on the machine
    ps aux | grep 'ssh -nNT -L' | grep -v 'grep' | awk '{ print $2 }' | xargs -n 1 kill
}
j() { # Jump to project code
    PROJ=$(find "$HOME/Work" -mindepth 2 -maxdepth 2 -type d -name "$1")
    if [[ -d "$PROJ/code" ]]; then
        cd "$PROJ/code"
    fi
}
ch() { # Force ownership on a projects files. Sometimes docker generates root owned files
    PROJ=$(find "$HOME/Work" -mindepth 2 -maxdepth 2 -type d -name "$1")
    sudo chown -R thorny:users "$PROJ/code"
}
finalurl() { # check that redirects are properly happening
    curl http://"$1" -s -L -o /dev/null -w '%{url_effective}'
    echo ''
    curl http://www."$1" -s -L -o /dev/null -w '%{url_effective}'
    echo ''
    curl https://"$1" -s -L -o /dev/null -w '%{url_effective}'
    echo ''
    curl https://www."$1" -s -L -o /dev/null -w '%{url_effective}'
    echo ''
}
newproj() { # Create a new cookiecuter project
    cookiecutter https://git.codyhiar.com/docker/cookiecutter-docker
    PROJECT=$(ls -t1 --color=never | head -1)
    mv "$PROJECT" code
    mkdir "$PROJECT"
    mv code "$PROJECT"
}
p() { # List all projects
    find "$HOME"/Work/* -mindepth 1 -maxdepth 1 -type d | xargs -n1 basename | sort
}
ssl() {
    echo | openssl s_client -servername "$1" -connect "$1":443 2>/dev/null | openssl x509 -noout -issuer -dates -subject -fingerprint
}

gfcc () {
    # This function assumes urls of one of the following formats. All others
    # will not work:
    #
    # git@github.com:user/repo.git
    # https://github.com/user/repo
    PROTOCOL=$(echo "$1" | cut -c1-3)
    if [[ "$PROTOCOL" == 'git' ]]; then
        REPO=$(echo "$1" | cut -d'/' -f2 | cut -d'.' -f1)
    elif [[ "$PROTOCOL" == 'htt' ]]; then
        REPO=$(echo "$1" | cut -d'/' -f5 )
    fi
    git clone "$1" "$REPO"/code
}

heartbeat() { # Keep a heartbeat on a website
    while true; do
        STATUS=$(nice curl -I "$1" 2> /dev/null | grep '200 OK')
        if [[ -n $STATUS ]]; then
            echo -e "$(date) ${G}$1 is up${NC}"
        else
            STATUS=$(nice curl -I "$1" 2> /dev/null | grep 'HTTP/2 200')
            if [[ -n $STATUS ]]; then
                echo -e "$(date) ${G}$1 is up${NC}"
            else
                echo -e "$(date) ${R}$1 is down${NC}"
            fi
        fi
        sleep 2
    done
}
mvw() { # i3 move workspace to monitor
    i3-msg "workspace ${1}, move workspace to output ${2}"
}
getip() { # Get ip for website, ignore cloudflare ips
    IS_CLOUDFLARE=$(dig +short NS "$1" | grep 'cloudflare')
    if [[ -n "$IS_CLOUDFLARE" ]]; then
        echo 'Behind Cloudflare'
        return
    fi
    IP_ADDR=$(dig +short "$1")
    echo "$IP_ADDR"
    grep -B 2 "$IP_ADDR" ~/.ssh/config | grep 'Host '
}
lorem() {
    WORD_LENGTH=$(((RANDOM % 5) + 5))
    WORD=$(openssl rand -base64 12| head -n 1 | cut -c1-"$WORD_LENGTH")
    SENTENCE="$WORD"
    for i in {1..40}; do
        WORD_LENGTH=$(((RANDOM % 5) + 5))
        WORD=$(openssl rand -base64 12| head -n 1 | cut -c1-"$WORD_LENGTH")
        SENTENCE="$SENTENCE $WORD"
    done
    echo $SENTENCE
}
amis() {
    aws ec2 describe-images --owners self | jq '.Images[] | {id: .ImageId, name: .Name, state: .State, snapshot: .BlockDeviceMappings[0].Ebs.SnapshotId}'
}
rm_ami() {
    AMI_NAME="$1"
    DATA=$(aws ec2 describe-images --owners self)
    AMI_ID=$(echo "$DATA"| jq '.Images[] | select(.Name | contains("'"$AMI_NAME"'")) | .ImageId' |  sed -e 's/^"//' -e 's/"$//')
    SNAPSHOT_ID=$(echo "$DATA"| jq '.Images[] | select(.Name | contains("'"$AMI_NAME"'")) | .BlockDeviceMappings[0].Ebs.SnapshotId' |  sed -e 's/^"//' -e 's/"$//')
    aws ec2 deregister-image --image-id "$AMI_ID"
    aws ec2 delete-snapshot --snapshot-id "$SNAPSHOT_ID"
}
settitle() {
    xdotool set_window --name "$*" $(xdotool getactivewindow)
}
csv() {
    clear; csvlook -d ',' --no-inference "$1" | less -s
}
y() {
    yank | xp
}
gbxm() { # Clear out branches
    git branch | egrep -v "(master)" | xargs -n 1 git branch -D
    rm -rf .git/refs/remotes/origin/*
    git fetch origin master
}
d() { # reset monitors on desktop
    i3-msg "workspace 1, move workspace to output DVI-D-1"
    i3-msg "workspace 2, move workspace to output DVI-I-1"
    i3-msg "workspace 3, move workspace to output HDMI-4"
}
mkv2mp4() { # Create an mp4 of mkv
    ffmpeg -i "$1" -codec copy "${1%.*}.mp4"
}
rzf() {
    local FILENAME=$(fzf)
    local DIRNAME=$(dirname "${FILENAME}")
    ranger "${DIRNAME}"
}

btc() { # Get current btc
    curl -s https://bitpay.com/api/rates | python -c "import json, sys; print(json.load(sys.stdin)[6]['rate'])"
}
btcc() { # convert btc to cad
    BTC_RATE=$(curl -s https://bitpay.com/api/rates | python -c 'import json, sys; print(json.load(sys.stdin)[6]["rate"])')
    echo $(($1 * $BTC_RATE))
}
brightd() {
    sudo python3 "$HOME/.dotfiles/repos/additional/scripts/brightness_daemon.py"
}
brightness_up() {
    echo 'up' | nc -U /tmp/brightd.sock
}
brightness_down() {
    echo 'down' | nc -U /tmp/brightd.sock
}
tlo () {
    if [[ -z "$1" ]]; then
        return
    fi
    local PROJS=($(find "$HOME"/Work/* -mindepth 1 -maxdepth 1 -type d))
    local PROJ_NAME=''
    local PROJ_DIR=''
    for dir in "${PROJS[@]}"; do
        if [[ $(basename "$dir") == "$1" ]]; then
            PROJ_NAME=$(basename "$dir")
            PROJ_DIR="$dir/code"
            tmux new-session -c "${PROJ_DIR}" -s "${PROJ_NAME}"
            return
        fi
    done
    echo "Project '${1}' was not found"
}

gpp() {
    MESSAGE=${1:-auto}
    git commit -m "$MESSAGE" && git push origin master
}
gppa() {
    MESSAGE=${1:-auto}
    git add -A; git commit -m "$MESSAGE" && git push origin master
}
cwh() {
    cat $(which "${1}")
}
vwh() {
    nvim $(which "${1}")
}
xephyr() {
    Xephyr -br -ac -noreset -screen 1080x1080 :1
}
pwgen() {
    date +%s | sha256sum | base64 | head -c 32 | cut -c1-10
}
# rotate uses ImageMagick
rotate() { convert "$1" -rotate 90 "$1" }
rotate90() { convert "$1" -rotate 90 "$1" }
rotate180() { convert "$1" -rotate 180 "$1" }
rotate270() { convert "$1" -rotate 270 "$1" }
# task warrior commands
tkwa() {task add "$1" +work; task sync}
tkpa() {task add "$1" +personal; task sync}
tkw() {task +work}
tkp() {task +personal}
ts() {task sync}
ttotal() {
    task "$1" information | grep 'duration' | awk -F'duration: ' '{ print $2 }' | cut -d')' -f1 | iso8601_adder
}
twstart() {
    TAG=$(cat ~/.timewarrior/my_tags | fzf)
    timew start "$TAG"
}
twstop() {
    TAG=$(cat ~/.timewarrior/my_tags | fzf)
    timew stop "$TAG"
}
twremove() {
    TAGS=(${(f)"$(cat ~/.timewarrior/my_tags | fzf --multi)"})
    for TAG in ${TAGS[@]}; do
        sed -i '/'"$TAG"'/d' ~/.timewarrior/my_tags
    done
}
twsummary() {
    timew summary
}
twsummaryt() {
    TAG=$(cat ~/.timewarrior/my_tags | fzf)
    timew summary "$TAG"
}
inc() {
    nvim ~/.dotfiles/zsh/includes
}
dot2png() {
    dot "${1}" -Tpng -o "${1%.*}.png"
}
dot2svg() {
    dot "${1}" -Tsvg -o "${1%.*}.svg"
}
alias vbm="vboxmanage"
xlsx2csv() {
    in2csv "${1}" > "${1%.*}.csv"
}
xls2csv() {
    in2csv "${1}" > "${1%.*}.csv"
}
klu() {
    CLUSTER=$(kubectl config get-contexts | tail -n +2 |  awk '{ print $2 }' | fzf)
    kubectl config use-context "$CLUSTER"
}
ksl() {
    kubectl get svc
}
kdl() {
    clear
    kubectl get deployment -o wide | less -S
}
kex() {
    POD=$(kubectl get pods | tail -n +2 |  awk '{ print $1 }' | fzf)
    kubectl exec -it "$POD" -- bash
}
klf() {
    POD=$(kubectl get pods | tail -n +2 |  awk '{ print $1 }' | fzf)
    kubectl logs --follow "$POD"
}
mrs() {
    TOKEN=$(sops -d /not/real/path/to/keys.yaml | yq -r .gitlab_token)
    curl --header "PRIVATE-TOKEN: ${TOKEN}" -X GET "https://gitlab.com/api/v4/projects/someproject/merge_requests?state=opened" 2> /dev/null | \
        jq ".[] | {title: .title, branch: .source_branch, author: .author.name, web_url: .web_url, labels: .labels}"
}
mrsc() {
    TOKEN=$(sops -d /not/real/path/to/keys.yaml | yq -r .gitlab_token)
    curl --header "PRIVATE-TOKEN: ${TOKEN}" -X GET "https://gitlab.com/api/v4/projects/someproject/merge_requests?state=merged&order_by=updated_at" 2> /dev/null | \
        jq "limit(4;.[]) | {title: .title, branch: .source_branch, author: .author.name, web_url: .web_url}"
}
glab_ci() {
    TOKEN=$(sops -d /not/real/path/to/keys.yaml | yq -r .gitlab_token)
    RUNNING_BRANCH=$(curl --header "PRIVATE-TOKEN: ${TOKEN}" -X GET "https://gitlab.com/api/v4/projects/someproject/pipelines?status=running" 2> /dev/null | jq -r ".[0].ref")
    glab ci view $RUNNING_BRANCH
}

2faimport() {
    if [[ "$#" -ne 2 ]]; then
        echo 'error in num args'
    else
        # 1 is image 2 is account
        zbarimg -q --raw "${1}" | pass otp append "${2}"
    fi
}
2fadisplay() {
    pass otp uri -q "${1}"
}
rst2md() {
    pandoc -s -o "${1%.*}.md" "${1}"
}
rtf2txt() {
    unoconv -f txt "${1}"
}
zshpure() {
    zsh -d -f -i
}
cheat() {
    curl https://cheat.sh/"${1}"
}
fz() {
    DIR=$(_z 2>&1 -l "${1}" | rg -v 'common:' | awk '{ print $2 }' | fzf --tac)
    cd $DIR
}
alias icat="kitty +kitten icat"
rwh() {
    readlink $(which "${1}")
}
cdrwh() {
    cd $(dirname $(dirname $(rwh "${1}")))
}
cdr() {
    cd $(dirname $(dirname "${1}"))
}
nums() {
    # set IFS to deal with dirs having spaces
    local IFS=$'\n\t'
    for DIR in $(find . -mindepth 1 -maxdepth 1 -type d | sort); do
        local MYDIR=$(basename "${DIR}")
        local NUMFILES=$(find ${MYDIR} -type f | wc -l)
        printf "%6s %s\n" $NUMFILES $MYDIR
    done
}
l() {
    if [ -x "$(command -v exa)" ]; then
        exa "$@"
    else
        ls "$@"
    fi
}
# This goes in an infinite recursion if exa is not installed. lol
ls() {
    if [ -x "$(command -v exa)" ]; then
        exa "$@"
    else
        ls "$@"
    fi
}
ll() {
    l -l
}
l1() {
    l -1
}

clean_nix_generations() {
    sudo nix-env -p /nix/var/nix/profiles/system --delete-generations +5
    sudo nix-collect-garbage
}
ghprl() {
    gh pr list --author @me --json number,title,headRefName,url | jq -r 'map({number,title,headRefName,url}) | (first | keys_unsorted) as $keys | map([to_entries[] | .value]) as $rows | $keys,$rows[] | @csv' | csvlook -d ',' --no-inference | less
    gh pr list --search "is:open is:pr review-requested:@me" --json number,title,headRefName,url | jq -r 'map({number,title,headRefName,url}) | (first | keys_unsorted) as $keys | map([to_entries[] | .value]) as $rows | $keys,$rows[] | @csv' | csvlook -d ',' --no-inference
}
ghpra() {
    gh pr list --search "is:open is:pr author:@me review:approved" --json number,title,headRefName,url | jq -r 'map({number,title,headRefName,url}) | (first | keys_unsorted) as $keys | map([to_entries[] | .value]) as $rows | $keys,$rows[] | @csv' | csvlook -d ',' --no-inference
}
ghpr() {
    local PR=$(gh pr list --author @me --json number,title -q '.[] | "\(.number) \(.title)"' | fzf --prompt "Which PR do you want to check out?" | awk '{ print $1 }')
    export GH_PR=$PR
}
ghprs() {
    gh pr checks $1
    echo ""
    gh pr view $1
}
ghprd() {
    gh pr diff "$1"
}
ghprm() {
    echo "Merge PR: $1?"
    read choice
    case "$choice" in
      y|Y ) gh pr merge --auto --rebase --delete-branch $1;;
      n|N ) return;;
      * ) echo "invalid";;
    esac
}
ghprr() {
    gh pr list -S 'review-requested:@me'
}
ghil() {
    gh issue list -a @me
}
ghprw() {
    while true :; do clear; gh pr checks "$1" ; sleep 7; done
}