aboutsummaryrefslogtreecommitdiff
path: root/bash/.bashrc
blob: e6dc3321601b10b7281b334a6d37458da29a23fb (plain) (blame)
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
# Test for an interactive shell. There is no need to set anything
# past this point for scp and rcp, and it's important to refrain from
# outputting anything in those cases.
if [[ $- != *i* ]] ; then
    # Shell is non-interactive. That's all, folks!
    return
fi

# {{{1 EXPORTS

# XDG Base Directories
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CACHE_HOME="$HOME/.cache"

# Set default programs
export TERMINAL=/usr/local/bin/st
export EDITOR=/usr/bin/vim
export PAGER=/usr/bin/less
export BROWSER=/usr/bin/firefox-bin
export MAILCAPS=$XDG_CONFIG_HOME/mailcap/mailcap

# Instruct less to use this control sequence every time it needs to
# display bold text. For example, this alters headers and keywords in
# man pages
export LESS_TERMCAP_md="${yellow}"

# Creates a user temporary directory.
mkdir -p /tmp/$USER
export TMPDIR=/tmp/$USER

# Home subdirectories
export GIT=$HOME/git
export BIN=$HOME/.local/bin
export MAIL=$HOME/mail
export IMGS=$HOME/imgs
export MUSIC=$HOME/music
export DOWNLOADS=$HOME/downloads
export OMNIA=$HOME/omnia
export DOCUMENTS=$HOME/documents
export NOTES=$DOCUMENTS/notes

# Use System fonts for Java applications (added to fix Protegé font
# problems)
export _JAVA_OPTIONS="-Dawt.useSystemAAFontSettings=on"

# History size for the in-memory list
export HISTSIZE='1024';
# History size for the $HISTFILE
export HISTFILESIZE=$HISTSIZE;
# Omit duplicates and commands that begin with a whitespace from history
export HISTCONTROL='ignoreboth';

# Make (relative) path relative to the cwd or the user's home (in this
# order, in case of collisions) when using `cd`
export CDPATH=".:$HOME:$GIT"

# Local path definitions
export PATH=$HOME/.local/bin:$HOME/.local/npm/bin:$PATH
export NODE_PATH=$NODE_PATH:$HOME/.local/npm/lib/node_modules

# SSH connection
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
    export SSH_SESSION=1
fi

# FZF-related config options
export FZF_DEFAULT_COMMAND='rg --files --hidden --smart-case'

# {{{1 ALIASES

# Folder shortcuts
alias dl="cd ~/downloads;clear"

# Suppress echoing of the directory due to the env variable $CDPATH
# being set
#alias cd='>/dev/null cd'

# List all files colorized in long format
alias ls="command ls -lF --color"
# Same as `ls', but including hidden files
alias la="command ls -laF --color"
# Same as `ls', but clears the terminal screen first
alias cls="clear;ls"
# Same as `la', but clears the terminal screen first
alias cla="clear;la"

# Git-specific aliases
alias gs="git status"
alias glo="git log --color --decorate --oneline --graph"

# Print each PATH entry on a separate line
alias path='echo -e ${PATH//:/\\n}'

# Open zathura
alias z='zathura'
# Open multiple Mutt instances in readonly mode to avoid conflicts
alias mutt='pgrep mutt && command mutt -R || command mutt'

# {{{1 FUNCTIONS

