Skip to content

Latest commit

 

History

History
1852 lines (1350 loc) · 54.9 KB

conforguration.org

File metadata and controls

1852 lines (1350 loc) · 54.9 KB

Conforguration

If you’re looking at this on GitHub, the BEGIN and END source block wrappers are hidden, so you can’t see the parameters. Look at the raw version of the file, or clone the repository and load it into Emacs, to read it properly.

Tangle everything

Before anything else, make sure that everything has been tangled, so all the dot files and install scripts are up to date.

There are three ways to do it:

  • Hit the keystroke C-c C-v t;
  • Run M-x org-babel-tangle;
  • Or hit C-c C-c on the following code block:
(org-babel-tangle)

They all do the same thing.

Initialize

This only needs to be done once per machine, to create /usr/local/src/ and make it owned by oneself. This is where all source code will be downloaded and compiled.

sudo mkdir -p /usr/local/src/
sudo chown $USER:$USER /usr/local/src

Installing

Copy the dot files and scripts into place

Everything in the conforg directory needs to be copied to $HOME. The easiest way to do this is with rsync, which will create any directories necessary. To make sure no old cruft accumulates, delete anything in the target directory that shouldn’t be there.

rsync --archive --delete ~/src/conforguration/conforg/ ${HOME}/conforg/

Script to create symlinks for the dot files

Once all the dot files are in ~/conforg/dotfiles/, we need a script to set them up in the home directory. This is done by making symlinks.

First, to be safe, move into the directory where the script is run.

cd "$(dirname "$0")"
# echo "PWD is " $(pwd)

The dot files are in two directories: mine and imported. Go into each directory and make a symbolic link (specifying the full path) to file from ~/.file. In other words, ~/.bashrc is a symlink to the mine/bashrc here.

(To be absolutely safe, all the filenames should be in double quotes, but there are no spaces or strange characters in my filenames, so I’m going to leave that out.)

for dir in mine imported; do
    echo $dir
    cd $dir
    for file in *; do
	echo "  " $file
	rm -f ~/.${file}
	ln -s ~/conforg/dotfiles/${dir}/${file} ~/.${file}
    done
    cd ..
done

Finally, make sure that the .bash_profile is the real .profile, so no errant leftover .profile can get in the way.

rm ~/.profile
ln -s ~/.bash_profile ~/.profile

Once this is run you need to open up a new shell, or source ~/.bashrc, to see any changes.

Install

Add a line to the install script to call the above linking script. This install.sh script can be run when Conforguration is pulled down fresh from GitHub on a new machine, and will put everything in place. To update and refresh dot files and scripts locally within Emacs, you should use the localhost section below.

~/conforg/dotfiles/link-dotfiles.sh

Noweb for installing remotely

TODO: Explain.

rsync --archive --compress --delete ~/src/conforguration/conforg/ ${hostname}:conforg/
ssh ${hostname} "conforg/dotfiles/link-dotfiles.sh"

Dot files

Introduction

Almost all of my “dot files” (run command files, containing configuration instructions for different programs) are in this Org file. Most lines have a comment explaining what they are for, and when I’ve cribbed something from some web page or another’s dot file (which is frequent), I’ve credited it where possible.

There are two kinds of dot files: “mine” and “imported.” Most are “mine,” and are handled completely in this Org file. The “imported” ones are copied completely from elsewhere, usually some software distribution that has one particular file I need. Right now there are only three imported files: one is a script that does completion for Git in bash, one makes ls listings be in colour, and the third, which configures a LaTeX linter, really should be under “mine” but it’s so long I can’t be bothered right now.

The files that are “mine” are all tangled from this Org file. The “imported” ones are copied as is.

If you need some special environment variables on a machine, put them in .bash.$HOSTNAME.rc, as described at the bottom of .bashrc. That’s one way of setting up private environment variables that hold passwords or API tokens.

A note about languages specified in the source blocks: the language setting is required, but it doesn’t have to be a known and supported language. So in order for the .tmuxrc to be tangled, for example, I say it has the language “tmux,” which doesn’t exist but makes it work.

Abcde

Config (.abcde.conf)

Abcde is A Better CD Encoder. With one program I can digitize a CD all in one go, and with luck get some metadata from MusicBrainz. This configuration I lifted from Andrew’s Corner and left alone. All I want to do is turn the CD into FLAC files, and with this all I have to do is run abcde without any options. Then I use EasyTAG to clean up the metadata.

LOWDISK “conserves disk space by encoding tracks immediately after reading them” (I quote from the man page) which may not be too big a deal, but: “Note that this option may also help when reading a CD with errors. This is because on a scratchy disk reading is quite timing sensitive and this option reduces the background load on the system which allows the ripping program more precise control.” That’s useful.

LOWDISK=y

Where to retrieve track information.

CDDBMETHOD=musicbrainz

Make a local cache of CDDB entries and then volunteer to use these entries when and if they match the CD.

CDDBCOPYLOCAL="y"
CDDBLOCALDIR="$HOME/.cddb"
CDDBLOCALRECURSIVE="y"
CDDBUSELOCAL="y"

Specify the encoder to use for FLAC. In this case flac is the only choice.

FLACENCODERSYNTAX=flac

Specify the path to the selected encoder. It’s in my PATH so I don’t need to specify a full path.

FLAC=flac

Specify your required encoding options here. Multiple options can be selected as ‘–best –another-option’ etc. Overall bitrate is about 880 kbs/s with level 8.

