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
|
# completion as advised by arch wiki
complete -cf sudo man which
# reduce history size
export HISTCONTROL=ignoreboth
# completions
if [ -f /usr/share/bash-completion/completions/pass ]; then
. /usr/share/bash-completion/completions/pass
fi
HISTSIZE=20000
# export PS1='bash-\v-\u@\h \W\$ '
# export PS1='\[\033[38;5;208m\]\u@\h:\w\$\[\033[0m\] '
#export PS1='\[\033[01;32m\]\u@\h:\w\$\[\033[0m\] '
export PS1='\[\033[01;36m\][\u@\h\[\033[01;37m\] \W\[\033[01;36m\]]\$\[\033[00m\] '
# vi mode
#set -o vi
# prevent clobbering of files
# echo "output" >| file.txt to do it manually
set -o noclobber
#alias vim='/usr/bin/nvim'
alias vi='/usr/bin/vim'
export EDITOR=vim
# export ALTERNATE_EDITOR=""
# export EDITOR="emacsclient -t" # $EDITOR opens in terminal
# export VISUAL="emacsclient -c -a emacs" # $VISUAL opens in GUI mode
# openai keys
source $HOME/Documents/sync/openai_key
# completion for beets
# from https://wiki.archlinux.org/title/Beets
#eval "$(beet completion)"
# aliases
alias am='append_to_masterlist'
alias annex-sync='cd ~/annex/ && git annex sync && cd -'
alias blog="cd ~/code/html/yulqen.org/"
alias brandom='beet play "$(beet random -p)"'
alias bud="cd ~/Budget/hledger/"
alias getip="curl ifconfig.me"
alias gitrepos="ssh git@joannalemon.com \"tree -L 2 repositories\""
alias gloga='git log --oneline --decorate --graph --all'
alias hd='openai_data'
alias h='hey_openai'
alias _hl_bal_lastmonth='hledger bal --period "this month" --depth 3 Expenses'
alias hn='curl hkkr.in'
alias k5days='khal list today 5 days'
alias khal="$HOME/src/virtualenvs/khal-venv/bin/khal"
alias khard="$HOME/src/virtualenvs/khal-venv/bin/khard"
alias ls="ls --color=auto"
alias ll="ls -larth" # sort by modified
alias mountmusic='sudo sshfs -o IdentityFile=/home/lemon/.ssh/id_ed25519,default_permissions,allow_other lemon@192.168.1.10:/mnt/music /mnt/music'
alias notesbackup='duplicity --encrypt-key 19014642A9FCD633B886B8F59C9841C3EF4E0B8E ~/Documents/Notes/ sftp://git@joannalemon.com:2222/notesbackup'
alias notes="cd $HOME/Documents/Notes/"
alias pacdel="pacman -Qq | fzf --multi --preview 'pacman -Qi {1}' | xargs -ro sudo pacman -Rns"
alias pacget="pacman -Slq | fzf --multi --preview 'pacman -Si {1}' | xargs -ro sudo pacman -S"
alias pacpreview="pacman -Qq | fzf --preview 'pacman -Qil {}' --layout=reverse --bind 'enter:execute(pacman -Qil {} | less)'"
alias qn2firefox='pandoc /home/lemon/Documents/Notes/quicknote.md -o /tmp/quicknote.html && firefox /tmp/quicknote.html'
alias qnarchive='mkdir /tmp/quicknotes && cp ~/code/html/yulqen.org/content/techjournal/quicknote_capture_* /tmp/quicknotes && cp ~/Documents/Notes/quicknote.md /tmp/quicknotes && tar czf quicknotes.tgz -C /tmp/quicknotes .'
alias rem1='ssh joannalemon.com rem -c+a1 -w140 -m'
alias rem2='ssh joannalemon.com rem -c+a2 -w140 -m'
alias sync-tunnel='ssh -N -L 9090:127.0.0.1:8384 syncthing@syncthing-ct.banded-neon.ts.net'
alias tcomptoday='task end.after:today-1d completed'
alias thisweek='khal list today 5days -d google_timebox'
alias thomeprojects='task _unique project|grep "h\."'
alias tkilled="task +killlist list"
alias tl="/home/lemon/Documents/Notes/todo/todo.sh list"
alias tprojects="task rc.list.all.projects=1 projects"
alias ttagged="task tags.any: list"
alias ttags="task rc.list.all.tags=1 tags"
alias t="task"
alias ttoday="task ml_due_or_scheduled_today"
alias tuntagged="task tags.none: list"
alias tworkprojects='task _unique project|grep "w\."'
alias upload_datafile_surgetracker='scp /home/lemon/Documents/Notes/Projects/Surgetracker/resources/master_add_data.csv surge@64.227.37.12:code/surgetracker/datafiles'
alias vdirsyncer="$HOME/src/virtualenvs/khal-venv/bin/vdirsyncer"
alias vi='vim'
alias weather='curl wttr.in'
alias xclip='xclip -selection c'
grepfishhistory () {
grep "$1" ~/.local/share/fish/fish_history |cut -f3- -d' '
}
# Environment variables
export LEDGER_FILE="$HOME/Budget/hledger/budget.ledger"
#export TERM="screen-256color" arch wiki says not to set this here.
export LESS="-iMRS -x2"
export NOTES="$HOME/Documents/Notes"
export RANGER_LOAD_DEFAULT_RC="FALSE"
export FZF_DEFAULT_COMMAND="rg --files --hidden --glob '!.git' "
# export FZF_DEFAULT_COMMAND='ag -l --path-to-ignore ~/.ignore --nocolor --hidden -g ""'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
export FZF_ALT_C_COMMAND="$FZF_DEFAULT_COMMAND"
#export FZF_DEFAULT_OPTS="--preview='bat --color=always {}' --bind shift-up:preview-page-up,shift-down:preview-page-down --color info:108,prompt:109,spinner:108,pointer:168,marker:168"
#export FZF_DEFAULT_OPTS="--preview='--bind shift-up:preview-page-up,shift-down:preview-page-down --color info:108,prompt:109,spinner:108,pointer:168,marker:168"
# taskwarrior tickler file - https://cs-syd.eu/posts/2015-06-28-gtd-with-taskwarrior-part-3-tickling
tickle () {
deadline=$1
shift
task add wait:$deadline $@
}
# taskwarrior read and review (ensure you have html-xml-utils package installed)
webpage_title (){
curl -s "$@" | hxselect -s '\n' -c 'title' 2>/dev/null
}
read_and_review (){
link="$1"
title=$(webpage_title $link)
echo $title
descr="\"Read and review: $title\""
id=$(task add pro:h.reading "$descr" | sed -n 's/Created task \(.*\)./\1/p')
task "$id" annotate "$link"
}
alias rnr=read_and_review
# gpg
export GPG_TTY="$(tty)"
gpgconf --launch gpg-agent
# find file tagged using filetags
_find_tagged ()
{
find ~/Documents -name "*--*$1*"
}
# ssh - from https://wiki.archlinux.org/title/SSH_keys#SSH_agents
if ! pgrep -u "$USER" ssh-agent > /dev/null; then
ssh-agent -t 1h > "$XDG_RUNTIME_DIR/ssh-agent.env"
fi
if [[ ! -f "$SSH_AUTH_SOCK" ]]; then
source "$XDG_RUNTIME_DIR/ssh-agent.env" >/dev/null
fi
# bind '"\C-r": "\C-x1\e^\er"'
# bind -x '"\C-x1": __fzf_history';
__fzf_history ()
{
__ehc $(history | fzf --tac --tiebreak=index | perl -ne 'm/^\s*([0-9]+)/ and print "!$1"')
}
__ehc()
{
if
[[ -n $1 ]]
then
bind '"\er": redraw-current-line'
bind '"\e^": magic-space'
READLINE_LINE=${READLINE_LINE:+${READLINE_LINE:0:READLINE_POINT}}${1}${READLINE_LINE:+${READLINE_LINE:READLINE_POINT}}
READLINE_POINT=$(( READLINE_POINT + ${#1} ))
else
bind '"\er":'
bind '"\e^":'
fi
}
# fkill - kill processes - list only the ones you can kill. Modified the earlier script.
fkill() {
local pid
if [ "$UID" != "0" ]; then
pid=$(ps -f -u $UID | sed 1d | fzf -m | awk '{print $2}')
else
pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}')
fi
if [ "x$pid" != "x" ]
then
echo $pid | xargs kill -${1:-9}
fi
}
# fco_preview - checkout git branch/tag, with a preview showing the commits between the tag/branch and HEAD
fco_preview() {
local tags branches target
branches=$(
git --no-pager branch --all \
--format="%(if)%(HEAD)%(then)%(else)%(if:equals=HEAD)%(refname:strip=3)%(then)%(else)%1B[0;34;1mbranch%09%1B[m%(refname:short)%(end)%(end)" \
| sed '/^$/d') || return
tags=$(
git --no-pager tag | awk '{print "\x1b[35;1mtag\x1b[m\t" $1}') || return
target=$(
(echo "$branches"; echo "$tags") |
fzf --no-hscroll --no-multi -n 2 \
--ansi --preview="git --no-pager log -150 --pretty=format:%s '..{2}'") || return
git checkout $(awk '{print $2}' <<<"$target" )
}
# fshow - git commit browser
fshow() {
git log --graph --color=always \
--format="%C(auto)%h%d %s %C(black)%C(bold)%cr" "$@" |
fzf --ansi --no-sort --reverse --tiebreak=index --bind=ctrl-s:toggle-sort \
--bind "ctrl-m:execute:
(grep -o '[a-f0-9]\{7\}' | head -1 |
xargs -I % sh -c 'git show --color=always % | less -R') << 'FZF-EOF'
{}
FZF-EOF"
}
# ftags - search ctags
ftags() {
local line
[ -e tags ] &&
line=$(
awk 'BEGIN { FS="\t" } !/^!/ {print toupper($4)"\t"$1"\t"$2"\t"$3}' tags |
cut -c1-80 | fzf --nth=1,2
) && ${EDITOR:-vim} $(cut -f3 <<< "$line") -c "set nocst" \
-c "silent tag $(cut -f2 <<< "$line")"
}
# tm - create new tmux session, or switch to existing one. Works from within tmux too. (@bag-man)
# `tm` will allow you to select your tmux session via fzf.
# `tm irc` will attach to the irc session (if it exists), else it will create it.
tm() {
[[ -n "$TMUX" ]] && change="switch-client" || change="attach-session"
if [ $1 ]; then
tmux $change -t "$1" 2>/dev/null || (tmux new-session -d -s $1 && tmux $change -t "$1"); return
fi
session=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | fzf --exit-0) && tmux $change -t "$session" || echo "No sessions found."
}
tmuxkillf() {
local sessions
sessions="$(tmux ls | fzf --exit-0 --multi)" || return $?
local i
for i in "${sessions[@]}"
do
if [[ $i =~ ([^:]*):.* ]]; then
echo "Killing ${BASH_REMATCH[1]}"
tmux kill-session -t "${BASH_REMATCH[1]}"
fi
done
}
fman() {
man -k . | fzf -q "$1" --prompt='man> ' --preview $'echo {} | tr -d \'()\' | awk \'{printf "%s ", $2} {print $1}\' | xargs -r man | col -bx | bat -l man -p --color always' | tr -d '()' | awk '{printf "%s ", $2} {print $1}' | xargs -r man
}
# Get the colors in the opened man page itself
#export MANPAGER="sh -c 'col -bx | bat -l man -p --paging always'"
#source $HOME/secrets
# Functions
##############################################################
# Quick way to create a new blog post with Hugo from wherever
# on the filesystem.
# Used ChatGPT to get the substitution and escaping correct.
# Called with a single string argument.
# ############################################################
function newpost() {
if [[ $# -ne 1 ]]; then echo "Give me the title!"; return; fi
title="$1"
# convert title to lowercase and replace spaces with hyphens for the slug
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
# create the new post file with Hugo
cd $HOME/code/html/yulqen.org
post_path="content/blog/$slug.md"
hugo new "$post_path"
# update the front matter with the original title string
echo "Looking for $post_path..."
awk -v title="$title" '{gsub(/title: .*/, "title: \""title"\"")}1' "$post_path" > tmp && mv tmp "$post_path"
vim $post_path
}
###################################################################
# To output in cat, just call todj.
# To enable editing the files in vim, call todj vim.
# You can use less or any other tool to display the text if you wish
# Arguments:
# None
# Output:
# Writes to stdout or opens program passed as first argument
###################################################################
todj () {
CMD=${1:-"cat"}
$CMD $(find /home/lemon/Documents/Notes/journal/home -name "*$(date '+%Y-%m-%d')*")
}
#########################################################################
# This function takes two arguments as strings. The idea is to enable
# passing file data into the function, such as a csv file or some code.
# Call like this openai_data "Please optimise the following function in
# python" "$(</path/to/file)" This is supposed to be a good way to read a
# file's contents in bash
# Arguments:
# Text prompt
# File contents
# Output:
# Writes to stdout
#########################################################################
openai_data() {
if [[ $# -ne 2 ]]; then echo "Give me two params!"; return; fi
text_prompt="$1"
data="$2"
prompt="${text_prompt}: ${data}"
json=$(jq -n --arg p "$data" '{model: "gpt-3.5-turbo", messages: [{role: "user", content: $p}], temperature: 0.7}')
local gpt=$(curl https://api.openai.com/v1/chat/completions -s \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_KEY" \
-H "OpenAI-Organization: $OPENAI_ORG_ID" \
-d "$json")
echo $gpt | jq -r '.choices[0].message.content'
}
################################################################################
# A straight forward request to the OpenAI GPT-3 model.
# Takes a single string argument and returns a simple response.
# hey_openai "What is the best way to open and interate through a file in Perl?"
# Arguments:
# Text prompt
# Output:
# Writes to stdout
################################################################################
hey_openai() {
prompt="$1"
local gpt=$(curl https://api.openai.com/v1/chat/completions -s \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_KEY" \
-H "OpenAI-Organization: $OPENAI_ORG_ID" \
-d "{
\"model\": \"gpt-3.5-turbo\",
\"messages\": [{\"role\": \"user\", \"content\": \"$prompt\"}],
\"temperature\": 0.7
}")
echo $gpt | jq -r '.choices[0].message.content'
}
append_to_masterlist() {
ml=~/Documents/Notes/todo/masterlist.txt
echo "$1" >> "$ml"
cat "$ml"
}
# Colors for ls - yellow directories
# export LS_COLORS="$LS_COLORS:di=1;33"
# Install Ruby Gems to ~/gems
export GEM_HOME="$HOME/gems"
# get best audio of YouTube file or playlist (just use the right URL)
ytmp3 () {
if [ -z "$1" ]; then print "I need a valid YouTube URL.\n"; fi
cd ~/Downloads/music && yt-dlp -f 'ba' -x --audio-format mp3 "$1" -o '%(title)s.%(ext)s' && cd - || return
}
ytmp3-split-to-chapters() {
if [ -z "$1" ]; then print "I need a valid YouTube URL.\n"; fi
yt-dlp -f 'bestaudio' -x --audio-format mp3 --split-chapters -o '%(title)s.%(ext)s' "$1" && cd - || return
}
. "$HOME/.cargo/env"
|