# Determine size of a file or total size of the current directory if no
# argument is given
filesize() {
	if du -b /dev/null > /dev/null 2>&1; then
		local arg=-sbh;
	else
		local arg=-sh;
	fi
	if [[ -n "$@" ]]; then
		du $arg -- "$@";
	else
		du $arg .[^.]* ./*;
	fi;
}

# This is a better version of `tree` with hidden files and color
# enabled, ignoring the `.git` directory, listing directories first. The
# output gets piped into `less` with options to preserve color and line
# numbers, unless the output is small enough for one screen.
tree() {
	command tree -aC -I '.git' --dirsfirst "$@" | less -FRNX;
}

# Prints out a weather chart (automatically detects location if none
# is passed).
weather() {
    curl wttr.in/$1;
}

zettel() {
  vim "+Zet $*"
}

zettelkasten() {
    for file in "$NOTES"/*.md ; do
        sed 's/^title: //;2q;d' "$file"
    done
}

# {{{1 PROMPT

# This is a variant of the bash prompt by Mathias Bynens at
# https://github.com/mathiasbynens/dotfiles

## Gruvbox colors (dark version)
## https://github.com/morhetz/gruvbox
black=$(tput setaf 0)
red=$(tput setaf 9);
green=$(tput setaf 10);
yellow=$(tput setaf 11);
blue=$(tput setaf 12);
magenta=$(tput setaf 13);
cyan=$(tput setaf 14);
orange=$(tput setaf 166)
white=$(tput setaf 15)
grey=$(tput setaf 8)
bold=$(tput bold);
reset=$(tput sgr0);

## Builds a Git prompt of the from:
## ... on <git_branch> [●●●]↑
## where the three dots indicate the presence of untracked, unstaged
## and uncommitted files. A little arrow notifies fi something needs
## to be pushed upstream.
git_prompt() {
    local state="";
    local symbol=">";
    local branch="${bold}${magenta}";

    # Check if the current directory is in a Git repository.
    if [ $(git rev-parse --is-inside-work-tree &>/dev/null; echo "${?}") == '0' ]; then

        # check if the current directory is in .git before running git checks
        if [ "$(git rev-parse --is-inside-git-dir 2> /dev/null)" == 'false' ]; then

            # Ensure the index is up to date.
            git update-index --really-refresh -q &>/dev/null;

            state+="${white}["

            # Check for untracked files.
            if [ -n "$(git ls-files --others --exclude-standard)" ]; then  
                state+="${red}";
            else 
                state+="${grey}";
            fi;
            state+="$symbol"

            # Check for unstashed files.
            if ! $(git diff-files --quiet --ignore-submodules --) ; then
                state+="${yellow}";
            else 
                state+="${grey}";
            fi;
            state+="$symbol"

            # Check for uncommitted changes in the index.
            if ! $(git diff --quiet --ignore-submodules --cached); then
                state+="${green}";
            else
                state+="${grey}"
            fi;
            state+="$symbol"

            state+="${white}]"

            # Check if tracked remote is up-to-date with the local
            # branch.
            #
            # NB: Output is redirected to /dev/null because calling `git
            # cherry` if no remote is set generates annoying messages
            # every time the prompt is refreshed.
            if [ -n "$(git cherry 2>/dev/null)" ]; then
                state+="${blue}↑"
            fi;
        fi;

        # Get the short symbolic ref. If HEAD is not a symbolic ref, get
        # the short SHA for the latest commit.
        branch+="$(git symbolic-ref --quiet --short HEAD 2> /dev/null || \
            git rev-parse --short HEAD 2> /dev/null || \
            echo '(unknown)')";

        echo -e " on ${branch} ${state}${reset}";
    else
        return;
    fi;
}

job_count() {
    if [ -n "$(jobs -p)" ]; then
        echo -e " ($(jobs -p | wc -l))"
    fi
}

## Prompt definition
PS1=""
## Username
PS1+="\[${bold}\]\[${green}\]\u\[${reset}\]" 
PS1+=" at "
## Hostname
PS1+="\[${bold}\]\[${yellow}\]\h\[${reset}\]"
PS1+=" in "
## Current working directory
PS1+="\[${bold}\]\[${blue}\]\w\[${reset}\]"
## Git prompt
PS1+="\[\$(git_prompt)\]"
PS1+="\n"
## Lambda prompt
PS1+="\[${bold}\]>\[${reset}\]"

PS1+="\$(job_count) "
export PS1;

# {{{1 MISC

## Other options

# Change cursor shape
# 0 -> blinking block.
# 1 -> blinking block (default).
# 2 -> steady block.
# 3 -> blinking underline.
# 4 -> steady underline.
# 5 -> blinking bar (xterm).
# 6 -> steady bar (xterm).
echo -ne "\e[6 q"

# Vi mode for bash
set -o vi;

# Disable flow control (CTRL-S and CTRL-Q)
stty -ixon

# Automatically prepend 'cd' to directory used as command names
shopt -s autocd;

# Autocorrect typos in path names when using `cd` or pathnames
shopt -s cdspell dirspell;

# Check window size after each command and reset LINES and COLUMNS
shopt -s checkwinsize;

# Bash tries to save multiline commands as a single entry in the history
shopt -s cmdhist lithist;

# Dotfiles are included in the results of pathname expantion
shopt -s dotglob;

# '**' can be used to expand directory paths/files
shopt -s globstar;

# Enable extended glob obtions like `!(...)` or `+(...)`
# For more info check `man bash` in the Pathname Expansion section.
shopt -s extglob

# Append to the history file, rather than overwriting it
shopt -s histappend;

# Does not try to perform autocompletion on an empty line
shopt -s no_empty_cmd_completion;

# Case-insensitive globbing (used in pathname expansion)
shopt -s nocaseglob;

# Network printers
export mono3dup=Ricoh_Aficio_MP_5001_in_horizontal_duplex_mode_cups_cs_ox_ac_

# {{{1 ADDITIONAL FILES

# Custom scripts bash completion
# for file in $HOME/.scripts/completion/wiki.completion; do
#     [ -r "$file" ] && [ -f "$file" ] && source "$file";
# done;

for file in $HOME/.bash/{tmux,vim,ripgrep,fzf,nnn,sxiv}.bash; do
    [ -r "$file" ] && [ -f "$file" ] && source "$file";
done;
unset file;