# FLACOPTS='-s -e -V -8'
FLACOPTS='--silent --exhaustive-model-search --verify --compression-level-8'

Output type for FLAC.

OUTPUTTYPE="flac"

The CD ripping program to use. There are a few choices here: cdda2wav, dagrab, cddafs (Mac OS X only) and flac.

CDROMREADERSYNTAX=cdparanoia

Specify the location of the ripping program and pass any extra options.

CDPARANOIA=cdparanoia
CDPARANOIAOPTS="--never-skip=40"

Path to the CD identification program.

CDDISCID=cd-discid

The base location for the encoded music files.

OUTPUTDIR="$HOME/Music"

Default actions that abcde will take.

ACTIONS=cddb,playlist,read,encode,tag,move,clean

Decide here how you want the tracks labelled for a standard ‘single-artist’, multi-track encode and also for a multi-track, ‘various-artist’ encode:

OUTPUTFORMAT='${OUTPUT}/${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
VAOUTPUTFORMAT='${OUTPUT}/Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'

Decide here how you want the tracks labelled for a standard ‘single-artist’, single-track encode and also for a single-track ‘various-artist’ encode. (Create a single-track encode with ‘abcde -1’ from the command line.)

ONETRACKOUTPUTFORMAT='${OUTPUT}/${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
VAONETRACKOUTPUTFORMAT='${OUTPUT}/Various-${ALBUMFILE}/${ALBUMFILE}'

Create playlists for single and various-artist encodes.

PLAYLISTFORMAT='${OUTPUT}/${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}.m3u'
VAPLAYLISTFORMAT='${OUTPUT}/Various-${ALBUMFILE}/${ALBUMFILE}.m3u'

The man page says, “mungefilename() is an abcde shell function that can be overridden via abcde.conf. It takes CDDB data as $1 and outputs the resulting filename on stdout.” This one takes out dots preceding the album name, and removes other difficult characters.

mungefilename ()
{
  echo "$@" | sed -e 's/^\.*//' | tr -d ":><|*/\"'?[:cntrl:]"
}

Use two encoders simultaneously.

MAXPROCS=2

Number tracks as 01 and 02, not 1 and 2.

PADTRACKS=y

Make output more verbose. Most verbose is 2.

EXTRAVERBOSE=1

Add a comment? No.

COMMENT=""

Finally, eject the CD when done.

EJECTCD=y

Bash

My shell is Bash. I’ve looked at other ones, and some do fancy impressive things, but my shell needs are fairly simple.

I’ve forgotten the intricacies of when a .profile is used and how interactive and non-interactive shells handle things differently, but what I have works for me.

Profile (.bash_profile)

First, I set locale environment variables to say I want to use English, specifically Canadian English.

export LANG=en_CA.UTF-8
export LC_ALL=en_CA.UTF-8

If these locales aren’t available—perhaps because this is running on a new machine—then I need to run these to configure it. This is only necessary once.

sudo locale-gen en_CA.UTF-8
sudo update-locale LANG=en_CA.UTF-8

Then the .bashrc is processed.

source ~/.bashrc

There are some settings or commands (like calling ssh-add for a particular host) that I use on a particular machine, and this makes that possible. If the machine is named dartagnan, put commands in ~/.profile.dartagnan (similar to the .bashrc) for them just to be run in login shells there.

if [ -f ~/.profile."$HOSTNAME" ] ; then
    . ~/.profile.$HOSTNAME
fi

Config (.bashrc)

File permissions

Set the default “user file-created mask” to 0022, so that by default regular files are created 644 (-rw-r--r--) and executables 755 (-rwxr-xr-x)

umask 0022

Editing

My preferred editor is Emacs (of course) but I define these so that if someone pops up an editor it doesn’t use vi.

export EDITOR=nano
export VISUAL=nano

Web

The only thing I ever use that pays attention to WWW_HOME is lynx, I think, but DuckDuckGo is a good default first page to load if something is going to try.

export WWW_HOME=https://duckduckgo.com/

History

Don’t put duplicate lines or lines starting with space in the history.

HISTCONTROL=ignoreboth

The commands listed here will be ignored by history. If I run cd and then hit <up>, cd doesn’t reappear.

HISTIGNORE="cd:df:pwd:[bf]g:exit:history"

Set the number of commands to remember, and the file size of .bash_history.

HISTSIZE=10000
HISTFILESIZE=1000000

Append to the history file, don’t overwrite it.

shopt -s histappend

Append and reload the history after each command, so the full history is available in all shells simultaneously. But watch out! If I’m being active in different shells at the same time then I need to be careful about which command reappears with <up>.

PROMPT_COMMAND="history -a; history -n"

Terminals

Check the terminal window size after each command and, if necessary, update the values of LINES and COLUMNS.

shopt -s checkwinsize

Puts wtd@hostname (or whatever) in the title bar of the terminal window. For it to change when you login to another machine, it needs to be in your .bashrc there too. Very handy when using tabs.

if [ "$TERM" = 'xterm' ] || [ "$TERM" = 'rxvt' ] || [ "$TERM" = 'xterm-256color' ]
then
    export PROMPT_COMMAND='echo -ne "\033]2;"`whoami`@`hostname -s`"\007"'
fi

Solarized theme

Apply a Solarized theme to color ls listings. Taken from dircolors-solarized. I’m using dircolors.ansi-dark.

