Skip to content

Latest commit

 

History

History
1804 lines (1449 loc) · 51.7 KB

dotfiles.org

File metadata and controls

1804 lines (1449 loc) · 51.7 KB

Dotfiles

Setup

This block of elisp loads an elisp file to set variables that can be used in :tangle arguments. It will be run automatically at document load due to local variables set at the bottom of this file; the user probabably needs to authorise this with ‘y’.

(setq system
      (let ((hostname (system-name)))
        (cond ((member hostname '("Angel" "Angel.lan" "Angel.local")) "Angel")
              ((member hostname '("ajj-mbp-1" "ajj-mbp-1.local"
                                  "dock-ajj-mbp-1" "dock-ajj-mbp-1.esc.rl.ac.uk"))
               "ajj-mbp-1")
              ;; To check the last part of hostname, we first pad to at least 16 char to avoid error on short names
              ((string= (substring (string-pad (system-name) 16) -16) "nubes.stfc.ac.uk") "SCD-cloud")
              ((string-match "host-[[:digit:]]+-[[:digit:]]+-[[:digit:]]+-[[:digit:]]+" (system-name)) "SCD-cloud")
              ('t hostname))
        ))

;; Centering, rows only supported for patched dmenu
(setq dmenu-patched-p
      (cond ((member system '("Arctopus" "scpc041")) 't)
            ('t nil)))

(defmacro if-workstation (arg1 arg2)
  `(if (member ,system '("Arctopus" "scpc041" "ajj-mbp-1" "SCLT452Mac"))
       ,arg1 ,arg2))

i3

i3 configuration mostly lives in one file.

# Super key
set $mod Mod4

font pango:Inconsolata 8

# Start XDG autostart .desktop files using dex. See also
# https://wiki.archlinux.org/index.php/XDG_Autostart
exec --no-startup-id dex-autostart --autostart --environment i3

# Hide titlebars unless tabbing/stacking
for_window [class="^.*"] border none

# NetworkManager is the most popular way to manage wireless networks on Linux,
# and nm-applet is a desktop environment-independent system tray GUI for it.
exec --no-startup-id nm-applet

# Use Mouse+$mod to drag floating windows to their wanted position
floating_modifier $mod

# move tiling windows via drag & drop by left-clicking into the title bar,
# or left-clicking anywhere into the window while holding the floating modifier.
tiling_drag modifier titlebar

# start a terminal
bindsym $mod+Return exec alacritty msg create-window || alacritty

# kill focused window
bindsym $mod+Shift+q kill

# change focus
bindsym $mod+j focus left
bindsym $mod+k focus down
bindsym $mod+l focus up
bindsym $mod+semicolon focus right

# move focused window
bindsym $mod+Shift+j move left
bindsym $mod+Shift+k move down
bindsym $mod+Shift+l move up
bindsym $mod+Shift+semicolon move right

# split in horizontal orientation
bindsym $mod+h split h

# split in vertical orientation
bindsym $mod+v split v

# enter fullscreen mode for the focused container
bindsym $mod+f fullscreen toggle

# change container layout (stacked, tabbed, toggle split)
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split

# toggle tiling / floating
bindsym $mod+Shift+space floating toggle

# change focus between tiling / floating windows
bindsym $mod+space focus mode_toggle

# focus the parent container
bindsym $mod+a focus parent

# focus the child container
bindsym $mod+z focus child

# Define names for default workspaces for which we configure key bindings later on.
# We use variables to avoid repeating the names in multiple places.
set $ws1 "1"
set $ws2 "2"
set $ws3 "3"
set $ws4 "4"
set $ws5 "5"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"

# switch to workspace
bindsym $mod+1 workspace number $ws1
bindsym $mod+2 workspace number $ws2
bindsym $mod+3 workspace number $ws3
bindsym $mod+4 workspace number $ws4
bindsym $mod+5 workspace number $ws5
bindsym $mod+6 workspace number $ws6
bindsym $mod+7 workspace number $ws7
bindsym $mod+8 workspace number $ws8
bindsym $mod+9 workspace number $ws9
bindsym $mod+0 workspace number $ws10

# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace number $ws1
bindsym $mod+Shift+2 move container to workspace number $ws2
bindsym $mod+Shift+3 move container to workspace number $ws3
bindsym $mod+Shift+4 move container to workspace number $ws4
bindsym $mod+Shift+5 move container to workspace number $ws5
bindsym $mod+Shift+6 move container to workspace number $ws6
bindsym $mod+Shift+7 move container to workspace number $ws7
bindsym $mod+Shift+8 move container to workspace number $ws8
bindsym $mod+Shift+9 move container to workspace number $ws9
bindsym $mod+Shift+0 move container to workspace number $ws10

# cycle workspaces
bindsym $mod+Tab workspace next
bindsym $mod+Shift+Tab workspace prev

# reload the configuration file
bindsym $mod+Shift+c reload
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym $mod+Shift+r restart
# exit i3 (logs you out of your X session)
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"

# resize window (you can also use the mouse for that)
mode "resize" {
        # These bindings trigger as soon as you enter the resize mode

        # Pressing left will shrink the window’s width.
        # Pressing right will grow the window’s width.
        # Pressing up will shrink the window’s height.
        # Pressing down will grow the window’s height.
        bindsym j resize shrink width 10 px or 10 ppt
        bindsym k resize grow height 10 px or 10 ppt
        bindsym l resize shrink height 10 px or 10 ppt
        bindsym semicolon resize grow width 10 px or 10 ppt

        # same bindings, but for the arrow keys
        bindsym Left resize shrink width 10 px or 10 ppt
        bindsym Down resize grow height 10 px or 10 ppt
        bindsym Up resize shrink height 10 px or 10 ppt
        bindsym Right resize grow width 10 px or 10 ppt

        # back to normal: Enter or Escape or $mod+r
        bindsym Return mode "default"
        bindsym Escape mode "default"
        bindsym $mod+r mode "default"
}

bindsym $mod+r mode "resize"

# Appearance tweaks
gaps inner 4
# gaps outer -4

# Start i3bar to display a workspace bar (plus the system information i3status
# finds out, if available)
# bar {
#         status_command i3status
# }

Dmenu

On patched systems, use a modified dmenu_run

dmenu_path | dmenu -c -l 6 -g 3 "$@" | ${SHELL:-"/bin/sh"} &

Launch dmenu or i3-dmenu-desktop with shortcuts

(if dmenu-patched-p "-c -l 6 -g 3" "")
bindsym $mod+d exec --no-startup-id dmenu_run <<get_dmenu_args()>>
bindsym $mod+Shift+d exec --no-startup-id i3-dmenu-desktop --dmenu='dmenu -i <<get_dmenu_args()>>'

Compositing

Use picom (may not be available on all systems)

  • on scpc041 and Arctopus this is started by /etc/xdg/autostart/picom.desktop so redundant to also include in i3 config
# Enable compositing (i.e. for transparent terminals)
exec --no-startup-id picom --backend glx

Actual picom configuration lives in another file

corner-radius = 10;
rounded-corners-exclude = [
"window_type = 'dock'",
"window_type = 'desktop'"
];

backend = "glx";

inactive-dim = 0.2;
inactive-opacity = 0.9;
opacity-rule=["100:class_g = 'i3lock'"];

Monitors

This is system-dependent, use xrandr commands to rotate and position monitors

# Sort out monitor positions
exec xrandr --output DVI-D-0 --rotate left --right-of HDMI-0 --pos 1980x0
exec xrandr --output HDMI-0 --pos 0x550

# They are in the wrong order so assign initial workspaces
workspace 1 output HDMI-0
workspace 2 output DVI-D-0
# Sort out monitor positions
exec xrandr --output DP-1 --rotate left --left-of DP-2 --pos 0x0
exec xrandr --output DP-2 --pos 1080x520

# They are in the wrong order so assign initial workspaces
workspace 1 output DP-2
workspace 2 output DP-1

Screen lock, suspend etc.

(cond ((equal system "scpc041") "-i /usr/share/backgrounds/f34/default/f34-02-night.png")
      ((equal system "Arctopus") "-i /home/adam/Pictures/Wallpapers/lock-screen-big.png")
      ('t ""))
# xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the
# screen before suspend. Use loginctl lock-session to lock your screen.
exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork <<get_wallpaper_args()>>

We also create a shell script for screen lock, shutdown etc, borrowed from https://faq.i3wm.org/question/239/how-do-i-suspendlockscreen-and-logout.1.html

lock() {
    i3lock <<get_wallpaper_args()>>
}

case "$1" in
    lock)
        lock
        ;;
    logout)
        i3-msg exit
        ;;
    suspend)
        systemctl suspend
        ;;
    hibernate)
        systemctl hibernate
        ;;
    reboot)
        systemctl reboot
        ;;
    shutdown)
        systemctl poweroff
        ;;
    *)
        echo "Usage: $0 {lock|logout|suspend|hibernate|reboot|shutdown}"
        exit 2
esac

exit 0

But instead of using an i3 mode, try using dmenu

bindsym $mod+c exec echo -e "lock\nlogout\nsuspend\nhibernate\nreboot\nshutdown" | dmenu <<get_dmenu_args()>> "$@" | xargs ~/.local/bin/i3exit

Launch some more programs and services

# Fancy status bar
exec --no-startup-id $HOME/.config/polybar/launch.sh

# Wallpaper
exec --no-startup-id nitrogen --restore

Polybar

Include polybar configuration with i3 configuration as I use them together. (To learn more about how to configure Polybar go to https://github.com/polybar/polybar. The wiki page is quite helpful.)

for m in $(xrandr --listactivemonitors | tail -n +2 | grep -o '[^ ]*$')
do
    MONITOR=$m polybar --reload bottom &
  done
else
  polybar --reload bottom &
fi
(cond ((member system '("Arctopus" "scpc041"))
       "[colors]
background = #2D3540
background-alt = #63738C
foreground = #C5C8C6
primary = #CFA43E
secondary = #8ABEB7
alert = #A54242
disabled = #707880"
       )
      ('t ""))
<<get_polybar_colours()>>

[bar/bottom]
monitor = ${env:MONITOR:HDMI-0}

bottom = true
; override-redirect = true
override-redirect = false

width = 100%
height = 16pt
radius = 0

; dpi = 96

background = ${colors.background}
foreground = ${colors.foreground}

line-size = 3pt

border-size = 0pt
border-color = #00000000

padding-left = 0
padding-right = 1

module-margin = 1

separator = |
separator-foreground = ${colors.disabled}

font-0 = "Inconsolata:weight=black:pixelsize=10"
;font-0 = "VT323:pixelsize=14"

modules-left = i3
modules-right = filesystem pulseaudio memory cpu eth date

cursor-click = pointer
scroll-up = "#i3.prev"
scroll-down = "#i3.next"

enable-ipc = true

; tray-position = right

; wm-restack = generic
; wm-restack = bspwm
wm-restack = i3

; override-redirect = true


[module/xworkspaces]
type = internal/xworkspaces

label-active = %name%
label-active-background = ${colors.background-alt}
label-active-underline= ${colors.primary}
label-active-padding = 1

label-occupied = %name%
label-occupied-padding = 1

label-urgent = %name%
label-urgent-background = ${colors.alert}
label-urgent-padding = 1

label-empty = %name%
label-empty-foreground = ${colors.disabled}
label-empty-padding = 1

[module/xwindow]
type = internal/xwindow
label = %title:0:60:...%

[module/filesystem]
type = internal/fs
interval = 25

mount-0 = /

label-mounted = %{F#F0C674}%mountpoint%%{F-} %percentage_used%%

label-unmounted = %mountpoint% not mounted
label-unmounted-foreground = ${colors.disabled}

[module/pulseaudio]
type = internal/pulseaudio

format-volume-prefix = "VOL "
format-volume-prefix-foreground = ${colors.primary}
format-volume = <label-volume>

label-volume = %percentage%%

label-muted = muted
label-muted-foreground = ${colors.disabled}

click-right = pavucontrol

[module/i3]
type = internal/i3
pin-workspaces = true
show-urgent = true
strip-wsnumbers = true
index-sort = true
enable-click = false
enable-scroll = false

; ws-icon-[0-9]+ = <label>;<icon>
; NOTE: The <label> needs to match the name of the i3 workspace
; Neither <label> nor <icon> can contain a semicolon (;)
ws-icon-0 = 1;♚
ws-icon-1 = 2;♛
ws-icon-2 = 3;♜
ws-icon-3 = 4;♝
ws-icon-4 = 5;♞
ws-icon-default = ♟
; NOTE: You cannot skip icons, e.g. to get a ws-icon-6
; you must also define a ws-icon-5.
; NOTE: Icon will be available as the %icon% token inside label-*

; Available tags:
;   <label-state> (default) - gets replaced with <label-(focused|unfocused|visible|urgent)>
;   <label-mode> (default)
format = <label-state> <label-mode>

; Available tokens:
;   %mode%
; Default: %mode%
label-mode = %mode%
label-mode-padding = 2
label-mode-background = #e60053

; Available tokens:
;   %name%
;   %icon%
;   %index%
;   %output%
; Default: %icon% %name%
label-focused = %index%
label-focused-foreground = ${colors.primary}
label-focused-background = ${colors.background}
label-focused-underline = ${colors.primary}
label-focused-padding = 2

; Available tokens:
;   %name%
;   %icon%
;   %index%
;   %output%
; Default: %icon% %name%
label-unfocused = %index%
label-unfocused-padding = 2

; Available tokens:
;   %name%
;   %icon%
;   %index%
;   %output%
; Default: %icon% %name%
label-visible = %index%
label-visible-underline = ${colors.foreground}
label-visible-padding = 2

; Available tokens:
;   %name%
;   %icon%
;   %index%
;   %output%
; Default: %icon% %name%
label-urgent = %index%
label-urgent-foreground = #000000
label-urgent-background = #bd2c40
label-urgent-padding = 4

; Separator in between workspaces
;label-separator = |
;label-separator-padding = 2
;label-separator-foreground = #ffb52a

[module/xkeyboard]
type = internal/xkeyboard
blacklist-0 = num lock

label-layout = %layout%
label-layout-foreground = ${colors.primary}

label-indicator-padding = 2
label-indicator-margin = 1
label-indicator-foreground = ${colors.background}
label-indicator-background = ${colors.secondary}

[module/memory]
type = internal/memory
interval = 2
format-prefix = "RAM "
format-prefix-foreground = ${colors.primary}
label = %percentage_used:2%%

[module/cpu]
type = internal/cpu
interval = 2
format-prefix = "CPU "
format-prefix-foreground = ${colors.primary}
label = %percentage:2%%

[network-base]
type = internal/network
interval = 5
format-connected = <label-connected>
format-disconnected = <label-disconnected>
label-disconnected = %{F#F0C674}%ifname%%{F#707880} disconnected

[module/wlan]
inherit = network-base
interface-type = wireless
label-connected = %{F#F0C674}%ifname%%{F-} %essid% %local_ip%

[module/eth]
inherit = network-base
interface-type = wired
label-connected = %{F#F0C674}%ifname%%{F-} %local_ip%

[module/date]
type = internal/date
interval = 1

date = %H:%M
date-alt = %Y-%m-%d %H:%M:%S

label = %date%
label-foreground = ${colors.primary}

[settings]
screenchange-reload = true
pseudo-transparency = true

; vim:ft=dosini

Alacritty

Configuration for Alacritty GPU-enhanced terminal emulator. I mostly use defaults for this, actually!

Alacritty has deprectated the yaml config I was using, and provided a migration tool. Still, I need to hack some of my literate emacs magic back in by hand…

New TOML config

Transparency is fun and lets us see our desktop background while working!

[window]
opacity = 0.9

Colour theme for Arctopus matching Hob wallpaper:

[colors.bright]
black = "0x63738c"
blue = "0x8cc7fe"
cyan = "0x34e2e2"
green = "0x94a7ae"
magenta = "0xad7fa8"
red = "0xef2929"
white = "0xeeeeec"
yellow = "0xe1c258"

[colors.normal]
black = "0x2d3540"
blue = "0x6c84a4"
cyan = "0x06989a"
green = "0x757f89"
magenta = "0x75507b"
red = "0xcc0000"
white = "0xd3d7cf"
yellow = "0xcfa43e"

[colors.primary]
background = "0x2d3c59"
foreground = "0xecf2f0"

Shells

Fish

Emacs can require a workaround to deal with glibc incompatibility; see corresponding section of Bash config for more info.

if status is-interactive
    # Commands to run in interactive sessions can go here

    if test -f "/usr/lib64/libc_malloc_debug.so.0"
        set -x EDITOR="LD_PRELOAD=/usr/lib64/libc_malloc_debug.so.0 emacsclient -t"
    else
        set -x EDITOR "emacsclient -t"
    end

    set -x ALTERNATE_EDITOR ''
    alias em $EDITOR
end

I might have installed some Chicken Scheme libraries, if so then export relevant variables.

set MY_CHICKEN_REPOSITORY $HOME/opt/eggs/lib/chicken/5
if test -d $MY_CHICKEN_REPOSITORY
  set -x CHICKEN_INSTALL_REPOSITORY $MY_CHICKEN_REPOSITORY
  set -x CHICKEN_REPOSITORY_PATH $MY_CHICKEN_REPOSITORY
end

Paths

Some systems don’t set ~/.local/bin or /usr/bin automatically. The former seems a liability for non-interactive use, wheras the latter should really always be available.

I also sometimes have a separate ~/bin; wheras ~.local/bin is for things installed by condax or Pip, ~/bin is mostly for things I compiled locally.

if not contains /usr/bin $PATH
    set -xp PATH /usr/bin
end

if status is-interactive
    for BINDIR in $HOME/.local/bin $HOME/bin
        if not contains $BINDIR $PATH
            set -xp PATH $BINDIR
        end
    end
end

I’m currently having some trouble on Arctopus where /usr/bin always ends up really early on the path; I think this is happening before Fish is launched, but haven’t yet found where. Could be /etc/gdm?

On a Mac we also want homebrew

if test -d /opt/homebrew
    eval (/opt/homebrew/bin/brew shellenv)
end

Conda setup

I use Conda on most machines but it’s not always installed the same way. On Fedora workstations we use system installation. Otherwise, have a look to see if some kind of (micro)mamba is available and get the fish shell hook set up.

Note that with older versions of fish (3.1ish?) the micromamba shell init will fail, because it uses more recent features of string-split.

if test -d /home/adam/.conda/envs/science
    # This is Arctopus, system Conda is in charge
    eval conda "shell.fish" "hook" $argv | source

else if test -d "$MAMBA_ROOT_PREFIX" -a -f "$MAMBA_EXE"
    # Mamba path already configured, this is probably a mambaorg/micromamba container

else if test -d "$HOME/mambaforge"
    # Probably a macbook
    set MAMBA_ROOT_PREFIX $HOME/mambaforge
    set CONDA_EXE $HOME/mambaforge/bin/conda

else if test -d "$HOME/micromamba"
    # Micromamba unpacked in home directory, probably a VM or server
    set MAMBA_ROOT_PREFIX $HOME/micromamba
    set MAMBA_EXE (which micromamba)
end

if test -d "$HOME/mambaforge"
    # Probably a macbook
    eval $CONDA_EXE "shell.fish" "hook" $argv | source
    source $MAMBA_ROOT_PREFIX/etc/fish/conf.d/mamba.fish
else if test -f "$MAMBA_EXE"
    $MAMBA_EXE shell hook --shell fish --root-prefix $MAMBA_ROOT_PREFIX | source
else if test -f "$CONDA_EXE"
    eval $CONDA_EXE "shell.fish" "hook" $argv | source
    source $MAMBA_ROOT_PREFIX/etc/fish/conf.d/mamba.fish
end

Functions

For convenience, the “n” function for use with nnn file manager is included in this repository. I didn’t write it so not much point having it in the literate file here. It is copied to . config/fish/functions

zoxide

if which zoxide &> /dev/null
    zoxide init fish | source
end

Environment modules

If environment modules are installed:

  • initialise
  • add user module path
  • load any default modules from ~/.modules.
    • ~/.modules is a non-standard config file that is not managed here. It should just contain a space-separated series of modules to load.
if test -f /usr/share/Modules/init/fish
  source /usr/share/Modules/init/fish
  set -xp MODULEPATH $HOME/.local/modulefiles

  if test -f $HOME/.modules
    module load (cat $HOME/.modules | string split -n " ")
  end
end

Quarantine

Quarantined blocks: not exported. Move to another section if needed.

~/.local/bin is an important place used by, among other things, pip install --user. Adding to PATH doesn’t seem to be necessary for fish on Arctopus, but I suspect it’s a complicated machine-specific thing that might change as I start cleaning things up.

set -xp PATH $HOME/.local/bin

Mantid / git

Some git aliases should go into ~/src/mantid/.git/config if it exists. As well as the usual add-data which is needed to upload test data, we can add some aliases that make working from Fish a bit nicer. (Basically, the mamba-installed GCC doesn’t configure the Fish environment properly. The simplest workaround is to wrap our build/test runs in a bash call.)

if test -f $HOME/src/mantid/.git/config
    pushd $HOME/src/mantid
    git config alias.build '!bash -cl \'$(basename $MAMBA_EXE) activate mantid-developer && cd ~/src/mantid && cmake --preset=linux && cd build && ninja\''
    git config alias.build-tests '!bash -cl \'$(basename $MAMBA_EXE) activate mantid-developer && cd ~/src/mantid && cmake --preset=linux && cd build && ninja AllTests\''
    git config alias.ctest '!bash -cl \'$(basename $MAMBA_EXE) activate mantid-developer && cd ~/src/mantid/build && ctest $*\' -'
    git config alias.systemtest '!bash -cl \'$(basename $MAMBA_EXE) activate mantid-developer && cd ~/src/mantid/build && ./systemtest $*\' -'
    popd
end

Bash

I still get a bit confused about bashrc vs bash_profile…

Some helpful stuff here https://unix.stackexchange.com/questions/170493/login-non-login-and-interactive-non-interactive-shells

  • bash_profile is loaded for login shells
    • i.e. a shell you would need to enter a username/password for
  • ~/.bashrc is loaded for non-login interactive shells
    • Easiest way to get one of these is open graphical terminal from desktop GUI
    • Of course we also usually source ~/.bashrc from ~/.bash_profile
  • Interactive shells have a prompt ($PS1) and source /etc/profile, ~/.profile
  • Non-interactive shells for scripts etc will generally also be non-login.
    • source /etc/bashrc
    • also receives exported variables from the parent shell

Yes, bash_profile is for login sessions and bashrc is for non-login but “interactive” shells. It’s generally recommended that PATH stuff happens in bash_profile and aliases/functions happen in bashrc. This is due to the way they are inherited: we don’t want export PATH=blah:$PATH to be extended in every subshell, and aliases/functions do not automatically get passed into subshells.

(Presumably this is why it is important to EXPORT any path manipulation; this allows it to get into any non-login subshells you launch.)

sh profile

~/.profile is run by non-bash login sessions. Usually this will be the graphical interface.

On Arctopus we add ~/.local/bin to path at this point so that the custom build of dmenu is available to i3. This seems a slightly dangerous/sweeping way of doing that; maybe it would be better to limit the scope to a directory that only contains those programs.

We’ll put this under the “bash” folder which isn’t strictly correct (it uses sh) but makes sense when installing things.

# Put custom scripts on the path where i3 can see them
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi

Profile

Source system-wide profile if available. (Is this actually necessary? Maybe not.)

if [ -f /etc/bashrc ]; then
  source /etc/bashrc
fi

Environment modules

Whether using lmod or the old tcl environment-modules, the standard location for init files is the same.

for MODULEINIT in /usr/share/Modules/init/bash /usr/local/opt/modules/init/bash
do
  if [ -f ${MODULEINIT} ]; then
    source ${MODULEINIT}
  fi
done

Add a user directory for custom modulefiles:

export MODULEPATH=${HOME}/.local/modulefiles:${MODULEPATH}

Quarantine

Quarantined blocks: not exported. Move to another section if needed.

Not sure what program I have ~/.cabal/bin for. I know that’s for Haskell stuff but it doesn’t seem to be on Arctopus. Maybe just add for whatever machines use this?

export PATH=$HOME/.cabal/bin:$PATH

Intel MKL things: I don’t think I really use these any more but it was a nuisance to figure out the first time.

for INTEL_INIT in /opt/intel/mkl/bin/mklvars.sh /opt/intel/bin/ifortvars.sh
do
  if [ -f ${INTEL_INIT} ]; then
    source ${INTEL_INIT} intel64
  fi
done

Paths

Most machines need ~/.local/bin adding, set it here and keep an eye out for where it might be redundant.

export PATH=$HOME/.local/bin:$PATH

I might have installed some Chicken Scheme libraries, if so then export relevant variables.

MY_CHICKEN_REPOSITORY=$HOME/opt/eggs/lib/chicken/5
if test -d $MY_CHICKEN_REPOSITORY
then
  export CHICKEN_INSTALL_REPOSITORY=$MY_CHICKEN_REPOSITORY
  export CHICKEN_REPOSITORY_PATH=$MY_CHICKEN_REPOSITORY
fi

Editor

The choice of editor is fairly clear at this point.

ALTERNATE_EDITOR="" means emacsclient will start a new daemon if none is available. This makes opening a new editor instantaneous after the first one.

LD_PRELOAD is needed when using Emacs from conda-forge (built against old libc) on a recent Linux version (built against new libc). Apparently Emacs was pretty much the only program using this deprecated feature! See conda-forge/emacs-feedstock#63

if [[ -f "/usr/lib64/libc_malloc_debug.so.0" ]]; then
    export EDITOR="LD_PRELOAD=/usr/lib64/libc_malloc_debug.so.0 emacsclient -t"
else
    export EDITOR="emacsclient -t"
fi

export ALTERNATE_EDITOR=""

Conda

On Mac the conda setup gets put in .bash_profile as this is the only file people can assume will be run. For now put it here in a system-specific block; should generalise this at some point as we have done for fish.

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/adam/mambaforge/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/Users/adam/mambaforge/etc/profile.d/conda.sh" ]; then
        . "/Users/adam/mambaforge/etc/profile.d/conda.sh"
    else
        export PATH="/Users/adam/mambaforge/bin:$PATH"
    fi
fi
unset __conda_setup

if [ -f "/Users/adam/mambaforge/etc/profile.d/mamba.sh" ]; then
    . "/Users/adam/mambaforge/etc/profile.d/mamba.sh"
fi
# <<< conda initialize <<<

Finally

Source bashrc for the stuff that should be run for every bash shell

source $HOME/.bashrc

RC

Environment

Source system-wide bashrc if available

if [ -f /etc/bashrc ]; then
  source /etc/bashrc
fi

If there are some custom environment modules that should be loaded in each shell session, they go in ~/.modules. Not clear if this is needed any more.

if [ -f $HOME/.modules ]; then
    module load $(cat $HOME/.modules)
fi

Non-ancient versions of tmux set TERM to tmux-256color, but not many tools know how to work with that so use screen-256color instead.

if [ $TERM = tmux-256color ]; then
    export TERM=screen-256color
fi

Compatibility fix for new versions of glibc with conda-forge emacs

export LD_PRELOAD=/usr/lib64/libc_malloc_debug.so.0

Appearance

Check the window size after each command, updating LINES and COLUMNS as necessary. This is only worth doing for interactive sessions so we look for “i” in the $- variable. (This is somewhat Bash specific.)

if [[ $- == *i* ]]; then
    shopt -s checkwinsize
fi

Colour handling is a bit system/OS-specific.

On MacOS we pass -G to ls; this does something totally different on other versions of Bash…

alias ls='ls -G'

On most Linux-y systems we instead use

alias ls='ls --color=auto'

Some HPC admins gripe about this taxing the file system, so we might need to add an exception if I start using ARCHER again.

The colours are set in the LS_COLORS variable; the dircolors program can generate the appropriate content from a user config file, conventionally ~/.dircolors. I have never felt the need to tweak this; I suppose it could be cute to one day add meaningful colours to DFT code input files etc? For now lets not bother with that stuff.

Aliases

Grep
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
Schedulers

I’m just using slurm at the moment, but we can check if it is available before setting alias.

if test $(command -v squeue)
then
    alias myjob='squeue -u $USER'
fi
Shortcuts
alias em=${EDITOR}
alias ll='ls -l'
alias la='ls -a'
Typos

For old times’ sake! I’ve been making these typos less frequently since moving to 40%-size keyboards.

alias celar='clear'
alias ks='ls'
Radio

Internet radio streaming with mplayer. Not useful for remote machines so only included for named ones.

alias soma-dronezone='mplayer -playlist http://somafm.com/dronezone130.pls < /dev/null >&0 2>&0 &'
alias soma-groovesalad='mplayer -playlist http://somafm.com/groovesalad130.pls < /dev/null >&0 2>&0 &'
alias soma-defcon='mplayer -playlist http://somafm.com/defcon130.pls < /dev/null >&0 2>&0 &'
alias soma-space='mplayer -playlist http://somafm.com/spacestation130.pls < /dev/null >&0 2>&0 &'
copy to fish config, maybe get rid of redundancy somehow

Functions

Set window title

set_title() { printf "\e]2;$*\a"; }

PDF manpages: first we need to find an appropriate PDF viewer

(if (equal system-type 'darwin) "open" "xdg-open")
PDF_VIEWER=<<get_pdf_viewer()>>

function pdfman() { man -t $1 | ps2pdf - /tmp/$1.pdf && ${PDF_VIEWER} /tmp/$1.pdf; }

nnn quitcd magic: Original source has useful comments. BSD 2-clause license, see header of the fish version.

  n ()
{
    # Block nesting of nnn in subshells
    if [[ "${NNNLVL:-0}" -ge 1 ]]; then
        echo "nnn is already running"
        return
    fi

    export NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
    \nnn "$@"

    if [ -f "$NNN_TMPFILE" ]; then
            . "$NNN_TMPFILE"
            rm -f "$NNN_TMPFILE" > /dev/null
    fi
}

Prompt

Some machines have nicknames and signature colours; I haven’t been using this mechanism so much lately but it’s neat so I’ll keep the ARCHER example.

case $(hostname) in
    eslogin0*)
        NICKNAME="ARCHER/${USER}"
        NICKCOLOUR="0;32m";;
    *)
        NICKNAME=$(hostname -s)
        NICKCOLOUR="0m";;
esac

Get git branch (Thanks to this blog) and construct prompt.

function parse_git_branch {
      ref=$(git symbolic-ref HEAD 2> /dev/null) || return
      echo " ("${ref#refs/heads/}")"
  }

RED="0;31m"

# (Simple prompt for dumb terminals: help emacs tramp mode)
case "$TERM" in
"dumb")
    PS1="> "
    ;;
xterm*|rxvt*|eterm*|screen*|tmux*|alacritty)
    PS1="\[\033[${NICKCOLOUR}\]${NICKNAME}\[\033[0m\]:\w\[\033[${RED}\]\$(parse_git_branch)\[\033[0m\]$ "
    ;;
*)
    PS1="> "
    ;;
esac

Password checks

Disable graphical password checks, as these are problematic when using a remote terminal.

unset SSH_ASKPASS

Completion

Bash completion doesn’t load automatically on a Mac if installed with Homebrew.

for COMPLETION in /usr/local/etc/profile.d/bash_completion.sh /opt/homebrew/etc/profile.d/bash_completion.sh ${HOME}/.local/completions/*
do
    if [ -f ${COMPLETION} ]; then
        source ${COMPLETION}
    fi
done

Tmux

I’m not using tmux so much on the desktop with i3 but it still has its uses especially on remote servers.

setw -g mode-keys emacs
set -g mouse on

I use ` as my leader key to avoid a chord and clashes with emacs cursor movement. Actually, since moving to very small custom keyboards this is less of an advantage: I use arrow keys in emacs and the backtick requires a chord to access! Maybe if I start using tmux heavily again I’ll switch back to C-b but for now this is what I’m comfortable with.

unbind-key C-b
set -g prefix '`'
bind-key '`' send-prefix

Add a shortcut for refreshing the config.

bind-key r source-file ~/.config/tmux/tmux.conf

When accessing a tmux session that was initiated in smaller window, try to resize it.

setw -g aggressive-resize on

Set up a nice simple blue colour scheme. This plays nicely with solarized, tango and my i3/alacrittys themes.

set -g status-style bg=blue,fg=white
set -g window-status-style bg=blue,fg=brightwhite
set -g pane-border-style fg=white
set -g pane-active-border-style fg=brightblue
set -g message-style bg=white,fg=blue

Make history longer so program output doesn’t clobber useful stuff.

set -g history-limit 100000

Add a few shortcuts for common new-pane needs.

# Create a new remote shell
bind-key S   command-prompt -p "host" "split-window 'ssh %1'"
bind-key C-s command-prompt -p "host" "new-window -n %1 'ssh %1'"

# Get an editor
bind-key y   new-window -n "emacs"  "emacsclient -t"

# Get a file manager
bind-key N   new-window -n "nnn"  "nnn"

More intuitive splitting commands. I always forget which direction % is going to split…

bind-key | split-window -h
bind-key - split-window -v

Count from 1 so loading windows with 1, 2, 3… keys is easy.

set -g base-index 1

Clipboard

First we unbind some keys we’re going to need

unbind -T copy-mode 'C-w'
unbind -T copy-mode 'M-w'
unbind -T copy-mode Enter

Some of the clipboard configuration is different for Mac vs Linux. On Mac we need to install “reattach-to-user-namespace”

# http://iancmacdonald.com/macos/emacs/tmux/2017/01/15/macOS-tmux-emacs-copy-past.html
set-option -g default-command "reattach-to-user-namespace -l $SHELL"
bind-key -T copy-mode 'C-w' send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy"
bind-key -T copy-mode 'M-w' send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy"
bind-key -T copy-mode Enter send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy"
bind ] run "reattach-to-user-namespace pbpaste | tmux load-buffer - && tmux paste-buffer"

whereas on Linux we use xclip.

bind-key -T copy-mode 'C-w' send-keys -X copy-pipe-and-cancel "xclip -sel clip -i"
bind-key -T copy-mode 'M-w' send-keys -X copy-pipe-and-cancel "xclip -sel clip -i"
bind-key -T copy-mode Enter send-keys -X copy-pipe-and-cancel "xclip -sel clip -i"

Git

Pretty barebones git config really

[user]
        name = Adam J. Jackson
        email = a.j.jackson@physics.org
[init]
        defaultBranch = main
[rebase]
        autosquash = true

aliases

  • git lol is a classic, found passed around the internet
    [alias]
            lol = log --graph --decorate --pretty=oneline --abbrev-commit --all --color
        
  • Here are some nice ones from https://www.reddit.com/r/commandline/comments/wf7oju:
    pr = "!f() { git fetch --force origin pull/$1/head:pr-$1; }; f"
        

SSH

My ssh config draws significant inspiration from (outragously steals from) https://github.com/jarvist/jarvist-dotfiles.

Host *
Protocol 2
UseRoaming no

Other goodies improve performance and reduce drop-outs:

Compression yes

ServerAliveCountMax 5
# Allowed pings with no reply before hang up

ServerAliveInterval 30
# Needs to be <60s for some home routers

Actual account details are pulled from another file to be copied and pasted manually: ssh-accounts.txt.

(let ((filename "ssh-accounts.txt")
      (get-text (lambda (filename)
                  (with-temp-buffer
                    (insert-file-contents filename)
                    (buffer-substring-no-properties
                     (point-min) (point-max))))))
  (if (file-exists-p filename)
      (funcall get-text filename)
      (message (concat "# Could not find " filename)))
  )
<<get_ssh_accounts()>>

nnn

Plugins

NNN plugins are programs that live in ~/.config/nnn/plugins. By default this directory is empty; the user copies/writes the plugins they wish to use and sets an NNN_PLUG environment variable that assigns shortcuts. We can also include simple commands directly, such as the git command to upload Mantid test data.

set -x NNN_PLUG 'u:!git add-test-data "$nnn"'

if test -f "$HOME/.config/nnn/plugins/nuke"
    set -x NNN_OPENER "$HOME/.config/nnn/plugins/nuke"
    set -x NNN_OPTS "c"
end

Notes

The default nuke plugin doesn’t play nicely with EDITOR=emacsclient -t; it’s a sh script and ends up keeping EDITOR in quotes when calling it, so it looks for binary name includeing the ~ -t~ and fails.

The workaround is to change the editor calls from

"${EDITOR}" "${FPATH}"

to

sh -c "${EDITOR} ${FPATH}"

For now I’m not managing that in this file.

MOC: Music On Console

I’m not using mocp much at the moment because of Linux Audio Hell but may as well keep my config around.

Config

The colour theme and keymap are stored in other files

Theme = my_theme
Keymap = my_keymap

Enable high quality audio when hardware allows.

ResampleMethod = SincMediumQuality
Allow24bitOutput = yes

Disabling TiMidity can prevent some buggy weirdness

TiMidity_Config = no

Audio backend options: these don’t seem to be playing well with whatever PulseAudio/Pipewire madness is going on these days :-(

# Sound driver - OSS, ALSA, JACK, SNDIO (on OpenBSD) or null (only for
# debugging).  You can enter more than one driver as a colon-separated
# list.  The first working driver will be used.
SoundDriver = JACK:ALSA:OSS

# Jack output settings.
#JackClientName = "moc"
#JackStartServer = no
JackOutLeft = "system:playback_1"
JackOutRight = "system:playback_2"

# OSS output settings.
#OSSDevice = /dev/dsp
#OSSMixerDevice = /dev/mixer
#OSSMixerChannel1 = pcm             # 'pcm', 'master' or 'speaker'
#OSSMixerChannel2 = master          # 'pcm', 'master' or 'speaker'

# ALSA output settings.
#ALSADevice = default
#ALSAMixer1 = PCM
#ALSAMixer2 = Master

Theme

Custom colour theme, nothing especially clever but looks nice on most of my machines.

background          = default default
frame               = blue      default   bold
window_title        = blue      default   bold
directory           = blue      default   bold
selected_directory  = black     yellow
playlist            = blue      default   bold
selected_playlist   = black     yellow
file                = blue      default   bold
selected_file       = black     yellow  bold
marked_file         = yellow default dim
marked_selected_file = black    yellow
marked_selected_info = black yellow
info                = blue     default   bold
marked_info         = yellow default dim
selected_info       = black yellow bold
status              = blue     default  bold
title               = blue     default   bold
state               = blue     default   bold
current_time        = yellow   default  bold
time_left           = yellow   default  bold
total_time          = yellow   default  bold
time_total_frames   = blue     default   bold
sound_parameters    = yellow   default  bold
legend              = blue     default   bold
disabled            = black    default
enabled             = blue     default   bold
empty_mixer_bar     = blue     default   bold
filled_mixer_bar    = black     yellow
empty_time_bar      = blue     default   bold
filled_time_bar     = black     yellow
entry               = blue     default  bold
entry_title         = blue     default  bold
error               = red      default  bold
message             = blue     default  bold
plist_time          = blue     default   bold

Keymap

MOCP keymap; mostly defaults but some emacs-y tweaks

# MOC control keys:
quit_client           = q
quit                  = Q

# Menu and interface control keys:
go                    = ENTER ^m ^j
menu_down             = DOWN ^n
menu_up               = UP ^p
menu_page_down        = PAGE_DOWN ^v
menu_page_up          = PAGE_UP  M-v
menu_first_item       = HOME M-<
menu_last_item        = END M->
search_menu           = / ^s
toggle_read_tags      = f
toggle_show_time      = ^t
toggle_show_format    = M-t
toggle_menu           = TAB
toggle_layout         = l
toggle_hidden_files   = H
# next_search           = ^g ^n
show_lyrics           = L
theme_menu            = T
help                  = h ?
refresh               = ^r
reload                = r g

# Audio playing and positioning keys:
seek_forward          = RIGHT ^f
seek_backward         = LEFT ^b
seek_forward_fast     = ] ^e
seek_backward_fast    = [ ^a
pause                 = SPACE
stop                  = s
next                  = n
previous              = p
toggle_shuffle        = S
toggle_repeat         = R
toggle_auto_next      = X
toggle_mixer          = x
go_url                = o

# Volume control keys:
volume_down_1         = <
volume_up_1           = >
volume_down_5         = ,
volume_up_5           = .
volume_10             = M-1
volume_20             = M-2
volume_30             = M-3
volume_40             = M-4
volume_50             = M-5
volume_60             = M-6
volume_70             = M-7
volume_80             = M-8
volume_90             = M-9

# Directory navigation keys: defaults are Shift-number
#                            (i.e., 'shift 1' -> '!' -> 'Fastdir1').
go_to_a_directory     = i
go_to_music_directory = m
go_to_fast_dir1       = !
go_to_fast_dir2       = @
go_to_fast_dir3       = #
go_to_fast_dir4       = $
go_to_fast_dir5       = %
go_to_fast_dir6       = ^
go_to_fast_dir7       = &
go_to_fast_dir8       = *
go_to_fast_dir9       = (
go_to_fast_dir10      = )
go_to_playing_file    = G
go_up                 = U

# Playlist specific keys:
add_file              = a
add_directory         = A
plist_add_stream      = ^u
delete_from_playlist  = d
playlist_full_paths   = P
plist_move_up         = u
plist_move_down       = j
save_playlist         = V
remove_dead_entries   = Y
clear_playlist        = C

# Queue manipulation keys:
enqueue_file          = z
clear_queue           = Z

# User interaction control:
history_up            = UP M-p
history_down          = DOWN M-n
delete_to_start       = ^u ^a
delete_to_end         = ^k
cancel                = ESCAPE ^g
hide_message          = M

# Softmixer specific keys:
toggle_softmixer      = w
toggle_make_mono      = J

# Equalizer specific keys:
toggle_equalizer      = E
equalizer_refresh     = e
equalizer_prev        = K
equalizer_next        = k

Chicken

Chicken repository stuff was set up under Fish and Bash sections. Maybe that should live here somehow? Or we should do noweb things?

Configuration file for chicken that enables realine support so interpreter is not horribly painful to use:

(This is directly from the GPL-licensed project archive. Hopefully they are cool with that.)

(import (chicken load))
(load-verbose #f)
(let ()
  (import (chicken format))
  (import (chicken process-context))
  (import (chicken process signal))
  (unless (get-environment-variable "INSIDE_EMACS")
    (import breadline)
    (import breadline-scheme-completion)
    (history-file (format "~a/.csi_history" (get-environment-variable "HOME")))
    (stifle-history! 10000)
    (completer-word-break-characters-set! "\"\'`;|(")
    (completer-set! scheme-completer)
    (basic-quote-characters-set! "\"|")
    (variable-bind! "blink-matching-paren" "on")
    (paren-blink-timeout-set! 200000)
    (let ((handler (signal-handler signal/int)))
      (set-signal-handler! signal/int
                           (lambda (s)
                             (cleanup-after-signal!)
                             (reset-after-signal!)
                             (handler s))))
    (on-exit reset-terminal!)
    (current-input-port (make-readline-port))))

Perl

I installed a few CPAN packages on scpc041 and it added this to my bashrc:

PATH="/home/adamjackson/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/home/adamjackson/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/home/adamjackson/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/home/adamjackson/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/home/adamjackson/perl5"; export PERL_MM_OPT;

I was using Fish at the time, which made it especially unhelpful. Let’s just leave them here and see if it’s actually a problem; I really just needed that stuff to run a test suite.

End matter

Experimenting with better export:

Add the codeblock name if available and some ugly symbols if not

(setq org-babel-exp-code-template
         (concat "\n=%name=:\n"
              org-babel-exp-code-template)
               )

Enable syntax highlighting

(require 'htmlize)
(setq org-src-fontify-natively t)