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.
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.
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
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/
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.
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
TODO: Explain.
rsync --archive --compress --delete ~/src/conforguration/conforg/ ${hostname}:conforg/
ssh ${hostname} "conforg/dotfiles/link-dotfiles.sh"
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 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
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.
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
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
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
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/
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"
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
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
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}"
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
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'
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'
orFile\ 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'
Make w
columns wider (very useful for hostnames).
export PROCPS_FROMLEN=40
export PROCPS_USERLEN=12
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
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 "$@" .
}
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
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/:.
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
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.
“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
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
https://github.com/git/git/blob/master/contrib/completion/git-completion.bash
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
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.
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:
- Pygments (see what it can handle with
pygmentize -L lexers
) - GNU source-highlight
- Poppler (for
pdftotext
)
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
set fill -8
set nonewlines
set nowrap
set softwrap
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.
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")
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"
---
:verbose: true
:benchmark: false
:bulk_threshold: 1000
:update_sources: true
:backtrace: false
gem: --no-document
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 “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
This is my personal sig.
--
William Denton
https://www.miskatonic.org/
Librarian, artist and licensed private investigator.
Toronto, Canada
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/
.headers on
.mode column
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
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.)
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
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
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.
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
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 |
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
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
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
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"
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.
3.3.4 |
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
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"
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"
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"
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
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.
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/
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"
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
install/install.sh
<<install-conforg-remotely>>
# ./emacs-install-requirements.sh
./emacs-install-personal.sh
<<ruby-rbenv-remotely>>
<<ruby-install-personal-remotely>>
Or log in to the machine itself and run the scripts there.
<<install-conforg-remotely>>
<<install-conforg-remotely>>
<<install-conforg-remotely>>
<<install-conforg-remotely>>