if command -v dircolors > /dev/null 2>&1
then
    eval "$(dircolors ~/.dircolors.ansi-dark)"
fi

Prompt

The Bash Profile Generator is very useful here. For colours, see also the colours section from this ancient Bash Prompt HOWTO.

First, set a bunch of colours, some of which I don’t use.

RED="\[\033[0;31m\]"
# LIGHT_RED="\[\033[1;31m\]"
# YELLOW="\[\033[1;33m\]"
GREEN="\[\033[0;32m\]"
# LIGHT_GREEN="\[\033[1;32m\]"
# CYAN="\[\033[0;36m\]"
# LIGHT_CYAN="\[\033[1;36m\]"
BLUE="\[\033[0;34m\]"
# LIGHT_BLUE="\[\033[1;34m\]"
PURPLE="\[\033[0;35m\]"
OCHRE="\e[38;2;204;119;34m\]" ## RGB (204, 119, 34), see https://stackoverflow.com/a/26665998

# WHITE='\e[0;37m'
# LIGHT_GRAY="\[\033[0;37m\]"
# GRAY="\[\033[1;30m\]"
# BLACK="\[\033[0;30m\]"

NO_COLOUR="\[\033[0m\]"

I use a blue prompt on my home machine(s), green on my hosted shell server, and red elsewhere.

case $HOSTNAME in
    marcus)
	PROMPT_COLOUR=$BLUE
	;;
    shell3)
	PROMPT_COLOUR=$GREEN
	;;
    ochre)
	PROMPT_COLOUR=$OCHRE
	;;
    *)
	PROMPT_COLOUR=$RED
esac

Root is purple.

if [[ ${EUID} == 0 ]] ; then
    PROMPT_COLOUR=$PURPLE
fi

Now I can define the actual prompt. Note that \$ is # if root, $ otherwise; it needs to be escaped.

First a prompt I don’t use, but it’s good to keep as a reference.

┌─[07:47 PM]─[wtd@marcus:~]
└─> $
export PS1="\342\224\214\342\224\200[\@]\342\224\200[\u@\h:\w]\n\342\224\224\342\224\200> \\$ "

Then the prompt I was using until I move this into Org.

┌─[marcus]─[~/src/conforguration/dotfiles]
└─> $

PS1="\342\224\214\342\224\200[\h]\342\224\200[\w]\n\342\224\224\342\224\200> \\$ "

I simplified it a bit and discovered I can use Unicode characters instead of those ugly escape characters!

┌─[marcus]─[~/src/conforguration/dotfiles]
└─$
PROMPT="┌─[\h]─[\w]\n└─\\$ "

Set the prompt to be the colour I want.

PS1="${PROMPT_COLOUR}${PROMPT}${NO_COLOUR}"

Glue the prompt to always go to the first column (source).

PS1="\[\033[G\]$PS1"

If I’m in a dumb terminal (when does that happen?) then use a very basic prompt.

if [[ "$TERM" == "dumb" ]] ; then
    PS1="$ "
fi

Do I ever see a secondary prompt? I’m not sure.

PS2="${PROMPT_COLOUR}\342\224\224> ${NO_COLOUR}"

Key remapping

I used to need to remap some keys on my Lenovo X240, but whatever the problem was, I figured it out some other way, so this isn’t needed.

if [ -f ~/.Xmodmap ]; then
    xmodmap ~/.Xmodmap
fi

Command aliases

Use colours when grepping.

export GREP_COLORS='mt=1;37;44'
alias grep='grep --color=auto'

Automatically page results from ag with less (see its options for how it works).

alias ag='\ag --pager=less'

Call up LibreOffice with just o file.

alias o='libreoffice'

Open up Alpine and go right to the inbox.

alias pi='alpine -i'

Be polite.

alias please='sudo'

In case rm -i is set system-wide.

alias rm="rm"

Always preserve timestamps when using scp.

alias scp="scp -p"

Get the weather with wttr.in.

alias ww="curl https://wttr.in/yyz"

Open any file in the default application with just x file.

alias x='xdg-open'

Don’t show snaps in df listings. They use a particular file system, which can be excluded.

alias df='df -x "squashfs"'

Set up fd (which on Ubuntu is used by another application) for fd the replacement for find.

alias fd='fdfind'

ls

Count in proper kilobytes.

export BLOCKSIZE=1024

Generally I’m on Linux machines, but if I’m on a FreeBSD box it has a different ls with different options, so I need to use a different alias to get colours.

On the Linux boxes:

  • classify: “append indicator (one of */=>@|) to entries” (to indicate directories, symlinks, etc.)
  • color: make the output in color (always)
  • quoting-style: show filenames as they are, so File One.txt, not 'File One.txt' or File\ One.txt. I’ll put things in quotes if needed.
if [[ $(uname) == "FreeBSD" ]] ; then
    alias ls='ls -F -G'
else # Presumably Linux
    alias ls='ls --classify --color --quoting-style=literal'
fi

Various short forms so I never have to actually type both letters of ls.

alias l='ls'
alias la='l --all'
alias ll='l -l'
alias lla='l -l --all'
alias lsort='l -l -S --reverse'

w

Make w columns wider (very useful for hostnames).

export PROCPS_FROMLEN=40
export PROCPS_USERLEN=12

More or less

I always want to use less, but I’m used to typing more.

alias more='less'
alias mroe='more'
export PAGER=less

