--- a/bash_profile Tue Feb 04 09:23:46 2020 -0500
+++ b/bash_profile Tue Feb 04 09:24:12 2020 -0500
@@ -23,7 +23,7 @@
ORANGE=$'\e[33m'
BLUE=$'\e[34m'
PINK=$'\e[35m'
-CYAN=$'\e[36m'
+# CYAN=$'\e[36m'
function last_return_value() {
x="$?"
@@ -67,8 +67,37 @@
}
fi
-export PATH=~/bin:~/src/dotfiles/bin:~/src/dotfiles/lisp/bin:/usr/local/bin/:$PATH
-export PAGER=less
+function prepend_to_path {
+ if test -d "$1"; then
+ PATH="$1":"$PATH"
+ fi
+}
+
+PATH="/sbin"
+prepend_to_path "/bin"
+prepend_to_path "/usr/bin"
+prepend_to_path "/usr/sbin"
+prepend_to_path "/usr/local/bin"
+prepend_to_path "/usr/local/sbin"
+prepend_to_path "/usr/local/go/bin"
+prepend_to_path "/usr/games"
+prepend_to_path "/snap/bin"
+prepend_to_path "$HOME/.local/bin"
+prepend_to_path "$HOME/.go/bin"
+prepend_to_path "$HOME/src/dotfiles/lisp/bin"
+prepend_to_path "$HOME/src/dotfiles/bin"
+prepend_to_path "$HOME/src/hg"
+prepend_to_path "$HOME/bin"
+export PATH
+
+export LESS_TERMCAP_mb=$(printf '\e[01;31m') # begin blinking
+export LESS_TERMCAP_md=$(printf '\e[01;38;5;74m') # begin bold
+export LESS_TERMCAP_me=$(printf '\e[0m') # end mode
+export LESS_TERMCAP_se=$(printf '\e[0m') # end standout-mode
+export LESS_TERMCAP_so=$(printf '\e[38;5;246m') # begin standout-mode - info box
+export LESS_TERMCAP_ue=$(printf '\e[0m') # end underline
+export LESS_TERMCAP_us=$(printf '\e[04;38;5;146m') # begin underline
+export PAGER='less -iX'
function psg() {
ps auxww | grep --color=always "$@" | grep -v grep | collapse | cuts -f 2,11-
--- a/bin/backup-backblaze Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/backup-backblaze Tue Feb 04 09:24:12 2020 -0500
@@ -2,6 +2,9 @@
set -euo pipefail
+
+ban "Backblaze"
+
source /home/sjl/.restic-backblaze-creds
restic --repo b2:backups-ouroboros:restic-repo \
--- a/bin/backup-local Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/backup-local Tue Feb 04 09:24:12 2020 -0500
@@ -2,6 +2,8 @@
set -euo pipefail
+ban -F metal "NAS"
+
restic --repo /mnt/cryo/restic-ouroboros/repo \
--exclude-file=/home/sjl/src/dotfiles/restic/excludes.txt \
--password-file /home/sjl/.restic-password-local \
--- a/bin/bootstrap.sh Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/bootstrap.sh Tue Feb 04 09:24:12 2020 -0500
@@ -39,6 +39,7 @@
ensure_link "src/dotfiles/fish/functions" ".config/fish/functions"
ensure_link "src/dotfiles/gitconfig" ".gitconfig"
ensure_link "src/dotfiles/gitignore" ".gitignore"
+ensure_link "src/dotfiles/gnuplot" ".gnuplot"
ensure_link "src/dotfiles/hgignore" ".hgignore"
ensure_link "src/dotfiles/lisprc" ".lisprc"
ensure_link "src/dotfiles/lispwords" ".lispwords"
--- a/bin/disks Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/disks Tue Feb 04 09:24:12 2020 -0500
@@ -2,7 +2,15 @@
set -euo pipefail
-lsblk -o name,mountpoint,model,label,size,fstype | egrep -v "^loop"
+lsblk -o name,mountpoint,model,label,size,fstype | grep -Pv "^loop" | awk '
+NR>1 && /^[a-zA-Z]/ { print "-----------------------------------------------------------------------------------------------------------------------" }
+ { print $0 }
+'
echo
echo
-df -h | egrep -v '^/dev/loop' | egrep -v tmpfs
+echo
+
+OUT=$(df -h)
+echo "$OUT" | head -1
+echo "$OUT" | head -1 | sed 's/./-/g'
+echo "$OUT" | tail +2 | grep -Pv '^/dev/loop' | grep -Pv tmpfs | sort -k6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/e Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+"$EDITOR" "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/external-ip Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+dig @resolver1.opendns.com ANY myip.opendns.com +short
+
--- a/bin/mangle-signature Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/mangle-signature Tue Feb 04 09:24:12 2020 -0500
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
-cat
+sed -Ee 's/^-- $/-- /'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/nnl Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+tr -d '\n'
--- a/bin/pastebin Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/pastebin Tue Feb 04 09:24:12 2020 -0500
@@ -2,11 +2,8 @@
set -euo pipefail
-PASTE_SHA=$(ssh paste.stevelosh.com 'cat > tmppaste && sha1sum tmppaste | cut -d" " -f1 && mv tmppaste /var/www/paste/`sha1sum tmppaste | cut -d" " -f1`')
+PASTE_SHA=$(ssh paste.stevelosh.com -- 'cat > tmppaste && sha1sum tmppaste | cut -d" " -f1 && mv tmppaste /var/www/paste/`sha1sum tmppaste | cut -d" " -f1`')
+URL="https://paste.stevelosh.com/$PASTE_SHA"
-echo -n "https://paste.stevelosh.com/$PASTE_SHA" | pbcopy
-echo -n 'Copied '
-tput bold
-pbpaste
-tput sgr0
-echo ' to the clipboard.'
+echo -n "$URL" | pbcopy
+echo "Copied $URL to the clipboard."
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/pbc Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,1 @@
+pbcopy
\ No newline at end of file
--- a/bin/pbcopy Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/pbcopy Tue Feb 04 09:24:12 2020 -0500
@@ -1,3 +1,5 @@
#!/usr/bin/env bash
-xclip -selection clipboard -i
+set -euo pipefail
+
+xsel --clipboard --input
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/pbp Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,1 @@
+pbpaste
\ No newline at end of file
--- a/bin/pbpaste Tue Feb 04 09:23:46 2020 -0500
+++ b/bin/pbpaste Tue Feb 04 09:24:12 2020 -0500
@@ -1,3 +1,5 @@
#!/usr/bin/env bash
-xclip -selection clipboard -o
+set -euo pipefail
+
+xsel --clipboard --output
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/u Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+du -hd1 "$@"
--- a/fish/config.fish Tue Feb 04 09:23:46 2020 -0500
+++ b/fish/config.fish Tue Feb 04 09:24:12 2020 -0500
@@ -13,6 +13,7 @@
function essh; nvim ~/.ssh/config; end
function js; cd ~/scratch; end
+function jd; cd /dump; end
function histgrep; history | grep "$argv" | tac; end
@@ -85,6 +86,7 @@
end
end
end
+
set -gx PATH "/sbin"
prepend_to_path "/snap/bin"
prepend_to_path "/usr/sbin"
@@ -107,7 +109,7 @@
set -g -x EDITOR nvim
set -g -x COMMAND_MODE unix2003
set -g -x RUBYOPT rubygems
-set -g -x PAGER 'less -X'
+set -g -x PAGER 'less -iX'
# set -g -x _JAVA_OPTIONS "-Djava.awt.headless=true"
set -g -x GPG_TTY (tty)
@@ -143,32 +145,47 @@
# }}}
# Prompt {{{
-set normal (set_color normal)
-set magenta (set_color magenta)
-set yellow (set_color yellow)
-set green (set_color green)
-set cyan (set_color cyan)
-set gray (set_color -o black)
+if status --is-interactive
+ set normal (set_color normal)
+ set magenta (set_color magenta)
+ set yellow (set_color yellow)
+ set green (set_color green)
+ set cyan (set_color cyan)
+ set gray (set_color -o black)
-set hg_promptstring "\
+ set hg_promptstring "\
< on $magenta<branch>$normal>\
< at $cyan<bookmark>$normal>\
$green<status|modified|unknown><update>$normal\
" 2>/dev/null
+ if test -n "$SSH_CLIENT"
+ or test -n "$SSH_TTY"
+ set host_color (set_color cyan)
+ set want_vcs_prompts 0
+ else
+ set host_color (set_color yellow)
+ set want_vcs_prompts 1
+ end
+end
+
function hg_prompt
- hg prompt --angle-brackets $hg_promptstring 2>/dev/null
+ if test -z "$NOVCSPROMPT"
+ hg prompt --angle-brackets $hg_promptstring 2>/dev/null
+ end
end
function git_prompt
- if git root >/dev/null 2>&1
- set_color normal
- printf ' on '
- set_color magenta
- printf '%s' (git current-branch ^/dev/null)
- set_color green
- git_prompt_status
- set_color normal
+ if test -z "$NOVCSPROMPT"
+ if git root >/dev/null 2>&1
+ set_color normal
+ printf ' on '
+ set_color magenta
+ printf '%s' (git current-branch ^/dev/null)
+ set_color green
+ git_prompt_status
+ set_color normal
+ end
end
end
@@ -176,14 +193,6 @@
echo $PWD | sed -e "s|^$HOME|~|"
end
-if test -n "$SSH_CLIENT"
- or test -n "$SSH_TTY"
- set host_color (set_color cyan)
- set want_vcs_prompts 0
-else
- set host_color (set_color yellow)
- set want_vcs_prompts 1
-end
function fish_prompt
set last_status $status
--- a/fish/functions/pbc.fish Tue Feb 04 09:23:46 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function pbc -d "pbcopy"
- xsel --clipboard --input
-end
--- a/fish/functions/pbp.fish Tue Feb 04 09:23:46 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function pbp -d "pbpaste"
- xsel --clipboard
-end
--- a/fish/functions/pbpb.fish Tue Feb 04 09:23:46 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function pbpb -d "pbpaste to pastebin site"
- pbp | pb
-end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gnuplot Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,51 @@
+# Basic Settings ---------------------------------------------------------- {{{
+
+set encoding utf8
+set terminal qt noraise
+set samples 1000
+
+# }}}
+# Constants --------------------------------------------------------------- {{{
+
+tau = 2 * pi
+e = 2.71828182845905
+r2 = sqrt(2.0)
+
+# }}}
+# Utility Functions ------------------------------------------------------- {{{
+
+min(a, b) = (a<b) ? a : b
+max(a, b) = (a>b) ? a : b
+
+# }}}
+# Exporting --------------------------------------------------------------- {{{
+
+export(file, terminal) = sprintf( \
+ "set terminal push;" . \
+ "set terminal %s;" . \
+ "set output '%s';" . \
+ "replot;" . \
+ "set output;" . \
+ "set terminal pop;" . \
+ "print system('realpath %s | nnl | pbcopy');" \
+ , terminal, file, file)
+
+export_pdf(file) = export(file . '.pdf', "pdfcairo")
+export_png(file) = export(file . '.png', "pngcairo")
+
+pdf = "eval export_pdf('graph')"
+png = "eval export_png('graph')"
+
+# }}}
+# Other ------------------------------------------------------------------- {{{
+
+kdens(file, column, bandwidth) = sprintf( \
+ "stats '%s' using %d;" . \
+ "plot '%s' using %d:(1.0/STATS_records) smooth kdensity bandwidth %f;" \
+ , file, column, file, column, bandwidth)
+
+cdf(file, column) = sprintf( \
+ "plot '%s' using %d:(1.0) smooth cnormal;" \
+ , file, column)
+
+# }}}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/lines.lisp Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,477 @@
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (ql:quickload '(:adopt :cl-ppcre :with-user-abort) :silent t))
+
+(defpackage :lines
+ (:use :cl)
+ (:export :toplevel :*ui*))
+
+(in-package :lines)
+
+;; TODO: Optimize by eliminating collection when all matchers are in order.
+
+;;;; Configuration ------------------------------------------------------------
+(defparameter *version* "1.0.0")
+(defparameter *index-base* 0)
+(defparameter *include-numbers* nil)
+(defparameter *limit* nil)
+
+
+;;;; Functionality ------------------------------------------------------------
+(defclass matcher ()
+ ((designator :type string :initarg :designator :accessor designator)))
+
+(defmethod print-object ((o matcher) stream)
+ (print-unreadable-object (o stream :type t)
+ (format stream "~S" (designator o))))
+
+(defgeneric matches-line-p (matcher line-number))
+(defgeneric map-matching-lines (matcher function min max))
+(defgeneric maximum (matcher))
+
+
+(defclass single-line-matcher (matcher)
+ ((n :type (integer 0) :initarg :n :accessor n)))
+
+(defmethod matches-line-p ((matcher single-line-matcher) i)
+ (= (n matcher) i))
+
+(defmethod map-matching-lines ((matcher single-line-matcher) function min max)
+ (when (<= min (n matcher) max)
+ (funcall function (n matcher))))
+
+(defmethod maximum ((matcher single-line-matcher))
+ (n matcher))
+
+
+(defclass range-matcher (matcher)
+ ((m :type (or null (integer 0)) :initarg :m :accessor m)
+ (n :type (or null (integer 0)) :initarg :n :accessor n)))
+
+(defmethod matches-line-p ((matcher range-matcher) i)
+ (let ((m (m matcher))
+ (n (n matcher)))
+ (cond ((null m) (if (null n)
+ t
+ (<= i n)))
+ ((null n) (<= m i))
+ (t (<= m i n)))))
+
+(defmethod map-matching-lines ((matcher range-matcher) function min max)
+ (loop :with m = (or (m matcher) min)
+ :with n = (or (n matcher) max)
+ :for i :from (max m min) :to (min n max)
+ :do (funcall function i)))
+
+(defmethod maximum ((matcher range-matcher))
+ (n matcher))
+
+
+(defclass modulo-matcher (matcher)
+ ((n :type (integer 0) :initarg :n :accessor n)
+ (modulus :type (integer 1) :initarg :modulus :accessor modulus)))
+
+(defmethod matches-line-p ((matcher modulo-matcher) i)
+ (= (mod i (modulus matcher))
+ (n matcher)))
+
+(defmethod map-matching-lines ((matcher modulo-matcher) function min max)
+ (loop
+ :with n = (n matcher)
+ :with modulus = (modulus matcher)
+ :with start = (if (< n min)
+ (+ n modulus)
+ n)
+ :for i :from start :to max :by modulus
+ :do (funcall function i)))
+
+(defmethod maximum ((matcher modulo-matcher))
+ nil)
+
+
+(defun parse-single-line-designator (designator)
+ (ppcre:register-groups-bind
+ ((#'parse-integer n))
+ ("^(\\d+)$" designator)
+ (make-instance 'single-line-matcher :designator designator :n n)))
+
+(defun parse-range-designator (designator)
+ (ppcre:register-groups-bind
+ ((#'parse-integer m n))
+ ("^(\\d+)?-(\\d+)?$" designator)
+ (when (and m n)
+ (assert (<= m n) ()
+ "Bad line range designator ~S: start (~D) must not be greater than end (~D)."
+ designator m n))
+ (make-instance 'range-matcher :designator designator :m m :n n)))
+
+(defun parse-modulo-designator (designator)
+ (ppcre:register-groups-bind
+ ((#'parse-integer n modulus))
+ ("^(\\d+)?m(\\d+)$" designator)
+ (when (null n)
+ (setf n 0))
+ (assert (< n modulus) ()
+ "Bad modulo designator ~S: offset (~D) must be less than modulus (~D)."
+ designator n modulus)
+ (make-instance 'modulo-matcher :designator designator :n n :modulus modulus)))
+
+(defun parse-line-designator (designator)
+ (or (parse-single-line-designator designator)
+ (parse-range-designator designator)
+ (parse-modulo-designator designator)
+ (error "Could not parse line designator ~S" designator)))
+
+(defun parse-line-designators (designators)
+ (mapcar #'parse-line-designator (ppcre:split "," designators)))
+
+
+(defun dbg (&rest args)
+ (apply #'format *error-output* args)
+ (finish-output *error-output*))
+
+(defun compute-limit (matchers)
+ (let ((maxes (mapcar #'maximum matchers)))
+ (unless (some #'null maxes)
+ (reduce #'max maxes))))
+
+(defun collect-lines (matchers)
+ (loop
+ :with limit = (compute-limit matchers)
+ :with min = *index-base*
+ :with max = nil
+ :with lines = (make-hash-table)
+ :for i :from min
+ :for line = (read-line *standard-input* nil)
+ :while line
+ :while (or (null limit) (<= i limit))
+ :do (progn (setf max i)
+ (dolist (matcher matchers)
+ (when (matches-line-p matcher i)
+ (setf (gethash i lines) line))))
+ :finally (return (values lines min max))))
+
+
+(defun output-line (line i)
+ (when i
+ (format *standard-output* "~D " i))
+ (write-line line))
+
+(defun run-slow (matchers)
+ (let ((include-numbers *include-numbers*))
+ (multiple-value-bind (lines min max) (collect-lines matchers)
+ (dolist (matcher matchers)
+ (map-matching-lines
+ matcher
+ (lambda (i)
+ (output-line (gethash i lines)
+ (when include-numbers i)))
+ min max)))))
+
+(defun run-fast (matcher)
+ (loop
+ :with limit = (when *limit* (+ *index-base* *limit*))
+ :with include-numbers = *include-numbers*
+ :for i :from *index-base*
+ :for line = (read-line *standard-input* nil)
+ :while (or (null limit) (< i limit))
+ :while line
+ :when (zerop (mod i 100000))
+ :do (progn #+sbcl (sb-ext:gc))
+ :when (matches-line-p matcher i)
+ :do (output-line line (when include-numbers i))))
+
+(defun run (line-designators)
+ (let ((matchers (parse-line-designators line-designators)))
+ (if (= 1 (length matchers))
+ (run-fast (first matchers))
+ (run-slow matchers)))
+ (values))
+
+
+;;;; User Interface -----------------------------------------------------------
+(defmacro defparameters (parameters values-form)
+ `(progn
+ ,@(loop :for parameter :in parameters
+ :collect `(defparameter ,parameter nil))
+ (setf (values ,@parameters) ,values-form)
+ ',parameters))
+
+(defun make-boolean-options
+ (name &key
+ (name-no (intern (concatenate 'string (string 'no-) (string name))))
+ long
+ (long-no (when long (format nil "no-~A" long)))
+ short
+ (short-no (when short (char-upcase short)))
+ (result-key name)
+ help
+ help-no
+ manual
+ manual-no
+ initial-value)
+ (values (adopt:make-option name
+ :result-key result-key
+ :long long
+ :short short
+ :help help
+ :manual manual
+ :initial-value initial-value
+ :reduce (constantly t))
+ (adopt:make-option name-no
+ :result-key result-key
+ :long long-no
+ :short short-no
+ :help help-no
+ :manual manual-no
+ :reduce (constantly nil))))
+
+
+(defparameters (*option-debug* *option-no-debug*)
+ (make-boolean-options 'debug
+ :long "debug"
+ :short #\d
+ :help "Enable the Lisp debugger."
+ :help-no "Disable the Lisp debugger (default)."))
+
+(defparameter *option-help*
+ (adopt:make-option 'help
+ :help "Display help and exit."
+ :long "help"
+ :short #\h
+ :reduce (constantly t)))
+
+(defparameter *option-version*
+ (adopt:make-option 'version
+ :help "Display version information and exit."
+ :long "version"
+ :reduce (constantly t)))
+
+
+(defparameter *option-one-based*
+ (adopt:make-option 'one-based
+ :result-key 'index-base
+ :help "Start numbering lines at 1 (default)."
+ :short #\1
+ :long "one"
+ :reduce (constantly 1)))
+
+(defparameter *option-zero-based*
+ (adopt:make-option 'zero-based
+ :result-key 'index-base
+ :help "Start numbering lines at 0."
+ :short #\0
+ :long "zero"
+ :reduce (constantly 0)))
+
+(defparameter *option-other-base*
+ (adopt:make-option 'other-base
+ :result-key 'index-base
+ :initial-value 0
+ :help "Start numbering lines at N."
+ :parameter "N"
+ :short #\s
+ :long "start"
+ :key #'parse-integer
+ :reduce #'adopt:last))
+
+(defparameters (*option-include-numbers* *option-no-include-numbers*)
+ (make-boolean-options 'include-numbers
+ :long "number"
+ :short #\n
+ :help "Add line numbers to the output."
+ :help-no "Do not add line number to the output (default)."))
+
+
+(defparameter *option-limit*
+ (adopt:make-option 'limit
+ :help "Read at most N lines."
+ :parameter "N"
+ :short #\l
+ :long "limit"
+ :key #'parse-integer
+ :reduce #'adopt:last))
+
+(defparameter *option-no-limit*
+ (adopt:make-option 'no-limit
+ :result-key 'limit
+ :help "Read all lines (default)."
+ :short #\L
+ :long "no-limit"
+ :reduce (constantly nil)))
+
+
+(defparameter *option-input-encoding*
+ (adopt:make-option 'input-encoding
+ :help "Treat input as being encoded with ENC (default utf-8)."
+ :parameter "ENC"
+ :short #\i
+ :long "input-encoding"
+ :initial-value "utf-8"
+ :reduce #'adopt:last))
+
+(defparameter *option-output-encoding*
+ (adopt:make-option 'output-encoding
+ :help "Output text encoded with ENC (default utf-8)."
+ :parameter "ENC"
+ :short #\o
+ :long "output-encoding"
+ :initial-value "utf-8"
+ :reduce #'adopt:last))
+
+(defparameter *option-input-replacement*
+ (adopt:make-option 'input-replacement
+ :help "If an input character is not valid in the selected encoding, replace it with REP."
+ :parameter "REP"
+ :short #\r
+ :long "input-replacement"
+ :reduce #'adopt:last))
+
+(defparameter *option-no-input-replacement*
+ (adopt:make-option 'no-input-replacement
+ :result-key 'input-replacement
+ :help "If an input character is not valid in the selected encoding, return an error (default)."
+ :short #\R
+ :long "no-input-replacement"
+ :reduce (constantly nil)))
+
+(defparameter *option-output-replacement*
+ (adopt:make-option 'output-replacement
+ :help "If an output character would not be not valid in the selected encoding, replace it with REP."
+ :parameter "REP"
+ :short #\q
+ :long "output-replacement"
+ :reduce #'adopt:last))
+
+(defparameter *option-no-output-replacement*
+ (adopt:make-option 'no-output-replacement
+ :result-key 'output-replacement
+ :help "If an output character would not be valid in the selected encoding, return an error (default)."
+ :short #\Q
+ :long "no-output-replacement"
+ :reduce (constantly nil)))
+
+
+(adopt:define-string *help-text*
+ "lines takes a string denoting which lines to print, and prints those lines ~
+ of standard input.")
+
+(defparameter *examples*
+ '(("Print line 1234:"
+ . "cat log.txt | lines 1234")
+ ("Print line 2, then line 1:"
+ . "cat log.txt | lines 2,1")
+ ("Print lines 6, 12, 100-200, and 999+ (1-indexed):"
+ . "cat log.txt | lines -1 6,12,100-200,999-")
+ ("Print lines 0, 2, 4, 6, …:"
+ . "cat log.txt | lines m2")
+ ("Print the third line of every set of four lines:"
+ . "cat foo.fastq | lines 3m4")))
+
+
+(defparameter *ui*
+ (adopt:make-interface
+ :name "lines"
+ :usage "[OPTIONS] LINE-DESIGNATORS"
+ :summary "print designated lines of standard input"
+ :help *help-text*
+ :examples *examples*
+ :contents (list
+ *option-limit*
+ *option-no-limit*
+ *option-help*
+ *option-version*
+ *option-debug*
+ *option-no-debug*
+ (adopt:make-group 'character-encodings
+ :title "Character Encodings"
+ :options (list
+ *option-input-encoding*
+ *option-input-replacement*
+ *option-no-input-replacement*
+ *option-output-encoding*
+ *option-output-replacement*
+ *option-no-output-replacement*))
+ (adopt:make-group 'line-numbering
+ :title "Line Numbering"
+ :options (list
+ *option-one-based*
+ *option-zero-based*
+ *option-other-base*
+ *option-include-numbers*
+ *option-no-include-numbers*)))))
+
+
+(defmacro without-debugger (&body body)
+ `(multiple-value-prog1
+ (progn
+ #+sbcl (sb-ext:disable-debugger)
+ (progn ,@body))
+ (progn
+ #+sbcl (sb-ext:enable-debugger))))
+
+(defmacro exit-on-error (&body body)
+ `(without-debugger
+ (handler-case (progn ,@body)
+ #+sbcl (sb-int:broken-pipe () (adopt:exit))
+ (error (c) (adopt:print-error-and-exit c)))))
+
+(defmacro exit-on-error-unless (expr &body body)
+ `(if ,expr
+ (progn ,@body)
+ (exit-on-error ,@body)))
+
+(defmacro exit-on-ctrl-c (&body body)
+ `(handler-case
+ (with-user-abort:with-user-abort (progn ,@body))
+ (with-user-abort:user-abort () (adopt:exit 130))))
+
+
+(defun determine-external-format (encoding replacement)
+ (let ((encoding (intern (string-upcase encoding) :keyword)))
+ (if (null replacement)
+ encoding
+ (list encoding :replacement replacement))))
+
+(defun toplevel ()
+ (exit-on-ctrl-c
+ (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
+ (exit-on-error-unless (gethash 'debug options)
+ (cond
+ ((gethash 'help options) (adopt:print-help-and-exit *ui*))
+ ((gethash 'version options) (write-line *version*) (adopt:exit))
+ ((null arguments) (error "LINE-DESIGNATORS are required."))
+ (t (destructuring-bind (line-designators . more) arguments
+ (when more
+ (error "Unrecognized command line arguments: ~S" more))
+ (let ((*index-base* (gethash 'index-base options))
+ (*include-numbers* (gethash 'include-numbers options))
+ (*limit* (gethash 'limit options))
+ (input-format (determine-external-format
+ (gethash 'input-encoding options)
+ (gethash 'input-replacement options)))
+ (output-format (determine-external-format
+ (gethash 'output-encoding options)
+ (gethash 'output-replacement options))))
+ (with-open-file (*standard-input* "/dev/stdin"
+ :external-format input-format)
+ (with-open-file (*standard-output* "/dev/stdout"
+ :external-format output-format
+ :direction :output
+ :if-exists :append)
+ (run line-designators)))))))))))
+
+
+#; Scratch --------------------------------------------------------------------
+
+(let ((*standard-input* (make-string-input-stream
+"0 a foo
+1 b bar
+2 c baz
+3 d hello
+4 a world
+5 b yes
+6 c this
+7 d is
+8 a cat
+9 b meow")))
+ (run "4m4"))
--- a/psqlrc Tue Feb 04 09:23:46 2020 -0500
+++ b/psqlrc Tue Feb 04 09:24:12 2020 -0500
@@ -7,3 +7,6 @@
\set PROMPT1 '%[%033[1;34m%]%M:%> %n@%/%R%#%x%[%033[0m%] '
\timing
+
+\setenv PAGER less
+\setenv LESS -iS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remote/bin/e Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,1 @@
+../../bin/e
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remote/bin/lines Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,1 @@
+../../lisp/bin/lines
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remote/bin/u Tue Feb 04 09:24:12 2020 -0500
@@ -0,0 +1,1 @@
+../../bin/u
\ No newline at end of file
--- a/restic/excludes.txt Tue Feb 04 09:23:46 2020 -0500
+++ b/restic/excludes.txt Tue Feb 04 09:24:12 2020 -0500
@@ -1,20 +1,31 @@
+*.fasl
.cache
-cache2
+/home/sjl/.arduino15
+/home/sjl/.config/chromium
+/home/sjl/.config/discord
+/home/sjl/.config/google-chrome
+/home/sjl/.config/libreoffice
+/home/sjl/.config/unity3d
+/home/sjl/.crawl
/home/sjl/.dbus
-/home/sjl/src/dotfiles/vim/tmp
-/home/sjl/snap
+/home/sjl/.dropbox
+/home/sjl/.dropbox-dist
+/home/sjl/.gimp-*
+/home/sjl/.go
+/home/sjl/.hg-git
+/home/sjl/.local/lib/python*
+/home/sjl/.local/share
+/home/sjl/.mozilla
+/home/sjl/.quicklisp
+/home/sjl/.rlwrap
+/home/sjl/.slime
+/home/sjl/.steam
+/home/sjl/.virtualenvs
+/home/sjl/Dropbox/.dropbox.cache
/home/sjl/Videos
/home/sjl/dwhelper
-/home/sjl/.mozilla
-/home/sjl/.dropbox
-/home/sjl/.steam
-/home/sjl/.quicklisp
-/home/sjl/.virtualenvs
-/home/sjl/.local/share
-/home/sjl/.local/lib/python*
-/home/sjl/.config/chromium
-/home/sjl/.config/libreoffice
-/home/sjl/.config/discord
-/home/sjl/.dropbox-dist
-/home/sjl/Dropbox/.dropbox.cache
-
+/home/sjl/snap
+/home/sjl/src/abcl
+/home/sjl/src/arduino
+/home/sjl/src/dotfiles/vim/tmp
+cache2
--- a/servers/bash_profile Tue Feb 04 09:23:46 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-
-shopt -s expand_aliases
-
-export PATH=~/bin:~/dotfiles/bin:$PATH
-
-alias l='ls -1 --color=auto'
-alias ll='ls -la1 --color=auto'
-alias h='hg'
-alias g='git'
-alias pj='python -m json.tool'
-alias ..='cd ..'
-alias ...='cd ../..'
-alias ....='cd ../../..'
-alias .....='cd ../../../..'
-alias ......='cd ../../../../..'
-alias nvim=vim
-
-function psg() {
- ps auxww | grep --color=always $* | grep -v grep | collapse | cuts -f 2,11-
-}
-
-export EDITOR=vim
-
-D=$'\e[37m'
-PINK=$'\e[35m'
-GREEN=$'\e[32m'
-ORANGE=$'\e[33m'
-
-export PS1='\n${PINK}\u ${D}at ${ORANGE}\h ${D}in ${GREEN}\w${D}\n$ '
--- a/servers/bin/collapse Tue Feb 04 09:23:46 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../../bin/collapse
\ No newline at end of file
--- a/servers/bin/cuts Tue Feb 04 09:23:46 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../../bin/cuts
\ No newline at end of file
--- a/servers/bin/f Tue Feb 04 09:23:46 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../../bin/f
\ No newline at end of file
--- a/vim/custom-dictionary.utf-8.add Tue Feb 04 09:23:46 2020 -0500
+++ b/vim/custom-dictionary.utf-8.add Tue Feb 04 09:24:12 2020 -0500
@@ -299,3 +299,7 @@
Phosphorylation
iterate's
memoization
+gnuplot
+Illumina
+Phred
+FastQC
--- a/vim/vimrc Tue Feb 04 09:23:46 2020 -0500
+++ b/vim/vimrc Tue Feb 04 09:24:12 2020 -0500
@@ -1405,7 +1405,7 @@
augroup ft_gnuplot
au!
- au BufNewFile,BufRead *.gp setlocal filetype=gnuplot
+ au BufNewFile,BufRead *.gp,.gnuplot setlocal filetype=gnuplot
au FileType gnuplot nnoremap <buffer> <silent> <localleader>o :call OpenGnuplotRepl()<cr>
@@ -1627,6 +1627,7 @@
au!
au Filetype make setlocal shiftwidth=8
+ au Filetype make setlocal foldmethod=marker foldmarker={{{,}}}
augroup END
" }}}
@@ -1790,7 +1791,7 @@
au BufNewFile,BufRead *.sql set filetype=pgsql
au BufNewFile,BufRead *.pgsql set filetype=pgsql
- au FileType pgsql set foldmethod=indent
+ au FileType pgsql set foldmethod=marker foldmarker=\ $$,$$\
au FileType pgsql set softtabstop=2 shiftwidth=2
au FileType pgsql setlocal commentstring=--\ %s comments=:--