Dotfiles and how i manage them
Published: 2023-02-01 10:33:00

Dotfiles are the configuration files for your system. It is what makes your `$HOME`, to `$HOME sweet $HOME`, basically your personalised settings.

In this blog, I will try to explain how my dotfiles are setup, and some settings/configurations I have. You can find a current copy of my dotfiles here, https://github.com/w3dg/dotfiles

---

## Shell

As for the shell i am using bash. I am working on windows for the while and the standard installation of Git Bash or WSL works fine for me. As well as i have picked up and learnt my way through bash and the command line in general and hence i stick to it.

I have tried out ZSH and `oh-my-zsh` and its great as well. Some suggestions are to use with zsh-autosuggestions package and zsh-syntaxhighlighting package.

## Bash Config

Customising bash requires you to edit your `.bashrc` file located in your home directory typically denoted by `~`.

Here's a top level view of what i have in my .bashrc

```bash
eval "$(dircolors -b ~/.dircolors)"
```

This evaluates dircolors for the ls command.

```bash
source ~/.bash/bindings.bash       # Bindings
source ~/.bash/shopts.bash         # Shopts
source ~/.bash/exports.bash        # Exports
source ~/.bash/functions.bash      # Custom functions
source ~/.bash/aliases.bash        # Aliases
source ~/.bash/git_aliases.bash    # Git aliases
```

These are various keybindings, shell options, exports of environment variables, custom functions and aliases which i have enabled.

### Useful Bindings

```bash
bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'
```

These will allow you to press the up key after typing a command to search your history to let you see the previous ways you had used it which is useful if you forgot the certain way you used a command before.

There are more, check out my dotfiles or anyone else's or research on the interet to find more!

### Useful functions

```bash
ex()
{
  if [ -f "$1" ] ; then
    case $1 in
      *.tar.bz2)   tar xjf $1   ;;
      *.tar.gz)    tar xzf $1   ;;
      *.bz2)       bunzip2 $1   ;;
      *.rar)       unrar x $1   ;;
      *.gz)        gunzip $1    ;;
      *.tar)       tar xf $1    ;;
      *.tbz2)      tar xjf $1   ;;
      *.tgz)       tar xzf $1   ;;
      *.zip)       unzip $1     ;;
      *.Z)         uncompress $1;;
      *.7z)        7z x $1      ;;
      *.deb)       ar x $1      ;;
      *.tar.xz)    tar xf $1    ;;
      *.tar.zst)   unzstd $1    ;;
      *)           echo "'$1' cannot be extracted via ex()" ;;
    esac
  else
    echo "'$1' is not a valid file"
  fi
}
```

This allows to extract given almost any sort of compressed file which is useful as I do not need to remember which command to use specifically.

```bash
mkcd() {
  mkdir $1 && cd $1
}
```

This function makes a directory and drops you into it all at once.

A great resource I had found for my git aliases is the `oh-my-zsh` repo - https://github.com/ohmyzsh/ohmyzsh/blob/master/plugins/git/git.plugin.zsh

For some bling in the terminal, this line displays a ascii cow saying a random quote each time i open a terminal. This uses the [fortune](<https://en.wikipedia.org/wiki/Fortune_(Unix)>) and [cowsay](https://en.wikipedia.org/wiki/Cowsay) programs.

```bash
fortune | cowsay
```

The next 3 lines allow for utf8 input and output in the terminal.

```bash
# Allow UTF-8 input and output, instead of showing stuff like $'\0123\0456'
set input-meta on
set output-meta on
set convert-meta off
```

A typical prompt of mine looks something like this - 

![My Prompt](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cg6r00joqe8lsfoexr1o.png)

Given all this custom settings and more you would obviously want to back them up and use it across machines or if you have a new machine.

---

## How to manage the various dotfiles across machines?

Typically on Linux, people will symlink their dotfiles kept in some other directory, generally under version control, to their home directory where everything should exist to allow the programs to pick the settings up.

So, you will see people doing this,

```bash
DOTFILES=(.bash_profile .gitconfig .gitignore)

#Remove old dotfiles and replace them
for dotfile in $(echo ${DOTFILES[*]});
do
    rm ~/$(echo $dotfile)
    ln -s ~/dotfiles/$(echo $dotfile) ~/$(echo $dotfile)
done
```

This code snippet above is a for loop in bash which loops through the given array of dotfiles and links them to the home directory.

Given on linux, this works very fine.

So granted I'm using Git Bash on Windows, it should work on Windows as well right?

The sad answer is no, even though there is a `ln` command, it doesn't seem to do anything.

So the other day, I decided to tackle this and write powershell script which does the same for me.

Heres that script,

```powershell
#!/usr/bin/env pwsh

# New-Item -path $HOME\.bashrc -itemType SymbolicLink -target $HOME\code\dotfiles\.bashrc

# .bashrc .bash_profile .gitconfig .inputrc .npmrc .gitignore .dircolors
$dotfiles = (".bashrc", ".bash_profile", ".dircolors", ".gitconfig", ".gitconfig", ".inputrc", ".npmrc", ".bash")

foreach ($element in $dotfiles) {
  echo Linking $element
  New-Item -path $HOME\$element -itemType SymbolicLink -target $HOME\code\dotfiles\$element
}

```

This does the same thing and now the files are correctly linked to the other directory under version control. And that directory is very much my dotfiles repository.