There is no .lessrc, so settings go in the LESS environment variable. (Source.)

  • quit-if-one-screen: if it all fits on screen, just show it and quit
  • ignore-case: search are case-insensitive unless a capital letter is used
  • status-column: show matches or where paging happened
  • LONG_PROMPT: more verbose prompt
  • RAW-CONTROL-CHARS: pass through raw ANSI colour escape sequences so colourizing can work
  • HILITE-UNREAD: indicate first unread line after scrolling
  • tabs=4: show a tab as four spaces
  • no-init: don’t clear screen after exiting; quit-if-one-screen needs this to be set
  • window=-4: scroll by window size minus 4 lines, so there’s overlap when scrolling

Pass through raw ANSI colour escape sequences. In other words, make colourizing work.

export LESS='--quit-if-one-screen --ignore-case --status-column --LONG-PROMPT --RAW-CONTROL-CHARS --HILITE-UNREAD --tabs=4 --no-init --window=-4'

Lessfile lets less open up tarred and gzipped files and so on and show what’s inside. If it’s not installed, fall back to a script I wrote myself (see Lessfilter section below).

if command -v lessfile > /dev/null 2>&1; then
    eval "$(lessfile)"
    # This sets LESSOPEN and will pick up on ~/.lessfilter.
else
    # Fall back to do the best we can.
    export LESSOPEN="| ~/.lessfilter %s"
fi

If any syntax highlighters are available, use them. Pygmentize does more, but source-highlight is still good.

if command -v pygmentize > /dev/null 2>&1; then
    export LESSCOLOURIZER="pygmentize -f terminal"
elif command -v source-highlight > /dev/null 2>&1; then
    export LESSCOLOURIZER="source-highlight --failsafe --infer-lang -f esc --style-file=esc.style -i"
fi

Small functions and helpers

Pretty-print directory tree. I never use this, but it could be useful as a reference.

function tree() {
    find "${1:-.}" -type d -print | sed -e 's:[ ]*/:|____:g;s:____|: |:g'
}

Set an “alert” alias for long running commands. Use like this: sleep 10; alert.

alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

Swap file $1 with $2.

function swap() {
    local TMPFILE=tmp.$$
    mv "$1" $TMPFILE
    mv "$2" "$1"
    mv $TMPFILE "$2"
}

Handy way to watch a file grow

function monitor() {
    while true ; do
	clear
	tail "$1"
	sleep 10
    done
}

”| order” is very handy for counting duplicated lines in a file or listing.

function order() {
    sort | uniq -c | sort -rn
}

Wipe all metadata from one or more images.

function wipe_image() {
    for FILE in "$@"; do
	exiftool -all= "$FILE"
    done
}

Wipe all metadata from one or more PDFs.

function wipe_pdf() {
    for FILE in "$@"; do
	exiftool -all= "$FILE"
	qpdf --linearize --replace-input "$FILE"
    done
}

Sum a list of numbers.

function colsum {
    paste -s -d+ | bc --
}
$ (echo 1; echo 3; echo 5) | colsum
9

Copy files from somewhere to here, preserving all metadata (timestamp and such) as is.

function get {
    rsync --archive --progress --human-readable "$@" .
}

Completions

Git. Can be found as part of Git source.

source ~/.git-completion.bash

Bash. Requires bash-completion package.

if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    source /etc/bash_completion
fi

PATH

Here I build up the PATH bit by bit. Put /usr/local/bin first (ahead of whatever is inherited from the system setting).

PATH=/usr/local/bin:$PATH

Make sure the rootly paths are there.

PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin

Emacs is run from source in /usr/local/src/emacs.

PATH=/usr/local/src/emacs/src:$PATH
alias emacsclient="/usr/local/src/emacs/lib-src/emacsclient"
alias e="emacsclient --no-wait"

I run R from source in /usr/local/src/R.

if [ -f /usr/local/src/R/R ] ; then
    PATH=/usr/local/src/R:$PATH
fi

Zotero needs to be installed by hand.

alias zotero="/usr/local/src/zotero/Zotero_linux-x86_64/zotero"

I put ircii’s irc in ~/.irc/.

PATH=$PATH:~/.irc/

Ruby: I use rbenv to handle Ruby. If rbenv isn’t there, it will default to the system Ruby.

if [ -d ~/.rbenv/ ] ; then
    PATH=$HOME/.rbenv/bin:$PATH
    eval "$(rbenv init -)"
fi

Go (go help gopath).

export GOPATH=~/.gopath
PATH=$PATH:$GOPATH/bin/

Pip (from Python).

PATH=$PATH:~/.local/bin/

Rust.

PATH=$PATH:~/.cargo/bin/

My own scripts, and finally, the current directory.

PATH=$PATH:~/bin/:.

Local settings

There are some settings that I want just on a particular machine, and this makes that possible. If the machine is named dartagnan, put machine-specific environment variables and settings in ~/.bash.dartagnan.rc.

if [ -f ~/.bash."$HOSTNAME".rc ] ; then
    . ~/.bash.$HOSTNAME.rc
fi

Dircolors (dircolors.ansi-dark) (imported)

https://github.com/seebi/dircolors-solarized/blob/master/dircolors.ansi-dark

“Solarized Color Theme for GNU ls (as setup by GNU dircolors)”

https://github.com/seebi/dircolors-solarized

Raw source: dircolors.ansi-dark.

I added a line at the bottom to make directories lighter: DIR 00;38;5;33.

Imported copy: conforg/dotfiles/imported/dircolors.ansi-dark.

Logout (.bash_logout)

“When an interactive login shell exits, or a non-interactive login shell executes the exit builtin command, bash reads and executes commands from the file ~/.bash_logout, if it exists,” says the bash man page.

The only command I have here is one I pasted in from I don’t know where. It clears the console when I log out, for privacy. It’s been years since I logged in through a console to run X, but who knows.

SHLVL is “incremented by one each time an instance of bash is started,” so this runs if the shell being exited is not a sub-shell of another.

if [ "$SHLVL" = 1 ]; then
    [ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
fi

ShellCheck (.shellcheckrc)

There is one directive I want to ignore when ShellCheck runs on a script: “Double quote to prevent globbing and word splitting” (SC2086). That’s because syntax highlighting in Emacs treats $VAR as a variable and colours it nicely, but "$VAR" is handled differently and not coloured, so I leave variables unquoted as much as possible, but I have to be careful about whitespace.

disable=SC2086

Git

Completion (imported)

https://github.com/git/git/blob/master/contrib/completion/git-completion.bash

Config (.gitconfig)

TODO: Expand on what all this means. Find a better way to handle the editor for cases where I’m on a remote server without Emacs running.

[include]
	path = ~/.gitconfig.local
[color]
	ui = auto
	pager = true
[column]
	ui = auto
[core]
	editor = emacsclient
[user]
	name = William Denton
	email = william@williamdenton.org
[push]
	default = current
[init]
  defaultBranch = main
[alias]
	hist = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all

LaTeX

ChkTeX (.chktexrc) (imported)

ChkTex is linter for LaTeX. I think it complained about not having a configuration file when I first ran it, so I copied the default.

TODO: did i tweak anything? investigate. for now, since it’s so long and complicated, just leave it here.

Raw source: chktexrc.

Imported copy: conforg/dotfiles/imported/chktexrc.

Less

Lessfilter (.lessfilter)

See More or less above for where this fits in to the less configuration. This short script enables pre-processing of files before less displays them, which allows syntax highlighting and even extracting text from PDFs. It’s pretty amazing when you can run less foo.pdf and see what’s in the PDF as plain text.

There are some requirements for this to work:

To install them on Ubuntu, run this:

sudo apt install python-pygments source-highlight poppler-utils

LESSCOLOURIZER is defined in .bashrc. It will be either pygmentize (preferred) or source-highlight (fallback, if it’s installed). Whichever is available, use it for everything except PDFs, where we use pdftotext.

This case statement defines which program handles which file types. Pygmentize can handle many more than are here; this is just the ones I want. My .bashrc doesn’t get processed correctly, maybe because of escape sequences, so I left it out.

if [ -v LESSCOLOURIZER ]; then
    case "$1" in
	.bash_|*.bat|*.bib|*.c|Changelog|*.diff|Gemfile|*.gemspec|*.h|*.html|*.ini|*.js|*.json|*.jsonld|\
	    Makefile|*.md|*.patch|*.php|*.pl|*.pm|*.py|Rakefile|*.rake|*.rb|*.R|*.Rprofile|*.rss|*.sh|*.sql|*.xsl|*.tex|*.toc|*.yaml|*.yml)
	    $LESSCOLOURIZER "$1" ;;
	*.pdf)
	    if command -v pdftotext > /dev/null 2>&1 ; then pdftotext -layout "$1" -
	    else echo "No pdftotext available; try installing poppler-utils"; fi ;;
	*)
	    # Pass through to lessfile
	    exit 1
    esac;
fi

Finally, if LESSCOLOURIZER is not set, hand off to lessfile.

exit 1

Nano

Config (.nanorc)

set fill -8
set nonewlines
set nowrap
set softwrap

R

R’s web site says it “is a free software environment for statistical computing and graphics,” which doesn’t adequately describe how awesome it is. I mainly use R through Emacs, but there are some settings that apply just to how R works that I want defined however R is run.

Rprofile (.Rprofile)

See also Expert R users, what’s in your .Rprofile? from Stack Overflow.

First, hard code a nearby (to me) repo for CRAN packages.

TODO: The mirror is also used in Setup: R … maybe I could put it into a bash environment variable in one place and get all the mentions from there?

r <- getOption("repos")
r["CRAN"] <- c("https://mirror.csclub.uwaterloo.ca/CRAN/")
options(repos = r)
rm(r)

I don’t need to keep histories of everything. I used to log everything to history files but never looked at them and discovered after a while that the directory was filled with 0-byte files. I’ll leave in the command to do that in case it’s useful again one day.

Sys.setenv(R_HISTSIZE = '0')
## sink(file = paste('~/R/history/r-log-', strftime(Sys.time(), '%F %H:%M:%OS9'), sep = ''), split=T)

Should R automatically convert strings to factor variables in a data.frame? No! This is the default in 4.0 and up, but I’ll leave it in for now.

options(stringsAsFactors = FALSE)

Override q() to not save by default. Same as saying q("no").

q <- function (save="no", ...) {
    quit(save=save, ...)
}

No menu popups: use the console.

options(menu.graphics = FALSE)

Tab completion on library() and require().

utils::rc.settings(ipck = TRUE)

Set the prompt? I used to use a fancy “ℝ”, but now just the default simple “>”. But I’ll leave this here in case I want to go back.

## options(prompt="ℝ> ")

Specify the precise location of lintr configuration file. It should look in my home directory by default, but it wasn’t.

options(lintr.linter_file="~/.lintr")

lintr (.lintr)

In my world tabs are four spaces, so I need to specify this for lintr, which thinks they should be two (!?).

linters: linters_with_defaults(
    indentation_linter = indentation_linter(4L)
)
encoding: "UTF-8"

Ruby

Gems (.gemrc)

---
:verbose: true
:benchmark: false
:bulk_threshold: 1000
:update_sources: true
:backtrace: false
gem: --no-document

Pry (.pryrc)

Pry “is a powerful alternative to the standard IRB shell for Ruby. It features syntax highlighting, a flexible plugin architecture, runtime invocation and source and documentation browsing.” See also the pryrc documentation.

The only setting here is to hook in awesome_print so that by default everything is nicely pretty-printed.

require "awesome_print"
AwesomePrint.pry!

Rubocop (.rubocop.yml)

Rubocop “is a Ruby static code analyzer (a.k.a. linter) and code formatter.”

I prefer using “double quotes” when quoting. Everything else I leave as is. When needed I can turn off a warning in the code itself.

Style/StringLiterals:
  EnforcedStyle: double_quotes
  SupportedStyles:
    - single_quotes
    - double_quotes

AllCops:
  NewCops: enable

Signature

Personal (.signature)

This is my personal sig.

--
William Denton
https://www.miskatonic.org/
Librarian, artist and licensed private investigator.
Toronto, Canada

Work (.signature.work)

This is the sig I use at work.

William Denton <wdenton@yorku.ca> (he/him)
Associate Librarian: Scholarly Analytics / Mathematics & Statistics
York University (Toronto, Canada) https://www.library.yorku.ca/

SQLite

Config (.sqliterc)

.headers on
.mode column

Tmux

Config (.tmux.conf)

Start window numbering at 1.

set -g base-index 1

Status bar formatting.

set -g status-left-length 20
set -g status-left ""
set -g status-right "[Session: #S]"
set -g status-justify centre

Colours, taken from tmux-colors-solarized. First, set the terminal type.

set -g default-terminal "screen-256color"

Default statusbar colors.

set-option -g status-bg black
set-option -g status-fg yellow

Pane number display.

set-option -g display-panes-active-colour blue
set-option -g display-panes-colour brightred

Clock.

set-window-option -g clock-mode-colour green

Bell.

set-window-option -g window-status-bell-style fg=black,bg=red

X

XCompose (.XCompose)

This allows the Compose key (for me Left-Ctrl, because I use CapLock as the Control key) to be used in Emacs.

include "%L"

(See also this xcompose project at GitHub that has a massive .XCompose file with and an enormous set of key combinations. More than I need right now, but maybe one day.)

Xmodmap (.xmodmaprc)

Do I actually need this? I’m not loading it in. Is it being caught automatically?

TODO: Try disabling it and see what happens.

keysym Home = Insert
keysym End = Insert

Emacs

Requirements

You can’t build anything from source without making sure all the necessary utilities and libraries are there first. Once done, this will never need to be run again. (Unless the version of GCC changes, in which case a new libgccjit-xx-dev will be needed. Check the current version with gcc --version.) These requirements go beyond the bare minimum in order to make native compilation work (on Ubuntu 22.04).

sudo apt-get build-dep emacs
sudo apt-get install libjansson-dev valgrind fonts-firacode libgccjit0 libgccjit-11-dev libgtk-3-dev
## On Linux Mint, at least, these are not installed when the above is done.  Curious.
## On other systems, it can't hurt.
sudo apt-get install texinfo libxpm-dev libjpeg-dev libgif-dev libtiff-dev libtinfo-dev libtree-sitter-dev

Install for personal use

First get the source for Emacs and compile it.

cd /usr/local/src/
git clone https://git.savannah.gnu.org/git/emacs.git
cd emacs
./autogen.sh
./configure --with-pgtk --with-tree-sitter && make -j

Then do the same for Org.

cd /usr/local/src/
git clone https://git.savannah.gnu.org/git/emacs/org-mode.git
cd org-mode
make -j

Finally, get my Emacs configuration (which is not here in Conforguration). It will be cloned into ~/.emacs.d/. (Requires a GitHub account when done this way.)

cd
git clone git@github.com:wdenton/.emacs.d.git
# Or if you don't want to use a GitHub account:
# git clone https://github.com/wdenton/.emacs.d.git
echo "Now run emacs, and say no when asked about a location for abbrev_defs."

Running emacs the first time will download and install all the packages needed, but some setting about abbrevs is misordered so it will ask a question it doesn’t need to ask. Saying no makes everything work.

It’s probably best to quit Emacs and restart after this, but you don’t actually need to.

Update

This is a simple script that pulls down the updated source for Emacs and Org and compiles them. If something goes wrong with the Emacs compile you might need to do make clean or make distclean or make extraclean and then try again.

If there are compilation problems then running make maintainer-clean in the Emacs source directory will probably fix it by resetting everything. I find I need to do this every few months.

cd /usr/local/src/emacs/
git pull
./configure --with-pgtk --with-tree-sitter && make -j && cd ../org-mode/ && make -j update

R

For running a personal version of R, PATH needs to include /usr/local/src/R, but my bashrc will set that up if it’s there.

Change the version number as needed, then tangle and run the install script again.

4.4.1

Requirements

The first line of requirements may be needed for R 3.3. The topicmodels package requires the GNU Scientific Library. Once done, this doesn’t need to be run again. Sync and run the script on machines as necessary.

sudo apt install libbz2-dev liblzma-dev libxml2-dev libpcre2-dev libpcre3-dev fonts-inconsolata
sudo apt install xorg-dev gfortran libreadline-dev libcurl4-openssl-dev libssl-dev libgsl-dev curl libcurl4-openssl-dev libudunits2-dev libgdal-dev
sudo apt build-dep r-base
mkdir -p ~/R/history/
mkdir -p ~/.R/lintr_cache/
mkdir -p /usr/local/src/R

Noweb setup

Whether R is being installed system-wide or just for personal use, this code will be run.

cd $(dirname "$0")
SCRIPTS_DIR=$(pwd)
MIRROR="https://mirror.csclub.uwaterloo.ca/CRAN/"
cd /usr/local/src/R

If the source has been untarred already, wipe that directory because we want to start fresh.

if [ -d "/usr/local/src/R/R-${R_VERSION}" ]; then
  echo "Removing old source directory ..."
  rm -r R-${R_VERSION}
fi

If the source tarball is there, use it, otherwise download. The R_MAJOR variable is there because we need to know the major version number, so we can get to e.g. base/R-4 to download 4.0.4.

if ! [ -f "R-${R_VERSION}.tar.gz" ]; then
  echo "Downloading R-${R_VERSION} tarball ..."
  R_MAJOR=${R_VERSION:0:1}
  curl -O $MIRROR/src/base/R-${R_MAJOR}/R-${R_VERSION}.tar.gz
else
  echo "Using existing R-${R_VERSION} tarball ..."
fi

Now uncompress, configure and compile. This could take a while.

echo "Uncompressing ..."
tar xzvf R-$R_VERSION.tar.gz

echo "Compiling ..."
cd R-$R_VERSION
./configure --enable-R-shlib
make && make check

Install for personal use

Here we set up symlinks to point to the R and Rscript executables, then source .bashrc to refresh $PATH to notice them and put that Rscript first, which makes the package installation work.

First, get R downloaded and compiled.

<<r_source_code_present_and_compiled>>

Next, set up the aliases for it in /usr/local/src/R/. To be sure they work, reload bash to pick up on the PATH.

cd /usr/local/src/R/
rm -f R Rscript
ln -s R-${R_VERSION}/bin/R R
ln -s R-${R_VERSION}/bin/Rscript Rscript

source ~/.bashrc

Finally, install the packages.

cd $SCRIPTS_DIR
./r-install-packages.sh

Install system-wide

R packages need to be installed in a full root login. There’s probably a way to do this with sudo -i, but I can’t figure it out, so I do it this convoluted way. It works, but if there’s a better way, please let me know. Here we become root, then get back to the directory where the package installation script is so we can run it.

<<r_source_code_present_and_compiled>>
sudo make install

sudo su - -c "cd $SCRIPTS_DIR; ./r-install-packages.sh"

Packages

There are quite a few R packages I want installed by default, including of course the Tidyverse, which I greatly admire. The packages are all in this next table. Add to (and resort) as needed.

RCurl
RSQLite
arules
arulesViz
cluster
dbplyr
devtools
docopt
flexdashboard
fpc
fs
geonames
geosphere
GGally
ggrepel
ggridges
ggvis
gmp
gtools
hms
igraph
knitr
lintr
lubridate
mapproj
maps
maptools
MESS
openxlsx
osmdata
primes
readODS
readxl
remotes
rgeos
roxygen2
seriation
sf
shiny
skimr
testthat
tidyverse
tm
topicmodels
usethis
xlsx

Now we need to transform that list into some shell commands. First, we’re going to turn the list into a shell variable, package_list, with a neat array join tip I saw on Stack Overflow. This code block sets up the variable in another code block. (Make sure the name packages-list-variable is set or the noweb tangling won’t work.)

echo -n 'package_list="'
IFS=" " ; echo -n "${pkgs[*]}"
echo -n '"'

And the above code block is included in the one below with noweb.

<<packages-list-variable>>
for pkg in $package_list
do
    Rscript --vanilla -e "install.packages('$pkg', repos=c('https://mirror.csclub.uwaterloo.ca/CRAN/'))"
done
Rscript --vanilla -e "devtools::install_github('yorkulibraries/yulr')"

When tangled, the script will have the full package_list definition with all the packages, and it loops through them all, installing one by one (with dependencies, where required). There are a lot of packages, so this will take a while.

Ruby

3.3.4

Requirements

Make sure some necessities are in place before trying to build from source.

sudo apt-get build-dep ruby
sudo apt-get install libreadline-dev libsqlite3-dev libyaml-dev libssl-dev libxslt1-dev

Install (or upgrade) rbenv

This script installs rbenv if it isn’t already in place; if it is, it updates it. It checks to see if ~/.rbenv/ exists; if it does, rbenv is installed, so it just tries to update it; if not, it installs it.

if [[ -d ~/.rbenv ]]; then
    echo "Upgrade if possible"
    cd ~/.rbenv/
    git pull
    cd plugins/ruby-build
    git pull
else
    echo "Installing"
    git clone https://github.com/rbenv/rbenv.git ~/.rbenv
    git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
    source ~/.bashrc
fi

This can be called with noweb by source blocks below to install rbenv on a remote machine.

ssh ${hostname} "conforg/scripts/ruby-rbenv.sh"

Install with rbenv for personal use

rbenv install --verbose $RUBY_VERSION
rbenv global $RUBY_VERSION
~/conforg/scripts/ruby-install-gems.sh
echo "Now run bundle install where needed (and perhaps bundle update --bundler)."
ssh ${hostname} "conforg/scripts/ruby-install-personal.sh"

Install system-wide

mkdir -p /usr/local/src/ruby
cd /usr/local/src/ruby

# The 3.0.2.tar.gz tarball is in the 3.0/ directory, for example.
MINOR_VERSION=$(echo ${RUBY_VERSION} | sed 's/\.[[:digit:]]$//')

curl --location --remote-name https://cache.ruby-lang.org/pub/ruby/${MINOR_VERSION}/ruby-${RUBY_VERSION}.tar.gz
tar xzvf ruby-${RUBY_VERSION}.tar.gz
cd ruby-${RUBY_VERSION}

./configure
make

sudo make install
sudo ~/conforg/scripts/ruby-install-gems.sh

echo "Now run bundle install where needed (and perhaps bundle update --bundler)."
ssh ${hostname} "conforg/scripts/ruby-install-system.sh"

Install gems

This works like the R packages do. First, a list of gems I want installed by default.

awesome_print
bundler
docopt
http
marc
nokogiri
pry
pry-doc
rubocop
rubyul
sqlite3

Now transform that list into some shell commands into a shell variable, GEM_LIST. This code block generates the next one.

echo -n 'GEM_LIST="'
IFS=" " ; echo -n "${gems[*]}"
echo -n '"'

And the above code block is included in the one below with noweb.

<<gem-list-variable>>
for gem in $GEM_LIST
do
    gem install $gem
done

Tor

0.4.8.13

I run two Tor relays (not exit points). These scripts let me update and run them—see my post How I set up a Tor bridge for more. The necessary torrc is not covered here; it requires special care to configure.

Requirements

Make sure some necessities are in place before trying to build from source.

sudo apt install build-essential
sudo apt install libevent-dev libssl-dev libcap-dev liblzma-dev libzstd-dev libseccomp-dev libscrypt-dev zlib1g zlib1g-dev
sudo apt install speedometer tmux vnstat
mkdir -p /usr/local/src/tor/

Install

cd /usr/local/src/tor/
curl --location --remote-name https://dist.torproject.org/tor-${TOR_VERSION}.tar.gz
tar --extract --verbose --gunzip --file tor-${TOR_VERSION}.tar.gz
cd tor-${TOR_VERSION}
./configure && make && sudo make install
echo "Now run ~/conforg/scripts/tor-run.sh"
ssh ${hostname} "conforg/scripts/tor-install-system.sh"

Script to run and monitor Tor

This runs Tor in a Tmux session with a window where the speedometer program is showing how much bandwidth is in use. Logging in and running tmux attach -t tor shows what’s going on, then C-b d detaches but leaves everything running.

First, if one of these is already running, kill it and everything inside. We need to wait at least thirty seconds for Tor to shut down nicely.

if tmux has-session -t tor
 then
     echo "Session tor exists; killing it nicely ..."
     tmux send-keys -t tor:1 "C-c"
     tmux send-keys -t tor:2 "C-c"
     tmux send-keys -t tor:3 "C-c"
     tmux send-keys -t tor:4 "C-c"
     sleep 35
     tmux kill-window -t tor:1
     tmux kill-window -t tor:2
     tmux kill-window -t tor:3
     tmux kill-window -t tor:4
 fi

Now start a new session with four windows in it: Tor; bandwidth notices in the log file; the speedometer visualization; and a shell for vnstat for traffic reports. Being able to script Tmux like this makes it very powerful.

By default, speedometer will show traffic on the wlan0 interface. To use another one, set the TOR_IFACE environment variable in ~/.bash.${HOSTNAME}.rc, like so: export TOR_IFACE=ens160.

echo "Starting tor session ..."

tmux new-session -d -s "tor"

if [[ -z $TOR_IFACE ]]; then
   TOR_IFACE=wlan0
fi

tmux new-window -t tor:2
tmux new-window -t tor:3
tmux new-window -t tor:4

tmux send-keys -t tor:3 "speedometer -t ${TOR_IFACE} -r ${TOR_IFACE} -l -m 1048576" "C-m"

tmux select-window -t 1
tmux send-keys -t tor:1 "tor" "C-m"

tmux send-keys -t tor:2 "tail -f /usr/local/src/tor/log/notices.log" "C-m"

tmux send-keys -t tor:4 "vnstat -d --iface ${TOR_IFACE}" "C-m"

Put this in the crontab to bring up Tor automatically when the machine reboots:

@reboot ~/conforg/scripts/tor-run.sh

If you defined TOR_IFACE specially, do this:

@reboot source ~/.bash.${HOSTNAME}.rc; ~/conforg/scripts/tor-run.sh

Machines

localhost

install/install.sh

music

<<install-conforg-remotely>>

Install Emacs remotely one way

# ./emacs-install-requirements.sh
./emacs-install-personal.sh

Install Ruby remotely the other way

<<ruby-rbenv-remotely>>
<<ruby-install-personal-remotely>>

Or log in to the machine itself and run the scripts there.

tor

<<install-conforg-remotely>>

pair

<<install-conforg-remotely>>

shell4

<<install-conforg-remotely>>

orez

<<install-conforg-remotely>>